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