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