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