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