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