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