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