1 /*---------------------------------------------------------------------------*
2   Project:    NET demo
3   File:       crypto.c
4 
5   Copyright (C) 2006 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   $Log: crypto.c,v $
14   Revision 1.1  2006/10/27 08:03:46  yosizaki
15   initial upload.
16 
17   $NoKeywords: $
18  *---------------------------------------------------------------------------*/
19 #include <demo.h>
20 #include <revolution/net.h>
21 #include <string.h>
22 
23 
24 #define LINES           24
25 #define STACK_SIZE      4000
26 
27 static void DoReport(void);
28 static void* DoTest(void* arg);
29 
30 GXColor Black = {   0,   0,   0, 0 };
31 GXColor Blue  = {   0,   0, 192, 0 };
32 GXColor Red   = { 255,   0,   0, 0 };
33 GXColor Green = {   0, 224,   0, 0 };
34 GXColor White = { 255, 255, 255, 0 };
35 
36 GXColor SucceededGreen = {   0, 128,   0, 0 };
37 GXColor FailedRed      = { 128,   0,   0, 0 };
38 
39 static char ReportBuffer[4096];
40 static char PrintBuffer[4096];
41 
42 static OSThread testThread;
43 static u8 testThreadStack[STACK_SIZE] ATTRIBUTE_ALIGN(32);
44 
45 
46 /*---------------------------------------------------------------------------*
47   Application main loop
48  *---------------------------------------------------------------------------*/
main(void)49 void main(void)
50 {
51     DEMOInit(NULL);
52     if ( ! DEMOInitROMFont() )
53     {
54         OSHalt("DEMOInitROMFont()");
55     }
56 
57     // Clear EFB
58     GXSetCopyClear(Blue, GX_MAX_Z24);
59     GXCopyDisp(DEMOGetCurrentBuffer(), GX_TRUE);
60 
61     (void)OSReport("NET Demo: Test crypto functions\n");
62 
63     // Launch the test thread
64     if( ! OSCreateThread( &testThread, DoTest, NULL,
65                               (void*)((u32)testThreadStack + STACK_SIZE), STACK_SIZE,
66                               20, 0 ) )
67     {
68         OSHalt( "OSCrateThread()" );
69     }
70     if ( OSResumeThread( &testThread ) < 0 )
71     {
72         OSHalt( "OSResumeThread()" );
73     }
74 
75     while ( ! OSIsThreadTerminated(&testThread) )
76     {
77         DEMOBeforeRender();
78         DoReport();
79         DEMODoneRender();
80     }
81 
82     {
83         BOOL result;
84 
85         if( ! OSJoinThread( &testThread, (void**)&result ) )
86         {
87             OSHalt( "OSJoinThread()" );
88         }
89         if ( result )
90         {
91             // succeeded
92             OSReport("------ Test Succeeded ------\n");
93             GXSetCopyClear(SucceededGreen, GX_MAX_Z24);
94             GXCopyDisp(DEMOGetCurrentBuffer(), GX_TRUE);
95         }
96         else
97         {
98             // failed
99             OSReport("****** Test Failed ******\n");
100             GXSetCopyClear(FailedRed, GX_MAX_Z24);
101             GXCopyDisp(DEMOGetCurrentBuffer(), GX_TRUE);
102         }
103     }
104 
105     while ( TRUE )
106     {
107         DEMOBeforeRender();
108         DoReport();
109         DEMODoneRender();
110     }
111 }
112 
113 /*---------------------------------------------------------------------------*
114   Display Settings
115  *---------------------------------------------------------------------------*/
116 
DoReport(void)117 static void DoReport(void)
118 {
119     GXRenderModeObj* rmp;
120 
121     rmp = DEMOGetRenderModeObj();
122     DEMOInitCaption(DM_FT_XLU, (s16) rmp->fbWidth, (s16) rmp->efbHeight);
123     DEMOSetROMFontSize(16, -1);
124     (void)DEMORFPuts(25, 25, 0, ReportBuffer);
125 }
126 
127 // Define program-specific OSReport() function.
OSReport(const char * msg,...)128 void OSReport(const char* msg, ...)
129 {
130     BOOL    enabled;
131     va_list marker;
132     u32     len;
133     int     c;
134     char*   p;
135     char*   q;
136 
137     va_start(marker, msg);
138     (void)vsnprintf(PrintBuffer, sizeof(PrintBuffer)-1, msg, marker);
139     va_end(marker);
140     PrintBuffer[sizeof(PrintBuffer)-1] = 0;
141 
142     (void)printf("%s", PrintBuffer);
143 
144     enabled = OSDisableInterrupts();
145 
146     (void)strncat(ReportBuffer, PrintBuffer, sizeof(ReportBuffer)-1);
147     ReportBuffer[sizeof(ReportBuffer)-1] = 0;
148     len = strlen(ReportBuffer);
149 
150     c = 0;
151     q = ReportBuffer;
152     for (p = ReportBuffer; p < ReportBuffer + len; ++p)
153     {
154         if (*p == '\n')
155         {
156             ++c;
157             if (LINES <= c)
158             {
159                 q = strchr(q, '\n');
160             }
161         }
162     }
163     if (LINES <= c)
164     {
165         (void)memmove(ReportBuffer, q + 1, len - (q - ReportBuffer));
166     }
167 
168     (void)OSRestoreInterrupts(enabled);
169 }
170 
PrintBinary(const void * buffer,u32 length)171 inline static void PrintBinary(const void *buffer, u32 length)
172 {
173     u32     i;
174     for (i = 0; i < length; ++i)
175     {
176         OSReport("%02X ", ((const u8 *)buffer)[i]);
177     }
178 }
179 
180 
181 /*---------------------------------------------------------------------------*
182   Tests
183  *---------------------------------------------------------------------------*/
184 
185 #define PrintResultEq( a, b, f ) \
186     do { OSReport( ((a) == (b)) ? "[--OK--] " : "[**NG**] " ); (f) = (f) && ((a) == (b)); } while( FALSE )
187 #define PrintResultBinaryEq( a, b, l, f ) \
188     do { OSReport( (memcmp((a), (b), (l)) == 0) ? "[--OK--] " : "[**NG**] " ); (f) = (f) && (memcmp((a), (b), (l)) == 0); } while( FALSE )
189 
DoTest(void * arg)190 static void* DoTest(void* arg)
191 {
192     BOOL    flag = TRUE;
193     int     i;
194 
195     (void)arg;
196 
197     if (!NETLockCrypto())
198     {
199         OSHalt("failed to lock crypto");
200     }
201 
202     // Test AES-128
203     // see: FIPS-197 Appendix B and C
204     {
205         static const struct
206         {
207             u32         keylen; /* in bytes */
208             const char *key;
209             const char *plain;
210             const char *cipher;
211         }
212         samples[] =
213         {
214             {
215                 128 / 8,
216                 "\x2b\x7e\x15\x16\x28\xae\xd2\xa6"
217                 "\xab\xf7\x15\x88\x09\xcf\x4f\x3c",
218                 "\x32\x43\xf6\xa8\x88\x5a\x30\x8d\x31\x31\x98\xa2\xe0\x37\x07\x34",
219                 "\x39\x25\x84\x1d\x02\xdc\x09\xfb\xdc\x11\x85\x97\x19\x6a\x0b\x32",
220 
221             },
222             {
223                 128 / 8,
224                 "\x00\x01\x02\x03\x04\x05\x06\x07"
225                 "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
226                 "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
227                 "\x69\xc4\xe0\xd8\x6a\x7b\x04\x30\xd8\xcd\xb7\x80\x70\xb4\xc5\x5a",
228             },
229             {
230                 192 / 8,
231                 "\x00\x01\x02\x03\x04\x05\x06\x07"
232                 "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
233                 "\x10\x11\x12\x13\x14\x15\x16\x17",
234                 "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
235                 "\xdd\xa9\x7c\xa4\x86\x4c\xdf\xe0\x6e\xaf\x70\xa0\xec\x0d\x71\x91",
236             },
237             {
238                 256 / 8,
239                 "\x00\x01\x02\x03\x04\x05\x06\x07"
240                 "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
241                 "\x10\x11\x12\x13\x14\x15\x16\x17"
242                 "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
243                 "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
244                 "\x8e\xa2\xb7\xca\x51\x67\x45\xbf\xea\xfc\x49\x90\x4b\x49\x60\x89",
245             },
246         };
247 
248         for (i = 0; i < sizeof(samples) / sizeof(*samples); ++i)
249         {
250             NETAESContext    ctx[1];
251             u8                  iv[16];
252             u8                  enc[NET_AES_BLOCK_LENGTH];
253             u8                  dec[NET_AES_BLOCK_LENGTH];
254             BOOL                result;
255 
256             OSReport("\ntest[%d] : AES-%d\n", i + 1, samples[i].keylen * 8);
257 
258             (void)memset(iv, 0x00, sizeof(iv));
259             (void)memset(enc, 0x00, sizeof(iv));
260             (void)memset(dec, 0x00, sizeof(iv));
261             (void)NETAESCreate(ctx, samples[i].key, samples[i].keylen, iv);
262             (void)NETAESEncrypt(ctx, enc, samples[i].plain, sizeof(enc));
263             (void)NETAESDelete(ctx);
264             result = TRUE;
265             PrintResultBinaryEq(enc, samples[i].cipher, NET_AES_BLOCK_LENGTH, result);
266             flag &= result;
267             if (!result)
268             {
269                 OSReport("\nenc-answer:");
270                 PrintBinary(samples[i].cipher, NET_AES_BLOCK_LENGTH);
271                 OSReport("\nenc-result:");
272                 PrintBinary(enc, NET_AES_BLOCK_LENGTH);
273                 OSReport("\n");
274             }
275             (void)memset(iv, 0x00, sizeof(iv));
276             (void)NETAESCreate(ctx, samples[i].key, samples[i].keylen, iv);
277             (void)NETAESDecrypt(ctx, dec, enc, sizeof(dec));
278             (void)NETAESDelete(ctx);
279             result = TRUE;
280             PrintResultBinaryEq(dec, samples[i].plain, NET_AES_BLOCK_LENGTH, result);
281             flag &= result;
282             if (!result)
283             {
284                 OSReport("\ndec-answer:");
285                 PrintBinary(samples[i].plain, NET_AES_BLOCK_LENGTH);
286                 OSReport("\ndec-result:");
287                 PrintBinary(dec, NET_AES_BLOCK_LENGTH);
288                 OSReport("\n");
289             }
290             OSReport("\n");
291         }
292     }
293 
294     NETUnlockCrypto();
295 
296     return (void*)flag;
297 }
298