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
27 #define SKEIN_ERR_CHECK 1
28 #include <cryptcommon/skeinApi.h>
29 #include <string.h>
30 #include <stdio.h>
31
skeinCtxPrepare(SkeinCtx_t * ctx,SkeinSize_t size)32 int skeinCtxPrepare(SkeinCtx_t* ctx, SkeinSize_t size)
33 {
34 Skein_Assert(ctx && size, SKEIN_FAIL);
35
36 memset(ctx ,0, sizeof(SkeinCtx_t));
37 ctx->skeinSize = size;
38
39 return SKEIN_SUCCESS;
40 }
41
skeinInit(SkeinCtx_t * ctx,size_t hashBitLen)42 int skeinInit(SkeinCtx_t* ctx, size_t hashBitLen)
43 {
44 int ret = SKEIN_FAIL;
45 size_t Xlen = 0;
46 u64b_t* X = NULL;
47 uint64_t treeInfo = SKEIN_CFG_TREE_INFO_SEQUENTIAL;
48
49 Skein_Assert(ctx, SKEIN_FAIL);
50 /*
51 * The following two lines rely of the fact that the real Skein contexts are
52 * a union in out context and thus have tha maximum memory available.
53 * The beauty of C :-) .
54 */
55 X = ctx->m.s256.X;
56 Xlen = (size_t)(ctx->skeinSize/8);
57 /*
58 * If size is the same and hash bit length is zero then reuse
59 * the save chaining variables.
60 */
61 switch (ctx->skeinSize) {
62 case Skein256:
63 ret = Skein_256_InitExt(&ctx->m.s256, hashBitLen,
64 treeInfo, NULL, 0);
65 break;
66 case Skein512:
67 ret = Skein_512_InitExt(&ctx->m.s512, hashBitLen,
68 treeInfo, NULL, 0);
69 break;
70 case Skein1024:
71 ret = Skein1024_InitExt(&ctx->m.s1024, hashBitLen,
72 treeInfo, NULL, 0);
73 break;
74 }
75
76 if (ret == SKEIN_SUCCESS) {
77 /* Save chaining variables for this combination of size and hashBitLen */
78 memcpy(ctx->XSave, X, Xlen);
79 }
80 return ret;
81 }
82
skeinMacInit(SkeinCtx_t * ctx,const uint8_t * key,size_t keyLen,size_t hashBitLen)83 int skeinMacInit(SkeinCtx_t* ctx, const uint8_t *key, size_t keyLen,
84 size_t hashBitLen)
85 {
86 int ret = SKEIN_FAIL;
87 u64b_t* X = NULL;
88 size_t Xlen = 0;
89 uint64_t treeInfo = SKEIN_CFG_TREE_INFO_SEQUENTIAL;
90
91 Skein_Assert(ctx, SKEIN_FAIL);
92
93 X = ctx->m.s256.X;
94 Xlen = (size_t)(ctx->skeinSize/8);
95
96 Skein_Assert(hashBitLen, SKEIN_BAD_HASHLEN);
97
98 switch (ctx->skeinSize) {
99 case Skein256:
100 ret = Skein_256_InitExt(&ctx->m.s256, hashBitLen,
101 treeInfo,
102 (const u08b_t*)key, keyLen);
103
104 break;
105 case Skein512:
106 ret = Skein_512_InitExt(&ctx->m.s512, hashBitLen,
107 treeInfo,
108 (const u08b_t*)key, keyLen);
109 break;
110 case Skein1024:
111 ret = Skein1024_InitExt(&ctx->m.s1024, hashBitLen,
112 treeInfo,
113 (const u08b_t*)key, keyLen);
114
115 break;
116 }
117 if (ret == SKEIN_SUCCESS) {
118 /* Save chaining variables for this combination of key, keyLen, hashBitLen */
119 memcpy(ctx->XSave, X, Xlen);
120 }
121 return ret;
122 }
123
skeinReset(SkeinCtx_t * ctx)124 void skeinReset(SkeinCtx_t* ctx)
125 {
126 size_t Xlen = 0;
127 u64b_t* X = NULL;
128
129 /*
130 * The following two lines rely of the fact that the real Skein contexts are
131 * a union in out context and thus have tha maximum memory available.
132 * The beautiy of C :-) .
133 */
134 X = ctx->m.s256.X;
135 Xlen = (size_t)(ctx->skeinSize/8);
136 /*
137 * If size is the same and hash bit length is zero then reuse
138 * the save chaining variables.
139 */
140 /* Restore the chaing variable, reset byte counter */
141 memcpy(X, ctx->XSave, Xlen);
142
143 /* Setup context to process the message */
144 Skein_Start_New_Type(&ctx->m, MSG);
145 }
146
skeinUpdate(SkeinCtx_t * ctx,const uint8_t * msg,size_t msgByteCnt)147 int skeinUpdate(SkeinCtx_t *ctx, const uint8_t *msg,
148 size_t msgByteCnt)
149 {
150 int ret = SKEIN_FAIL;
151 Skein_Assert(ctx, SKEIN_FAIL);
152
153 switch (ctx->skeinSize) {
154 case Skein256:
155 ret = Skein_256_Update(&ctx->m.s256, (const u08b_t*)msg, msgByteCnt);
156 break;
157 case Skein512:
158 ret = Skein_512_Update(&ctx->m.s512, (const u08b_t*)msg, msgByteCnt);
159 break;
160 case Skein1024:
161 ret = Skein1024_Update(&ctx->m.s1024, (const u08b_t*)msg, msgByteCnt);
162 break;
163 }
164 return ret;
165
166 }
167
skeinUpdateBits(SkeinCtx_t * ctx,const uint8_t * msg,size_t msgBitCnt)168 int skeinUpdateBits(SkeinCtx_t *ctx, const uint8_t *msg,
169 size_t msgBitCnt)
170 {
171 /*
172 * I've used the bit pad implementation from skein_test.c (see NIST CD)
173 * and modified it to use the convenience functions and added some pointer
174 * arithmetic.
175 */
176 size_t length;
177 uint8_t mask;
178 uint8_t* up;
179
180 /* only the final Update() call is allowed do partial bytes, else assert an error */
181 Skein_Assert((ctx->m.h.T[1] & SKEIN_T1_FLAG_BIT_PAD) == 0 || msgBitCnt == 0, SKEIN_FAIL);
182
183 /* if number of bits is a multiple of bytes - that's easy */
184 if ((msgBitCnt & 0x7) == 0) {
185 return skeinUpdate(ctx, msg, msgBitCnt >> 3);
186 }
187 skeinUpdate(ctx, msg, (msgBitCnt >> 3) + 1);
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 */
195 up = (uint8_t*)ctx->m.s256.X + ctx->skeinSize / 8;
196
197 Skein_Set_Bit_Pad_Flag(ctx->m.h); /* set tweak flag for the skeinFinal call */
198
199 /* now "pad" the final partial byte the way NIST likes */
200 length = ctx->m.h.bCnt; /* get the bCnt value (same location for all block sizes) */
201 Skein_assert(length != 0); /* internal sanity check: there IS a partial byte in the buffer! */
202 mask = (uint8_t) (1u << (7 - (msgBitCnt & 7))); /* partial byte bit mask */
203 up[length-1] = (uint8_t)((up[length-1] & (0-mask))|mask); /* apply bit padding on final byte (in the buffer) */
204
205 return SKEIN_SUCCESS;
206 }
207
skeinFinal(SkeinCtx_t * ctx,uint8_t * hash)208 int skeinFinal(SkeinCtx_t* ctx, uint8_t* hash)
209 {
210 int ret = SKEIN_FAIL;
211 Skein_Assert(ctx, SKEIN_FAIL);
212
213 switch (ctx->skeinSize) {
214 case Skein256:
215 ret = Skein_256_Final(&ctx->m.s256, (u08b_t*)hash);
216 break;
217 case Skein512:
218 ret = Skein_512_Final(&ctx->m.s512, (u08b_t*)hash);
219 break;
220 case Skein1024:
221 ret = Skein1024_Final(&ctx->m.s1024, (u08b_t*)hash);
222 break;
223 }
224 return ret;
225 }
226