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