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