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