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