blob: c24a57396483df3ff72e2f9905dba5b037d141f1 [file] [log] [blame]
Jason Cooper449bb812014-03-24 01:48:58 +00001/***********************************************************************
2**
3** Implementation of the Skein hash function.
4**
5** Source code author: Doug Whiting, 2008.
6**
7** This algorithm and source code is released to the public domain.
8**
9************************************************************************/
10
Jason Cooperc2c74262014-03-24 02:32:49 +000011#include <linux/string.h> /* get the memcpy/memset functions */
Eric Rostc17cdeb2014-10-24 17:32:53 -050012#include <linux/export.h>
13#include "skein_base.h" /* get the Skein API definitions */
Jake Edge85dfd522014-05-19 17:48:24 -060014#include "skein_iv.h" /* get precomputed IVs */
15#include "skein_block.h"
Jason Cooper449bb812014-03-24 01:48:58 +000016
17/*****************************************************************/
18/* 256-bit Skein */
19/*****************************************************************/
20
21/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
22/* init the context for a straight hashing operation */
Anton Saraev95f1840a2014-05-19 12:09:55 +040023int skein_256_init(struct skein_256_ctx *ctx, size_t hash_bit_len)
Jason Cooper449bb812014-03-24 01:48:58 +000024{
Jason Cooper161a2af2014-03-24 01:49:13 +000025 union {
Anton Saraev95f1840a2014-05-19 12:09:55 +040026 u8 b[SKEIN_256_STATE_BYTES];
27 u64 w[SKEIN_256_STATE_WORDS];
Jason Cooper39bd42b2014-03-24 01:49:09 +000028 } cfg; /* config block */
Jason Cooper449bb812014-03-24 01:48:58 +000029
Anton Saraev0264b7b2014-05-19 12:09:58 +040030 skein_assert_ret(hash_bit_len > 0, SKEIN_BAD_HASHLEN);
Anton Saraev95f1840a2014-05-19 12:09:55 +040031 ctx->h.hash_bit_len = hash_bit_len; /* output hash bit count */
Jason Cooper449bb812014-03-24 01:48:58 +000032
Anton Saraev95f1840a2014-05-19 12:09:55 +040033 switch (hash_bit_len) { /* use pre-computed values, where available */
Jason Cooper39bd42b2014-03-24 01:49:09 +000034 case 256:
Jake Edge007dfe52014-05-20 08:02:28 -060035 memcpy(ctx->x, SKEIN_256_IV_256, sizeof(ctx->x));
Jason Cooper39bd42b2014-03-24 01:49:09 +000036 break;
37 case 224:
Jake Edge007dfe52014-05-20 08:02:28 -060038 memcpy(ctx->x, SKEIN_256_IV_224, sizeof(ctx->x));
Jason Cooper39bd42b2014-03-24 01:49:09 +000039 break;
40 case 160:
Jake Edge007dfe52014-05-20 08:02:28 -060041 memcpy(ctx->x, SKEIN_256_IV_160, sizeof(ctx->x));
Jason Cooper39bd42b2014-03-24 01:49:09 +000042 break;
43 case 128:
Jake Edge007dfe52014-05-20 08:02:28 -060044 memcpy(ctx->x, SKEIN_256_IV_128, sizeof(ctx->x));
Jason Cooper39bd42b2014-03-24 01:49:09 +000045 break;
46 default:
47 /* here if there is no precomputed IV value available */
Jason Cooper60eb8172014-03-24 01:49:11 +000048 /*
49 * build/process the config block, type == CONFIG (could be
50 * precomputed)
51 */
52 /* set tweaks: T0=0; T1=CFG | FINAL */
Anton Saraev0264b7b2014-05-19 12:09:58 +040053 skein_start_new_type(ctx, CFG_FINAL);
Jason Cooper449bb812014-03-24 01:48:58 +000054
Jason Cooper60eb8172014-03-24 01:49:11 +000055 /* set the schema, version */
Anton Saraev0264b7b2014-05-19 12:09:58 +040056 cfg.w[0] = skein_swap64(SKEIN_SCHEMA_VER);
Jason Cooper60eb8172014-03-24 01:49:11 +000057 /* hash result length in bits */
Anton Saraev0264b7b2014-05-19 12:09:58 +040058 cfg.w[1] = skein_swap64(hash_bit_len);
59 cfg.w[2] = skein_swap64(SKEIN_CFG_TREE_INFO_SEQUENTIAL);
Jason Cooper60eb8172014-03-24 01:49:11 +000060 /* zero pad config block */
Manu Kumar78930e72016-04-04 16:53:01 -070061 memset(&cfg.w[3], 0, sizeof(cfg) - 3 * sizeof(cfg.w[0]));
Jason Cooper449bb812014-03-24 01:48:58 +000062
Jason Cooper39bd42b2014-03-24 01:49:09 +000063 /* compute the initial chaining values from config block */
Jason Cooper60eb8172014-03-24 01:49:11 +000064 /* zero the chaining variables */
Jake Edge007dfe52014-05-20 08:02:28 -060065 memset(ctx->x, 0, sizeof(ctx->x));
Anton Saraev68ace622014-05-19 12:09:54 +040066 skein_256_process_block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN);
Jason Cooper39bd42b2014-03-24 01:49:09 +000067 break;
68 }
Jake Edge007dfe52014-05-20 08:02:28 -060069 /* The chaining vars ctx->x are now initialized for hash_bit_len. */
Jason Cooper39bd42b2014-03-24 01:49:09 +000070 /* Set up to process the data message portion of the hash (default) */
Anton Saraev0264b7b2014-05-19 12:09:58 +040071 skein_start_new_type(ctx, MSG); /* T0=0, T1= MSG type */
Jason Cooper449bb812014-03-24 01:48:58 +000072
Jason Cooper39bd42b2014-03-24 01:49:09 +000073 return SKEIN_SUCCESS;
Jason Cooper449bb812014-03-24 01:48:58 +000074}
75
76/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
77/* init the context for a MAC and/or tree hash operation */
Deepa Dinamani7d27a182015-10-08 21:58:36 -070078/*
79 * [identical to skein_256_init() when key_bytes == 0 && \
80 * tree_info == SKEIN_CFG_TREE_INFO_SEQUENTIAL]
81 */
Anton Saraev95f1840a2014-05-19 12:09:55 +040082int skein_256_init_ext(struct skein_256_ctx *ctx, size_t hash_bit_len,
83 u64 tree_info, const u8 *key, size_t key_bytes)
Jason Cooper449bb812014-03-24 01:48:58 +000084{
Jason Cooper161a2af2014-03-24 01:49:13 +000085 union {
Jason Cooper39bd42b2014-03-24 01:49:09 +000086 u8 b[SKEIN_256_STATE_BYTES];
Anton Saraev95f1840a2014-05-19 12:09:55 +040087 u64 w[SKEIN_256_STATE_WORDS];
Jason Cooper60eb8172014-03-24 01:49:11 +000088 } cfg; /* config block */
Jason Cooper449bb812014-03-24 01:48:58 +000089
Anton Saraev0264b7b2014-05-19 12:09:58 +040090 skein_assert_ret(hash_bit_len > 0, SKEIN_BAD_HASHLEN);
Aybuke Ozdemir26368fd2015-10-13 23:55:07 +030091 skein_assert_ret(key_bytes == 0 || key, SKEIN_FAIL);
Jason Cooper449bb812014-03-24 01:48:58 +000092
Jake Edge007dfe52014-05-20 08:02:28 -060093 /* compute the initial chaining values ctx->x[], based on key */
Anton Saraev95f1840a2014-05-19 12:09:55 +040094 if (key_bytes == 0) { /* is there a key? */
Jason Cooper60eb8172014-03-24 01:49:11 +000095 /* no key: use all zeroes as key for config block */
Jake Edge007dfe52014-05-20 08:02:28 -060096 memset(ctx->x, 0, sizeof(ctx->x));
Jason Cooper161a2af2014-03-24 01:49:13 +000097 } else { /* here to pre-process a key */
Jake Edge007dfe52014-05-20 08:02:28 -060098 skein_assert(sizeof(cfg.b) >= sizeof(ctx->x));
Jason Cooper39bd42b2014-03-24 01:49:09 +000099 /* do a mini-Init right here */
Jason Cooper60eb8172014-03-24 01:49:11 +0000100 /* set output hash bit count = state size */
Manu Kumar78930e72016-04-04 16:53:01 -0700101 ctx->h.hash_bit_len = 8 * sizeof(ctx->x);
Jason Cooper60eb8172014-03-24 01:49:11 +0000102 /* set tweaks: T0 = 0; T1 = KEY type */
Anton Saraev0264b7b2014-05-19 12:09:58 +0400103 skein_start_new_type(ctx, KEY);
Jason Cooper60eb8172014-03-24 01:49:11 +0000104 /* zero the initial chaining variables */
Jake Edge007dfe52014-05-20 08:02:28 -0600105 memset(ctx->x, 0, sizeof(ctx->x));
Jason Cooper60eb8172014-03-24 01:49:11 +0000106 /* hash the key */
Anton Saraev95f1840a2014-05-19 12:09:55 +0400107 skein_256_update(ctx, key, key_bytes);
Jason Cooper60eb8172014-03-24 01:49:11 +0000108 /* put result into cfg.b[] */
Anton Saraev68ace622014-05-19 12:09:54 +0400109 skein_256_final_pad(ctx, cfg.b);
Jake Edge007dfe52014-05-20 08:02:28 -0600110 /* copy over into ctx->x[] */
111 memcpy(ctx->x, cfg.b, sizeof(cfg.b));
Jason Cooper39bd42b2014-03-24 01:49:09 +0000112 }
Jason Cooper60eb8172014-03-24 01:49:11 +0000113 /*
114 * build/process the config block, type == CONFIG (could be
115 * precomputed for each key)
116 */
117 /* output hash bit count */
Anton Saraev95f1840a2014-05-19 12:09:55 +0400118 ctx->h.hash_bit_len = hash_bit_len;
Anton Saraev0264b7b2014-05-19 12:09:58 +0400119 skein_start_new_type(ctx, CFG_FINAL);
Jason Cooper449bb812014-03-24 01:48:58 +0000120
Jason Cooper60eb8172014-03-24 01:49:11 +0000121 /* pre-pad cfg.w[] with zeroes */
122 memset(&cfg.w, 0, sizeof(cfg.w));
Anton Saraev0264b7b2014-05-19 12:09:58 +0400123 cfg.w[0] = skein_swap64(SKEIN_SCHEMA_VER);
Jason Cooper60eb8172014-03-24 01:49:11 +0000124 /* hash result length in bits */
Anton Saraev0264b7b2014-05-19 12:09:58 +0400125 cfg.w[1] = skein_swap64(hash_bit_len);
Jason Cooper60eb8172014-03-24 01:49:11 +0000126 /* tree hash config info (or SKEIN_CFG_TREE_INFO_SEQUENTIAL) */
Anton Saraev0264b7b2014-05-19 12:09:58 +0400127 cfg.w[2] = skein_swap64(tree_info);
Jason Cooper449bb812014-03-24 01:48:58 +0000128
Jason Cooper39bd42b2014-03-24 01:49:09 +0000129 /* compute the initial chaining values from config block */
Anton Saraev68ace622014-05-19 12:09:54 +0400130 skein_256_process_block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN);
Jason Cooper449bb812014-03-24 01:48:58 +0000131
Jake Edge007dfe52014-05-20 08:02:28 -0600132 /* The chaining vars ctx->x are now initialized */
Jason Cooper39bd42b2014-03-24 01:49:09 +0000133 /* Set up to process the data message portion of the hash (default) */
Anton Saraev0264b7b2014-05-19 12:09:58 +0400134 skein_start_new_type(ctx, MSG);
Jason Cooper449bb812014-03-24 01:48:58 +0000135
Jason Cooper39bd42b2014-03-24 01:49:09 +0000136 return SKEIN_SUCCESS;
Jason Cooper449bb812014-03-24 01:48:58 +0000137}
138
139/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
140/* process the input bytes */
Anton Saraev68ace622014-05-19 12:09:54 +0400141int skein_256_update(struct skein_256_ctx *ctx, const u8 *msg,
Anton Saraev95f1840a2014-05-19 12:09:55 +0400142 size_t msg_byte_cnt)
Jason Cooper449bb812014-03-24 01:48:58 +0000143{
Jason Cooper39bd42b2014-03-24 01:49:09 +0000144 size_t n;
Jason Cooper449bb812014-03-24 01:48:58 +0000145
Jason Cooper60eb8172014-03-24 01:49:11 +0000146 /* catch uninitialized context */
Anton Saraev0264b7b2014-05-19 12:09:58 +0400147 skein_assert_ret(ctx->h.b_cnt <= SKEIN_256_BLOCK_BYTES, SKEIN_FAIL);
Jason Cooper449bb812014-03-24 01:48:58 +0000148
Jason Cooper39bd42b2014-03-24 01:49:09 +0000149 /* process full blocks, if any */
Anton Saraev95f1840a2014-05-19 12:09:55 +0400150 if (msg_byte_cnt + ctx->h.b_cnt > SKEIN_256_BLOCK_BYTES) {
Jason Cooper60eb8172014-03-24 01:49:11 +0000151 /* finish up any buffered message data */
Anton Saraev95f1840a2014-05-19 12:09:55 +0400152 if (ctx->h.b_cnt) {
Jason Cooper60eb8172014-03-24 01:49:11 +0000153 /* # bytes free in buffer b[] */
Anton Saraev95f1840a2014-05-19 12:09:55 +0400154 n = SKEIN_256_BLOCK_BYTES - ctx->h.b_cnt;
Jason Cooper161a2af2014-03-24 01:49:13 +0000155 if (n) {
Jason Cooper60eb8172014-03-24 01:49:11 +0000156 /* check on our logic here */
Anton Saraev0264b7b2014-05-19 12:09:58 +0400157 skein_assert(n < msg_byte_cnt);
Anton Saraev95f1840a2014-05-19 12:09:55 +0400158 memcpy(&ctx->b[ctx->h.b_cnt], msg, n);
159 msg_byte_cnt -= n;
Jason Cooper39bd42b2014-03-24 01:49:09 +0000160 msg += n;
Anton Saraev95f1840a2014-05-19 12:09:55 +0400161 ctx->h.b_cnt += n;
Jason Cooper39bd42b2014-03-24 01:49:09 +0000162 }
Anton Saraev0264b7b2014-05-19 12:09:58 +0400163 skein_assert(ctx->h.b_cnt == SKEIN_256_BLOCK_BYTES);
Anton Saraev68ace622014-05-19 12:09:54 +0400164 skein_256_process_block(ctx, ctx->b, 1,
Jason Cooper60eb8172014-03-24 01:49:11 +0000165 SKEIN_256_BLOCK_BYTES);
Anton Saraev95f1840a2014-05-19 12:09:55 +0400166 ctx->h.b_cnt = 0;
Jason Cooper39bd42b2014-03-24 01:49:09 +0000167 }
Jason Cooper60eb8172014-03-24 01:49:11 +0000168 /*
169 * now process any remaining full blocks, directly from input
170 * message data
171 */
Anton Saraev95f1840a2014-05-19 12:09:55 +0400172 if (msg_byte_cnt > SKEIN_256_BLOCK_BYTES) {
Jason Cooper60eb8172014-03-24 01:49:11 +0000173 /* number of full blocks to process */
Manu Kumar78930e72016-04-04 16:53:01 -0700174 n = (msg_byte_cnt - 1) / SKEIN_256_BLOCK_BYTES;
Anton Saraev68ace622014-05-19 12:09:54 +0400175 skein_256_process_block(ctx, msg, n,
Jason Cooper60eb8172014-03-24 01:49:11 +0000176 SKEIN_256_BLOCK_BYTES);
Anton Saraev95f1840a2014-05-19 12:09:55 +0400177 msg_byte_cnt -= n * SKEIN_256_BLOCK_BYTES;
Jason Cooper39bd42b2014-03-24 01:49:09 +0000178 msg += n * SKEIN_256_BLOCK_BYTES;
179 }
Anton Saraev0264b7b2014-05-19 12:09:58 +0400180 skein_assert(ctx->h.b_cnt == 0);
Jason Cooper39bd42b2014-03-24 01:49:09 +0000181 }
Jason Cooper449bb812014-03-24 01:48:58 +0000182
Jason Cooper39bd42b2014-03-24 01:49:09 +0000183 /* copy any remaining source message data bytes into b[] */
Anton Saraev95f1840a2014-05-19 12:09:55 +0400184 if (msg_byte_cnt) {
Anton Saraev0264b7b2014-05-19 12:09:58 +0400185 skein_assert(msg_byte_cnt + ctx->h.b_cnt <=
Anton Saraev95f1840a2014-05-19 12:09:55 +0400186 SKEIN_256_BLOCK_BYTES);
187 memcpy(&ctx->b[ctx->h.b_cnt], msg, msg_byte_cnt);
188 ctx->h.b_cnt += msg_byte_cnt;
Jason Cooper39bd42b2014-03-24 01:49:09 +0000189 }
Jason Cooper449bb812014-03-24 01:48:58 +0000190
Jason Cooper39bd42b2014-03-24 01:49:09 +0000191 return SKEIN_SUCCESS;
Jason Cooper449bb812014-03-24 01:48:58 +0000192}
193
194/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
195/* finalize the hash computation and output the result */
Anton Saraev95f1840a2014-05-19 12:09:55 +0400196int skein_256_final(struct skein_256_ctx *ctx, u8 *hash_val)
Jason Cooper449bb812014-03-24 01:48:58 +0000197{
Anton Saraev95f1840a2014-05-19 12:09:55 +0400198 size_t i, n, byte_cnt;
Jake Edge007dfe52014-05-20 08:02:28 -0600199 u64 x[SKEIN_256_STATE_WORDS];
Jason Cooper60eb8172014-03-24 01:49:11 +0000200 /* catch uninitialized context */
Anton Saraev0264b7b2014-05-19 12:09:58 +0400201 skein_assert_ret(ctx->h.b_cnt <= SKEIN_256_BLOCK_BYTES, SKEIN_FAIL);
Jason Cooper449bb812014-03-24 01:48:58 +0000202
Jason Cooper60eb8172014-03-24 01:49:11 +0000203 /* tag as the final block */
Jake Edge007dfe52014-05-20 08:02:28 -0600204 ctx->h.tweak[1] |= SKEIN_T1_FLAG_FINAL;
Jason Cooper60eb8172014-03-24 01:49:11 +0000205 /* zero pad b[] if necessary */
Anton Saraev95f1840a2014-05-19 12:09:55 +0400206 if (ctx->h.b_cnt < SKEIN_256_BLOCK_BYTES)
207 memset(&ctx->b[ctx->h.b_cnt], 0,
Manu Kumar3faa9662016-04-04 20:09:12 -0700208 SKEIN_256_BLOCK_BYTES - ctx->h.b_cnt);
Jason Cooper449bb812014-03-24 01:48:58 +0000209
Jason Cooper60eb8172014-03-24 01:49:11 +0000210 /* process the final block */
Anton Saraev95f1840a2014-05-19 12:09:55 +0400211 skein_256_process_block(ctx, ctx->b, 1, ctx->h.b_cnt);
Jason Cooper449bb812014-03-24 01:48:58 +0000212
Jason Cooper39bd42b2014-03-24 01:49:09 +0000213 /* now output the result */
Jason Cooper60eb8172014-03-24 01:49:11 +0000214 /* total number of output bytes */
Anton Saraev95f1840a2014-05-19 12:09:55 +0400215 byte_cnt = (ctx->h.hash_bit_len + 7) >> 3;
Jason Cooper449bb812014-03-24 01:48:58 +0000216
Jason Cooper39bd42b2014-03-24 01:49:09 +0000217 /* run Threefish in "counter mode" to generate output */
Jason Cooper60eb8172014-03-24 01:49:11 +0000218 /* zero out b[], so it can hold the counter */
219 memset(ctx->b, 0, sizeof(ctx->b));
220 /* keep a local copy of counter mode "key" */
Jake Edge007dfe52014-05-20 08:02:28 -0600221 memcpy(x, ctx->x, sizeof(x));
Manu Kumar78930e72016-04-04 16:53:01 -0700222 for (i = 0; i * SKEIN_256_BLOCK_BYTES < byte_cnt; i++) {
Jason Cooper60eb8172014-03-24 01:49:11 +0000223 /* build the counter block */
Manu Kumare602a8082016-05-01 16:38:34 -0700224 ((u64 *)ctx->b)[0] = skein_swap64((u64)i);
Anton Saraev0264b7b2014-05-19 12:09:58 +0400225 skein_start_new_type(ctx, OUT_FINAL);
Jason Cooper60eb8172014-03-24 01:49:11 +0000226 /* run "counter mode" */
Anton Saraev68ace622014-05-19 12:09:54 +0400227 skein_256_process_block(ctx, ctx->b, 1, sizeof(u64));
Jason Cooper60eb8172014-03-24 01:49:11 +0000228 /* number of output bytes left to go */
Manu Kumar78930e72016-04-04 16:53:01 -0700229 n = byte_cnt - i * SKEIN_256_BLOCK_BYTES;
Jason Cooper39bd42b2014-03-24 01:49:09 +0000230 if (n >= SKEIN_256_BLOCK_BYTES)
231 n = SKEIN_256_BLOCK_BYTES;
Jason Cooper60eb8172014-03-24 01:49:11 +0000232 /* "output" the ctr mode bytes */
Manu Kumar5b05c1e2016-05-01 16:38:33 -0700233 skein_put64_lsb_first(hash_val + (i * SKEIN_256_BLOCK_BYTES),
Manu Kumar43bb50e2016-05-01 16:38:35 -0700234 ctx->x, n);
Jason Cooper60eb8172014-03-24 01:49:11 +0000235 /* restore the counter mode key for next time */
Jake Edge007dfe52014-05-20 08:02:28 -0600236 memcpy(ctx->x, x, sizeof(x));
Jason Cooper39bd42b2014-03-24 01:49:09 +0000237 }
238 return SKEIN_SUCCESS;
Jason Cooper449bb812014-03-24 01:48:58 +0000239}
240
241/*****************************************************************/
242/* 512-bit Skein */
243/*****************************************************************/
244
245/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
246/* init the context for a straight hashing operation */
Anton Saraev95f1840a2014-05-19 12:09:55 +0400247int skein_512_init(struct skein_512_ctx *ctx, size_t hash_bit_len)
Jason Cooper449bb812014-03-24 01:48:58 +0000248{
Jason Cooper161a2af2014-03-24 01:49:13 +0000249 union {
Anton Saraev95f1840a2014-05-19 12:09:55 +0400250 u8 b[SKEIN_512_STATE_BYTES];
251 u64 w[SKEIN_512_STATE_WORDS];
Jason Cooper39bd42b2014-03-24 01:49:09 +0000252 } cfg; /* config block */
Jason Cooper449bb812014-03-24 01:48:58 +0000253
Anton Saraev0264b7b2014-05-19 12:09:58 +0400254 skein_assert_ret(hash_bit_len > 0, SKEIN_BAD_HASHLEN);
Anton Saraev95f1840a2014-05-19 12:09:55 +0400255 ctx->h.hash_bit_len = hash_bit_len; /* output hash bit count */
Jason Cooper449bb812014-03-24 01:48:58 +0000256
Anton Saraev95f1840a2014-05-19 12:09:55 +0400257 switch (hash_bit_len) { /* use pre-computed values, where available */
Jason Cooper39bd42b2014-03-24 01:49:09 +0000258 case 512:
Jake Edge007dfe52014-05-20 08:02:28 -0600259 memcpy(ctx->x, SKEIN_512_IV_512, sizeof(ctx->x));
Jason Cooper39bd42b2014-03-24 01:49:09 +0000260 break;
261 case 384:
Jake Edge007dfe52014-05-20 08:02:28 -0600262 memcpy(ctx->x, SKEIN_512_IV_384, sizeof(ctx->x));
Jason Cooper39bd42b2014-03-24 01:49:09 +0000263 break;
264 case 256:
Jake Edge007dfe52014-05-20 08:02:28 -0600265 memcpy(ctx->x, SKEIN_512_IV_256, sizeof(ctx->x));
Jason Cooper39bd42b2014-03-24 01:49:09 +0000266 break;
267 case 224:
Jake Edge007dfe52014-05-20 08:02:28 -0600268 memcpy(ctx->x, SKEIN_512_IV_224, sizeof(ctx->x));
Jason Cooper39bd42b2014-03-24 01:49:09 +0000269 break;
270 default:
271 /* here if there is no precomputed IV value available */
Jason Cooper60eb8172014-03-24 01:49:11 +0000272 /*
273 * build/process the config block, type == CONFIG (could be
274 * precomputed)
275 */
276 /* set tweaks: T0=0; T1=CFG | FINAL */
Anton Saraev0264b7b2014-05-19 12:09:58 +0400277 skein_start_new_type(ctx, CFG_FINAL);
Jason Cooper449bb812014-03-24 01:48:58 +0000278
Jason Cooper60eb8172014-03-24 01:49:11 +0000279 /* set the schema, version */
Anton Saraev0264b7b2014-05-19 12:09:58 +0400280 cfg.w[0] = skein_swap64(SKEIN_SCHEMA_VER);
Jason Cooper60eb8172014-03-24 01:49:11 +0000281 /* hash result length in bits */
Anton Saraev0264b7b2014-05-19 12:09:58 +0400282 cfg.w[1] = skein_swap64(hash_bit_len);
283 cfg.w[2] = skein_swap64(SKEIN_CFG_TREE_INFO_SEQUENTIAL);
Jason Cooper60eb8172014-03-24 01:49:11 +0000284 /* zero pad config block */
Manu Kumar78930e72016-04-04 16:53:01 -0700285 memset(&cfg.w[3], 0, sizeof(cfg) - 3 * sizeof(cfg.w[0]));
Jason Cooper449bb812014-03-24 01:48:58 +0000286
Jason Cooper39bd42b2014-03-24 01:49:09 +0000287 /* compute the initial chaining values from config block */
Jason Cooper60eb8172014-03-24 01:49:11 +0000288 /* zero the chaining variables */
Jake Edge007dfe52014-05-20 08:02:28 -0600289 memset(ctx->x, 0, sizeof(ctx->x));
Anton Saraev68ace622014-05-19 12:09:54 +0400290 skein_512_process_block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN);
Jason Cooper39bd42b2014-03-24 01:49:09 +0000291 break;
292 }
Jason Cooper449bb812014-03-24 01:48:58 +0000293
Jason Cooper60eb8172014-03-24 01:49:11 +0000294 /*
Jake Edge007dfe52014-05-20 08:02:28 -0600295 * The chaining vars ctx->x are now initialized for the given
Anton Saraev95f1840a2014-05-19 12:09:55 +0400296 * hash_bit_len.
Jason Cooper60eb8172014-03-24 01:49:11 +0000297 */
Jason Cooper39bd42b2014-03-24 01:49:09 +0000298 /* Set up to process the data message portion of the hash (default) */
Anton Saraev0264b7b2014-05-19 12:09:58 +0400299 skein_start_new_type(ctx, MSG); /* T0=0, T1= MSG type */
Jason Cooper449bb812014-03-24 01:48:58 +0000300
Jason Cooper39bd42b2014-03-24 01:49:09 +0000301 return SKEIN_SUCCESS;
Jason Cooper449bb812014-03-24 01:48:58 +0000302}
303
304/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
305/* init the context for a MAC and/or tree hash operation */
Deepa Dinamani7d27a182015-10-08 21:58:36 -0700306/*
307 * [identical to skein_512_init() when key_bytes == 0 && \
308 * tree_info == SKEIN_CFG_TREE_INFO_SEQUENTIAL]
309 */
Anton Saraev95f1840a2014-05-19 12:09:55 +0400310int skein_512_init_ext(struct skein_512_ctx *ctx, size_t hash_bit_len,
311 u64 tree_info, const u8 *key, size_t key_bytes)
Jason Cooper449bb812014-03-24 01:48:58 +0000312{
Jason Cooper161a2af2014-03-24 01:49:13 +0000313 union {
Anton Saraev95f1840a2014-05-19 12:09:55 +0400314 u8 b[SKEIN_512_STATE_BYTES];
315 u64 w[SKEIN_512_STATE_WORDS];
Jason Cooper39bd42b2014-03-24 01:49:09 +0000316 } cfg; /* config block */
Jason Cooper449bb812014-03-24 01:48:58 +0000317
Anton Saraev0264b7b2014-05-19 12:09:58 +0400318 skein_assert_ret(hash_bit_len > 0, SKEIN_BAD_HASHLEN);
Aybuke Ozdemir26368fd2015-10-13 23:55:07 +0300319 skein_assert_ret(key_bytes == 0 || key, SKEIN_FAIL);
Jason Cooper449bb812014-03-24 01:48:58 +0000320
Jake Edge007dfe52014-05-20 08:02:28 -0600321 /* compute the initial chaining values ctx->x[], based on key */
Anton Saraev95f1840a2014-05-19 12:09:55 +0400322 if (key_bytes == 0) { /* is there a key? */
Jason Cooper60eb8172014-03-24 01:49:11 +0000323 /* no key: use all zeroes as key for config block */
Jake Edge007dfe52014-05-20 08:02:28 -0600324 memset(ctx->x, 0, sizeof(ctx->x));
Jason Cooper161a2af2014-03-24 01:49:13 +0000325 } else { /* here to pre-process a key */
Jake Edge007dfe52014-05-20 08:02:28 -0600326 skein_assert(sizeof(cfg.b) >= sizeof(ctx->x));
Jason Cooper39bd42b2014-03-24 01:49:09 +0000327 /* do a mini-Init right here */
Jason Cooper60eb8172014-03-24 01:49:11 +0000328 /* set output hash bit count = state size */
Manu Kumar78930e72016-04-04 16:53:01 -0700329 ctx->h.hash_bit_len = 8 * sizeof(ctx->x);
Jason Cooper60eb8172014-03-24 01:49:11 +0000330 /* set tweaks: T0 = 0; T1 = KEY type */
Anton Saraev0264b7b2014-05-19 12:09:58 +0400331 skein_start_new_type(ctx, KEY);
Jason Cooper60eb8172014-03-24 01:49:11 +0000332 /* zero the initial chaining variables */
Jake Edge007dfe52014-05-20 08:02:28 -0600333 memset(ctx->x, 0, sizeof(ctx->x));
Jason Cooper60eb8172014-03-24 01:49:11 +0000334 /* hash the key */
Anton Saraev95f1840a2014-05-19 12:09:55 +0400335 skein_512_update(ctx, key, key_bytes);
Jason Cooper60eb8172014-03-24 01:49:11 +0000336 /* put result into cfg.b[] */
Anton Saraev68ace622014-05-19 12:09:54 +0400337 skein_512_final_pad(ctx, cfg.b);
Jake Edge007dfe52014-05-20 08:02:28 -0600338 /* copy over into ctx->x[] */
339 memcpy(ctx->x, cfg.b, sizeof(cfg.b));
Jason Cooper39bd42b2014-03-24 01:49:09 +0000340 }
Jason Cooper60eb8172014-03-24 01:49:11 +0000341 /*
342 * build/process the config block, type == CONFIG (could be
343 * precomputed for each key)
344 */
Anton Saraev95f1840a2014-05-19 12:09:55 +0400345 ctx->h.hash_bit_len = hash_bit_len; /* output hash bit count */
Anton Saraev0264b7b2014-05-19 12:09:58 +0400346 skein_start_new_type(ctx, CFG_FINAL);
Jason Cooper449bb812014-03-24 01:48:58 +0000347
Jason Cooper60eb8172014-03-24 01:49:11 +0000348 /* pre-pad cfg.w[] with zeroes */
349 memset(&cfg.w, 0, sizeof(cfg.w));
Anton Saraev0264b7b2014-05-19 12:09:58 +0400350 cfg.w[0] = skein_swap64(SKEIN_SCHEMA_VER);
Jason Cooper60eb8172014-03-24 01:49:11 +0000351 /* hash result length in bits */
Anton Saraev0264b7b2014-05-19 12:09:58 +0400352 cfg.w[1] = skein_swap64(hash_bit_len);
Jason Cooper60eb8172014-03-24 01:49:11 +0000353 /* tree hash config info (or SKEIN_CFG_TREE_INFO_SEQUENTIAL) */
Anton Saraev0264b7b2014-05-19 12:09:58 +0400354 cfg.w[2] = skein_swap64(tree_info);
Jason Cooper449bb812014-03-24 01:48:58 +0000355
Jason Cooper39bd42b2014-03-24 01:49:09 +0000356 /* compute the initial chaining values from config block */
Anton Saraev68ace622014-05-19 12:09:54 +0400357 skein_512_process_block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN);
Jason Cooper449bb812014-03-24 01:48:58 +0000358
Jake Edge007dfe52014-05-20 08:02:28 -0600359 /* The chaining vars ctx->x are now initialized */
Jason Cooper39bd42b2014-03-24 01:49:09 +0000360 /* Set up to process the data message portion of the hash (default) */
Anton Saraev0264b7b2014-05-19 12:09:58 +0400361 skein_start_new_type(ctx, MSG);
Jason Cooper449bb812014-03-24 01:48:58 +0000362
Jason Cooper39bd42b2014-03-24 01:49:09 +0000363 return SKEIN_SUCCESS;
Jason Cooper449bb812014-03-24 01:48:58 +0000364}
365
366/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
367/* process the input bytes */
Anton Saraev68ace622014-05-19 12:09:54 +0400368int skein_512_update(struct skein_512_ctx *ctx, const u8 *msg,
Anton Saraev95f1840a2014-05-19 12:09:55 +0400369 size_t msg_byte_cnt)
Jason Cooper449bb812014-03-24 01:48:58 +0000370{
Jason Cooper39bd42b2014-03-24 01:49:09 +0000371 size_t n;
Jason Cooper449bb812014-03-24 01:48:58 +0000372
Jason Cooper60eb8172014-03-24 01:49:11 +0000373 /* catch uninitialized context */
Anton Saraev0264b7b2014-05-19 12:09:58 +0400374 skein_assert_ret(ctx->h.b_cnt <= SKEIN_512_BLOCK_BYTES, SKEIN_FAIL);
Jason Cooper449bb812014-03-24 01:48:58 +0000375
Jason Cooper39bd42b2014-03-24 01:49:09 +0000376 /* process full blocks, if any */
Anton Saraev95f1840a2014-05-19 12:09:55 +0400377 if (msg_byte_cnt + ctx->h.b_cnt > SKEIN_512_BLOCK_BYTES) {
Jason Cooper60eb8172014-03-24 01:49:11 +0000378 /* finish up any buffered message data */
Anton Saraev95f1840a2014-05-19 12:09:55 +0400379 if (ctx->h.b_cnt) {
Jason Cooper60eb8172014-03-24 01:49:11 +0000380 /* # bytes free in buffer b[] */
Anton Saraev95f1840a2014-05-19 12:09:55 +0400381 n = SKEIN_512_BLOCK_BYTES - ctx->h.b_cnt;
Jason Cooper161a2af2014-03-24 01:49:13 +0000382 if (n) {
Jason Cooper60eb8172014-03-24 01:49:11 +0000383 /* check on our logic here */
Anton Saraev0264b7b2014-05-19 12:09:58 +0400384 skein_assert(n < msg_byte_cnt);
Anton Saraev95f1840a2014-05-19 12:09:55 +0400385 memcpy(&ctx->b[ctx->h.b_cnt], msg, n);
386 msg_byte_cnt -= n;
Jason Cooper39bd42b2014-03-24 01:49:09 +0000387 msg += n;
Anton Saraev95f1840a2014-05-19 12:09:55 +0400388 ctx->h.b_cnt += n;
Jason Cooper39bd42b2014-03-24 01:49:09 +0000389 }
Anton Saraev0264b7b2014-05-19 12:09:58 +0400390 skein_assert(ctx->h.b_cnt == SKEIN_512_BLOCK_BYTES);
Anton Saraev68ace622014-05-19 12:09:54 +0400391 skein_512_process_block(ctx, ctx->b, 1,
Jason Cooper60eb8172014-03-24 01:49:11 +0000392 SKEIN_512_BLOCK_BYTES);
Anton Saraev95f1840a2014-05-19 12:09:55 +0400393 ctx->h.b_cnt = 0;
Jason Cooper39bd42b2014-03-24 01:49:09 +0000394 }
Jason Cooper60eb8172014-03-24 01:49:11 +0000395 /*
396 * now process any remaining full blocks, directly from input
397 * message data
398 */
Anton Saraev95f1840a2014-05-19 12:09:55 +0400399 if (msg_byte_cnt > SKEIN_512_BLOCK_BYTES) {
Jason Cooper60eb8172014-03-24 01:49:11 +0000400 /* number of full blocks to process */
Manu Kumar78930e72016-04-04 16:53:01 -0700401 n = (msg_byte_cnt - 1) / SKEIN_512_BLOCK_BYTES;
Anton Saraev68ace622014-05-19 12:09:54 +0400402 skein_512_process_block(ctx, msg, n,
Jason Cooper60eb8172014-03-24 01:49:11 +0000403 SKEIN_512_BLOCK_BYTES);
Anton Saraev95f1840a2014-05-19 12:09:55 +0400404 msg_byte_cnt -= n * SKEIN_512_BLOCK_BYTES;
Jason Cooper39bd42b2014-03-24 01:49:09 +0000405 msg += n * SKEIN_512_BLOCK_BYTES;
406 }
Anton Saraev0264b7b2014-05-19 12:09:58 +0400407 skein_assert(ctx->h.b_cnt == 0);
Jason Cooper39bd42b2014-03-24 01:49:09 +0000408 }
Jason Cooper449bb812014-03-24 01:48:58 +0000409
Jason Cooper39bd42b2014-03-24 01:49:09 +0000410 /* copy any remaining source message data bytes into b[] */
Anton Saraev95f1840a2014-05-19 12:09:55 +0400411 if (msg_byte_cnt) {
Anton Saraev0264b7b2014-05-19 12:09:58 +0400412 skein_assert(msg_byte_cnt + ctx->h.b_cnt <=
Anton Saraev95f1840a2014-05-19 12:09:55 +0400413 SKEIN_512_BLOCK_BYTES);
414 memcpy(&ctx->b[ctx->h.b_cnt], msg, msg_byte_cnt);
415 ctx->h.b_cnt += msg_byte_cnt;
Jason Cooper39bd42b2014-03-24 01:49:09 +0000416 }
Jason Cooper449bb812014-03-24 01:48:58 +0000417
Jason Cooper39bd42b2014-03-24 01:49:09 +0000418 return SKEIN_SUCCESS;
Jason Cooper449bb812014-03-24 01:48:58 +0000419}
420
421/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
422/* finalize the hash computation and output the result */
Anton Saraev95f1840a2014-05-19 12:09:55 +0400423int skein_512_final(struct skein_512_ctx *ctx, u8 *hash_val)
Jason Cooper449bb812014-03-24 01:48:58 +0000424{
Anton Saraev95f1840a2014-05-19 12:09:55 +0400425 size_t i, n, byte_cnt;
Jake Edge007dfe52014-05-20 08:02:28 -0600426 u64 x[SKEIN_512_STATE_WORDS];
Jason Cooper60eb8172014-03-24 01:49:11 +0000427 /* catch uninitialized context */
Anton Saraev0264b7b2014-05-19 12:09:58 +0400428 skein_assert_ret(ctx->h.b_cnt <= SKEIN_512_BLOCK_BYTES, SKEIN_FAIL);
Jason Cooper449bb812014-03-24 01:48:58 +0000429
Jason Cooper60eb8172014-03-24 01:49:11 +0000430 /* tag as the final block */
Jake Edge007dfe52014-05-20 08:02:28 -0600431 ctx->h.tweak[1] |= SKEIN_T1_FLAG_FINAL;
Jason Cooper60eb8172014-03-24 01:49:11 +0000432 /* zero pad b[] if necessary */
Anton Saraev95f1840a2014-05-19 12:09:55 +0400433 if (ctx->h.b_cnt < SKEIN_512_BLOCK_BYTES)
434 memset(&ctx->b[ctx->h.b_cnt], 0,
Manu Kumar3faa9662016-04-04 20:09:12 -0700435 SKEIN_512_BLOCK_BYTES - ctx->h.b_cnt);
Jason Cooper449bb812014-03-24 01:48:58 +0000436
Jason Cooper60eb8172014-03-24 01:49:11 +0000437 /* process the final block */
Anton Saraev95f1840a2014-05-19 12:09:55 +0400438 skein_512_process_block(ctx, ctx->b, 1, ctx->h.b_cnt);
Jason Cooper449bb812014-03-24 01:48:58 +0000439
Jason Cooper39bd42b2014-03-24 01:49:09 +0000440 /* now output the result */
Jason Cooper60eb8172014-03-24 01:49:11 +0000441 /* total number of output bytes */
Anton Saraev95f1840a2014-05-19 12:09:55 +0400442 byte_cnt = (ctx->h.hash_bit_len + 7) >> 3;
Jason Cooper449bb812014-03-24 01:48:58 +0000443
Jason Cooper39bd42b2014-03-24 01:49:09 +0000444 /* run Threefish in "counter mode" to generate output */
Jason Cooper60eb8172014-03-24 01:49:11 +0000445 /* zero out b[], so it can hold the counter */
446 memset(ctx->b, 0, sizeof(ctx->b));
447 /* keep a local copy of counter mode "key" */
Jake Edge007dfe52014-05-20 08:02:28 -0600448 memcpy(x, ctx->x, sizeof(x));
Manu Kumar78930e72016-04-04 16:53:01 -0700449 for (i = 0; i * SKEIN_512_BLOCK_BYTES < byte_cnt; i++) {
Jason Cooper60eb8172014-03-24 01:49:11 +0000450 /* build the counter block */
Manu Kumare602a8082016-05-01 16:38:34 -0700451 ((u64 *)ctx->b)[0] = skein_swap64((u64)i);
Anton Saraev0264b7b2014-05-19 12:09:58 +0400452 skein_start_new_type(ctx, OUT_FINAL);
Jason Cooper60eb8172014-03-24 01:49:11 +0000453 /* run "counter mode" */
Anton Saraev68ace622014-05-19 12:09:54 +0400454 skein_512_process_block(ctx, ctx->b, 1, sizeof(u64));
Jason Cooper60eb8172014-03-24 01:49:11 +0000455 /* number of output bytes left to go */
Manu Kumar78930e72016-04-04 16:53:01 -0700456 n = byte_cnt - i * SKEIN_512_BLOCK_BYTES;
Jason Cooper39bd42b2014-03-24 01:49:09 +0000457 if (n >= SKEIN_512_BLOCK_BYTES)
458 n = SKEIN_512_BLOCK_BYTES;
Jason Cooper60eb8172014-03-24 01:49:11 +0000459 /* "output" the ctr mode bytes */
Manu Kumar5b05c1e2016-05-01 16:38:33 -0700460 skein_put64_lsb_first(hash_val + (i * SKEIN_512_BLOCK_BYTES),
Manu Kumar43bb50e2016-05-01 16:38:35 -0700461 ctx->x, n);
Jason Cooper60eb8172014-03-24 01:49:11 +0000462 /* restore the counter mode key for next time */
Jake Edge007dfe52014-05-20 08:02:28 -0600463 memcpy(ctx->x, x, sizeof(x));
Jason Cooper39bd42b2014-03-24 01:49:09 +0000464 }
465 return SKEIN_SUCCESS;
Jason Cooper449bb812014-03-24 01:48:58 +0000466}
467
468/*****************************************************************/
469/* 1024-bit Skein */
470/*****************************************************************/
471
472/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
473/* init the context for a straight hashing operation */
Anton Saraev3201b7f2014-05-19 12:09:56 +0400474int skein_1024_init(struct skein_1024_ctx *ctx, size_t hash_bit_len)
Jason Cooper449bb812014-03-24 01:48:58 +0000475{
Jason Cooper161a2af2014-03-24 01:49:13 +0000476 union {
Anton Saraev0264b7b2014-05-19 12:09:58 +0400477 u8 b[SKEIN_1024_STATE_BYTES];
478 u64 w[SKEIN_1024_STATE_WORDS];
Jason Cooper39bd42b2014-03-24 01:49:09 +0000479 } cfg; /* config block */
Jason Cooper449bb812014-03-24 01:48:58 +0000480
Anton Saraev0264b7b2014-05-19 12:09:58 +0400481 skein_assert_ret(hash_bit_len > 0, SKEIN_BAD_HASHLEN);
Anton Saraev95f1840a2014-05-19 12:09:55 +0400482 ctx->h.hash_bit_len = hash_bit_len; /* output hash bit count */
Jason Cooper449bb812014-03-24 01:48:58 +0000483
Anton Saraev95f1840a2014-05-19 12:09:55 +0400484 switch (hash_bit_len) { /* use pre-computed values, where available */
Jason Cooper39bd42b2014-03-24 01:49:09 +0000485 case 512:
Jake Edge007dfe52014-05-20 08:02:28 -0600486 memcpy(ctx->x, SKEIN_1024_IV_512, sizeof(ctx->x));
Jason Cooper39bd42b2014-03-24 01:49:09 +0000487 break;
488 case 384:
Jake Edge007dfe52014-05-20 08:02:28 -0600489 memcpy(ctx->x, SKEIN_1024_IV_384, sizeof(ctx->x));
Jason Cooper39bd42b2014-03-24 01:49:09 +0000490 break;
491 case 1024:
Jake Edge007dfe52014-05-20 08:02:28 -0600492 memcpy(ctx->x, SKEIN_1024_IV_1024, sizeof(ctx->x));
Jason Cooper39bd42b2014-03-24 01:49:09 +0000493 break;
494 default:
495 /* here if there is no precomputed IV value available */
Jason Cooper60eb8172014-03-24 01:49:11 +0000496 /*
497 * build/process the config block, type == CONFIG
498 * (could be precomputed)
499 */
500 /* set tweaks: T0=0; T1=CFG | FINAL */
Anton Saraev0264b7b2014-05-19 12:09:58 +0400501 skein_start_new_type(ctx, CFG_FINAL);
Jason Cooper449bb812014-03-24 01:48:58 +0000502
Jason Cooper60eb8172014-03-24 01:49:11 +0000503 /* set the schema, version */
Anton Saraev0264b7b2014-05-19 12:09:58 +0400504 cfg.w[0] = skein_swap64(SKEIN_SCHEMA_VER);
Jason Cooper60eb8172014-03-24 01:49:11 +0000505 /* hash result length in bits */
Anton Saraev0264b7b2014-05-19 12:09:58 +0400506 cfg.w[1] = skein_swap64(hash_bit_len);
507 cfg.w[2] = skein_swap64(SKEIN_CFG_TREE_INFO_SEQUENTIAL);
Jason Cooper60eb8172014-03-24 01:49:11 +0000508 /* zero pad config block */
Manu Kumar78930e72016-04-04 16:53:01 -0700509 memset(&cfg.w[3], 0, sizeof(cfg) - 3 * sizeof(cfg.w[0]));
Jason Cooper449bb812014-03-24 01:48:58 +0000510
Jason Cooper39bd42b2014-03-24 01:49:09 +0000511 /* compute the initial chaining values from config block */
Jason Cooper60eb8172014-03-24 01:49:11 +0000512 /* zero the chaining variables */
Jake Edge007dfe52014-05-20 08:02:28 -0600513 memset(ctx->x, 0, sizeof(ctx->x));
Anton Saraev68ace622014-05-19 12:09:54 +0400514 skein_1024_process_block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN);
Jason Cooper39bd42b2014-03-24 01:49:09 +0000515 break;
516 }
Jason Cooper449bb812014-03-24 01:48:58 +0000517
Jake Edge007dfe52014-05-20 08:02:28 -0600518 /* The chaining vars ctx->x are now initialized for the hash_bit_len. */
Jason Cooper39bd42b2014-03-24 01:49:09 +0000519 /* Set up to process the data message portion of the hash (default) */
Anton Saraev0264b7b2014-05-19 12:09:58 +0400520 skein_start_new_type(ctx, MSG); /* T0=0, T1= MSG type */
Jason Cooper449bb812014-03-24 01:48:58 +0000521
Jason Cooper39bd42b2014-03-24 01:49:09 +0000522 return SKEIN_SUCCESS;
Jason Cooper449bb812014-03-24 01:48:58 +0000523}
524
525/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
526/* init the context for a MAC and/or tree hash operation */
Deepa Dinamani7d27a182015-10-08 21:58:36 -0700527/*
528 * [identical to skein_1024_init() when key_bytes == 0 && \
529 * tree_info == SKEIN_CFG_TREE_INFO_SEQUENTIAL]
530 */
Anton Saraev3201b7f2014-05-19 12:09:56 +0400531int skein_1024_init_ext(struct skein_1024_ctx *ctx, size_t hash_bit_len,
Anton Saraev95f1840a2014-05-19 12:09:55 +0400532 u64 tree_info, const u8 *key, size_t key_bytes)
Jason Cooper449bb812014-03-24 01:48:58 +0000533{
Jason Cooper161a2af2014-03-24 01:49:13 +0000534 union {
Anton Saraev0264b7b2014-05-19 12:09:58 +0400535 u8 b[SKEIN_1024_STATE_BYTES];
536 u64 w[SKEIN_1024_STATE_WORDS];
Jason Cooper39bd42b2014-03-24 01:49:09 +0000537 } cfg; /* config block */
Jason Cooper449bb812014-03-24 01:48:58 +0000538
Anton Saraev0264b7b2014-05-19 12:09:58 +0400539 skein_assert_ret(hash_bit_len > 0, SKEIN_BAD_HASHLEN);
Aybuke Ozdemir26368fd2015-10-13 23:55:07 +0300540 skein_assert_ret(key_bytes == 0 || key, SKEIN_FAIL);
Jason Cooper449bb812014-03-24 01:48:58 +0000541
Jake Edge007dfe52014-05-20 08:02:28 -0600542 /* compute the initial chaining values ctx->x[], based on key */
Anton Saraev95f1840a2014-05-19 12:09:55 +0400543 if (key_bytes == 0) { /* is there a key? */
Jason Cooper60eb8172014-03-24 01:49:11 +0000544 /* no key: use all zeroes as key for config block */
Jake Edge007dfe52014-05-20 08:02:28 -0600545 memset(ctx->x, 0, sizeof(ctx->x));
Jason Cooper161a2af2014-03-24 01:49:13 +0000546 } else { /* here to pre-process a key */
Jake Edge007dfe52014-05-20 08:02:28 -0600547 skein_assert(sizeof(cfg.b) >= sizeof(ctx->x));
Jason Cooper39bd42b2014-03-24 01:49:09 +0000548 /* do a mini-Init right here */
Jason Cooper60eb8172014-03-24 01:49:11 +0000549 /* set output hash bit count = state size */
Manu Kumar78930e72016-04-04 16:53:01 -0700550 ctx->h.hash_bit_len = 8 * sizeof(ctx->x);
Jason Cooper60eb8172014-03-24 01:49:11 +0000551 /* set tweaks: T0 = 0; T1 = KEY type */
Anton Saraev0264b7b2014-05-19 12:09:58 +0400552 skein_start_new_type(ctx, KEY);
Jason Cooper60eb8172014-03-24 01:49:11 +0000553 /* zero the initial chaining variables */
Jake Edge007dfe52014-05-20 08:02:28 -0600554 memset(ctx->x, 0, sizeof(ctx->x));
Jason Cooper60eb8172014-03-24 01:49:11 +0000555 /* hash the key */
Anton Saraev95f1840a2014-05-19 12:09:55 +0400556 skein_1024_update(ctx, key, key_bytes);
Jason Cooper60eb8172014-03-24 01:49:11 +0000557 /* put result into cfg.b[] */
Anton Saraev68ace622014-05-19 12:09:54 +0400558 skein_1024_final_pad(ctx, cfg.b);
Jake Edge007dfe52014-05-20 08:02:28 -0600559 /* copy over into ctx->x[] */
560 memcpy(ctx->x, cfg.b, sizeof(cfg.b));
Jason Cooper39bd42b2014-03-24 01:49:09 +0000561 }
Jason Cooper60eb8172014-03-24 01:49:11 +0000562 /*
563 * build/process the config block, type == CONFIG (could be
564 * precomputed for each key)
565 */
566 /* output hash bit count */
Anton Saraev95f1840a2014-05-19 12:09:55 +0400567 ctx->h.hash_bit_len = hash_bit_len;
Anton Saraev0264b7b2014-05-19 12:09:58 +0400568 skein_start_new_type(ctx, CFG_FINAL);
Jason Cooper449bb812014-03-24 01:48:58 +0000569
Jason Cooper60eb8172014-03-24 01:49:11 +0000570 /* pre-pad cfg.w[] with zeroes */
571 memset(&cfg.w, 0, sizeof(cfg.w));
Anton Saraev0264b7b2014-05-19 12:09:58 +0400572 cfg.w[0] = skein_swap64(SKEIN_SCHEMA_VER);
Jason Cooper60eb8172014-03-24 01:49:11 +0000573 /* hash result length in bits */
Anton Saraev0264b7b2014-05-19 12:09:58 +0400574 cfg.w[1] = skein_swap64(hash_bit_len);
Jason Cooper60eb8172014-03-24 01:49:11 +0000575 /* tree hash config info (or SKEIN_CFG_TREE_INFO_SEQUENTIAL) */
Anton Saraev0264b7b2014-05-19 12:09:58 +0400576 cfg.w[2] = skein_swap64(tree_info);
Jason Cooper449bb812014-03-24 01:48:58 +0000577
Jason Cooper39bd42b2014-03-24 01:49:09 +0000578 /* compute the initial chaining values from config block */
Anton Saraev68ace622014-05-19 12:09:54 +0400579 skein_1024_process_block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN);
Jason Cooper449bb812014-03-24 01:48:58 +0000580
Jake Edge007dfe52014-05-20 08:02:28 -0600581 /* The chaining vars ctx->x are now initialized */
Jason Cooper39bd42b2014-03-24 01:49:09 +0000582 /* Set up to process the data message portion of the hash (default) */
Anton Saraev0264b7b2014-05-19 12:09:58 +0400583 skein_start_new_type(ctx, MSG);
Jason Cooper449bb812014-03-24 01:48:58 +0000584
Jason Cooper39bd42b2014-03-24 01:49:09 +0000585 return SKEIN_SUCCESS;
Jason Cooper449bb812014-03-24 01:48:58 +0000586}
587
588/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
589/* process the input bytes */
Anton Saraev3201b7f2014-05-19 12:09:56 +0400590int skein_1024_update(struct skein_1024_ctx *ctx, const u8 *msg,
Anton Saraev95f1840a2014-05-19 12:09:55 +0400591 size_t msg_byte_cnt)
Jason Cooper449bb812014-03-24 01:48:58 +0000592{
Jason Cooper39bd42b2014-03-24 01:49:09 +0000593 size_t n;
Jason Cooper449bb812014-03-24 01:48:58 +0000594
Jason Cooper60eb8172014-03-24 01:49:11 +0000595 /* catch uninitialized context */
Anton Saraev0264b7b2014-05-19 12:09:58 +0400596 skein_assert_ret(ctx->h.b_cnt <= SKEIN_1024_BLOCK_BYTES, SKEIN_FAIL);
Jason Cooper449bb812014-03-24 01:48:58 +0000597
Jason Cooper39bd42b2014-03-24 01:49:09 +0000598 /* process full blocks, if any */
Anton Saraev0264b7b2014-05-19 12:09:58 +0400599 if (msg_byte_cnt + ctx->h.b_cnt > SKEIN_1024_BLOCK_BYTES) {
Jason Cooper60eb8172014-03-24 01:49:11 +0000600 /* finish up any buffered message data */
Anton Saraev95f1840a2014-05-19 12:09:55 +0400601 if (ctx->h.b_cnt) {
Jason Cooper60eb8172014-03-24 01:49:11 +0000602 /* # bytes free in buffer b[] */
Anton Saraev0264b7b2014-05-19 12:09:58 +0400603 n = SKEIN_1024_BLOCK_BYTES - ctx->h.b_cnt;
Jason Cooper161a2af2014-03-24 01:49:13 +0000604 if (n) {
Jason Cooper60eb8172014-03-24 01:49:11 +0000605 /* check on our logic here */
Anton Saraev0264b7b2014-05-19 12:09:58 +0400606 skein_assert(n < msg_byte_cnt);
Anton Saraev95f1840a2014-05-19 12:09:55 +0400607 memcpy(&ctx->b[ctx->h.b_cnt], msg, n);
608 msg_byte_cnt -= n;
Jason Cooper39bd42b2014-03-24 01:49:09 +0000609 msg += n;
Anton Saraev95f1840a2014-05-19 12:09:55 +0400610 ctx->h.b_cnt += n;
Jason Cooper39bd42b2014-03-24 01:49:09 +0000611 }
Anton Saraev0264b7b2014-05-19 12:09:58 +0400612 skein_assert(ctx->h.b_cnt == SKEIN_1024_BLOCK_BYTES);
Anton Saraev68ace622014-05-19 12:09:54 +0400613 skein_1024_process_block(ctx, ctx->b, 1,
Anton Saraev0264b7b2014-05-19 12:09:58 +0400614 SKEIN_1024_BLOCK_BYTES);
Anton Saraev95f1840a2014-05-19 12:09:55 +0400615 ctx->h.b_cnt = 0;
Jason Cooper39bd42b2014-03-24 01:49:09 +0000616 }
Jason Cooper60eb8172014-03-24 01:49:11 +0000617 /*
618 * now process any remaining full blocks, directly from input
619 * message data
620 */
Anton Saraev0264b7b2014-05-19 12:09:58 +0400621 if (msg_byte_cnt > SKEIN_1024_BLOCK_BYTES) {
Jason Cooper60eb8172014-03-24 01:49:11 +0000622 /* number of full blocks to process */
Manu Kumar78930e72016-04-04 16:53:01 -0700623 n = (msg_byte_cnt - 1) / SKEIN_1024_BLOCK_BYTES;
Anton Saraev68ace622014-05-19 12:09:54 +0400624 skein_1024_process_block(ctx, msg, n,
Anton Saraev0264b7b2014-05-19 12:09:58 +0400625 SKEIN_1024_BLOCK_BYTES);
626 msg_byte_cnt -= n * SKEIN_1024_BLOCK_BYTES;
627 msg += n * SKEIN_1024_BLOCK_BYTES;
Jason Cooper39bd42b2014-03-24 01:49:09 +0000628 }
Anton Saraev0264b7b2014-05-19 12:09:58 +0400629 skein_assert(ctx->h.b_cnt == 0);
Jason Cooper39bd42b2014-03-24 01:49:09 +0000630 }
Jason Cooper449bb812014-03-24 01:48:58 +0000631
Jason Cooper39bd42b2014-03-24 01:49:09 +0000632 /* copy any remaining source message data bytes into b[] */
Anton Saraev95f1840a2014-05-19 12:09:55 +0400633 if (msg_byte_cnt) {
Anton Saraev0264b7b2014-05-19 12:09:58 +0400634 skein_assert(msg_byte_cnt + ctx->h.b_cnt <=
635 SKEIN_1024_BLOCK_BYTES);
Anton Saraev95f1840a2014-05-19 12:09:55 +0400636 memcpy(&ctx->b[ctx->h.b_cnt], msg, msg_byte_cnt);
637 ctx->h.b_cnt += msg_byte_cnt;
Jason Cooper39bd42b2014-03-24 01:49:09 +0000638 }
Jason Cooper449bb812014-03-24 01:48:58 +0000639
Jason Cooper39bd42b2014-03-24 01:49:09 +0000640 return SKEIN_SUCCESS;
Jason Cooper449bb812014-03-24 01:48:58 +0000641}
642
643/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
644/* finalize the hash computation and output the result */
Anton Saraev3201b7f2014-05-19 12:09:56 +0400645int skein_1024_final(struct skein_1024_ctx *ctx, u8 *hash_val)
Jason Cooper449bb812014-03-24 01:48:58 +0000646{
Anton Saraev95f1840a2014-05-19 12:09:55 +0400647 size_t i, n, byte_cnt;
Jake Edge007dfe52014-05-20 08:02:28 -0600648 u64 x[SKEIN_1024_STATE_WORDS];
Jason Cooper60eb8172014-03-24 01:49:11 +0000649 /* catch uninitialized context */
Anton Saraev0264b7b2014-05-19 12:09:58 +0400650 skein_assert_ret(ctx->h.b_cnt <= SKEIN_1024_BLOCK_BYTES, SKEIN_FAIL);
Jason Cooper449bb812014-03-24 01:48:58 +0000651
Jason Cooper60eb8172014-03-24 01:49:11 +0000652 /* tag as the final block */
Jake Edge007dfe52014-05-20 08:02:28 -0600653 ctx->h.tweak[1] |= SKEIN_T1_FLAG_FINAL;
Jason Cooper60eb8172014-03-24 01:49:11 +0000654 /* zero pad b[] if necessary */
Anton Saraev0264b7b2014-05-19 12:09:58 +0400655 if (ctx->h.b_cnt < SKEIN_1024_BLOCK_BYTES)
Anton Saraev95f1840a2014-05-19 12:09:55 +0400656 memset(&ctx->b[ctx->h.b_cnt], 0,
Manu Kumar3faa9662016-04-04 20:09:12 -0700657 SKEIN_1024_BLOCK_BYTES - ctx->h.b_cnt);
Jason Cooper449bb812014-03-24 01:48:58 +0000658
Jason Cooper60eb8172014-03-24 01:49:11 +0000659 /* process the final block */
Anton Saraev95f1840a2014-05-19 12:09:55 +0400660 skein_1024_process_block(ctx, ctx->b, 1, ctx->h.b_cnt);
Jason Cooper449bb812014-03-24 01:48:58 +0000661
Jason Cooper39bd42b2014-03-24 01:49:09 +0000662 /* now output the result */
Jason Cooper60eb8172014-03-24 01:49:11 +0000663 /* total number of output bytes */
Anton Saraev95f1840a2014-05-19 12:09:55 +0400664 byte_cnt = (ctx->h.hash_bit_len + 7) >> 3;
Jason Cooper449bb812014-03-24 01:48:58 +0000665
Jason Cooper39bd42b2014-03-24 01:49:09 +0000666 /* run Threefish in "counter mode" to generate output */
Jason Cooper60eb8172014-03-24 01:49:11 +0000667 /* zero out b[], so it can hold the counter */
668 memset(ctx->b, 0, sizeof(ctx->b));
669 /* keep a local copy of counter mode "key" */
Jake Edge007dfe52014-05-20 08:02:28 -0600670 memcpy(x, ctx->x, sizeof(x));
Manu Kumar78930e72016-04-04 16:53:01 -0700671 for (i = 0; i * SKEIN_1024_BLOCK_BYTES < byte_cnt; i++) {
Jason Cooper60eb8172014-03-24 01:49:11 +0000672 /* build the counter block */
Manu Kumare602a8082016-05-01 16:38:34 -0700673 ((u64 *)ctx->b)[0] = skein_swap64((u64)i);
Anton Saraev0264b7b2014-05-19 12:09:58 +0400674 skein_start_new_type(ctx, OUT_FINAL);
Jason Cooper60eb8172014-03-24 01:49:11 +0000675 /* run "counter mode" */
Anton Saraev68ace622014-05-19 12:09:54 +0400676 skein_1024_process_block(ctx, ctx->b, 1, sizeof(u64));
Jason Cooper60eb8172014-03-24 01:49:11 +0000677 /* number of output bytes left to go */
Manu Kumar78930e72016-04-04 16:53:01 -0700678 n = byte_cnt - i * SKEIN_1024_BLOCK_BYTES;
Anton Saraev0264b7b2014-05-19 12:09:58 +0400679 if (n >= SKEIN_1024_BLOCK_BYTES)
680 n = SKEIN_1024_BLOCK_BYTES;
Jason Cooper60eb8172014-03-24 01:49:11 +0000681 /* "output" the ctr mode bytes */
Manu Kumar5b05c1e2016-05-01 16:38:33 -0700682 skein_put64_lsb_first(hash_val + (i * SKEIN_1024_BLOCK_BYTES),
Manu Kumar43bb50e2016-05-01 16:38:35 -0700683 ctx->x, n);
Jason Cooper60eb8172014-03-24 01:49:11 +0000684 /* restore the counter mode key for next time */
Jake Edge007dfe52014-05-20 08:02:28 -0600685 memcpy(ctx->x, x, sizeof(x));
Jason Cooper39bd42b2014-03-24 01:49:09 +0000686 }
687 return SKEIN_SUCCESS;
Jason Cooper449bb812014-03-24 01:48:58 +0000688}
689
690/**************** Functions to support MAC/tree hashing ***************/
691/* (this code is identical for Optimized and Reference versions) */
692
693/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
694/* finalize the hash computation and output the block, no OUTPUT stage */
Anton Saraev95f1840a2014-05-19 12:09:55 +0400695int skein_256_final_pad(struct skein_256_ctx *ctx, u8 *hash_val)
Jason Cooper449bb812014-03-24 01:48:58 +0000696{
Jason Cooper60eb8172014-03-24 01:49:11 +0000697 /* catch uninitialized context */
Anton Saraev0264b7b2014-05-19 12:09:58 +0400698 skein_assert_ret(ctx->h.b_cnt <= SKEIN_256_BLOCK_BYTES, SKEIN_FAIL);
Jason Cooper449bb812014-03-24 01:48:58 +0000699
Jason Cooper60eb8172014-03-24 01:49:11 +0000700 /* tag as the final block */
Jake Edge007dfe52014-05-20 08:02:28 -0600701 ctx->h.tweak[1] |= SKEIN_T1_FLAG_FINAL;
Jason Cooper60eb8172014-03-24 01:49:11 +0000702 /* zero pad b[] if necessary */
Anton Saraev95f1840a2014-05-19 12:09:55 +0400703 if (ctx->h.b_cnt < SKEIN_256_BLOCK_BYTES)
704 memset(&ctx->b[ctx->h.b_cnt], 0,
Manu Kumar3faa9662016-04-04 20:09:12 -0700705 SKEIN_256_BLOCK_BYTES - ctx->h.b_cnt);
Jason Cooper60eb8172014-03-24 01:49:11 +0000706 /* process the final block */
Anton Saraev95f1840a2014-05-19 12:09:55 +0400707 skein_256_process_block(ctx, ctx->b, 1, ctx->h.b_cnt);
Jason Cooper449bb812014-03-24 01:48:58 +0000708
Jason Cooper60eb8172014-03-24 01:49:11 +0000709 /* "output" the state bytes */
Jake Edge007dfe52014-05-20 08:02:28 -0600710 skein_put64_lsb_first(hash_val, ctx->x, SKEIN_256_BLOCK_BYTES);
Jason Cooper449bb812014-03-24 01:48:58 +0000711
Jason Cooper39bd42b2014-03-24 01:49:09 +0000712 return SKEIN_SUCCESS;
Jason Cooper449bb812014-03-24 01:48:58 +0000713}
714
715/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
716/* finalize the hash computation and output the block, no OUTPUT stage */
Anton Saraev95f1840a2014-05-19 12:09:55 +0400717int skein_512_final_pad(struct skein_512_ctx *ctx, u8 *hash_val)
Jason Cooper449bb812014-03-24 01:48:58 +0000718{
Jason Cooper60eb8172014-03-24 01:49:11 +0000719 /* catch uninitialized context */
Anton Saraev0264b7b2014-05-19 12:09:58 +0400720 skein_assert_ret(ctx->h.b_cnt <= SKEIN_512_BLOCK_BYTES, SKEIN_FAIL);
Jason Cooper449bb812014-03-24 01:48:58 +0000721
Jason Cooper60eb8172014-03-24 01:49:11 +0000722 /* tag as the final block */
Jake Edge007dfe52014-05-20 08:02:28 -0600723 ctx->h.tweak[1] |= SKEIN_T1_FLAG_FINAL;
Jason Cooper60eb8172014-03-24 01:49:11 +0000724 /* zero pad b[] if necessary */
Anton Saraev95f1840a2014-05-19 12:09:55 +0400725 if (ctx->h.b_cnt < SKEIN_512_BLOCK_BYTES)
726 memset(&ctx->b[ctx->h.b_cnt], 0,
Manu Kumar3faa9662016-04-04 20:09:12 -0700727 SKEIN_512_BLOCK_BYTES - ctx->h.b_cnt);
Jason Cooper60eb8172014-03-24 01:49:11 +0000728 /* process the final block */
Anton Saraev95f1840a2014-05-19 12:09:55 +0400729 skein_512_process_block(ctx, ctx->b, 1, ctx->h.b_cnt);
Jason Cooper449bb812014-03-24 01:48:58 +0000730
Jason Cooper60eb8172014-03-24 01:49:11 +0000731 /* "output" the state bytes */
Jake Edge007dfe52014-05-20 08:02:28 -0600732 skein_put64_lsb_first(hash_val, ctx->x, SKEIN_512_BLOCK_BYTES);
Jason Cooper449bb812014-03-24 01:48:58 +0000733
Jason Cooper39bd42b2014-03-24 01:49:09 +0000734 return SKEIN_SUCCESS;
Jason Cooper449bb812014-03-24 01:48:58 +0000735}
736
737/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
738/* finalize the hash computation and output the block, no OUTPUT stage */
Anton Saraev3201b7f2014-05-19 12:09:56 +0400739int skein_1024_final_pad(struct skein_1024_ctx *ctx, u8 *hash_val)
Jason Cooper449bb812014-03-24 01:48:58 +0000740{
Jason Cooper60eb8172014-03-24 01:49:11 +0000741 /* catch uninitialized context */
Anton Saraev0264b7b2014-05-19 12:09:58 +0400742 skein_assert_ret(ctx->h.b_cnt <= SKEIN_1024_BLOCK_BYTES, SKEIN_FAIL);
Jason Cooper449bb812014-03-24 01:48:58 +0000743
Jason Cooper60eb8172014-03-24 01:49:11 +0000744 /* tag as the final block */
Jake Edge007dfe52014-05-20 08:02:28 -0600745 ctx->h.tweak[1] |= SKEIN_T1_FLAG_FINAL;
Jason Cooper60eb8172014-03-24 01:49:11 +0000746 /* zero pad b[] if necessary */
Anton Saraev0264b7b2014-05-19 12:09:58 +0400747 if (ctx->h.b_cnt < SKEIN_1024_BLOCK_BYTES)
Anton Saraev95f1840a2014-05-19 12:09:55 +0400748 memset(&ctx->b[ctx->h.b_cnt], 0,
Manu Kumar3faa9662016-04-04 20:09:12 -0700749 SKEIN_1024_BLOCK_BYTES - ctx->h.b_cnt);
Jason Cooper60eb8172014-03-24 01:49:11 +0000750 /* process the final block */
Anton Saraev95f1840a2014-05-19 12:09:55 +0400751 skein_1024_process_block(ctx, ctx->b, 1, ctx->h.b_cnt);
Jason Cooper449bb812014-03-24 01:48:58 +0000752
Jason Cooper60eb8172014-03-24 01:49:11 +0000753 /* "output" the state bytes */
Jake Edge007dfe52014-05-20 08:02:28 -0600754 skein_put64_lsb_first(hash_val, ctx->x, SKEIN_1024_BLOCK_BYTES);
Jason Cooper449bb812014-03-24 01:48:58 +0000755
Jason Cooper39bd42b2014-03-24 01:49:09 +0000756 return SKEIN_SUCCESS;
Jason Cooper449bb812014-03-24 01:48:58 +0000757}
758
759#if SKEIN_TREE_HASH
760/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
761/* just do the OUTPUT stage */
Anton Saraev95f1840a2014-05-19 12:09:55 +0400762int skein_256_output(struct skein_256_ctx *ctx, u8 *hash_val)
Jason Cooper449bb812014-03-24 01:48:58 +0000763{
Anton Saraev95f1840a2014-05-19 12:09:55 +0400764 size_t i, n, byte_cnt;
Jake Edge007dfe52014-05-20 08:02:28 -0600765 u64 x[SKEIN_256_STATE_WORDS];
Jason Cooper60eb8172014-03-24 01:49:11 +0000766 /* catch uninitialized context */
Anton Saraev0264b7b2014-05-19 12:09:58 +0400767 skein_assert_ret(ctx->h.b_cnt <= SKEIN_256_BLOCK_BYTES, SKEIN_FAIL);
Jason Cooper449bb812014-03-24 01:48:58 +0000768
Jason Cooper39bd42b2014-03-24 01:49:09 +0000769 /* now output the result */
Jason Cooper60eb8172014-03-24 01:49:11 +0000770 /* total number of output bytes */
Anton Saraev95f1840a2014-05-19 12:09:55 +0400771 byte_cnt = (ctx->h.hash_bit_len + 7) >> 3;
Jason Cooper449bb812014-03-24 01:48:58 +0000772
Jason Cooper39bd42b2014-03-24 01:49:09 +0000773 /* run Threefish in "counter mode" to generate output */
Jason Cooper60eb8172014-03-24 01:49:11 +0000774 /* zero out b[], so it can hold the counter */
775 memset(ctx->b, 0, sizeof(ctx->b));
776 /* keep a local copy of counter mode "key" */
Jake Edge007dfe52014-05-20 08:02:28 -0600777 memcpy(x, ctx->x, sizeof(x));
Manu Kumar78930e72016-04-04 16:53:01 -0700778 for (i = 0; i * SKEIN_256_BLOCK_BYTES < byte_cnt; i++) {
Jason Cooper60eb8172014-03-24 01:49:11 +0000779 /* build the counter block */
Manu Kumare602a8082016-05-01 16:38:34 -0700780 ((u64 *)ctx->b)[0] = skein_swap64((u64)i);
Anton Saraev0264b7b2014-05-19 12:09:58 +0400781 skein_start_new_type(ctx, OUT_FINAL);
Jason Cooper60eb8172014-03-24 01:49:11 +0000782 /* run "counter mode" */
Anton Saraev68ace622014-05-19 12:09:54 +0400783 skein_256_process_block(ctx, ctx->b, 1, sizeof(u64));
Jason Cooper60eb8172014-03-24 01:49:11 +0000784 /* number of output bytes left to go */
Manu Kumar78930e72016-04-04 16:53:01 -0700785 n = byte_cnt - i * SKEIN_256_BLOCK_BYTES;
Jason Cooper39bd42b2014-03-24 01:49:09 +0000786 if (n >= SKEIN_256_BLOCK_BYTES)
787 n = SKEIN_256_BLOCK_BYTES;
Jason Cooper60eb8172014-03-24 01:49:11 +0000788 /* "output" the ctr mode bytes */
Manu Kumar5b05c1e2016-05-01 16:38:33 -0700789 skein_put64_lsb_first(hash_val + (i * SKEIN_256_BLOCK_BYTES),
Manu Kumar43bb50e2016-05-01 16:38:35 -0700790 ctx->x, n);
Jason Cooper60eb8172014-03-24 01:49:11 +0000791 /* restore the counter mode key for next time */
Jake Edge007dfe52014-05-20 08:02:28 -0600792 memcpy(ctx->x, x, sizeof(x));
Jason Cooper39bd42b2014-03-24 01:49:09 +0000793 }
794 return SKEIN_SUCCESS;
Jason Cooper449bb812014-03-24 01:48:58 +0000795}
796
797/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
798/* just do the OUTPUT stage */
Anton Saraev95f1840a2014-05-19 12:09:55 +0400799int skein_512_output(struct skein_512_ctx *ctx, u8 *hash_val)
Jason Cooper449bb812014-03-24 01:48:58 +0000800{
Anton Saraev95f1840a2014-05-19 12:09:55 +0400801 size_t i, n, byte_cnt;
Jake Edge007dfe52014-05-20 08:02:28 -0600802 u64 x[SKEIN_512_STATE_WORDS];
Jason Cooper60eb8172014-03-24 01:49:11 +0000803 /* catch uninitialized context */
Anton Saraev0264b7b2014-05-19 12:09:58 +0400804 skein_assert_ret(ctx->h.b_cnt <= SKEIN_512_BLOCK_BYTES, SKEIN_FAIL);
Jason Cooper449bb812014-03-24 01:48:58 +0000805
Jason Cooper39bd42b2014-03-24 01:49:09 +0000806 /* now output the result */
Jason Cooper60eb8172014-03-24 01:49:11 +0000807 /* total number of output bytes */
Anton Saraev95f1840a2014-05-19 12:09:55 +0400808 byte_cnt = (ctx->h.hash_bit_len + 7) >> 3;
Jason Cooper449bb812014-03-24 01:48:58 +0000809
Jason Cooper39bd42b2014-03-24 01:49:09 +0000810 /* run Threefish in "counter mode" to generate output */
Jason Cooper60eb8172014-03-24 01:49:11 +0000811 /* zero out b[], so it can hold the counter */
812 memset(ctx->b, 0, sizeof(ctx->b));
813 /* keep a local copy of counter mode "key" */
Jake Edge007dfe52014-05-20 08:02:28 -0600814 memcpy(x, ctx->x, sizeof(x));
Manu Kumar78930e72016-04-04 16:53:01 -0700815 for (i = 0; i * SKEIN_512_BLOCK_BYTES < byte_cnt; i++) {
Jason Cooper60eb8172014-03-24 01:49:11 +0000816 /* build the counter block */
Manu Kumare602a8082016-05-01 16:38:34 -0700817 ((u64 *)ctx->b)[0] = skein_swap64((u64)i);
Anton Saraev0264b7b2014-05-19 12:09:58 +0400818 skein_start_new_type(ctx, OUT_FINAL);
Jason Cooper60eb8172014-03-24 01:49:11 +0000819 /* run "counter mode" */
Anton Saraev68ace622014-05-19 12:09:54 +0400820 skein_512_process_block(ctx, ctx->b, 1, sizeof(u64));
Jason Cooper60eb8172014-03-24 01:49:11 +0000821 /* number of output bytes left to go */
Manu Kumar78930e72016-04-04 16:53:01 -0700822 n = byte_cnt - i * SKEIN_512_BLOCK_BYTES;
Jason Cooper39bd42b2014-03-24 01:49:09 +0000823 if (n >= SKEIN_512_BLOCK_BYTES)
824 n = SKEIN_512_BLOCK_BYTES;
Jason Cooper60eb8172014-03-24 01:49:11 +0000825 /* "output" the ctr mode bytes */
Manu Kumar5b05c1e2016-05-01 16:38:33 -0700826 skein_put64_lsb_first(hash_val + (i * SKEIN_512_BLOCK_BYTES),
Manu Kumar43bb50e2016-05-01 16:38:35 -0700827 ctx->x, n);
Jason Cooper60eb8172014-03-24 01:49:11 +0000828 /* restore the counter mode key for next time */
Jake Edge007dfe52014-05-20 08:02:28 -0600829 memcpy(ctx->x, x, sizeof(x));
Jason Cooper39bd42b2014-03-24 01:49:09 +0000830 }
831 return SKEIN_SUCCESS;
Jason Cooper449bb812014-03-24 01:48:58 +0000832}
833
834/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
835/* just do the OUTPUT stage */
Anton Saraev3201b7f2014-05-19 12:09:56 +0400836int skein_1024_output(struct skein_1024_ctx *ctx, u8 *hash_val)
Jason Cooper449bb812014-03-24 01:48:58 +0000837{
Anton Saraev95f1840a2014-05-19 12:09:55 +0400838 size_t i, n, byte_cnt;
Jake Edge007dfe52014-05-20 08:02:28 -0600839 u64 x[SKEIN_1024_STATE_WORDS];
Jason Cooper60eb8172014-03-24 01:49:11 +0000840 /* catch uninitialized context */
Anton Saraev0264b7b2014-05-19 12:09:58 +0400841 skein_assert_ret(ctx->h.b_cnt <= SKEIN_1024_BLOCK_BYTES, SKEIN_FAIL);
Jason Cooper449bb812014-03-24 01:48:58 +0000842
Jason Cooper39bd42b2014-03-24 01:49:09 +0000843 /* now output the result */
Jason Cooper60eb8172014-03-24 01:49:11 +0000844 /* total number of output bytes */
Anton Saraev95f1840a2014-05-19 12:09:55 +0400845 byte_cnt = (ctx->h.hash_bit_len + 7) >> 3;
Jason Cooper449bb812014-03-24 01:48:58 +0000846
Jason Cooper39bd42b2014-03-24 01:49:09 +0000847 /* run Threefish in "counter mode" to generate output */
Jason Cooper60eb8172014-03-24 01:49:11 +0000848 /* zero out b[], so it can hold the counter */
849 memset(ctx->b, 0, sizeof(ctx->b));
850 /* keep a local copy of counter mode "key" */
Jake Edge007dfe52014-05-20 08:02:28 -0600851 memcpy(x, ctx->x, sizeof(x));
Manu Kumar78930e72016-04-04 16:53:01 -0700852 for (i = 0; i * SKEIN_1024_BLOCK_BYTES < byte_cnt; i++) {
Jason Cooper60eb8172014-03-24 01:49:11 +0000853 /* build the counter block */
Manu Kumare602a8082016-05-01 16:38:34 -0700854 ((u64 *)ctx->b)[0] = skein_swap64((u64)i);
Anton Saraev0264b7b2014-05-19 12:09:58 +0400855 skein_start_new_type(ctx, OUT_FINAL);
Jason Cooper60eb8172014-03-24 01:49:11 +0000856 /* run "counter mode" */
Anton Saraev68ace622014-05-19 12:09:54 +0400857 skein_1024_process_block(ctx, ctx->b, 1, sizeof(u64));
Jason Cooper60eb8172014-03-24 01:49:11 +0000858 /* number of output bytes left to go */
Manu Kumar78930e72016-04-04 16:53:01 -0700859 n = byte_cnt - i * SKEIN_1024_BLOCK_BYTES;
Anton Saraev0264b7b2014-05-19 12:09:58 +0400860 if (n >= SKEIN_1024_BLOCK_BYTES)
861 n = SKEIN_1024_BLOCK_BYTES;
Jason Cooper60eb8172014-03-24 01:49:11 +0000862 /* "output" the ctr mode bytes */
Manu Kumar5b05c1e2016-05-01 16:38:33 -0700863 skein_put64_lsb_first(hash_val + (i * SKEIN_1024_BLOCK_BYTES),
Manu Kumar43bb50e2016-05-01 16:38:35 -0700864 ctx->x, n);
Jason Cooper60eb8172014-03-24 01:49:11 +0000865 /* restore the counter mode key for next time */
Jake Edge007dfe52014-05-20 08:02:28 -0600866 memcpy(ctx->x, x, sizeof(x));
Jason Cooper39bd42b2014-03-24 01:49:09 +0000867 }
868 return SKEIN_SUCCESS;
Jason Cooper449bb812014-03-24 01:48:58 +0000869}
870#endif