123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870 |
- /***********************************************************************
- **
- ** Implementation of the Skein hash function.
- **
- ** Source code author: Doug Whiting, 2008.
- **
- ** This algorithm and source code is released to the public domain.
- **
- ************************************************************************/
- #include <linux/string.h> /* get the memcpy/memset functions */
- #include <linux/export.h>
- #include "skein_base.h" /* get the Skein API definitions */
- #include "skein_iv.h" /* get precomputed IVs */
- #include "skein_block.h"
- /*****************************************************************/
- /* 256-bit Skein */
- /*****************************************************************/
- /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
- /* init the context for a straight hashing operation */
- int skein_256_init(struct skein_256_ctx *ctx, size_t hash_bit_len)
- {
- union {
- u8 b[SKEIN_256_STATE_BYTES];
- u64 w[SKEIN_256_STATE_WORDS];
- } cfg; /* config block */
- skein_assert_ret(hash_bit_len > 0, SKEIN_BAD_HASHLEN);
- ctx->h.hash_bit_len = hash_bit_len; /* output hash bit count */
- switch (hash_bit_len) { /* use pre-computed values, where available */
- case 256:
- memcpy(ctx->x, SKEIN_256_IV_256, sizeof(ctx->x));
- break;
- case 224:
- memcpy(ctx->x, SKEIN_256_IV_224, sizeof(ctx->x));
- break;
- case 160:
- memcpy(ctx->x, SKEIN_256_IV_160, sizeof(ctx->x));
- break;
- case 128:
- memcpy(ctx->x, SKEIN_256_IV_128, sizeof(ctx->x));
- break;
- default:
- /* here if there is no precomputed IV value available */
- /*
- * build/process the config block, type == CONFIG (could be
- * precomputed)
- */
- /* set tweaks: T0=0; T1=CFG | FINAL */
- skein_start_new_type(ctx, CFG_FINAL);
- /* set the schema, version */
- cfg.w[0] = skein_swap64(SKEIN_SCHEMA_VER);
- /* hash result length in bits */
- cfg.w[1] = skein_swap64(hash_bit_len);
- cfg.w[2] = skein_swap64(SKEIN_CFG_TREE_INFO_SEQUENTIAL);
- /* zero pad config block */
- memset(&cfg.w[3], 0, sizeof(cfg) - 3*sizeof(cfg.w[0]));
- /* compute the initial chaining values from config block */
- /* zero the chaining variables */
- memset(ctx->x, 0, sizeof(ctx->x));
- skein_256_process_block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN);
- break;
- }
- /* The chaining vars ctx->x are now initialized for hash_bit_len. */
- /* Set up to process the data message portion of the hash (default) */
- skein_start_new_type(ctx, MSG); /* T0=0, T1= MSG type */
- return SKEIN_SUCCESS;
- }
- /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
- /* init the context for a MAC and/or tree hash operation */
- /*
- * [identical to skein_256_init() when key_bytes == 0 && \
- * tree_info == SKEIN_CFG_TREE_INFO_SEQUENTIAL]
- */
- int skein_256_init_ext(struct skein_256_ctx *ctx, size_t hash_bit_len,
- u64 tree_info, const u8 *key, size_t key_bytes)
- {
- union {
- u8 b[SKEIN_256_STATE_BYTES];
- u64 w[SKEIN_256_STATE_WORDS];
- } cfg; /* config block */
- skein_assert_ret(hash_bit_len > 0, SKEIN_BAD_HASHLEN);
- skein_assert_ret(key_bytes == 0 || key, SKEIN_FAIL);
- /* compute the initial chaining values ctx->x[], based on key */
- if (key_bytes == 0) { /* is there a key? */
- /* no key: use all zeroes as key for config block */
- memset(ctx->x, 0, sizeof(ctx->x));
- } else { /* here to pre-process a key */
- skein_assert(sizeof(cfg.b) >= sizeof(ctx->x));
- /* do a mini-Init right here */
- /* set output hash bit count = state size */
- ctx->h.hash_bit_len = 8*sizeof(ctx->x);
- /* set tweaks: T0 = 0; T1 = KEY type */
- skein_start_new_type(ctx, KEY);
- /* zero the initial chaining variables */
- memset(ctx->x, 0, sizeof(ctx->x));
- /* hash the key */
- skein_256_update(ctx, key, key_bytes);
- /* put result into cfg.b[] */
- skein_256_final_pad(ctx, cfg.b);
- /* copy over into ctx->x[] */
- memcpy(ctx->x, cfg.b, sizeof(cfg.b));
- }
- /*
- * build/process the config block, type == CONFIG (could be
- * precomputed for each key)
- */
- /* output hash bit count */
- ctx->h.hash_bit_len = hash_bit_len;
- skein_start_new_type(ctx, CFG_FINAL);
- /* pre-pad cfg.w[] with zeroes */
- memset(&cfg.w, 0, sizeof(cfg.w));
- cfg.w[0] = skein_swap64(SKEIN_SCHEMA_VER);
- /* hash result length in bits */
- cfg.w[1] = skein_swap64(hash_bit_len);
- /* tree hash config info (or SKEIN_CFG_TREE_INFO_SEQUENTIAL) */
- cfg.w[2] = skein_swap64(tree_info);
- /* compute the initial chaining values from config block */
- skein_256_process_block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN);
- /* The chaining vars ctx->x are now initialized */
- /* Set up to process the data message portion of the hash (default) */
- skein_start_new_type(ctx, MSG);
- return SKEIN_SUCCESS;
- }
- /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
- /* process the input bytes */
- int skein_256_update(struct skein_256_ctx *ctx, const u8 *msg,
- size_t msg_byte_cnt)
- {
- size_t n;
- /* catch uninitialized context */
- skein_assert_ret(ctx->h.b_cnt <= SKEIN_256_BLOCK_BYTES, SKEIN_FAIL);
- /* process full blocks, if any */
- if (msg_byte_cnt + ctx->h.b_cnt > SKEIN_256_BLOCK_BYTES) {
- /* finish up any buffered message data */
- if (ctx->h.b_cnt) {
- /* # bytes free in buffer b[] */
- n = SKEIN_256_BLOCK_BYTES - ctx->h.b_cnt;
- if (n) {
- /* check on our logic here */
- skein_assert(n < msg_byte_cnt);
- memcpy(&ctx->b[ctx->h.b_cnt], msg, n);
- msg_byte_cnt -= n;
- msg += n;
- ctx->h.b_cnt += n;
- }
- skein_assert(ctx->h.b_cnt == SKEIN_256_BLOCK_BYTES);
- skein_256_process_block(ctx, ctx->b, 1,
- SKEIN_256_BLOCK_BYTES);
- ctx->h.b_cnt = 0;
- }
- /*
- * now process any remaining full blocks, directly from input
- * message data
- */
- if (msg_byte_cnt > SKEIN_256_BLOCK_BYTES) {
- /* number of full blocks to process */
- n = (msg_byte_cnt-1) / SKEIN_256_BLOCK_BYTES;
- skein_256_process_block(ctx, msg, n,
- SKEIN_256_BLOCK_BYTES);
- msg_byte_cnt -= n * SKEIN_256_BLOCK_BYTES;
- msg += n * SKEIN_256_BLOCK_BYTES;
- }
- skein_assert(ctx->h.b_cnt == 0);
- }
- /* copy any remaining source message data bytes into b[] */
- if (msg_byte_cnt) {
- skein_assert(msg_byte_cnt + ctx->h.b_cnt <=
- SKEIN_256_BLOCK_BYTES);
- memcpy(&ctx->b[ctx->h.b_cnt], msg, msg_byte_cnt);
- ctx->h.b_cnt += msg_byte_cnt;
- }
- return SKEIN_SUCCESS;
- }
- /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
- /* finalize the hash computation and output the result */
- int skein_256_final(struct skein_256_ctx *ctx, u8 *hash_val)
- {
- size_t i, n, byte_cnt;
- u64 x[SKEIN_256_STATE_WORDS];
- /* catch uninitialized context */
- skein_assert_ret(ctx->h.b_cnt <= SKEIN_256_BLOCK_BYTES, SKEIN_FAIL);
- /* tag as the final block */
- ctx->h.tweak[1] |= SKEIN_T1_FLAG_FINAL;
- /* zero pad b[] if necessary */
- if (ctx->h.b_cnt < SKEIN_256_BLOCK_BYTES)
- memset(&ctx->b[ctx->h.b_cnt], 0,
- SKEIN_256_BLOCK_BYTES - ctx->h.b_cnt);
- /* process the final block */
- skein_256_process_block(ctx, ctx->b, 1, ctx->h.b_cnt);
- /* now output the result */
- /* total number of output bytes */
- byte_cnt = (ctx->h.hash_bit_len + 7) >> 3;
- /* run Threefish in "counter mode" to generate output */
- /* zero out b[], so it can hold the counter */
- memset(ctx->b, 0, sizeof(ctx->b));
- /* keep a local copy of counter mode "key" */
- memcpy(x, ctx->x, sizeof(x));
- for (i = 0; i*SKEIN_256_BLOCK_BYTES < byte_cnt; i++) {
- /* build the counter block */
- ((u64 *)ctx->b)[0] = skein_swap64((u64) i);
- skein_start_new_type(ctx, OUT_FINAL);
- /* run "counter mode" */
- skein_256_process_block(ctx, ctx->b, 1, sizeof(u64));
- /* number of output bytes left to go */
- n = byte_cnt - i*SKEIN_256_BLOCK_BYTES;
- if (n >= SKEIN_256_BLOCK_BYTES)
- n = SKEIN_256_BLOCK_BYTES;
- /* "output" the ctr mode bytes */
- skein_put64_lsb_first(hash_val+i*SKEIN_256_BLOCK_BYTES, ctx->x,
- n);
- /* restore the counter mode key for next time */
- memcpy(ctx->x, x, sizeof(x));
- }
- return SKEIN_SUCCESS;
- }
- /*****************************************************************/
- /* 512-bit Skein */
- /*****************************************************************/
- /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
- /* init the context for a straight hashing operation */
- int skein_512_init(struct skein_512_ctx *ctx, size_t hash_bit_len)
- {
- union {
- u8 b[SKEIN_512_STATE_BYTES];
- u64 w[SKEIN_512_STATE_WORDS];
- } cfg; /* config block */
- skein_assert_ret(hash_bit_len > 0, SKEIN_BAD_HASHLEN);
- ctx->h.hash_bit_len = hash_bit_len; /* output hash bit count */
- switch (hash_bit_len) { /* use pre-computed values, where available */
- case 512:
- memcpy(ctx->x, SKEIN_512_IV_512, sizeof(ctx->x));
- break;
- case 384:
- memcpy(ctx->x, SKEIN_512_IV_384, sizeof(ctx->x));
- break;
- case 256:
- memcpy(ctx->x, SKEIN_512_IV_256, sizeof(ctx->x));
- break;
- case 224:
- memcpy(ctx->x, SKEIN_512_IV_224, sizeof(ctx->x));
- break;
- default:
- /* here if there is no precomputed IV value available */
- /*
- * build/process the config block, type == CONFIG (could be
- * precomputed)
- */
- /* set tweaks: T0=0; T1=CFG | FINAL */
- skein_start_new_type(ctx, CFG_FINAL);
- /* set the schema, version */
- cfg.w[0] = skein_swap64(SKEIN_SCHEMA_VER);
- /* hash result length in bits */
- cfg.w[1] = skein_swap64(hash_bit_len);
- cfg.w[2] = skein_swap64(SKEIN_CFG_TREE_INFO_SEQUENTIAL);
- /* zero pad config block */
- memset(&cfg.w[3], 0, sizeof(cfg) - 3*sizeof(cfg.w[0]));
- /* compute the initial chaining values from config block */
- /* zero the chaining variables */
- memset(ctx->x, 0, sizeof(ctx->x));
- skein_512_process_block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN);
- break;
- }
- /*
- * The chaining vars ctx->x are now initialized for the given
- * hash_bit_len.
- */
- /* Set up to process the data message portion of the hash (default) */
- skein_start_new_type(ctx, MSG); /* T0=0, T1= MSG type */
- return SKEIN_SUCCESS;
- }
- /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
- /* init the context for a MAC and/or tree hash operation */
- /*
- * [identical to skein_512_init() when key_bytes == 0 && \
- * tree_info == SKEIN_CFG_TREE_INFO_SEQUENTIAL]
- */
- int skein_512_init_ext(struct skein_512_ctx *ctx, size_t hash_bit_len,
- u64 tree_info, const u8 *key, size_t key_bytes)
- {
- union {
- u8 b[SKEIN_512_STATE_BYTES];
- u64 w[SKEIN_512_STATE_WORDS];
- } cfg; /* config block */
- skein_assert_ret(hash_bit_len > 0, SKEIN_BAD_HASHLEN);
- skein_assert_ret(key_bytes == 0 || key, SKEIN_FAIL);
- /* compute the initial chaining values ctx->x[], based on key */
- if (key_bytes == 0) { /* is there a key? */
- /* no key: use all zeroes as key for config block */
- memset(ctx->x, 0, sizeof(ctx->x));
- } else { /* here to pre-process a key */
- skein_assert(sizeof(cfg.b) >= sizeof(ctx->x));
- /* do a mini-Init right here */
- /* set output hash bit count = state size */
- ctx->h.hash_bit_len = 8*sizeof(ctx->x);
- /* set tweaks: T0 = 0; T1 = KEY type */
- skein_start_new_type(ctx, KEY);
- /* zero the initial chaining variables */
- memset(ctx->x, 0, sizeof(ctx->x));
- /* hash the key */
- skein_512_update(ctx, key, key_bytes);
- /* put result into cfg.b[] */
- skein_512_final_pad(ctx, cfg.b);
- /* copy over into ctx->x[] */
- memcpy(ctx->x, cfg.b, sizeof(cfg.b));
- }
- /*
- * build/process the config block, type == CONFIG (could be
- * precomputed for each key)
- */
- ctx->h.hash_bit_len = hash_bit_len; /* output hash bit count */
- skein_start_new_type(ctx, CFG_FINAL);
- /* pre-pad cfg.w[] with zeroes */
- memset(&cfg.w, 0, sizeof(cfg.w));
- cfg.w[0] = skein_swap64(SKEIN_SCHEMA_VER);
- /* hash result length in bits */
- cfg.w[1] = skein_swap64(hash_bit_len);
- /* tree hash config info (or SKEIN_CFG_TREE_INFO_SEQUENTIAL) */
- cfg.w[2] = skein_swap64(tree_info);
- /* compute the initial chaining values from config block */
- skein_512_process_block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN);
- /* The chaining vars ctx->x are now initialized */
- /* Set up to process the data message portion of the hash (default) */
- skein_start_new_type(ctx, MSG);
- return SKEIN_SUCCESS;
- }
- /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
- /* process the input bytes */
- int skein_512_update(struct skein_512_ctx *ctx, const u8 *msg,
- size_t msg_byte_cnt)
- {
- size_t n;
- /* catch uninitialized context */
- skein_assert_ret(ctx->h.b_cnt <= SKEIN_512_BLOCK_BYTES, SKEIN_FAIL);
- /* process full blocks, if any */
- if (msg_byte_cnt + ctx->h.b_cnt > SKEIN_512_BLOCK_BYTES) {
- /* finish up any buffered message data */
- if (ctx->h.b_cnt) {
- /* # bytes free in buffer b[] */
- n = SKEIN_512_BLOCK_BYTES - ctx->h.b_cnt;
- if (n) {
- /* check on our logic here */
- skein_assert(n < msg_byte_cnt);
- memcpy(&ctx->b[ctx->h.b_cnt], msg, n);
- msg_byte_cnt -= n;
- msg += n;
- ctx->h.b_cnt += n;
- }
- skein_assert(ctx->h.b_cnt == SKEIN_512_BLOCK_BYTES);
- skein_512_process_block(ctx, ctx->b, 1,
- SKEIN_512_BLOCK_BYTES);
- ctx->h.b_cnt = 0;
- }
- /*
- * now process any remaining full blocks, directly from input
- * message data
- */
- if (msg_byte_cnt > SKEIN_512_BLOCK_BYTES) {
- /* number of full blocks to process */
- n = (msg_byte_cnt-1) / SKEIN_512_BLOCK_BYTES;
- skein_512_process_block(ctx, msg, n,
- SKEIN_512_BLOCK_BYTES);
- msg_byte_cnt -= n * SKEIN_512_BLOCK_BYTES;
- msg += n * SKEIN_512_BLOCK_BYTES;
- }
- skein_assert(ctx->h.b_cnt == 0);
- }
- /* copy any remaining source message data bytes into b[] */
- if (msg_byte_cnt) {
- skein_assert(msg_byte_cnt + ctx->h.b_cnt <=
- SKEIN_512_BLOCK_BYTES);
- memcpy(&ctx->b[ctx->h.b_cnt], msg, msg_byte_cnt);
- ctx->h.b_cnt += msg_byte_cnt;
- }
- return SKEIN_SUCCESS;
- }
- /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
- /* finalize the hash computation and output the result */
- int skein_512_final(struct skein_512_ctx *ctx, u8 *hash_val)
- {
- size_t i, n, byte_cnt;
- u64 x[SKEIN_512_STATE_WORDS];
- /* catch uninitialized context */
- skein_assert_ret(ctx->h.b_cnt <= SKEIN_512_BLOCK_BYTES, SKEIN_FAIL);
- /* tag as the final block */
- ctx->h.tweak[1] |= SKEIN_T1_FLAG_FINAL;
- /* zero pad b[] if necessary */
- if (ctx->h.b_cnt < SKEIN_512_BLOCK_BYTES)
- memset(&ctx->b[ctx->h.b_cnt], 0,
- SKEIN_512_BLOCK_BYTES - ctx->h.b_cnt);
- /* process the final block */
- skein_512_process_block(ctx, ctx->b, 1, ctx->h.b_cnt);
- /* now output the result */
- /* total number of output bytes */
- byte_cnt = (ctx->h.hash_bit_len + 7) >> 3;
- /* run Threefish in "counter mode" to generate output */
- /* zero out b[], so it can hold the counter */
- memset(ctx->b, 0, sizeof(ctx->b));
- /* keep a local copy of counter mode "key" */
- memcpy(x, ctx->x, sizeof(x));
- for (i = 0; i*SKEIN_512_BLOCK_BYTES < byte_cnt; i++) {
- /* build the counter block */
- ((u64 *)ctx->b)[0] = skein_swap64((u64) i);
- skein_start_new_type(ctx, OUT_FINAL);
- /* run "counter mode" */
- skein_512_process_block(ctx, ctx->b, 1, sizeof(u64));
- /* number of output bytes left to go */
- n = byte_cnt - i*SKEIN_512_BLOCK_BYTES;
- if (n >= SKEIN_512_BLOCK_BYTES)
- n = SKEIN_512_BLOCK_BYTES;
- /* "output" the ctr mode bytes */
- skein_put64_lsb_first(hash_val+i*SKEIN_512_BLOCK_BYTES, ctx->x,
- n);
- /* restore the counter mode key for next time */
- memcpy(ctx->x, x, sizeof(x));
- }
- return SKEIN_SUCCESS;
- }
- /*****************************************************************/
- /* 1024-bit Skein */
- /*****************************************************************/
- /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
- /* init the context for a straight hashing operation */
- int skein_1024_init(struct skein_1024_ctx *ctx, size_t hash_bit_len)
- {
- union {
- u8 b[SKEIN_1024_STATE_BYTES];
- u64 w[SKEIN_1024_STATE_WORDS];
- } cfg; /* config block */
- skein_assert_ret(hash_bit_len > 0, SKEIN_BAD_HASHLEN);
- ctx->h.hash_bit_len = hash_bit_len; /* output hash bit count */
- switch (hash_bit_len) { /* use pre-computed values, where available */
- case 512:
- memcpy(ctx->x, SKEIN_1024_IV_512, sizeof(ctx->x));
- break;
- case 384:
- memcpy(ctx->x, SKEIN_1024_IV_384, sizeof(ctx->x));
- break;
- case 1024:
- memcpy(ctx->x, SKEIN_1024_IV_1024, sizeof(ctx->x));
- break;
- default:
- /* here if there is no precomputed IV value available */
- /*
- * build/process the config block, type == CONFIG
- * (could be precomputed)
- */
- /* set tweaks: T0=0; T1=CFG | FINAL */
- skein_start_new_type(ctx, CFG_FINAL);
- /* set the schema, version */
- cfg.w[0] = skein_swap64(SKEIN_SCHEMA_VER);
- /* hash result length in bits */
- cfg.w[1] = skein_swap64(hash_bit_len);
- cfg.w[2] = skein_swap64(SKEIN_CFG_TREE_INFO_SEQUENTIAL);
- /* zero pad config block */
- memset(&cfg.w[3], 0, sizeof(cfg) - 3*sizeof(cfg.w[0]));
- /* compute the initial chaining values from config block */
- /* zero the chaining variables */
- memset(ctx->x, 0, sizeof(ctx->x));
- skein_1024_process_block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN);
- break;
- }
- /* The chaining vars ctx->x are now initialized for the hash_bit_len. */
- /* Set up to process the data message portion of the hash (default) */
- skein_start_new_type(ctx, MSG); /* T0=0, T1= MSG type */
- return SKEIN_SUCCESS;
- }
- /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
- /* init the context for a MAC and/or tree hash operation */
- /*
- * [identical to skein_1024_init() when key_bytes == 0 && \
- * tree_info == SKEIN_CFG_TREE_INFO_SEQUENTIAL]
- */
- int skein_1024_init_ext(struct skein_1024_ctx *ctx, size_t hash_bit_len,
- u64 tree_info, const u8 *key, size_t key_bytes)
- {
- union {
- u8 b[SKEIN_1024_STATE_BYTES];
- u64 w[SKEIN_1024_STATE_WORDS];
- } cfg; /* config block */
- skein_assert_ret(hash_bit_len > 0, SKEIN_BAD_HASHLEN);
- skein_assert_ret(key_bytes == 0 || key, SKEIN_FAIL);
- /* compute the initial chaining values ctx->x[], based on key */
- if (key_bytes == 0) { /* is there a key? */
- /* no key: use all zeroes as key for config block */
- memset(ctx->x, 0, sizeof(ctx->x));
- } else { /* here to pre-process a key */
- skein_assert(sizeof(cfg.b) >= sizeof(ctx->x));
- /* do a mini-Init right here */
- /* set output hash bit count = state size */
- ctx->h.hash_bit_len = 8*sizeof(ctx->x);
- /* set tweaks: T0 = 0; T1 = KEY type */
- skein_start_new_type(ctx, KEY);
- /* zero the initial chaining variables */
- memset(ctx->x, 0, sizeof(ctx->x));
- /* hash the key */
- skein_1024_update(ctx, key, key_bytes);
- /* put result into cfg.b[] */
- skein_1024_final_pad(ctx, cfg.b);
- /* copy over into ctx->x[] */
- memcpy(ctx->x, cfg.b, sizeof(cfg.b));
- }
- /*
- * build/process the config block, type == CONFIG (could be
- * precomputed for each key)
- */
- /* output hash bit count */
- ctx->h.hash_bit_len = hash_bit_len;
- skein_start_new_type(ctx, CFG_FINAL);
- /* pre-pad cfg.w[] with zeroes */
- memset(&cfg.w, 0, sizeof(cfg.w));
- cfg.w[0] = skein_swap64(SKEIN_SCHEMA_VER);
- /* hash result length in bits */
- cfg.w[1] = skein_swap64(hash_bit_len);
- /* tree hash config info (or SKEIN_CFG_TREE_INFO_SEQUENTIAL) */
- cfg.w[2] = skein_swap64(tree_info);
- /* compute the initial chaining values from config block */
- skein_1024_process_block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN);
- /* The chaining vars ctx->x are now initialized */
- /* Set up to process the data message portion of the hash (default) */
- skein_start_new_type(ctx, MSG);
- return SKEIN_SUCCESS;
- }
- /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
- /* process the input bytes */
- int skein_1024_update(struct skein_1024_ctx *ctx, const u8 *msg,
- size_t msg_byte_cnt)
- {
- size_t n;
- /* catch uninitialized context */
- skein_assert_ret(ctx->h.b_cnt <= SKEIN_1024_BLOCK_BYTES, SKEIN_FAIL);
- /* process full blocks, if any */
- if (msg_byte_cnt + ctx->h.b_cnt > SKEIN_1024_BLOCK_BYTES) {
- /* finish up any buffered message data */
- if (ctx->h.b_cnt) {
- /* # bytes free in buffer b[] */
- n = SKEIN_1024_BLOCK_BYTES - ctx->h.b_cnt;
- if (n) {
- /* check on our logic here */
- skein_assert(n < msg_byte_cnt);
- memcpy(&ctx->b[ctx->h.b_cnt], msg, n);
- msg_byte_cnt -= n;
- msg += n;
- ctx->h.b_cnt += n;
- }
- skein_assert(ctx->h.b_cnt == SKEIN_1024_BLOCK_BYTES);
- skein_1024_process_block(ctx, ctx->b, 1,
- SKEIN_1024_BLOCK_BYTES);
- ctx->h.b_cnt = 0;
- }
- /*
- * now process any remaining full blocks, directly from input
- * message data
- */
- if (msg_byte_cnt > SKEIN_1024_BLOCK_BYTES) {
- /* number of full blocks to process */
- n = (msg_byte_cnt-1) / SKEIN_1024_BLOCK_BYTES;
- skein_1024_process_block(ctx, msg, n,
- SKEIN_1024_BLOCK_BYTES);
- msg_byte_cnt -= n * SKEIN_1024_BLOCK_BYTES;
- msg += n * SKEIN_1024_BLOCK_BYTES;
- }
- skein_assert(ctx->h.b_cnt == 0);
- }
- /* copy any remaining source message data bytes into b[] */
- if (msg_byte_cnt) {
- skein_assert(msg_byte_cnt + ctx->h.b_cnt <=
- SKEIN_1024_BLOCK_BYTES);
- memcpy(&ctx->b[ctx->h.b_cnt], msg, msg_byte_cnt);
- ctx->h.b_cnt += msg_byte_cnt;
- }
- return SKEIN_SUCCESS;
- }
- /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
- /* finalize the hash computation and output the result */
- int skein_1024_final(struct skein_1024_ctx *ctx, u8 *hash_val)
- {
- size_t i, n, byte_cnt;
- u64 x[SKEIN_1024_STATE_WORDS];
- /* catch uninitialized context */
- skein_assert_ret(ctx->h.b_cnt <= SKEIN_1024_BLOCK_BYTES, SKEIN_FAIL);
- /* tag as the final block */
- ctx->h.tweak[1] |= SKEIN_T1_FLAG_FINAL;
- /* zero pad b[] if necessary */
- if (ctx->h.b_cnt < SKEIN_1024_BLOCK_BYTES)
- memset(&ctx->b[ctx->h.b_cnt], 0,
- SKEIN_1024_BLOCK_BYTES - ctx->h.b_cnt);
- /* process the final block */
- skein_1024_process_block(ctx, ctx->b, 1, ctx->h.b_cnt);
- /* now output the result */
- /* total number of output bytes */
- byte_cnt = (ctx->h.hash_bit_len + 7) >> 3;
- /* run Threefish in "counter mode" to generate output */
- /* zero out b[], so it can hold the counter */
- memset(ctx->b, 0, sizeof(ctx->b));
- /* keep a local copy of counter mode "key" */
- memcpy(x, ctx->x, sizeof(x));
- for (i = 0; i*SKEIN_1024_BLOCK_BYTES < byte_cnt; i++) {
- /* build the counter block */
- ((u64 *)ctx->b)[0] = skein_swap64((u64) i);
- skein_start_new_type(ctx, OUT_FINAL);
- /* run "counter mode" */
- skein_1024_process_block(ctx, ctx->b, 1, sizeof(u64));
- /* number of output bytes left to go */
- n = byte_cnt - i*SKEIN_1024_BLOCK_BYTES;
- if (n >= SKEIN_1024_BLOCK_BYTES)
- n = SKEIN_1024_BLOCK_BYTES;
- /* "output" the ctr mode bytes */
- skein_put64_lsb_first(hash_val+i*SKEIN_1024_BLOCK_BYTES, ctx->x,
- n);
- /* restore the counter mode key for next time */
- memcpy(ctx->x, x, sizeof(x));
- }
- return SKEIN_SUCCESS;
- }
- /**************** Functions to support MAC/tree hashing ***************/
- /* (this code is identical for Optimized and Reference versions) */
- /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
- /* finalize the hash computation and output the block, no OUTPUT stage */
- int skein_256_final_pad(struct skein_256_ctx *ctx, u8 *hash_val)
- {
- /* catch uninitialized context */
- skein_assert_ret(ctx->h.b_cnt <= SKEIN_256_BLOCK_BYTES, SKEIN_FAIL);
- /* tag as the final block */
- ctx->h.tweak[1] |= SKEIN_T1_FLAG_FINAL;
- /* zero pad b[] if necessary */
- if (ctx->h.b_cnt < SKEIN_256_BLOCK_BYTES)
- memset(&ctx->b[ctx->h.b_cnt], 0,
- SKEIN_256_BLOCK_BYTES - ctx->h.b_cnt);
- /* process the final block */
- skein_256_process_block(ctx, ctx->b, 1, ctx->h.b_cnt);
- /* "output" the state bytes */
- skein_put64_lsb_first(hash_val, ctx->x, SKEIN_256_BLOCK_BYTES);
- return SKEIN_SUCCESS;
- }
- /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
- /* finalize the hash computation and output the block, no OUTPUT stage */
- int skein_512_final_pad(struct skein_512_ctx *ctx, u8 *hash_val)
- {
- /* catch uninitialized context */
- skein_assert_ret(ctx->h.b_cnt <= SKEIN_512_BLOCK_BYTES, SKEIN_FAIL);
- /* tag as the final block */
- ctx->h.tweak[1] |= SKEIN_T1_FLAG_FINAL;
- /* zero pad b[] if necessary */
- if (ctx->h.b_cnt < SKEIN_512_BLOCK_BYTES)
- memset(&ctx->b[ctx->h.b_cnt], 0,
- SKEIN_512_BLOCK_BYTES - ctx->h.b_cnt);
- /* process the final block */
- skein_512_process_block(ctx, ctx->b, 1, ctx->h.b_cnt);
- /* "output" the state bytes */
- skein_put64_lsb_first(hash_val, ctx->x, SKEIN_512_BLOCK_BYTES);
- return SKEIN_SUCCESS;
- }
- /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
- /* finalize the hash computation and output the block, no OUTPUT stage */
- int skein_1024_final_pad(struct skein_1024_ctx *ctx, u8 *hash_val)
- {
- /* catch uninitialized context */
- skein_assert_ret(ctx->h.b_cnt <= SKEIN_1024_BLOCK_BYTES, SKEIN_FAIL);
- /* tag as the final block */
- ctx->h.tweak[1] |= SKEIN_T1_FLAG_FINAL;
- /* zero pad b[] if necessary */
- if (ctx->h.b_cnt < SKEIN_1024_BLOCK_BYTES)
- memset(&ctx->b[ctx->h.b_cnt], 0,
- SKEIN_1024_BLOCK_BYTES - ctx->h.b_cnt);
- /* process the final block */
- skein_1024_process_block(ctx, ctx->b, 1, ctx->h.b_cnt);
- /* "output" the state bytes */
- skein_put64_lsb_first(hash_val, ctx->x, SKEIN_1024_BLOCK_BYTES);
- return SKEIN_SUCCESS;
- }
- #if SKEIN_TREE_HASH
- /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
- /* just do the OUTPUT stage */
- int skein_256_output(struct skein_256_ctx *ctx, u8 *hash_val)
- {
- size_t i, n, byte_cnt;
- u64 x[SKEIN_256_STATE_WORDS];
- /* catch uninitialized context */
- skein_assert_ret(ctx->h.b_cnt <= SKEIN_256_BLOCK_BYTES, SKEIN_FAIL);
- /* now output the result */
- /* total number of output bytes */
- byte_cnt = (ctx->h.hash_bit_len + 7) >> 3;
- /* run Threefish in "counter mode" to generate output */
- /* zero out b[], so it can hold the counter */
- memset(ctx->b, 0, sizeof(ctx->b));
- /* keep a local copy of counter mode "key" */
- memcpy(x, ctx->x, sizeof(x));
- for (i = 0; i*SKEIN_256_BLOCK_BYTES < byte_cnt; i++) {
- /* build the counter block */
- ((u64 *)ctx->b)[0] = skein_swap64((u64) i);
- skein_start_new_type(ctx, OUT_FINAL);
- /* run "counter mode" */
- skein_256_process_block(ctx, ctx->b, 1, sizeof(u64));
- /* number of output bytes left to go */
- n = byte_cnt - i*SKEIN_256_BLOCK_BYTES;
- if (n >= SKEIN_256_BLOCK_BYTES)
- n = SKEIN_256_BLOCK_BYTES;
- /* "output" the ctr mode bytes */
- skein_put64_lsb_first(hash_val+i*SKEIN_256_BLOCK_BYTES, ctx->x,
- n);
- /* restore the counter mode key for next time */
- memcpy(ctx->x, x, sizeof(x));
- }
- return SKEIN_SUCCESS;
- }
- /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
- /* just do the OUTPUT stage */
- int skein_512_output(struct skein_512_ctx *ctx, u8 *hash_val)
- {
- size_t i, n, byte_cnt;
- u64 x[SKEIN_512_STATE_WORDS];
- /* catch uninitialized context */
- skein_assert_ret(ctx->h.b_cnt <= SKEIN_512_BLOCK_BYTES, SKEIN_FAIL);
- /* now output the result */
- /* total number of output bytes */
- byte_cnt = (ctx->h.hash_bit_len + 7) >> 3;
- /* run Threefish in "counter mode" to generate output */
- /* zero out b[], so it can hold the counter */
- memset(ctx->b, 0, sizeof(ctx->b));
- /* keep a local copy of counter mode "key" */
- memcpy(x, ctx->x, sizeof(x));
- for (i = 0; i*SKEIN_512_BLOCK_BYTES < byte_cnt; i++) {
- /* build the counter block */
- ((u64 *)ctx->b)[0] = skein_swap64((u64) i);
- skein_start_new_type(ctx, OUT_FINAL);
- /* run "counter mode" */
- skein_512_process_block(ctx, ctx->b, 1, sizeof(u64));
- /* number of output bytes left to go */
- n = byte_cnt - i*SKEIN_512_BLOCK_BYTES;
- if (n >= SKEIN_512_BLOCK_BYTES)
- n = SKEIN_512_BLOCK_BYTES;
- /* "output" the ctr mode bytes */
- skein_put64_lsb_first(hash_val+i*SKEIN_512_BLOCK_BYTES, ctx->x,
- n);
- /* restore the counter mode key for next time */
- memcpy(ctx->x, x, sizeof(x));
- }
- return SKEIN_SUCCESS;
- }
- /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
- /* just do the OUTPUT stage */
- int skein_1024_output(struct skein_1024_ctx *ctx, u8 *hash_val)
- {
- size_t i, n, byte_cnt;
- u64 x[SKEIN_1024_STATE_WORDS];
- /* catch uninitialized context */
- skein_assert_ret(ctx->h.b_cnt <= SKEIN_1024_BLOCK_BYTES, SKEIN_FAIL);
- /* now output the result */
- /* total number of output bytes */
- byte_cnt = (ctx->h.hash_bit_len + 7) >> 3;
- /* run Threefish in "counter mode" to generate output */
- /* zero out b[], so it can hold the counter */
- memset(ctx->b, 0, sizeof(ctx->b));
- /* keep a local copy of counter mode "key" */
- memcpy(x, ctx->x, sizeof(x));
- for (i = 0; i*SKEIN_1024_BLOCK_BYTES < byte_cnt; i++) {
- /* build the counter block */
- ((u64 *)ctx->b)[0] = skein_swap64((u64) i);
- skein_start_new_type(ctx, OUT_FINAL);
- /* run "counter mode" */
- skein_1024_process_block(ctx, ctx->b, 1, sizeof(u64));
- /* number of output bytes left to go */
- n = byte_cnt - i*SKEIN_1024_BLOCK_BYTES;
- if (n >= SKEIN_1024_BLOCK_BYTES)
- n = SKEIN_1024_BLOCK_BYTES;
- /* "output" the ctr mode bytes */
- skein_put64_lsb_first(hash_val+i*SKEIN_1024_BLOCK_BYTES, ctx->x,
- n);
- /* restore the counter mode key for next time */
- memcpy(ctx->x, x, sizeof(x));
- }
- return SKEIN_SUCCESS;
- }
- #endif
|