]>
Commit | Line | Data |
---|---|---|
449bb812 | 1 | /* |
7d27a184 DD |
2 | * Copyright (c) 2010 Werner Dittmann |
3 | * | |
4 | * Permission is hereby granted, free of charge, to any person | |
5 | * obtaining a copy of this software and associated documentation | |
6 | * files (the "Software"), to deal in the Software without | |
7 | * restriction, including without limitation the rights to use, | |
8 | * copy, modify, merge, publish, distribute, sublicense, and/or sell | |
9 | * copies of the Software, and to permit persons to whom the | |
10 | * Software is furnished to do so, subject to the following | |
11 | * conditions: | |
12 | * | |
13 | * The above copyright notice and this permission notice shall be | |
14 | * included in all copies or substantial portions of the Software. | |
15 | * | |
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES | |
18 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | |
20 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | |
21 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
23 | * OTHER DEALINGS IN THE SOFTWARE. | |
24 | */ | |
449bb812 | 25 | |
c2c7426b | 26 | #include <linux/string.h> |
85dfd522 | 27 | #include "skein_api.h" |
449bb812 | 28 | |
68ace624 | 29 | int skein_ctx_prepare(struct skein_ctx *ctx, enum skein_size size) |
449bb812 | 30 | { |
0264b7b7 | 31 | skein_assert_ret(ctx && size, SKEIN_FAIL); |
449bb812 | 32 | |
2d375457 | 33 | memset(ctx, 0, sizeof(struct skein_ctx)); |
95f1840a | 34 | ctx->skein_size = size; |
449bb812 | 35 | |
39bd42b0 | 36 | return SKEIN_SUCCESS; |
449bb812 JC |
37 | } |
38 | ||
95f1840a | 39 | int skein_init(struct skein_ctx *ctx, size_t hash_bit_len) |
449bb812 | 40 | { |
39bd42b0 | 41 | int ret = SKEIN_FAIL; |
007dfe5a JE |
42 | size_t x_len = 0; |
43 | u64 *x = NULL; | |
95f1840a | 44 | u64 tree_info = SKEIN_CFG_TREE_INFO_SEQUENTIAL; |
39bd42b0 | 45 | |
0264b7b7 | 46 | skein_assert_ret(ctx, SKEIN_FAIL); |
39bd42b0 | 47 | /* |
60eb8175 JC |
48 | * The following two lines rely of the fact that the real Skein |
49 | * contexts are a union in out context and thus have tha maximum | |
50 | * memory available. The beauty of C :-) . | |
39bd42b0 | 51 | */ |
007dfe5a | 52 | x = ctx->m.s256.x; |
9efbbfad | 53 | x_len = ctx->skein_size / 8; |
39bd42b0 JC |
54 | /* |
55 | * If size is the same and hash bit length is zero then reuse | |
56 | * the save chaining variables. | |
57 | */ | |
95f1840a | 58 | switch (ctx->skein_size) { |
9435d3ac | 59 | case SKEIN_256: |
95f1840a AS |
60 | ret = skein_256_init_ext(&ctx->m.s256, hash_bit_len, |
61 | tree_info, NULL, 0); | |
39bd42b0 | 62 | break; |
9435d3ac | 63 | case SKEIN_512: |
95f1840a AS |
64 | ret = skein_512_init_ext(&ctx->m.s512, hash_bit_len, |
65 | tree_info, NULL, 0); | |
39bd42b0 | 66 | break; |
9435d3ac | 67 | case SKEIN_1024: |
95f1840a AS |
68 | ret = skein_1024_init_ext(&ctx->m.s1024, hash_bit_len, |
69 | tree_info, NULL, 0); | |
39bd42b0 JC |
70 | break; |
71 | } | |
72 | ||
73 | if (ret == SKEIN_SUCCESS) { | |
60eb8175 JC |
74 | /* |
75 | * Save chaining variables for this combination of size and | |
95f1840a | 76 | * hash_bit_len |
60eb8175 | 77 | */ |
007dfe5a | 78 | memcpy(ctx->x_save, x, x_len); |
39bd42b0 JC |
79 | } |
80 | return ret; | |
449bb812 JC |
81 | } |
82 | ||
95f1840a AS |
83 | int skein_mac_init(struct skein_ctx *ctx, const u8 *key, size_t key_len, |
84 | size_t hash_bit_len) | |
449bb812 | 85 | { |
39bd42b0 | 86 | int ret = SKEIN_FAIL; |
007dfe5a JE |
87 | u64 *x = NULL; |
88 | size_t x_len = 0; | |
95f1840a | 89 | u64 tree_info = SKEIN_CFG_TREE_INFO_SEQUENTIAL; |
39bd42b0 | 90 | |
0264b7b7 | 91 | skein_assert_ret(ctx, SKEIN_FAIL); |
39bd42b0 | 92 | |
007dfe5a | 93 | x = ctx->m.s256.x; |
9efbbfad | 94 | x_len = ctx->skein_size / 8; |
39bd42b0 | 95 | |
0264b7b7 | 96 | skein_assert_ret(hash_bit_len, SKEIN_BAD_HASHLEN); |
39bd42b0 | 97 | |
95f1840a | 98 | switch (ctx->skein_size) { |
9435d3ac | 99 | case SKEIN_256: |
95f1840a | 100 | ret = skein_256_init_ext(&ctx->m.s256, hash_bit_len, |
1af172fa | 101 | tree_info, key, key_len); |
39bd42b0 JC |
102 | |
103 | break; | |
9435d3ac | 104 | case SKEIN_512: |
95f1840a | 105 | ret = skein_512_init_ext(&ctx->m.s512, hash_bit_len, |
1af172fa | 106 | tree_info, key, key_len); |
39bd42b0 | 107 | break; |
9435d3ac | 108 | case SKEIN_1024: |
95f1840a | 109 | ret = skein_1024_init_ext(&ctx->m.s1024, hash_bit_len, |
1af172fa | 110 | tree_info, key, key_len); |
39bd42b0 JC |
111 | |
112 | break; | |
113 | } | |
114 | if (ret == SKEIN_SUCCESS) { | |
60eb8175 JC |
115 | /* |
116 | * Save chaining variables for this combination of key, | |
95f1840a | 117 | * key_len, hash_bit_len |
60eb8175 | 118 | */ |
007dfe5a | 119 | memcpy(ctx->x_save, x, x_len); |
39bd42b0 JC |
120 | } |
121 | return ret; | |
449bb812 JC |
122 | } |
123 | ||
68ace624 | 124 | void skein_reset(struct skein_ctx *ctx) |
449bb812 | 125 | { |
007dfe5a | 126 | size_t x_len = 0; |
779fcc84 | 127 | u64 *x; |
39bd42b0 JC |
128 | |
129 | /* | |
60eb8175 JC |
130 | * The following two lines rely of the fact that the real Skein |
131 | * contexts are a union in out context and thus have tha maximum | |
132 | * memory available. The beautiy of C :-) . | |
39bd42b0 | 133 | */ |
007dfe5a | 134 | x = ctx->m.s256.x; |
9efbbfad | 135 | x_len = ctx->skein_size / 8; |
39bd42b0 | 136 | /* Restore the chaing variable, reset byte counter */ |
007dfe5a | 137 | memcpy(x, ctx->x_save, x_len); |
39bd42b0 JC |
138 | |
139 | /* Setup context to process the message */ | |
0264b7b7 | 140 | skein_start_new_type(&ctx->m, MSG); |
449bb812 JC |
141 | } |
142 | ||
68ace624 | 143 | int skein_update(struct skein_ctx *ctx, const u8 *msg, |
95f1840a | 144 | size_t msg_byte_cnt) |
449bb812 | 145 | { |
39bd42b0 | 146 | int ret = SKEIN_FAIL; |
95f1840a | 147 | |
0264b7b7 | 148 | skein_assert_ret(ctx, SKEIN_FAIL); |
39bd42b0 | 149 | |
95f1840a | 150 | switch (ctx->skein_size) { |
9435d3ac | 151 | case SKEIN_256: |
1af172fa | 152 | ret = skein_256_update(&ctx->m.s256, msg, msg_byte_cnt); |
39bd42b0 | 153 | break; |
9435d3ac | 154 | case SKEIN_512: |
1af172fa | 155 | ret = skein_512_update(&ctx->m.s512, msg, msg_byte_cnt); |
39bd42b0 | 156 | break; |
9435d3ac | 157 | case SKEIN_1024: |
1af172fa | 158 | ret = skein_1024_update(&ctx->m.s1024, msg, msg_byte_cnt); |
39bd42b0 JC |
159 | break; |
160 | } | |
161 | return ret; | |
449bb812 JC |
162 | } |
163 | ||
68ace624 | 164 | int skein_update_bits(struct skein_ctx *ctx, const u8 *msg, |
95f1840a | 165 | size_t msg_bit_cnt) |
449bb812 | 166 | { |
39bd42b0 JC |
167 | /* |
168 | * I've used the bit pad implementation from skein_test.c (see NIST CD) | |
60eb8175 JC |
169 | * and modified it to use the convenience functions and added some |
170 | * pointer arithmetic. | |
39bd42b0 JC |
171 | */ |
172 | size_t length; | |
173 | u8 mask; | |
174 | u8 *up; | |
175 | ||
60eb8175 JC |
176 | /* |
177 | * only the final Update() call is allowed do partial bytes, else | |
178 | * assert an error | |
179 | */ | |
0264b7b7 AS |
180 | skein_assert_ret((ctx->m.h.T[1] & SKEIN_T1_FLAG_BIT_PAD) == 0 || |
181 | msg_bit_cnt == 0, SKEIN_FAIL); | |
39bd42b0 JC |
182 | |
183 | /* if number of bits is a multiple of bytes - that's easy */ | |
95f1840a AS |
184 | if ((msg_bit_cnt & 0x7) == 0) |
185 | return skein_update(ctx, msg, msg_bit_cnt >> 3); | |
7584a878 | 186 | |
95f1840a | 187 | skein_update(ctx, msg, (msg_bit_cnt >> 3) + 1); |
39bd42b0 JC |
188 | |
189 | /* | |
190 | * The next line rely on the fact that the real Skein contexts | |
191 | * are a union in our context. After the addition the pointer points to | |
192 | * Skein's real partial block buffer. | |
193 | * If this layout ever changes we have to adapt this as well. | |
194 | */ | |
007dfe5a | 195 | up = (u8 *)ctx->m.s256.x + ctx->skein_size / 8; |
39bd42b0 | 196 | |
68ace624 | 197 | /* set tweak flag for the skein_final call */ |
0264b7b7 | 198 | skein_set_bit_pad_flag(ctx->m.h); |
39bd42b0 JC |
199 | |
200 | /* now "pad" the final partial byte the way NIST likes */ | |
95f1840a AS |
201 | /* get the b_cnt value (same location for all block sizes) */ |
202 | length = ctx->m.h.b_cnt; | |
60eb8175 | 203 | /* internal sanity check: there IS a partial byte in the buffer! */ |
0264b7b7 | 204 | skein_assert(length != 0); |
60eb8175 | 205 | /* partial byte bit mask */ |
e602a808 | 206 | mask = (u8)(1u << (7 - (msg_bit_cnt & 7))); |
60eb8175 | 207 | /* apply bit padding on final byte (in the buffer) */ |
1af172fa | 208 | up[length - 1] = (up[length - 1] & (0 - mask)) | mask; |
39bd42b0 JC |
209 | |
210 | return SKEIN_SUCCESS; | |
449bb812 JC |
211 | } |
212 | ||
68ace624 | 213 | int skein_final(struct skein_ctx *ctx, u8 *hash) |
449bb812 | 214 | { |
39bd42b0 | 215 | int ret = SKEIN_FAIL; |
95f1840a | 216 | |
0264b7b7 | 217 | skein_assert_ret(ctx, SKEIN_FAIL); |
39bd42b0 | 218 | |
95f1840a | 219 | switch (ctx->skein_size) { |
9435d3ac | 220 | case SKEIN_256: |
1af172fa | 221 | ret = skein_256_final(&ctx->m.s256, hash); |
39bd42b0 | 222 | break; |
9435d3ac | 223 | case SKEIN_512: |
1af172fa | 224 | ret = skein_512_final(&ctx->m.s512, hash); |
39bd42b0 | 225 | break; |
9435d3ac | 226 | case SKEIN_1024: |
1af172fa | 227 | ret = skein_1024_final(&ctx->m.s1024, hash); |
39bd42b0 JC |
228 | break; |
229 | } | |
230 | return ret; | |
449bb812 | 231 | } |