• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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  */
25 
26 #include <linux/string.h>
27 #include "skein_api.h"
28 
skein_ctx_prepare(struct skein_ctx * ctx,enum skein_size size)29 int skein_ctx_prepare(struct skein_ctx *ctx, enum skein_size size)
30 {
31 	skein_assert_ret(ctx && size, SKEIN_FAIL);
32 
33 	memset(ctx, 0, sizeof(struct skein_ctx));
34 	ctx->skein_size = size;
35 
36 	return SKEIN_SUCCESS;
37 }
38 
skein_init(struct skein_ctx * ctx,size_t hash_bit_len)39 int skein_init(struct skein_ctx *ctx, size_t hash_bit_len)
40 {
41 	int ret = SKEIN_FAIL;
42 	size_t x_len = 0;
43 	u64 *x = NULL;
44 	u64 tree_info = SKEIN_CFG_TREE_INFO_SEQUENTIAL;
45 
46 	skein_assert_ret(ctx, SKEIN_FAIL);
47 	/*
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 :-) .
51 	 */
52 	x = ctx->m.s256.x;
53 	x_len = ctx->skein_size / 8;
54 	/*
55 	 * If size is the same and hash bit length is zero then reuse
56 	 * the save chaining variables.
57 	 */
58 	switch (ctx->skein_size) {
59 	case SKEIN_256:
60 		ret = skein_256_init_ext(&ctx->m.s256, hash_bit_len,
61 					 tree_info, NULL, 0);
62 		break;
63 	case SKEIN_512:
64 		ret = skein_512_init_ext(&ctx->m.s512, hash_bit_len,
65 					 tree_info, NULL, 0);
66 		break;
67 	case SKEIN_1024:
68 		ret = skein_1024_init_ext(&ctx->m.s1024, hash_bit_len,
69 					  tree_info, NULL, 0);
70 		break;
71 	}
72 
73 	if (ret == SKEIN_SUCCESS) {
74 		/*
75 		 * Save chaining variables for this combination of size and
76 		 * hash_bit_len
77 		 */
78 		memcpy(ctx->x_save, x, x_len);
79 	}
80 	return ret;
81 }
82 
skein_mac_init(struct skein_ctx * ctx,const u8 * key,size_t key_len,size_t hash_bit_len)83 int skein_mac_init(struct skein_ctx *ctx, const u8 *key, size_t key_len,
84 		   size_t hash_bit_len)
85 {
86 	int ret = SKEIN_FAIL;
87 	u64 *x = NULL;
88 	size_t x_len = 0;
89 	u64 tree_info = SKEIN_CFG_TREE_INFO_SEQUENTIAL;
90 
91 	skein_assert_ret(ctx, SKEIN_FAIL);
92 
93 	x = ctx->m.s256.x;
94 	x_len = ctx->skein_size / 8;
95 
96 	skein_assert_ret(hash_bit_len, SKEIN_BAD_HASHLEN);
97 
98 	switch (ctx->skein_size) {
99 	case SKEIN_256:
100 		ret = skein_256_init_ext(&ctx->m.s256, hash_bit_len,
101 					 tree_info,
102 					 (const u8 *)key, key_len);
103 
104 		break;
105 	case SKEIN_512:
106 		ret = skein_512_init_ext(&ctx->m.s512, hash_bit_len,
107 					 tree_info,
108 					 (const u8 *)key, key_len);
109 		break;
110 	case SKEIN_1024:
111 		ret = skein_1024_init_ext(&ctx->m.s1024, hash_bit_len,
112 					  tree_info,
113 					  (const u8 *)key, key_len);
114 
115 		break;
116 	}
117 	if (ret == SKEIN_SUCCESS) {
118 		/*
119 		 * Save chaining variables for this combination of key,
120 		 * key_len, hash_bit_len
121 		 */
122 		memcpy(ctx->x_save, x, x_len);
123 	}
124 	return ret;
125 }
126 
skein_reset(struct skein_ctx * ctx)127 void skein_reset(struct skein_ctx *ctx)
128 {
129 	size_t x_len = 0;
130 	u64 *x;
131 
132 	/*
133 	 * The following two lines rely of the fact that the real Skein
134 	 * contexts are a union in out context and thus have tha maximum
135 	 * memory available.  The beautiy of C :-) .
136 	 */
137 	x = ctx->m.s256.x;
138 	x_len = ctx->skein_size / 8;
139 	/* Restore the chaing variable, reset byte counter */
140 	memcpy(x, ctx->x_save, x_len);
141 
142 	/* Setup context to process the message */
143 	skein_start_new_type(&ctx->m, MSG);
144 }
145 
skein_update(struct skein_ctx * ctx,const u8 * msg,size_t msg_byte_cnt)146 int skein_update(struct skein_ctx *ctx, const u8 *msg,
147 		 size_t msg_byte_cnt)
148 {
149 	int ret = SKEIN_FAIL;
150 
151 	skein_assert_ret(ctx, SKEIN_FAIL);
152 
153 	switch (ctx->skein_size) {
154 	case SKEIN_256:
155 		ret = skein_256_update(&ctx->m.s256, (const u8 *)msg,
156 				       msg_byte_cnt);
157 		break;
158 	case SKEIN_512:
159 		ret = skein_512_update(&ctx->m.s512, (const u8 *)msg,
160 				       msg_byte_cnt);
161 		break;
162 	case SKEIN_1024:
163 		ret = skein_1024_update(&ctx->m.s1024, (const u8 *)msg,
164 					msg_byte_cnt);
165 		break;
166 	}
167 	return ret;
168 }
169 
skein_update_bits(struct skein_ctx * ctx,const u8 * msg,size_t msg_bit_cnt)170 int skein_update_bits(struct skein_ctx *ctx, const u8 *msg,
171 		      size_t msg_bit_cnt)
172 {
173 	/*
174 	 * I've used the bit pad implementation from skein_test.c (see NIST CD)
175 	 * and modified it to use the convenience functions and added some
176 	 * pointer arithmetic.
177 	 */
178 	size_t length;
179 	u8 mask;
180 	u8 *up;
181 
182 	/*
183 	 * only the final Update() call is allowed do partial bytes, else
184 	 * assert an error
185 	 */
186 	skein_assert_ret((ctx->m.h.T[1] & SKEIN_T1_FLAG_BIT_PAD) == 0 ||
187 			 msg_bit_cnt == 0, SKEIN_FAIL);
188 
189 	/* if number of bits is a multiple of bytes - that's easy */
190 	if ((msg_bit_cnt & 0x7) == 0)
191 		return skein_update(ctx, msg, msg_bit_cnt >> 3);
192 
193 	skein_update(ctx, msg, (msg_bit_cnt >> 3) + 1);
194 
195 	/*
196 	 * The next line rely on the fact that the real Skein contexts
197 	 * are a union in our context. After the addition the pointer points to
198 	 * Skein's real partial block buffer.
199 	 * If this layout ever changes we have to adapt this as well.
200 	 */
201 	up = (u8 *)ctx->m.s256.x + ctx->skein_size / 8;
202 
203 	/* set tweak flag for the skein_final call */
204 	skein_set_bit_pad_flag(ctx->m.h);
205 
206 	/* now "pad" the final partial byte the way NIST likes */
207 	/* get the b_cnt value (same location for all block sizes) */
208 	length = ctx->m.h.b_cnt;
209 	/* internal sanity check: there IS a partial byte in the buffer! */
210 	skein_assert(length != 0);
211 	/* partial byte bit mask */
212 	mask = (u8)(1u << (7 - (msg_bit_cnt & 7)));
213 	/* apply bit padding on final byte (in the buffer) */
214 	up[length - 1]  = (u8)((up[length - 1] & (0 - mask)) | mask);
215 
216 	return SKEIN_SUCCESS;
217 }
218 
skein_final(struct skein_ctx * ctx,u8 * hash)219 int skein_final(struct skein_ctx *ctx, u8 *hash)
220 {
221 	int ret = SKEIN_FAIL;
222 
223 	skein_assert_ret(ctx, SKEIN_FAIL);
224 
225 	switch (ctx->skein_size) {
226 	case SKEIN_256:
227 		ret = skein_256_final(&ctx->m.s256, (u8 *)hash);
228 		break;
229 	case SKEIN_512:
230 		ret = skein_512_final(&ctx->m.s512, (u8 *)hash);
231 		break;
232 	case SKEIN_1024:
233 		ret = skein_1024_final(&ctx->m.s1024, (u8 *)hash);
234 		break;
235 	}
236 	return ret;
237 }
238