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