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