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