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
29int 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
39int 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
83int 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
127void 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
146int 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}
170
171int skein_update_bits(struct skein_ctx *ctx, const u8 *msg,
172		      size_t msg_bit_cnt)
173{
174	/*
175	 * I've used the bit pad implementation from skein_test.c (see NIST CD)
176	 * and modified it to use the convenience functions and added some
177	 * pointer arithmetic.
178	 */
179	size_t length;
180	u8 mask;
181	u8 *up;
182
183	/*
184	 * only the final Update() call is allowed do partial bytes, else
185	 * assert an error
186	 */
187	skein_assert_ret((ctx->m.h.T[1] & SKEIN_T1_FLAG_BIT_PAD) == 0 ||
188			 msg_bit_cnt == 0, SKEIN_FAIL);
189
190	/* if number of bits is a multiple of bytes - that's easy */
191	if ((msg_bit_cnt & 0x7) == 0)
192		return skein_update(ctx, msg, msg_bit_cnt >> 3);
193
194	skein_update(ctx, msg, (msg_bit_cnt >> 3) + 1);
195
196	/*
197	 * The next line rely on the fact that the real Skein contexts
198	 * are a union in our context. After the addition the pointer points to
199	 * Skein's real partial block buffer.
200	 * If this layout ever changes we have to adapt this as well.
201	 */
202	up = (u8 *)ctx->m.s256.x + ctx->skein_size / 8;
203
204	/* set tweak flag for the skein_final call */
205	skein_set_bit_pad_flag(ctx->m.h);
206
207	/* now "pad" the final partial byte the way NIST likes */
208	/* get the b_cnt value (same location for all block sizes) */
209	length = ctx->m.h.b_cnt;
210	/* internal sanity check: there IS a partial byte in the buffer! */
211	skein_assert(length != 0);
212	/* partial byte bit mask */
213	mask = (u8) (1u << (7 - (msg_bit_cnt & 7)));
214	/* apply bit padding on final byte (in the buffer) */
215	up[length - 1]  = (u8)((up[length - 1] & (0 - mask)) | mask);
216
217	return SKEIN_SUCCESS;
218}
219
220int skein_final(struct skein_ctx *ctx, u8 *hash)
221{
222	int ret = SKEIN_FAIL;
223
224	skein_assert_ret(ctx, SKEIN_FAIL);
225
226	switch (ctx->skein_size) {
227	case SKEIN_256:
228		ret = skein_256_final(&ctx->m.s256, (u8 *)hash);
229		break;
230	case SKEIN_512:
231		ret = skein_512_final(&ctx->m.s512, (u8 *)hash);
232		break;
233	case SKEIN_1024:
234		ret = skein_1024_final(&ctx->m.s1024, (u8 *)hash);
235		break;
236	}
237	return ret;
238}
239