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