1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - MATH - libraries
3 File: dgt_sha256.c
4
5 Copyright 2007-2008 Nintendo. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Date::$
14 $Rev:$
15 $Author:$
16 *---------------------------------------------------------------------------*/
17
18 /*---------------------------------------------------------------------------*
19 SHA-256
20 *---------------------------------------------------------------------------*/
21
22
23 #include <nitro/math/dgt.h>
24 #include <nitro/mi/memory.h>
25 #include <nitro/mi/endian.h>
26 #include "hmac.h"
27
28
29 /*---------------------------------------------------------------------------*/
30 #define NOT_USE_SHA256FILL 0 // Do not use MATH_SHA256Fill
31 // Instead, consumption of the 64byte RAM increases
32
33 #define memcpy(_x_, _y_, _z_) MI_CpuCopy8(_y_, _x_, _z_)
34 #define memset MI_CpuFill8
35 #define NETConvert32HToBE(val) MI_HToBE32(val)
36
37 #if !defined(MATH_SHA256_ASM)
38 static void MATH_SHA256iProcessBlock(MATHSHA256Context *context);
39 #else
40 extern void MATH_SHA256iProcessBlock(MATHSHA256Context *context);
41 #endif
42
43
44 /*---------------------------------------------------------------------------*
45 32-bit operations required in SHA-256 calculation
46 *---------------------------------------------------------------------------*/
47 #define SHA256_ROTR(r, x) (NETRotateLeft32((32-r),x))
48 #define SHA256_SHR(s, x) (x>>s)
49
50 #define SHA256_CH(x, y, z) (((x)&(y))^((~x)&(z)))
51 #define SHA256_MAJ(x, y, z) (((x)&(y))^((x)&(z))^((y)&(z)))
52
53 #define SHA256_LSIGMA_0(x) \
54 (SHA256_ROTR(2,x) ^ SHA256_ROTR(13,x) ^ SHA256_ROTR(22,x))
55
56 #define SHA256_LSIGMA_1(x) \
57 (SHA256_ROTR(6,x) ^ SHA256_ROTR(11,x) ^ SHA256_ROTR(25,x))
58
59 #define SHA256_SSIGMA_0(x) \
60 (SHA256_ROTR(7,x) ^ SHA256_ROTR(18,x) ^ SHA256_SHR(3,x))
61
62 #define SHA256_SSIGMA_1(x) \
63 (SHA256_ROTR(17,x) ^ SHA256_ROTR(19,x) ^ SHA256_SHR(10,x))
64
65
66 /*---------------------------------------------------------------------------*/
67
68 /*---------------------------------------------------------------------------*
69 SHA-256 Constant table
70 *---------------------------------------------------------------------------*/
71 #if !defined(MATH_SHA256_ASM)
72 static u32 MATH_SHA256iConst[64] =
73 #else
74 u32 MATH_SHA256iConst[64] =
75 #endif
76 {
77 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
78 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
79 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
80 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
81 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
82 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
83 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
84 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
85 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
86 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
87 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
88 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
89 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
90 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
91 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
92 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
93 };
94
95
96 /*---------------------------------------------------------------------------*
97 Name: NETRotateLeft32
98
99 Description: Bit-rotates the 32-bit value
100
101 Arguments: shift Rotation bit count
102 value Rotated value
103
104 Returns: Rotated 32-bit value
105 *---------------------------------------------------------------------------*/
NETRotateLeft32(int shift,u32 value)106 inline static u32 NETRotateLeft32(int shift, u32 value)
107 {
108 return (u32)((value << shift) | (value >> (u32)(32 - shift)));
109 }
110
111 /*---------------------------------------------------------------------------*
112 Name: MATH_SHA256Init
113
114 Description: Initializes the MATHSHA256Context structure used for finding the SHA-256 value.
115
116 Arguments: context: MATHSHA256Context structure
117
118 Returns: None.
119 *---------------------------------------------------------------------------*/
120 void
MATH_SHA256Init(MATHSHA256Context * context)121 MATH_SHA256Init(MATHSHA256Context* context)
122 {
123 context->Nl = 0;
124 context->Nh = 0;
125 context->num = 0;
126 context->h[0] = 0x6a09e667;
127 context->h[1] = 0xbb67ae85;
128 context->h[2] = 0x3c6ef372;
129 context->h[3] = 0xa54ff53a;
130 context->h[4] = 0x510e527f;
131 context->h[5] = 0x9b05688c;
132 context->h[6] = 0x1f83d9ab;
133 context->h[7] = 0x5be0cd19;
134 }
135
136 /*---------------------------------------------------------------------------*
137 Name: MATH_SHA256Update
138
139 Description: Updates the SHA-256 value with added data.
140
141 Arguments: context: MATHSHA256Context structure
142 input: Pointer to input data.
143 length: Length of input data.
144
145 Returns: None.
146 *---------------------------------------------------------------------------*/
147 void
MATH_SHA256Update(MATHSHA256Context * context,const void * input,u32 length)148 MATH_SHA256Update(MATHSHA256Context* context, const void* input, u32 length)
149 {
150 while (length > 0)
151 {
152 /* Fill data to the block margins */
153 u32 rest = MATHSHA256_CBLOCK - (u32)context->num;
154 u8 *dat;
155 if (rest > length)
156 {
157 rest = length;
158 }
159 dat = (u8*)context->data;
160 (void)memcpy(&dat[context->num], input, rest);
161 input = (const u8 *)input + rest;
162 length -= rest;
163 context->num += rest;
164 /* Execute the hash calculation if the block has expired. */
165 if (context->num >= MATHSHA256_CBLOCK)
166 {
167 MATH_SHA256iProcessBlock(context);
168 context->num = 0;
169 ++context->Nl;
170 if (!context->Nl)
171 {
172 ++context->Nh;
173 }
174 }
175 }
176 }
177
178 #if (NOT_USE_SHA256FILL == 0)
179 /*---------------------------------------------------------------------------*
180 Name: MATH_SHA256Fill
181
182 Description: Update with continuous data of fixed values that specified SHA-256.
183
184 Arguments: context: MATHSHA256Context structure
185 input u8 value to be input as continuous data
186 length: Length of input data.
187
188 Returns: None.
189 *---------------------------------------------------------------------------*/
190 static void
MATH_SHA256Fill(MATHSHA256Context * context,u8 input,u32 length)191 MATH_SHA256Fill(MATHSHA256Context* context, u8 input, u32 length)
192 {
193 while (length > 0)
194 {
195 /* Fill data to the block margins */
196 u32 rest = MATHSHA256_CBLOCK - (u32)context->num;
197 u8 *dat;
198 if (rest > length)
199 {
200 rest = length;
201 }
202 dat = (u8*)context->data;
203 (void)memset(&dat[context->num], input, rest);
204 length -= rest;
205 context->num += rest;
206 /* Execute the hash calculation if the block has expired. */
207 if (context->num >= MATHSHA256_CBLOCK)
208 {
209 MATH_SHA256iProcessBlock(context);
210 context->num = 0;
211 ++context->Nl;
212 if (!context->Nl)
213 {
214 ++context->Nh;
215 }
216 }
217 }
218 }
219 #endif /* (NOT_USE_SHA256FILL == 0) */
220
221 /*---------------------------------------------------------------------------*
222 Name: MATH_SHA256GetDigest
223
224 Description: Gets the final SHA-256 value.
225
226 Arguments: context: MATHSHA256Context structure
227 digest: Pointer to the location where SHA-256 is stored.
228
229 Returns: None.
230 *---------------------------------------------------------------------------*/
231 #if (NOT_USE_SHA256FILL == 1)
232 static u8 padding[64] =
233 {
234 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
235 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
236 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
237 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
238 };
239 #endif
240 void
MATH_SHA256GetHash(MATHSHA256Context * context,void * digest)241 MATH_SHA256GetHash(MATHSHA256Context *context, void *digest)
242 {
243 /* Method for filling packets is the same as SHA-1 */
244 u32 footer[2];
245 static const u8 padlead[1] = { 0x80 };
246 static const u8 padalign[sizeof(footer)] = { 0x00, };
247 /* setup footer field (in bits, big endian) */
248 footer[1] = NETConvert32HToBE((u32)
249 (context->Nl << (6 + 3)) + (context->num << (0 + 3)));
250 footer[0] = NETConvert32HToBE((u32)
251 (context->Nh << (6 + 3)) + (context->Nl >> (u32)(32 - (6 + 3))));
252 #if (NOT_USE_SHA256FILL == 0)
253 /* add leading padbyte '0x80' */
254 MATH_SHA256Update(context, padlead, sizeof(padlead));
255 /* if necessary, add 2 padblocks */
256 if (MATHSHA256_CBLOCK - context->num < sizeof(footer))
257 {
258 MATH_SHA256Update(context, padalign, MATHSHA256_CBLOCK - (u32)context->num);
259 }
260 /* add trailing padbytes '0x00' */
261 MATH_SHA256Fill(context, 0x00, MATHSHA256_CBLOCK - context->num - sizeof(footer));
262 /* add footer length */
263 MATH_SHA256Update(context, footer, sizeof(footer));
264 #else /* (NOT_USE_SHA256FILL == 1) */
265 {
266 u32 last, padn;
267
268 last = context->num;
269 padn = (last < 56) ? (56 - last) : (120 - last);
270 MATH_SHA256Update(context, padding, padn);
271 MATH_SHA256Update(context, footer, sizeof(footer));
272 }
273 #endif /* (NOT_USE_SHA256FILL == 1) */
274 /* copy registers to the dst */
275 context->h[0] = NETConvert32HToBE((u32)context->h[0]);
276 context->h[1] = NETConvert32HToBE((u32)context->h[1]);
277 context->h[2] = NETConvert32HToBE((u32)context->h[2]);
278 context->h[3] = NETConvert32HToBE((u32)context->h[3]);
279 context->h[4] = NETConvert32HToBE((u32)context->h[4]);
280 context->h[5] = NETConvert32HToBE((u32)context->h[5]);
281 context->h[6] = NETConvert32HToBE((u32)context->h[6]);
282 context->h[7] = NETConvert32HToBE((u32)context->h[7]);
283 (void)memcpy(digest, &context->h, MATHSHA256_DIGEST_LENGTH);
284 }
285
286 #if 0
287 /*---------------------------------------------------------------------------*
288 Name: NETGetSHA256Interface
289
290 Description: Gets the hash interface for SHA256.
291
292 Arguments: None.
293
294 Returns: Hash interface for SHA256
295 *---------------------------------------------------------------------------*/
296 const NETHashInterface* NETGetSHA256Interface(void)
297 {
298 static const NETHashInterface sha1template =
299 {
300 MATHSHA256_DIGEST_LENGTH,
301 MATHSHA256_CBLOCK,
302 sizeof(MATHSHA256Context),
303 NULL,
304 (void (*)(void*))MATH_SHA256Init,
305 (void (*)(void*, const void*, u32))MATH_SHA256Update,
306 (void (*)(void*, void *))MATH_SHA256GetDigest,
307 };
308 return &sha1template;
309 }
310 #endif
311
312 #if !defined(MATH_SHA256_ASM)
313 /*---------------------------------------------------------------------------*
314 Name: MATH_SHA256iProcessBlock
315
316 Description: Calculate hash using 1 block that expired in the SHA-256 context.
317
318 Arguments: context: MATHSHA256Context structure
319
320 Returns: None.
321 *---------------------------------------------------------------------------*/
MATH_SHA256iProcessBlock(MATHSHA256Context * context)322 static void MATH_SHA256iProcessBlock(MATHSHA256Context *context)
323 {
324 u32 a = context->h[0];
325 u32 b = context->h[1];
326 u32 c = context->h[2];
327 u32 d = context->h[3];
328 u32 e = context->h[4];
329 u32 f = context->h[5];
330 u32 g = context->h[6];
331 u32 h = context->h[7];
332 u32 w[64];
333 u32 tmp1, tmp2;
334 u32 *prev;
335
336 int t;
337 for (t = 0; t < 16; ++t)
338 {
339 w[t] = NETConvert32HToBE(((u32*)context->data)[t]);
340 }
341
342 for (; t < 64; ++t)
343 {
344 prev = &w[t - 16];
345 w[t] = prev[ 0]
346 + SHA256_SSIGMA_0(prev[ 1])
347 + prev[ 9]
348 + SHA256_SSIGMA_1(prev[14]);
349 }
350
351 for (t = 0; t < 64; ++t)
352 {
353 tmp1 = h
354 + SHA256_LSIGMA_1(e)
355 + SHA256_CH(e,f,g)
356 + MATH_SHA256iConst[t]
357 + w[t];
358
359 tmp2 = SHA256_LSIGMA_0(a)
360 + SHA256_MAJ(a,b,c);
361
362 h = g;
363 g = f;
364 f = e;
365 e = d + tmp1;
366 d = c;
367 c = b;
368 b = a;
369 a = tmp1 + tmp2;
370 }
371
372 context->h[0] += a;
373 context->h[1] += b;
374 context->h[2] += c;
375 context->h[3] += d;
376 context->h[4] += e;
377 context->h[5] += f;
378 context->h[6] += g;
379 context->h[7] += h;
380 }
381 #endif /* !defined(MATH_SHA256_ASM) */
382
383
384 /*---------------------------------------------------------------------------*
385 Name: MATH_CalcSHA256
386
387 Description: Calculates SHA-256.
388
389 Arguments: digest: Pointer to the location where SHA-256 is stored.
390 data: Pointer to input data.
391 dataLength: Length of input data.
392
393 Returns: None.
394 *---------------------------------------------------------------------------*/
MATH_CalcSHA256(void * digest,const void * data,u32 dataLength)395 void MATH_CalcSHA256(void *digest, const void *data, u32 dataLength)
396 {
397 MATHSHA256Context context;
398 MATH_SHA256Init(&context);
399 MATH_SHA256Update(&context, data, dataLength);
400 MATH_SHA256GetHash(&context, digest);
401 }
402
403
404
405 // HMAC
406
407 /*---------------------------------------------------------------------------*
408 Name: MATH_CalcHMACSHA256
409
410 Description: Calculates HMAC-SHA-256.
411
412 Arguments: digest: Pointer to the location where the HMAC-SHA-256 value is stored.
413 data: Pointer to input data.
414 dataLength: Length of input data.
415 key: Pointer to the key
416 keyLength: Length of the key
417
418 Returns: None.
419 *---------------------------------------------------------------------------*/
MATH_CalcHMACSHA256(void * digest,const void * bin_ptr,u32 bin_len,const void * key_ptr,u32 key_len)420 void MATH_CalcHMACSHA256(void *digest, const void *bin_ptr, u32 bin_len, const void *key_ptr, u32 key_len)
421 {
422 MATHSHA256Context context;
423 unsigned char hash_buf[ MATH_SHA256_DIGEST_SIZE ]; /* Hash value gotten from the hash function */
424
425 MATHiHMACFuncs hash2funcs = {
426 MATH_SHA256_DIGEST_SIZE,
427 (512/8),
428 };
429
430 hash2funcs.context = &context;
431 hash2funcs.hash_buf = hash_buf;
432 hash2funcs.HashReset = (void (*)(void*)) MATH_SHA256Init;
433 hash2funcs.HashSetSource = (void (*)(void*, const void*, u32)) MATH_SHA256Update;
434 hash2funcs.HashGetDigest = (void (*)(void*, void*)) MATH_SHA256GetHash;
435
436 MATHi_CalcHMAC(digest, bin_ptr, bin_len, key_ptr, key_len, &hash2funcs);
437 }
438
439 /*---------------------------------------------------------------------------*/
440