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