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:: 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_SIGN_HEADER_SIZE.
86     plainSize = (u32)STD_GetStringLength(pPlainText) + 1;
87     cipherSize = plainSize + AES_SIGN_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 CCM Mode
119         aesResult = AES_EncryptAndSign(
120                         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_EncryptAndSign 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_EncryptAndSign 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 CCM Mode
156         aesResult = AES_DecryptAndVerify(
157                         pEncrypted,         // Data to be decrypted
158                         cipherSize,         // Size of the data to decrypt
159                         pDecrypted,         // Buffer that stores decrypted data
160                         DEMO_AESCallback,   // Callback called at completion
161                         &sMsgQ );           // Callback parameters
162         if( aesResult != AES_RESULT_SUCCESS )
163         {
164             OS_TPrintf("AES_DecryptAndVerify failed(%d)\n", aesResult);
165             goto error_exit;
166         }
167 
168         // Wait for decryption to end
169         aesResult = DEMO_WaitAes(&sMsgQ);
170 
171         // If the encrypted data has been falsified, the aesResult obtained here is AES_RESULT_VERIFICATION_FAILED
172         //
173         if( aesResult != AES_RESULT_SUCCESS )
174         {
175             OS_TPrintf("AES_DecryptAndVerify failed(%d)\n", aesResult);
176             goto error_exit;
177         }
178 
179 
180         // Display results
181         OS_TPrintf("---- decrypt -------------\n");
182         OS_TPrintf("-- encrypted (hex)\n");
183         DEMO_PrintBytes(pEncrypted, cipherSize);
184 
185         OS_TPrintf("-- decrypted (hex)\n");
186         DEMO_PrintBytes(pDecrypted, plainSize);
187 
188         OS_TPrintf("-- decrypted (ascii)\n");
189         OS_PutString(pDecrypted);   // Use OS_PutString because OS_*Printf has a limit of 256 characters
190         OS_TPrintf("\n");
191     }
192 
193     // Confirm that data that was encrypted, then decrypted, matches original
194     if( MI_CpuComp8(pDecrypted, pPlainText, plainSize) == 0 )
195     {
196         OS_TPrintf("** pDecrypted == pPlainText\n");
197         bSuccess = TRUE;
198     }
199     else
200     {
201         OS_TPrintf("** pDecrypted != pPlainText\n");
202     }
203 
204 error_exit:
205     OS_Free(pDecrypted);
206     OS_Free(pEncrypted);
207 
208     return bSuccess;
209 }
210 
211 
212 
213 /*---------------------------------------------------------------------------*
214   Name:         TwlMain
215 
216   Description:  The main function.
217 
218   Arguments:    None.
219 
220   Returns:      None.
221  *---------------------------------------------------------------------------*/
TwlMain(void)222 void TwlMain(void)
223 {
224     BOOL bSampleSucceeded = FALSE;
225 
226     // Initialization
227     OS_Init();
228     DEMO_InitInteruptSystem();
229     DEMO_InitAllocSystem();
230     OS_TPrintf("*** start aes demo\n");
231 
232 
233     // Run demo
234     if( OS_IsRunOnTwl() )
235     {
236         bSampleSucceeded = SampleMain();
237     }
238     else
239     {
240         OS_Warning("demo is not run on TWL");
241     }
242 
243 
244     // Display demo run results
245     OS_TPrintf("*** End of demo\n");
246     OS_TPrintf("demo %s\n", (bSampleSucceeded ? "succeeded": "failed"));
247     GX_Init();
248     *(GXRgb*)HW_BG_PLTT = (GXRgb)(bSampleSucceeded ? GX_RGB(0, 31, 0): GX_RGB(31, 0, 0));
249     GX_DispOn();
250     OS_Terminate();
251 }
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:  Returns the result of awaiting AES processing completion.
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