1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - aes - demos - encrypt
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     const char* pPlainText = DEMO_TEXT;
77     void* pEncrypted;
78     void* pDecrypted;
79     u32 plainSize;
80     u32 cipherSize;
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     // The encrypted data will increase in size by exactly the amount of AES_ENCRYPT_HEADER_SIZE.
87     plainSize = (u32)STD_GetStringLength(pPlainText) + 1;
88     cipherSize = plainSize + AES_ENCRYPT_HEADER_SIZE;
89     pEncrypted = OS_Alloc(cipherSize);
90     pDecrypted = OS_Alloc(plainSize);
91 
92     if( ! SDK_IS_VALID_POINTER(pEncrypted)
93      || ! SDK_IS_VALID_POINTER(pDecrypted) )
94     {
95         OS_TPrintf("fail to OS_Alloc\n");
96         return FALSE;
97     }
98 
99     // The first AES function called must be AES_Init.
100     AES_Init();
101 
102     // Configure the encryption key
103     aesResult = AES_SetKey(&DEMO_KEY);
104     if( aesResult != AES_RESULT_SUCCESS )
105     {
106         OS_TPrintf("AES_SetKey failed(%d)\n", aesResult);
107         goto error_exit;
108     }
109 
110 
111     // Display parameters
112     OS_TPrintf("---- parameter -----------\n");
113     OS_TPrintf("-- key\n");
114     DEMO_PrintBytes(&DEMO_KEY, sizeof(DEMO_KEY));
115 
116 
117     // Encryption
118     {
119         // Performs encryption in AES CTR Mode
120         aesResult = AES_Encrypt( pPlainText,         // Data to be encrypted
121                                  plainSize,            // Size of the data to encrypt
122                                  pEncrypted,         // Buffer that stores encrypted data
123                                  DEMO_AESCallback,   // Callback called at completion
124                                  &sMsgQ );           // Callback parameters
125         if( aesResult != AES_RESULT_SUCCESS )
126         {
127             OS_TPrintf("AES_Encrypt failed(%d)\n", aesResult);
128             goto error_exit;
129         }
130 
131         // Wait for encryption to end
132         aesResult = DEMO_WaitAes(&sMsgQ);
133         if( aesResult != AES_RESULT_SUCCESS )
134         {
135             OS_TPrintf("AES_Encrypt failed(%d)\n", aesResult);
136             goto error_exit;
137         }
138 
139 
140         // Display results
141         OS_TPrintf("---- encrypt -------------\n");
142         OS_TPrintf("-- plain text (ascii)\n");
143         OS_PutString(pPlainText);   // Use OS_PutString because OS_*Printf has a limit of 256 characters
144         OS_TPrintf("\n");
145 
146         OS_TPrintf("-- plain text (hex)\n");
147         DEMO_PrintBytes(pPlainText, plainSize);
148 
149         OS_TPrintf("-- encrypted (hex)\n");
150         DEMO_PrintBytes(pEncrypted, cipherSize);
151     }
152 
153     // Decryption
154     {
155         // Performs decryption in AES CTR Mode
156         aesResult = AES_Decrypt( pEncrypted,         // Data to be decrypted
157                                  cipherSize,         // Size of the data to decrypt
158                                  pDecrypted,         // Buffer that stores decrypted data
159                                  DEMO_AESCallback,   // Callback called at completion
160                                  &sMsgQ );           // Callback parameters
161         if( aesResult != AES_RESULT_SUCCESS )
162         {
163             OS_TPrintf("AES_Decrypt failed(%d)\n", aesResult);
164             goto error_exit;
165         }
166 
167         // Wait for decryption to end
168         aesResult = DEMO_WaitAes(&sMsgQ);
169         if( aesResult != AES_RESULT_SUCCESS )
170         {
171             OS_TPrintf("AES_Decrypt failed(%d)\n", aesResult);
172             goto error_exit;
173         }
174 
175 
176         // Display results
177         OS_TPrintf("---- decrypt -------------\n");
178         OS_TPrintf("-- encrypted (hex)\n");
179         DEMO_PrintBytes(pEncrypted, cipherSize);
180 
181         OS_TPrintf("-- decrypted (hex)\n");
182         DEMO_PrintBytes(pDecrypted, plainSize);
183 
184         OS_TPrintf("-- decrypted (ascii)\n");
185         OS_PutString(pDecrypted);   // Use OS_PutString because OS_*Printf has a limit of 256 characters
186         OS_TPrintf("\n");
187     }
188 
189     // Confirm that data that was encrypted, then decrypted, matches original
190     if( MI_CpuComp8(pDecrypted, pPlainText, plainSize) == 0 )
191     {
192         OS_TPrintf("** pDecrypted == pPlainText\n");
193         bSuccess = TRUE;
194     }
195     else
196     {
197         OS_TPrintf("** pDecrypted != pPlainText\n");
198     }
199 
200 error_exit:
201     OS_Free(pDecrypted);
202     OS_Free(pEncrypted);
203 
204     return bSuccess;
205 }
206 
207 
208 /*---------------------------------------------------------------------------*
209   Name:         TwlMain
210 
211   Description:  The main function.
212 
213   Arguments:    None.
214 
215   Returns:      None.
216  *---------------------------------------------------------------------------*/
TwlMain(void)217 void TwlMain(void)
218 {
219     BOOL bSampleSucceeded = FALSE;
220 
221     // Initialization
222     OS_Init();
223     DEMO_InitInteruptSystem();
224     DEMO_InitAllocSystem();
225     OS_TPrintf("*** start aes demo\n");
226 
227     // When in NITRO mode, stopped by Panic
228     DEMOCheckRunOnTWL();
229     // Run demo
230     bSampleSucceeded = SampleMain();
231 
232     // Display demo run results
233     OS_TPrintf("*** End of demo\n");
234     OS_TPrintf("demo %s\n", (bSampleSucceeded ? "succeeded": "failed"));
235     GX_Init();
236     *(GXRgb*)HW_BG_PLTT = (GXRgb)(bSampleSucceeded ? GX_RGB(0, 31, 0): GX_RGB(31, 0, 0));
237     GX_DispOn();
238     OS_Terminate();
239 }
240 
241 
242 /*---------------------------------------------------------------------------*
243   Name:         DEMO_AESCallback
244 
245   Description:  This is the callback called at AES processing completion.
246                 It is of type AESCallback.
247 
248   Arguments:    result: AES processing result.
249                 arg:    Last argument passed in AES_Ctr
250 
251   Returns:      None.
252  *---------------------------------------------------------------------------*/
DEMO_AESCallback(AESResult result,void * arg)253 static void DEMO_AESCallback(AESResult result, void* arg)
254 {
255     OSMessageQueue* pQ = (OSMessageQueue*)arg;
256     (void)OS_SendMessage(pQ, (OSMessage)result, OS_MESSAGE_BLOCK);
257 }
258 
259 /*---------------------------------------------------------------------------*
260   Name:         DEMO_WaitAes
261 
262   Description:  Waits for AES processing completion and returns results.
263                 DEMO_AESCallback must have been specified in AES_Ctr.
264 
265   Arguments:    pQ: Message queue passed as the last AES_Ctr argument
266 
267   Returns:      AES processing result.
268  *---------------------------------------------------------------------------*/
DEMO_WaitAes(OSMessageQueue * pQ)269 static AESResult DEMO_WaitAes(OSMessageQueue* pQ)
270 {
271     OSMessage msg;
272     (void)OS_ReceiveMessage(pQ, &msg, OS_MESSAGE_BLOCK);
273     return (AESResult)msg;
274 }
275 
276 /*---------------------------------------------------------------------------*
277   Name:         DEMO_PrintBytes
278 
279   Description:  Outputs the specified binary array in hexadecimal to debug output.
280 
281   Arguments:    pvoid:  Pointer to the target binary array.
282                 size:   Number of bytes in the target binary array.
283 
284   Returns:      None.
285  *---------------------------------------------------------------------------*/
DEMO_PrintBytes(const void * pvoid,u32 size)286 static void DEMO_PrintBytes(const void* pvoid, u32 size)
287 {
288     const u8* p = (const u8*)pvoid;
289     u32 i;
290 
291     for( i = 0; i < size; ++i )
292     {
293         OS_TPrintf("%02X ", p[i]);
294         if( i % 16 == 15 )
295         {
296             OS_TPrintf("\n");
297         }
298     }
299 
300     if( i % 16 != 0 )
301     {
302         OS_TPrintf("\n");
303     }
304 }
305 
306 /*---------------------------------------------------------------------------*
307   Name:         DEMO_InitInteruptSystem
308 
309   Description:  Initializes interrupts.
310 
311   Arguments:    None.
312 
313   Returns:      None.
314  *---------------------------------------------------------------------------*/
DEMO_InitInteruptSystem(void)315 static void DEMO_InitInteruptSystem(void)
316 {
317     // Enable master interrupt flag
318     (void)OS_EnableIrq();
319 }
320 
321 /*---------------------------------------------------------------------------*
322   Name:         DEMO_InitAllocSystem
323 
324   Description:  Creates a heap and makes OS_Alloc usable.
325 
326   Arguments:    None.
327 
328   Returns:      None.
329  *---------------------------------------------------------------------------*/
DEMO_InitAllocSystem(void)330 static void DEMO_InitAllocSystem(void)
331 {
332     void* newArenaLo;
333     OSHeapHandle hHeap;
334 
335     // Initialize the main arena's allocation system
336     newArenaLo = OS_InitAlloc(OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi(), 1);
337     OS_SetMainArenaLo(newArenaLo);
338 
339     // Create a heap in the main arena
340     hHeap = OS_CreateHeap(OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi());
341     (void)OS_SetCurrentHeap(OS_ARENA_MAIN, hHeap);
342 }
343