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