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