1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - aes - demos - ctr
3 File: main.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:: 2008-12-08#$
14 $Rev: 9567 $
15 $Author: hatamoto_minoru $
16 *---------------------------------------------------------------------------*/
17 #include <twl.h>
18 #include <twl/aes.h>
19
20
21 /*---------------------------------------------------------------------------*
22 Declare internal variables
23 *---------------------------------------------------------------------------*/
24
25 // Message queue used for waiting for the end of AES processing
26 #define DEMO_MESSAGE_Q_SIZE 1
27 static OSMessageQueue sMsgQ;
28 static OSMessage sMsgQBuffer[DEMO_MESSAGE_Q_SIZE];
29
30 // Sample data to encrypt
31 static const char DEMO_TEXT[] =
32 "These coded instructions, statements, and computer programs contain "
33 "proprietary information of Nintendo of America Inc. and/or Nintendo "
34 "Company Ltd., and are protected by Federal copyright law. They may "
35 "not be disclosed to third parties or copied or duplicated in any form, "
36 "in whole or in part, without the prior written consent of Nintendo.";
37
38 // Appropriate key to use for encryption
39 static const AESKey DEMO_KEY =
40 { 0xb3,0x2f,0x3a,0x91,0xe6,0x98,0xc2,0x76,
41 0x70,0x6d,0xfd,0x71,0xbc,0xdd,0xb3,0x93, };
42
43
44
45 /*---------------------------------------------------------------------------*
46 Internal function declarations
47 *---------------------------------------------------------------------------*/
48
49 static void DEMO_InitInteruptSystem(void);
50 static void DEMO_InitAllocSystem(void);
51 static void DEMO_AESCallback(AESResult result, void* arg);
52 static AESResult DEMO_WaitAes(OSMessageQueue* pQ);
53 static void DEMO_PrintBytes(const void* pvoid, u32 size);
54
55
56
57 /*---------------------------------------------------------------------------*
58 Function definitions
59 *---------------------------------------------------------------------------*/
60
61 /*---------------------------------------------------------------------------*
62 Name: SampleMain
63
64 Description: The main body of the sample.
65
66 Arguments: None.
67
68 Returns: Whether sample processing succeeded.
69 *---------------------------------------------------------------------------*/
SampleMain(void)70 static BOOL SampleMain(void)
71 {
72 BOOL bSuccess = FALSE;
73
74 AESResult aesResult;
75 AESCounter counter;
76 const char* pPlainText = DEMO_TEXT;
77 void* pEncrypted;
78 void* pDecrypted;
79 u32 srcSize;
80
81 // Initialize the message queue for waiting on AES processing
82 OS_InitMessageQueue(&sMsgQ, sMsgQBuffer, DEMO_MESSAGE_Q_SIZE);
83
84 // Allocate the buffer to store encrypted/decrypted data.
85 // Data size doesn't change with encryption/decryption.
86 srcSize = (u32)STD_GetStringLength(pPlainText) + 1;
87 pEncrypted = OS_Alloc(srcSize);
88 pDecrypted = OS_Alloc(srcSize);
89
90 if( ! SDK_IS_VALID_POINTER(pEncrypted)
91 || ! SDK_IS_VALID_POINTER(pDecrypted) )
92 {
93 OS_TPrintf("fail to OS_Alloc\n");
94 return FALSE;
95 }
96
97 // The first AES function to call must be AES_Init
98 AES_Init();
99
100 // The AES_Rand function is used to generate the initial counter value.
101 // The initial counter value can be any number, but you must avoid ever reusing values if at all possible.
102 //
103 aesResult = AES_Rand(&counter, sizeof(counter));
104 if( aesResult != AES_RESULT_SUCCESS )
105 {
106 OS_TPrintf("AES_Rand failed(%d)", aesResult);
107 goto error_exit;
108 }
109
110 // Configure the encryption key
111 aesResult = AES_SetKey(&DEMO_KEY);
112 if( aesResult != AES_RESULT_SUCCESS )
113 {
114 OS_TPrintf("AES_SetKey failed(%d)", aesResult);
115 goto error_exit;
116 }
117
118
119 // Display parameters
120 OS_TPrintf("---- parameter -----------\n");
121 OS_TPrintf("-- key\n");
122 DEMO_PrintBytes(&DEMO_KEY, sizeof(DEMO_KEY));
123 OS_TPrintf("-- counter initial value\n");
124 DEMO_PrintBytes(&counter, sizeof(counter));
125
126
127 // Encryption
128 {
129 // Performs encryption in AES CTR Mode
130 aesResult = AES_CtrEncrypt( &counter, // Initial counter value
131 pPlainText, // Data to be encrypted
132 srcSize, // Size of the data to encrypt
133 pEncrypted, // Buffer that stores encrypted data
134 DEMO_AESCallback, // Callback called at completion
135 &sMsgQ ); // Callback parameters
136 if( aesResult != AES_RESULT_SUCCESS )
137 {
138 OS_TPrintf("AES_CtrEncrypt failed(%d)", aesResult);
139 goto error_exit;
140 }
141
142 // Wait for encryption to end
143 aesResult = DEMO_WaitAes(&sMsgQ);
144 if( aesResult != AES_RESULT_SUCCESS )
145 {
146 OS_TPrintf("AES_CtrEncrypt failed(%d)", aesResult);
147 goto error_exit;
148 }
149
150
151 // Display results
152 OS_TPrintf("---- encrypt -------------\n");
153 OS_TPrintf("-- plain text (ascii)\n");
154 OS_PutString(pPlainText); // Use OS_PutString because OS_*Printf has a limit of 256 characters
155 OS_TPrintf("\n");
156
157 OS_TPrintf("-- plain text (hex)\n");
158 DEMO_PrintBytes(pPlainText, srcSize);
159
160 OS_TPrintf("-- encrypted (hex)\n");
161 DEMO_PrintBytes(pEncrypted, srcSize);
162 }
163
164 // Decryption
165 {
166 // Performs decryption in AES CTR Mode
167 aesResult = AES_CtrDecrypt( &counter, // Initial counter value (must be the same as that used during encryption)
168 pEncrypted, // Data to be decrypted
169 srcSize, // Size of the data to decrypt
170 pDecrypted, // Buffer that stores decrypted data
171 DEMO_AESCallback, // Callback called at completion
172 &sMsgQ ); // Callback parameters
173 if( aesResult != AES_RESULT_SUCCESS )
174 {
175 OS_TPrintf("AES_CtrDecrypt failed(%d)", aesResult);
176 goto error_exit;
177 }
178
179 // Wait for decryption to end
180 aesResult = DEMO_WaitAes(&sMsgQ);
181 if( aesResult != AES_RESULT_SUCCESS )
182 {
183 OS_TPrintf("AES_CtrDecrypt failed(%d)", aesResult);
184 goto error_exit;
185 }
186
187
188 // Display results
189 OS_TPrintf("---- decrypt -------------\n");
190 OS_TPrintf("-- encrypted (hex)\n");
191 DEMO_PrintBytes(pEncrypted, srcSize);
192
193 OS_TPrintf("-- decrypted (hex)\n");
194 DEMO_PrintBytes(pDecrypted, srcSize);
195
196 OS_TPrintf("-- decrypted (ascii)\n");
197 OS_PutString(pDecrypted); // Use OS_PutString because OS_*Printf has a limit of 256 characters
198 OS_TPrintf("\n");
199 }
200
201 // Confirm that data that was encrypted, then decrypted, matches original
202 if( MI_CpuComp8(pDecrypted, pPlainText, srcSize) == 0 )
203 {
204 OS_TPrintf("** pDecrypted == pPlainText\n");
205 bSuccess = TRUE;
206 }
207 else
208 {
209 OS_TPrintf("** pDecrypted != pPlainText\n");
210 }
211
212 error_exit:
213 OS_Free(pDecrypted);
214 OS_Free(pEncrypted);
215
216 return bSuccess;
217 }
218
219
220 /*---------------------------------------------------------------------------*
221 Name: TwlMain
222
223 Description: The main function.
224
225 Arguments: None.
226
227 Returns: None.
228 *---------------------------------------------------------------------------*/
TwlMain(void)229 void TwlMain(void)
230 {
231 BOOL bSampleSucceeded = FALSE;
232
233 // Initialization
234 OS_Init();
235 DEMO_InitInteruptSystem();
236 DEMO_InitAllocSystem();
237 OS_TPrintf("*** start aes demo\n");
238
239
240 // Run demo
241 if( OS_IsRunOnTwl() )
242 {
243 bSampleSucceeded = SampleMain();
244 }
245 else
246 {
247 OS_Warning("demo is not run on TWL");
248 }
249
250
251 // Display demo run results
252 OS_TPrintf("*** End of demo\n");
253 OS_TPrintf("demo %s\n", (bSampleSucceeded ? "succeeded": "failed"));
254 GX_Init();
255 *(GXRgb*)HW_BG_PLTT = (GXRgb)(bSampleSucceeded ? GX_RGB(0, 31, 0): GX_RGB(31, 0, 0));
256 GX_DispOn();
257 OS_Terminate();
258 }
259
260
261 /*---------------------------------------------------------------------------*
262 Name: DEMO_AESCallback
263
264 Description: This is the callback called at AES processing completion.
265 It is of type AESCallback.
266
267 Arguments: result: AES processing result
268 arg: Last argument passed in AES_Ctr
269
270 Returns: None.
271 *---------------------------------------------------------------------------*/
DEMO_AESCallback(AESResult result,void * arg)272 static void DEMO_AESCallback(AESResult result, void* arg)
273 {
274 OSMessageQueue* pQ = (OSMessageQueue*)arg;
275 (void)OS_SendMessage(pQ, (OSMessage)result, OS_MESSAGE_BLOCK);
276 }
277
278 /*---------------------------------------------------------------------------*
279 Name: DEMO_WaitAes
280
281 Description: Returns the result of awaiting AES processing completion.
282 DEMO_AESCallback must have been specified in AES_Ctr.
283
284 Arguments: pQ: Message queue passed as the last AES_Ctr argument
285
286 Returns: AES processing result.
287 *---------------------------------------------------------------------------*/
DEMO_WaitAes(OSMessageQueue * pQ)288 static AESResult DEMO_WaitAes(OSMessageQueue* pQ)
289 {
290 OSMessage msg;
291 (void)OS_ReceiveMessage(pQ, &msg, OS_MESSAGE_BLOCK);
292 return (AESResult)msg;
293 }
294
295 /*---------------------------------------------------------------------------*
296 Name: DEMO_PrintBytes
297
298 Description: Outputs the specified binary array in hexadecimal to debug output.
299
300 Arguments: pvoid: Pointer to the target binary array
301 size: Number of bytes in the target binary array
302
303 Returns: None.
304 *---------------------------------------------------------------------------*/
DEMO_PrintBytes(const void * pvoid,u32 size)305 static void DEMO_PrintBytes(const void* pvoid, u32 size)
306 {
307 const u8* p = (const u8*)pvoid;
308 u32 i;
309
310 for( i = 0; i < size; ++i )
311 {
312 OS_TPrintf("%02X ", p[i]);
313 if( i % 16 == 15 )
314 {
315 OS_TPrintf("\n");
316 }
317 }
318
319 if( i % 16 != 0 )
320 {
321 OS_TPrintf("\n");
322 }
323 }
324
325 /*---------------------------------------------------------------------------*
326 Name: DEMO_InitInteruptSystem
327
328 Description: Initializes interrupts.
329
330 Arguments: None.
331
332 Returns: None.
333 *---------------------------------------------------------------------------*/
DEMO_InitInteruptSystem(void)334 static void DEMO_InitInteruptSystem(void)
335 {
336 // Enable master interrupt flag
337 (void)OS_EnableIrq();
338 }
339
340 /*---------------------------------------------------------------------------*
341 Name: DEMO_InitAllocSystem
342
343 Description: Creates a heap and makes OS_Alloc usable.
344
345 Arguments: None.
346
347 Returns: None.
348 *---------------------------------------------------------------------------*/
DEMO_InitAllocSystem(void)349 static void DEMO_InitAllocSystem(void)
350 {
351 void* newArenaLo;
352 OSHeapHandle hHeap;
353
354 // Initialize the main arena's allocation system
355 newArenaLo = OS_InitAlloc(OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi(), 1);
356 OS_SetMainArenaLo(newArenaLo);
357
358 // Create a heap in the main arena
359 hHeap = OS_CreateHeap(OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi());
360 (void)OS_SetCurrentHeap(OS_ARENA_MAIN, hHeap);
361 }
362