1 /*---------------------------------------------------------------------------*
2   Project:  NitroSDK - CRYPTO - demos
3   File:     main.c
4 
5   Copyright 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   This demo confirms that the CRYPTO library's RSA electronic signature functions operate properly.
19  *---------------------------------------------------------------------------*/
20 
21 #include <nitro.h>
22 #include <nitro/crypto.h>
23 #include <string.h>
24 #include "DEMO.h"
25 
26 //#define PRINT_ALLOCATION
27 //#define PRINT_TIME
28 
29 extern const unsigned char rsa1024_pub[], rsa1024_sec[];
30 extern const unsigned long rsa1024_pub_len, rsa1024_sec_len;
31 
32 static void InitializeAllocateSystem(void);
33 static void VBlankIntr(void);
34 static void DisplayInit(void);
35 static void FillScreen(u16 col);
36 static BOOL RsaTest(void);
37 static BOOL sign_verify( char *teststr, void *pubkey, void *seckey, const unsigned long seckey_len );
38 static u32 GetStringLength(char* str);
39 static void PrintBinary(u8* ptr, int len);
40 
41 /*---------------------------------------------------------------------------*
42     Variable Definitions
43  *---------------------------------------------------------------------------*/
44 
45 #ifdef PRINT_ALLOCATION
46 static u32 total_allocated_size = 0;
47 #endif
48 
49 static const unsigned char rsa512_pub[]={
50     0x30, 0x5C, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05,
51     0x00, 0x03, 0x4B, 0x00, 0x30, 0x48, 0x02, 0x41, 0x00, 0xAA, 0x3D, 0x39, 0x23, 0x81, 0x1E, 0x04,
52     0xDB, 0x25, 0x91, 0xE4, 0x15, 0xA5, 0x3A, 0x9A, 0xCF, 0x64, 0x7F, 0x2F, 0xD6, 0x03, 0xB1, 0x6C,
53     0xA4, 0x1E, 0x6A, 0x4D, 0x7C, 0x9A, 0x02, 0x7D, 0x9A, 0x8E, 0xF9, 0x8F, 0x61, 0x9C, 0x0E, 0x42,
54     0x49, 0x58, 0xBB, 0x96, 0xB1, 0x1F, 0x7C, 0xCA, 0x7B, 0x2A, 0x75, 0x3A, 0x6C, 0x82, 0x4F, 0xF9,
55     0xF5, 0xB2, 0x11, 0xB7, 0xC4, 0xCC, 0xF9, 0x6D, 0xE7, 0x02, 0x03, 0x01, 0x00, 0x01
56 };
57 static const int rsa512_pub_len = 0x5E;
58 
59 static const unsigned char rsa512_sec[]={
60     0x30, 0x82, 0x01, 0x3A, 0x02, 0x01, 0x00, 0x02, 0x41, 0x00, 0xAA, 0x3D, 0x39, 0x23, 0x81, 0x1E,
61     0x04, 0xDB, 0x25, 0x91, 0xE4, 0x15, 0xA5, 0x3A, 0x9A, 0xCF, 0x64, 0x7F, 0x2F, 0xD6, 0x03, 0xB1,
62     0x6C, 0xA4, 0x1E, 0x6A, 0x4D, 0x7C, 0x9A, 0x02, 0x7D, 0x9A, 0x8E, 0xF9, 0x8F, 0x61, 0x9C, 0x0E,
63     0x42, 0x49, 0x58, 0xBB, 0x96, 0xB1, 0x1F, 0x7C, 0xCA, 0x7B, 0x2A, 0x75, 0x3A, 0x6C, 0x82, 0x4F,
64     0xF9, 0xF5, 0xB2, 0x11, 0xB7, 0xC4, 0xCC, 0xF9, 0x6D, 0xE7, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02,
65     0x40, 0x75, 0x8E, 0xA1, 0x8E, 0x6A, 0xF3, 0x17, 0xD7, 0x5D, 0x32, 0x49, 0x96, 0xC8, 0xEA, 0x97,
66     0x4C, 0xEF, 0xD1, 0x04, 0x6F, 0x7D, 0x4D, 0x60, 0x00, 0x55, 0x20, 0x83, 0x31, 0xB0, 0x08, 0x58,
67     0x42, 0xEA, 0x75, 0x28, 0xB7, 0xB7, 0x44, 0xA7, 0x03, 0xF8, 0xEC, 0x80, 0x67, 0xD2, 0xF5, 0x44,
68     0x14, 0x77, 0x7D, 0x3F, 0xE7, 0x12, 0x2C, 0xAB, 0xE8, 0xBA, 0x52, 0x0E, 0xD5, 0x1F, 0xE5, 0xC1,
69     0x81, 0x02, 0x21, 0x00, 0xD1, 0xE4, 0x7B, 0xDE, 0x44, 0xE2, 0x4E, 0x03, 0xE5, 0x74, 0xCD, 0x89,
70     0xFD, 0x15, 0x8A, 0xD8, 0xAE, 0xF4, 0x67, 0x87, 0xCF, 0x65, 0x52, 0x3C, 0x23, 0x13, 0x2B, 0xE9,
71     0x97, 0x33, 0x26, 0x69, 0x02, 0x21, 0x00, 0xCF, 0xA2, 0xCA, 0xF1, 0x9F, 0xB0, 0x49, 0x1E, 0x4E,
72     0x64, 0x5F, 0xC7, 0x21, 0xE0, 0x71, 0x7E, 0x93, 0x7A, 0x5B, 0x20, 0xB1, 0x89, 0xAF, 0xF9, 0xC8,
73     0x96, 0x23, 0xBB, 0x72, 0xFC, 0x87, 0xCF, 0x02, 0x21, 0x00, 0xA8, 0xF7, 0x3C, 0x58, 0x44, 0x2F,
74     0xC2, 0x0A, 0x14, 0xEF, 0xA0, 0x7F, 0x13, 0x04, 0x02, 0x90, 0x48, 0xD7, 0x6B, 0x78, 0xC3, 0x16,
75     0x97, 0xCA, 0xDD, 0x99, 0x93, 0x62, 0x2A, 0x5B, 0xFC, 0xF1, 0x02, 0x20, 0x11, 0x44, 0x4E, 0x70,
76     0x2D, 0x81, 0x71, 0x73, 0x2D, 0xBD, 0xB7, 0x21, 0x4E, 0x35, 0xE5, 0xFA, 0x4A, 0xB5, 0x60, 0x22,
77     0xA5, 0xE0, 0xF7, 0x5B, 0x64, 0x4C, 0xE8, 0x07, 0xCC, 0x96, 0x27, 0x8D, 0x02, 0x20, 0x42, 0xEA,
78     0x98, 0x73, 0x96, 0x3E, 0xAC, 0x03, 0x3B, 0x19, 0xD0, 0xB7, 0x29, 0x11, 0x94, 0x25, 0x0E, 0x98,
79     0xC4, 0x7C, 0xA5, 0x95, 0x64, 0x02, 0x34, 0xB8, 0x4B, 0x66, 0x1E, 0x7B, 0x99, 0xB4
80 };
81 static const int rsa512_sec_len = 0x13E;
82 
83 
84 /*---------------------------------------------------------------------------*
85     Function definitions
86  *---------------------------------------------------------------------------*/
87 
88 /*---------------------------------------------------------------------------*
89   Name:         MyAlloc
90 
91   Description:  OS_Alloc wrapper function.
92  *---------------------------------------------------------------------------*/
MyAlloc(u32 size)93 static void* MyAlloc(u32 size)
94 {
95     void* ptr;
96 #ifdef PRINT_ALLOCATION
97     ptr = OS_Alloc(size+4);
98     *(u32*)ptr = size;
99     (u8*)ptr += 4;
100     total_allocated_size += size;
101     OS_TPrintf("Allocate %d bytes from %p: total %d bytes\n", size, ptr, total_allocated_size);
102 #else
103     ptr = OS_Alloc(size);
104 #endif
105     return ptr;
106 }
107 
108 /*---------------------------------------------------------------------------*
109   Name:         MyFree
110 
111   Description:  OS_Free wrapper function.
112  *---------------------------------------------------------------------------*/
MyFree(void * ptr)113 static void MyFree(void* ptr)
114 {
115 #ifdef PRINT_ALLOCATION
116     u32 size;
117     (u8*)ptr -= 4;
118     size = *(u32*)ptr;
119     total_allocated_size -= size;
120     OS_TPrintf("Free %d bytes from %p: total %d bytes\n", size, ptr, total_allocated_size);
121 #endif
122     OS_Free(ptr);
123 }
124 
125 /*---------------------------------------------------------------------------*
126   Name:         MyRealloc
127 
128   Description:  The realloc function.
129  *---------------------------------------------------------------------------*/
130 #ifndef MIN
131 #define MIN(a, b) (((a) < (b)) ? (a) : (b))
132 #endif
133 
MyRealloc(void * ptr,u32 new_size,u32 old_size)134 static void* MyRealloc(void* ptr, u32 new_size, u32 old_size)
135 {
136     void *buf;
137 #ifdef PRINT_ALLOCATION
138     u32 size;
139 
140 	buf = OS_Alloc(new_size+4);
141     *(u32*)buf = new_size;
142     (u8*)buf += 4;
143     total_allocated_size += new_size;
144     OS_TPrintf("Reallocate %d bytes from %p: total %d bytes\n", new_size, ptr, total_allocated_size);
145 
146     (u8*)ptr -= 4;
147     size = *(u32*)ptr;
148     total_allocated_size -= size;
149     OS_TPrintf("Free(for realloc) %d bytes from %p: total %d bytes\n", size, ptr, total_allocated_size);
150 	SDK_ASSERT(size == old_size);
151     OS_Free(ptr);
152 #else
153     if ((buf = OS_Alloc(new_size)) == NULL)
154     {
155         return NULL;
156     }
157 
158     MI_CpuCopy8(ptr, buf, MIN(new_size, old_size));
159     OS_Free(ptr);
160 #endif
161 
162     return buf;
163 }
164 
165 /*---------------------------------------------------------------------------*
166   Name:         NitroMain
167 
168   Description:  Initialization and main loop.
169 
170   Arguments:    None.
171 
172   Returns:      None.
173  *---------------------------------------------------------------------------*/
NitroMain(void)174 void NitroMain(void)
175 {
176     // Various types of initialization
177     OS_Init();
178     InitializeAllocateSystem();
179 
180     // When in NITRO mode, stopped by Panic
181     DEMOCheckRunOnTWL();
182 
183     DisplayInit();
184 
185     if (RsaTest())
186     {
187         // Success
188         OS_TPrintf("------ Test Succeeded ------\n");
189         FillScreen(GX_RGB(0, 31, 0));
190     }
191     else
192     {
193         // Failed
194         OS_TPrintf("****** Test Failed ******\n");
195         FillScreen(GX_RGB(31, 0, 0));
196     }
197 
198     // Main loop
199     while (TRUE)
200     {
201         // Waiting for the V-Blank
202         OS_WaitVBlankIntr();
203     }
204 }
205 
206 /*---------------------------------------------------------------------------*
207   Name:         VBlankIntr
208 
209   Description:  V-Blank interrupt vector.
210 
211   Arguments:    None.
212 
213   Returns:      None.
214  *---------------------------------------------------------------------------*/
VBlankIntr(void)215 static void VBlankIntr(void)
216 {
217     // Sets the IRQ check flag
218     OS_SetIrqCheckFlag(OS_IE_V_BLANK);
219 }
220 
221 /*---------------------------------------------------------------------------*
222   Name:         InitializeAllocateSystem
223 
224   Description:  Initializes the memory allocation system within the main memory arena.
225 
226   Arguments:    None.
227 
228   Returns:      None.
229  *---------------------------------------------------------------------------*/
InitializeAllocateSystem(void)230 static void InitializeAllocateSystem(void)
231 {
232     void *tempLo;
233     OSHeapHandle hh;
234 
235     tempLo = OS_InitAlloc(OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi(), 1);
236     OS_SetArenaLo(OS_ARENA_MAIN, tempLo);
237     hh = OS_CreateHeap(OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi());
238     if (hh < 0)
239     {
240         OS_Panic("ARM9: Fail to create heap...\n");
241     }
242     hh = OS_SetCurrentHeap(OS_ARENA_MAIN, hh);
243 }
244 
245 /*---------------------------------------------------------------------------*
246   Name:         DisplayInit
247 
248   Description:  Graphics initialization.
249 
250   Arguments:    None.
251 
252   Returns:      None.
253  *---------------------------------------------------------------------------*/
DisplayInit(void)254 static void DisplayInit(void)
255 {
256 
257     GX_Init();
258     FX_Init();
259 
260     GX_DispOff();
261     GXS_DispOff();
262 
263     GX_SetDispSelect(GX_DISP_SELECT_SUB_MAIN);
264 
265     OS_SetIrqFunction(OS_IE_V_BLANK, VBlankIntr);
266     (void)OS_EnableIrqMask(OS_IE_V_BLANK);
267     (void)GX_VBlankIntr(TRUE);         // To generate V-Blank interrupt request
268     (void)OS_EnableIrq();
269 
270 
271     GX_SetBankForLCDC(GX_VRAM_LCDC_ALL);
272     MI_CpuClearFast((void *)HW_LCDC_VRAM, HW_LCDC_VRAM_SIZE);
273 
274     MI_CpuFillFast((void *)HW_OAM, 192, HW_OAM_SIZE);   // Clear OAM
275     MI_CpuClearFast((void *)HW_PLTT, HW_PLTT_SIZE);     // Clear the standard palette
276 
277     MI_CpuFillFast((void *)HW_DB_OAM, 192, HW_DB_OAM_SIZE);     // Clear OAM
278     MI_CpuClearFast((void *)HW_DB_PLTT, HW_DB_PLTT_SIZE);       // Clear the standard palette
279     MI_DmaFill32(3, (void *)HW_LCDC_VRAM_C, 0x7FFF7FFF, 256 * 192 * sizeof(u16));
280 
281 
282     GX_SetBankForOBJ(GX_VRAM_OBJ_256_AB);       // Set VRAM-A, B for OBJ
283 
284     GX_SetGraphicsMode(GX_DISPMODE_VRAM_C,      // VRAM mode
285                        (GXBGMode)0,    // Dummy
286                        (GXBG0As)0);    // Dummy
287 
288     GX_SetVisiblePlane(GX_PLANEMASK_OBJ);       // Make OBJ visible
289     GX_SetOBJVRamModeBmp(GX_OBJVRAMMODE_BMP_1D_128K);   // 2D mapping OBJ
290 
291     OS_WaitVBlankIntr();              // Waiting for the end of the V-Blank interrupt
292     GX_DispOn();
293 
294 }
295 
296 
297 /*---------------------------------------------------------------------------*
298   Name:         FillScreen
299 
300   Description:  Fills the screen.
301 
302   Arguments:    col: FillColor
303 
304   Returns:      None.
305  *---------------------------------------------------------------------------*/
FillScreen(u16 col)306 static void FillScreen(u16 col)
307 {
308     MI_CpuFill16((void *)HW_LCDC_VRAM_C, col, 256 * 192 * 2);
309 }
310 
311 /*---------------------------------------------------------------------------*
312   Name:         RsaTest
313 
314   Description:  Test routine for the electronic signature functions.
315 
316   Arguments:    None.
317 
318   Returns:      TRUE if test succeeds.
319  *---------------------------------------------------------------------------*/
320 #define PrintResultEq( a, b, f ) \
321     { OS_TPrintf( ((a) == (b)) ? "[--OK--] " : "[**NG**] " ); (f) = (f) && ((a) == (b)); }
322 
323 #define CheckAndPrintErr( result, str ) \
324     { if(OS_IsRunOnTwl() == TRUE){      \
325           if(result < 0) { OS_TPrintf( "Error: %d (%s)\n", result, str ); return FALSE;}  \
326       }else{                            \
327           if(result >= 0){ OS_TPrintf( "Error: %d (%s)\n", result, str ); return FALSE;}  \
328       }  \
329     }
330 
RsaTest(void)331 static BOOL RsaTest(void)
332 {
333     BOOL flag = TRUE;
334 
335     // Perform electronic signature operation test
336     {
337         char teststr[] = "Copyright 2003-2005 Nintendo.  All rights reserved.";
338 		BOOL ret;
339 
340         CRYPTO_SetMemAllocator(MyAlloc, MyFree, MyRealloc);
341 
342         /* RSA sign and verify */
343 		ret = sign_verify(teststr, (void *)rsa1024_pub, (void *)rsa1024_sec, rsa1024_sec_len);
344 		PrintResultEq(ret, TRUE, flag);	OS_TPrintf("RSA sign test\n");
345     }
346 
347 
348     return flag;
349 }
350 
sign_verify(char * teststr,void * pubkey,void * seckey,const unsigned long seckey_len)351 static BOOL sign_verify( char *teststr, void *pubkey,
352 								void *seckey, const unsigned long seckey_len )
353 {
354 	char                         signstr[144];
355 	unsigned char                *mod_ptr;
356     s32                          result;
357 	s32                          len;
358     CRYPTORSASignContext         context;
359     CRYPTORSASignInitParam       signinitparam;
360     CRYPTORSASignParam           signparam;
361 #ifdef PRINT_TIME
362     OSTick                       begin, end, term;
363 #endif
364 
365 #ifdef PRINT_TIME
366 	begin = OS_GetTick();
367 #endif
368 
369     /* RSA sign */
370     signinitparam.key     = (void*)seckey;
371     signinitparam.key_len = seckey_len;
372     result = CRYPTO_RSA_SignInit(&context, &signinitparam);
373     CheckAndPrintErr(result, "CRYPTO_RSA_SignInit");
374 
375     signparam.in      = teststr;
376     signparam.in_len  = strlen(teststr);
377     signparam.out     = signstr;
378     signparam.out_size = sizeof(signstr);
379     len = CRYPTO_RSA_Sign(&context, &signparam);
380     CheckAndPrintErr(len, "CRYPTO_RSA_Sign");
381 
382     result = CRYPTO_RSA_SignTerminate(&context);
383     CheckAndPrintErr(result, "CRYPTO_RSA_SignTerminate");
384 
385 #ifdef PRINT_TIME
386     end = OS_GetTick();
387 	term = OS_TicksToMicroSeconds(end - begin);
388     OS_TPrintf("   RSA sign: %d.%03d ms - %d tick\n", (u32)(term/1000), (u32)(term%1000), term);
389 
390 	begin = OS_GetTick();
391 #endif
392 
393 	if(OS_IsRunOnTwl() == FALSE){
394 		return TRUE;
395 	}
396 
397     /* SIGN verify */
398 	if((mod_ptr = CRYPTO_SIGN_GetModulus(pubkey)) == NULL)
399 	{
400 		OS_TPrintf( "Error: pubkey modulus find error . (CRYPTO_SIGN_GetModulus)\n" );
401 		return FALSE;
402 	}
403 	if(CRYPTO_VerifySignature(teststr, (int)strlen(teststr), signstr, mod_ptr) == FALSE)
404 	{
405 		OS_TPrintf( "Error: SIGN verify error . (CRYPTO_VerifySignature)\n" );
406 		return FALSE;
407 	}
408 
409 #ifdef PRINT_TIME
410     end = OS_GetTick();
411 	term = OS_TicksToMicroSeconds(end - begin);
412     OS_TPrintf("   SIGN verify: %d.%03d ms - %d tick\n", (u32)(term/1000), (u32)(term%1000), term);
413 #endif
414 
415 	return TRUE;
416 }
417 
418 
419 /*---------------------------------------------------------------------------*
420   Name:         GetStringLength
421 
422   Description:  Gets the length of a string.
423 
424   Arguments:    str: Pointer to a string
425 
426   Returns:      Length of string
427  *---------------------------------------------------------------------------*/
GetStringLength(char * str)428 static u32 GetStringLength(char* str)
429 {
430     u32 i;
431     for (i = 0; ; i++)
432     {
433         if (*(str++) == '\0')
434         {
435             return i;
436         }
437     }
438 }
439 
440 /*---------------------------------------------------------------------------*
441   Name:         PrintBinary
442 
443   Description:  binary string output
444 
445   Arguments:    ptr: Memory location to output
446                 len: Length to output
447 
448   Returns:      None.
449  *---------------------------------------------------------------------------*/
PrintBinary(u8 * ptr,int len)450 static void PrintBinary(u8* ptr, int len)
451 {
452 #ifndef SDK_FINALROM
453     int i;
454     for (i = 0; i < len; i++)
455     {
456         if (i != 0)
457         {
458             OS_PutString(":");
459         }
460         OS_TPrintf("%02x", ptr[i]);
461     }
462 #else
463 #pragma unused(ptr,len)
464 #endif
465     return;
466 }
467 
468 /*---------------------------------------------------------------------------*
469   End of file
470  *---------------------------------------------------------------------------*/
471