1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - aes - demos - ccm-compatible
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 /*---------------------------------------------------------------------------*
26 Internal function declarations
27 *---------------------------------------------------------------------------*/
28
29 static void DEMO_InitInteruptSystem(void);
30 static void DEMO_InitAllocSystem(void);
31 static void DEMO_InitFileSystem(void);
32 static void DEMO_AESCallback(AESResult result, void* arg);
33 static AESResult DEMO_WaitAes(OSMessageQueue* pQ);
34 static void DEMO_PrintText(const void* pvoid, u32 size);
35 static void DEMO_PrintBytes(const void* pvoid, u32 size);
36 static void* DEMO_LoadFile(u32* pSize, const char* path);
37
38 #define DEMO_CCM_COMPATIBLE_2_MAX_ADATA_SIZE 0xFEFF
39 #define DEMO_CCM_COMPATIBLE_6_MAX_ADATA_SIZE AES_ADATA_SIZE_MAX // Originally and normally 0xFFFFFFFF
40 #define DEMO_CCM_COMPATIBLE_2_HEADER_SIZE 2
41 #define DEMO_CCM_COMPATIBLE_6_HEADER_SIZE 6
42 #define DEMO_CCM_COMPATIBLE_6_MAGIC_NUMBER 0xFFFE
43
44 static u32 DEMO_CalcAdataHeaderSize(u32 adataSize);
45 static void DEMO_MakeAdataHeader(void* pv, u32 adataSize);
46 static AESResult DEMO_CcmEncryptCompatible(
47 const AESKey* pKey,
48 const AESNonce* pNonce,
49 void* pWorkBuffer,
50 const void* pAdata,
51 u32 adataSize,
52 const void* pPdata,
53 u32 pdataSize,
54 AESMacLength macLength,
55 void* dst );
56 static AESResult DEMO_CcmDecryptCompatible(
57 const AESKey* pKey,
58 const AESNonce* pNonce,
59 void* pWorkBuffer,
60 const void* pAdata,
61 u32 adataSize,
62 const void* pCdata,
63 u32 cdataSize,
64 AESMacLength macLength,
65 void* dst );
66
67
68
69 /*---------------------------------------------------------------------------*
70 Function Definitions
71 *---------------------------------------------------------------------------*/
72
73 /*---------------------------------------------------------------------------*
74 Name: SampleMain
75
76 Description: The main body of the sample.
77
78 Arguments: None.
79
80 Returns: Whether sample processing succeeded.
81 *---------------------------------------------------------------------------*/
SampleMain(void)82 static BOOL SampleMain(void)
83 {
84 BOOL bSuccess = FALSE;
85 AESResult aesResult;
86
87 // The first AES function to call must be AES_Init
88 AES_Init();
89
90 // CCM mode encryption
91 {
92 const AESMacLength macLength = AES_MAC_LENGTH_16;
93
94 const u32 macSize = AES_GetMacLengthValue(macLength);
95 void* pAdata;
96 void* pPdata;
97 void* pEncrypted;
98 void* pKey;
99 void* pNonce;
100 u32 adataSize;
101 u32 pdataSize;
102
103 // Load the data needed for encryption.
104 // In this sample, the nonce is loaded from a file so data can be compared with data encrypted on a PC, but ordinarily you must not use a fixed value for the nonce.
105 //
106 //
107 pKey = DEMO_LoadFile(NULL, "key.bin");
108 pNonce = DEMO_LoadFile(NULL, "nonce.bin");
109 pAdata = DEMO_LoadFile(&adataSize, "sample_adata.txt");
110 pPdata = DEMO_LoadFile(&pdataSize, "sample_pdata.txt");
111
112 if( (pdataSize % AES_BLOCK_SIZE) != 0 )
113 {
114 OS_TPrintf("pdataSize(=%d) must be multiple of 16.\n", pdataSize);
115 return FALSE;
116 }
117
118
119 // Allocate the buffer to store encrypted data.
120 // Only the MAC portion requires a large buffer.
121 pEncrypted = OS_Alloc(pdataSize + macSize);
122
123 if( ! SDK_IS_VALID_POINTER(pEncrypted) )
124 {
125 OS_TPrintf("fail to OS_Alloc\n");
126 return FALSE;
127 }
128
129
130 // Display parameters
131 OS_TPrintf("== CCM encrypt ==========================\n");
132 OS_TPrintf("---- parameter -----------\n");
133 OS_TPrintf("-- key\n");
134 DEMO_PrintBytes(pKey, sizeof(AESKey));
135 OS_TPrintf("-- nonce\n");
136 DEMO_PrintBytes(pNonce, sizeof(AESNonce));
137
138 OS_TPrintf("---- encrypt -------------\n");
139 OS_TPrintf("-- Adata (ascii)\n");
140 DEMO_PrintText(pAdata, adataSize);
141 OS_TPrintf("-- Pdata (ascii)\n");
142 DEMO_PrintText(pPdata, pdataSize);
143 OS_TPrintf("\n");
144 OS_TPrintf("-- Adata (hex)\n");
145 DEMO_PrintBytes(pAdata, adataSize);
146 OS_TPrintf("-- Pdata (hex)\n");
147 DEMO_PrintBytes(pPdata, pdataSize);
148
149
150 // Perform encryption that is compatible with the general-purpose AES libraries
151 if( adataSize <= DEMO_CCM_COMPATIBLE_6_MAX_ADATA_SIZE )
152 {
153 const u32 headerSize = DEMO_CalcAdataHeaderSize(adataSize);
154 const u32 workSize = headerSize + adataSize + pdataSize;
155 void* pWorkBuffer = OS_Alloc(workSize);
156
157 aesResult = DEMO_CcmEncryptCompatible(
158 pKey, // Key
159 pNonce, // Nonce
160 pWorkBuffer, // Working buffer
161 pAdata, // Pointer to buffer where Adata is stored
162 adataSize, // Adata's size
163 pPdata, // Pointer to buffer where Pdata is stored
164 pdataSize, // Pdata's size
165 macLength, // MAC size
166 pEncrypted ); // Buffer that stores encrypted data
167
168 OS_Free(pWorkBuffer);
169 }
170 else
171 {
172 OS_TPrintf("Too huge Adata size(=%d)\n", adataSize);
173 OS_Free(pEncrypted);
174 OS_Free(pPdata);
175 OS_Free(pAdata);
176 OS_Free(pNonce);
177 OS_Free(pKey);
178 return FALSE;
179 }
180 if( aesResult != AES_RESULT_SUCCESS )
181 {
182 OS_TPrintf("DEMO_CcmEncryptCompatible failed(%d)\n", aesResult);
183 OS_Free(pEncrypted);
184 OS_Free(pPdata);
185 OS_Free(pAdata);
186 OS_Free(pNonce);
187 OS_Free(pKey);
188 return FALSE;
189 }
190
191
192 // Display results
193 OS_TPrintf("-- encrypted (hex)\n");
194 DEMO_PrintBytes(pEncrypted, pdataSize);
195
196 OS_TPrintf("-- mac (hex)\n");
197 DEMO_PrintBytes((u8*)pEncrypted + pdataSize, macSize);
198
199 // Confirm that the data matches data encrypted on the PC
200 {
201 void* pEncryptedOnPC;
202 u32 size;
203
204 pEncryptedOnPC = DEMO_LoadFile(&size, "encrypted.bin");
205
206 if( (pdataSize + macSize == size) && MI_CpuComp8(pEncrypted, pEncryptedOnPC, size) == 0 )
207 {
208 OS_TPrintf("** pEncrypted == pEncryptedOnPC\n");
209 }
210 else
211 {
212 OS_TPrintf("** pEncrypted != pEncryptedOnPC\n");
213 }
214
215 OS_Free(pEncryptedOnPC);
216 }
217
218 OS_Free(pEncrypted);
219 OS_Free(pPdata);
220 OS_Free(pAdata);
221 OS_Free(pNonce);
222 OS_Free(pKey);
223 }
224
225 // CCM Mode Decryption
226 {
227 const AESMacLength macLength = AES_MAC_LENGTH_16;
228
229 const u32 macSize = AES_GetMacLengthValue(macLength);
230 void* pAdata;
231 void* pEncrypted;
232 void* pDecrypted;
233 void* pKey;
234 void* pNonce;
235 u32 adataSize;
236 u32 cdataSize;
237 u32 srcFileSize;
238
239 // Load data encrypted on a PC.
240 // In the sample, both the key and the ciphertext are in ROM, but they should normally not both be obtainable via the same method.
241 //
242 pKey = DEMO_LoadFile(NULL, "key.bin");
243 pNonce = DEMO_LoadFile(NULL, "nonce.bin");
244 pAdata = DEMO_LoadFile(&adataSize, "sample_adata.txt");
245 pEncrypted = DEMO_LoadFile(&srcFileSize, "encrypted.bin");
246 cdataSize = srcFileSize - macSize;
247
248 // Allocate the buffer to store decrypted data
249 pDecrypted = OS_Alloc(cdataSize);
250
251 if( ! SDK_IS_VALID_POINTER(pDecrypted) )
252 {
253 OS_TPrintf("fail to OS_Alloc\n");
254 return FALSE;
255 }
256
257 // Display parameters
258 OS_TPrintf("== CCM decrypt ==========================\n");
259 OS_TPrintf("---- parameter -----------\n");
260 OS_TPrintf("-- key\n");
261 DEMO_PrintBytes(pKey, sizeof(AESKey));
262 OS_TPrintf("-- nonce\n");
263 DEMO_PrintBytes(pNonce, sizeof(AESNonce));
264
265 OS_TPrintf("---- decrypt -------------\n");
266 OS_TPrintf("-- Adata (ascii)\n");
267 DEMO_PrintText(pAdata, adataSize);
268 OS_TPrintf("\n");
269 OS_TPrintf("-- Adata (hex)\n");
270 DEMO_PrintBytes(pAdata, adataSize);
271 OS_TPrintf("-- encrypted (hex)\n");
272 DEMO_PrintBytes(pEncrypted, cdataSize + macSize);
273
274 // Performs decryption that is compatible with general-purpose AES libraries
275 if( adataSize <= DEMO_CCM_COMPATIBLE_6_MAX_ADATA_SIZE )
276 {
277 const u32 headerSize = DEMO_CalcAdataHeaderSize(adataSize);
278 const u32 workSize = headerSize + adataSize + cdataSize + macSize;
279 void* pWorkBuffer = OS_Alloc(workSize);
280
281 aesResult = DEMO_CcmDecryptCompatible(
282 pKey, // Key
283 pNonce, // Nonce
284 pWorkBuffer, // Working buffer
285 pAdata, // Pointer to buffer where Adata is stored
286 adataSize, // Adata's size
287 pEncrypted, // Pointer to buffer where ciphertext and MAC are stored
288 cdataSize, // Ciphertext size
289 macLength, // MAC size
290 pDecrypted ); // Buffer that stores decrypted data
291
292 OS_Free(pWorkBuffer);
293 }
294 else
295 {
296 OS_TPrintf("Too huge Adata size(=%d)\n", adataSize);
297 OS_Free(pEncrypted);
298 OS_Free(pAdata);
299 OS_Free(pNonce);
300 OS_Free(pKey);
301 return FALSE;
302 }
303 // If the encrypted data has been falsified, the aesResult obtained here is AES_RESULT_VERIFICATION_FAILED
304 //
305 if( aesResult != AES_RESULT_SUCCESS )
306 {
307 OS_TPrintf("DEMO_CcmDecryptCompatible failed(%d)\n", aesResult);
308 OS_Free(pDecrypted);
309 OS_Free(pEncrypted);
310 OS_Free(pAdata);
311 OS_Free(pNonce);
312 OS_Free(pKey);
313 return FALSE;
314 }
315
316
317 // Display results
318 OS_TPrintf("-- decrypted (hex)\n");
319 DEMO_PrintBytes(pDecrypted, cdataSize);
320
321 OS_TPrintf("-- decrypted (ascii)\n");
322 DEMO_PrintText(pDecrypted, cdataSize);
323 OS_TPrintf("\n");
324
325 // Confirm whether it matches the original
326 {
327 void* pOriginal;
328 u32 size;
329
330 pOriginal = DEMO_LoadFile(&size, "sample_pdata.txt");
331
332 if( (cdataSize == size) && MI_CpuComp8(pDecrypted, pOriginal, size) == 0 )
333 {
334 OS_TPrintf("** pDecrypted == pOriginal\n");
335 bSuccess = TRUE;
336 }
337 else
338 {
339 OS_TPrintf("** pDecrypted != pOriginal\n");
340 }
341
342 OS_Free(pOriginal);
343 }
344
345
346 OS_Free(pDecrypted);
347 OS_Free(pEncrypted);
348 OS_Free(pAdata);
349 OS_Free(pNonce);
350 OS_Free(pKey);
351 }
352
353 return bSuccess;
354 }
355
356 /*---------------------------------------------------------------------------*
357 Name: TwlMain
358
359 Description: Main function.
360
361 Arguments: None.
362
363 Returns: None.
364 *---------------------------------------------------------------------------*/
TwlMain(void)365 void TwlMain(void)
366 {
367 BOOL bSampleSucceeded = FALSE;
368
369 // Initialization
370 OS_Init();
371 DEMO_InitInteruptSystem();
372 DEMO_InitAllocSystem();
373 DEMO_InitFileSystem();
374 OS_TPrintf("*** start aes demo\n");
375
376
377 // Run demo
378 if( OS_IsRunOnTwl() )
379 {
380 bSampleSucceeded = SampleMain();
381 }
382 else
383 {
384 OS_Warning("demo is not run on TWL");
385 }
386
387
388 // Display demo run results
389 OS_TPrintf("*** End of demo\n");
390 OS_TPrintf("demo %s\n", (bSampleSucceeded ? "succeeded": "failed"));
391 GX_Init();
392 *(GXRgb*)HW_BG_PLTT = (GXRgb)(bSampleSucceeded ? GX_RGB(0, 31, 0): GX_RGB(31, 0, 0));
393 GX_DispOn();
394 OS_Terminate();
395 }
396
397
398
399 /*---------------------------------------------------------------------------*
400 Name: DEMO_CalcAdataHeaderSize
401
402 Description: There is no compatibility for output results between those of the TWL-SDK AES library and those of general AES libraries.
403
404 As one example of incompatibility, sometimes the size of the Adata immediately following the CCM header is NOT automatically added.
405
406
407 This function calculates the size of the region needed to store the Adata size.
408
409
410 Arguments: adataSize: Adata's size
411
412 Returns: Returns the region size needed to store a size equivalent to the Adata size.
413 *---------------------------------------------------------------------------*/
DEMO_CalcAdataHeaderSize(u32 adataSize)414 static u32 DEMO_CalcAdataHeaderSize(u32 adataSize)
415 {
416 return (u32)( (adataSize <= DEMO_CCM_COMPATIBLE_2_MAX_ADATA_SIZE)
417 ? DEMO_CCM_COMPATIBLE_2_HEADER_SIZE:
418 DEMO_CCM_COMPATIBLE_6_HEADER_SIZE );
419 }
420
421
422
423 /*---------------------------------------------------------------------------*
424 Name: DEMO_MakeAdataHeader
425
426 Description: There is no compatibility for output results between those of the TWL-SDK AES library and those of general AES libraries.
427
428 As one example of incompatibility, sometimes the size of the Adata immediately following the CCM header is NOT automatically added.
429
430
431 This function writes out the Adata size in the prescribed format to a buffer.
432
433
434 Arguments: pv: Pointer to the buffer where the Adata size is written
435 adataSize: Adata's size
436
437 Returns: None.
438 *---------------------------------------------------------------------------*/
DEMO_MakeAdataHeader(void * pv,u32 adataSize)439 static void DEMO_MakeAdataHeader(void* pv, u32 adataSize)
440 {
441 u8* p = (u8*)pv;
442
443 if( adataSize <= DEMO_CCM_COMPATIBLE_2_MAX_ADATA_SIZE )
444 {
445 MI_StoreBE16(p, (u16)adataSize);
446 }
447 else
448 {
449 MI_StoreBE16(p + 0, DEMO_CCM_COMPATIBLE_6_MAGIC_NUMBER);
450 MI_StoreBE32(p + 2, adataSize);
451 }
452 }
453
454
455
456 /*---------------------------------------------------------------------------*
457 Name: DEMO_CcmEncryptCompatible
458
459 Description: There is no compatibility for output results between those of the TWL-SDK AES library and those of general AES libraries.
460
461 This function uses appropriate processing before and after AES processes to perform encryption compatible with general AES libraries.
462
463 However, there is a limitation compared to AES_CcmEncryptAndSign: pdataSize must be a multiple of AES_BLOCK_SIZE (=16).
464
465 Also, the limit on adataSize is not a multiple of 16. In some cases it will be a multiple of 16 minus 2 or a multiple of 16 minus 4.
466
467
468 Arguments: pKey: Key to use
469 pNonce: Nonce to use
470 pWorkBuffer: Passes a pointer to the working buffer used by the function internally.
471
472 A size equivalent to [adataSize + pdataSize + DEMO_CalcAdataHeaderSize(adataSize)] is needed.
473
474
475 The pointer must be 4-byte aligned.
476 pAdata: Pointer to Adata
477 adataSize: Adata size.
478 Must be a multiple of 16 minus DEMO_CalcAdataHeaderSize(adataSize).
479
480 pPdata: Pointer to Pdata
481 pdataSize: Pdata size.
482 Must be a multiple of 16.
483 macLength: MAC size
484 dst: Pointer to the buffer where the ciphertext is written out.
485 A size equivalent to [pdataSize + DEMO_CalcAdataHeaderSize(adataSize)] is needed.
486
487 The pointer must be 4-byte aligned.
488
489 Returns: Returns the processing result.
490 *---------------------------------------------------------------------------*/
DEMO_CcmEncryptCompatible(const AESKey * pKey,const AESNonce * pNonce,void * pWorkBuffer,const void * pAdata,u32 adataSize,const void * pPdata,u32 pdataSize,AESMacLength macLength,void * dst)491 AESResult DEMO_CcmEncryptCompatible(
492 const AESKey* pKey,
493 const AESNonce* pNonce,
494 void* pWorkBuffer,
495 const void* pAdata,
496 u32 adataSize,
497 const void* pPdata,
498 u32 pdataSize,
499 AESMacLength macLength,
500 void* dst )
501 {
502 const u32 headerSize = DEMO_CalcAdataHeaderSize(adataSize);
503 AESKey key;
504 AESNonce nonce;
505
506 SDK_POINTER_ASSERT(pKey);
507 SDK_POINTER_ASSERT(pNonce);
508 SDK_POINTER_ASSERT(pWorkBuffer);
509 SDK_POINTER_ASSERT(pAdata);
510 SDK_POINTER_ASSERT(pPdata);
511 SDK_POINTER_ASSERT(dst);
512 SDK_MAX_ASSERT( adataSize, AES_ADATA_SIZE_MAX );
513 SDK_MAX_ASSERT( pdataSize, AES_PDATA_SIZE_MAX );
514 SDK_ASSERT( (adataSize > DEMO_CCM_COMPATIBLE_2_MAX_ADATA_SIZE) || ((adataSize % 16) == 14) );
515 SDK_ASSERT( (adataSize <= DEMO_CCM_COMPATIBLE_2_MAX_ADATA_SIZE) || ((adataSize % 16) == 10) );
516 SDK_ASSERT( (pdataSize % 16) == 0 );
517
518 // Create the input data
519 {
520 const u32 offsetHeader = 0;
521 const u32 offsetAdata = offsetHeader + headerSize;
522 const u32 offsetPdata = offsetAdata + adataSize;
523
524 u8* pWork = (u8*)pWorkBuffer;
525 DEMO_MakeAdataHeader(pWork + offsetHeader, adataSize); // Adata size
526 MI_CpuCopy(pAdata, pWork + offsetAdata, adataSize); // Adata
527 MI_CpuCopy(pPdata, pWork + offsetPdata, pdataSize); // Pdata
528 }
529
530 // Switch the byte order of all input
531 {
532 const u32 workSize = headerSize + adataSize + pdataSize;
533
534 AES_ReverseBytes(pKey, &key, sizeof(key)); // Key
535 AES_ReverseBytes(pNonce, &nonce, sizeof(nonce)); // Nonce
536 AES_SwapEndianEach128(pWorkBuffer, pWorkBuffer, workSize); // Adata size, Adata, Pdata
537 }
538
539 // AES processing
540 {
541 OSMessageQueue msgQ;
542 OSMessage msgQBuffer[1];
543 AESResult aesResult;
544
545 OS_InitMessageQueue(&msgQ, msgQBuffer, sizeof(msgQBuffer)/sizeof(*msgQBuffer));
546
547 aesResult = AES_SetKey(&key);
548 if( aesResult != AES_RESULT_SUCCESS )
549 {
550 return aesResult;
551 }
552
553 aesResult = AES_CcmEncryptAndSign(
554 &nonce,
555 pWorkBuffer,
556 adataSize + headerSize,
557 pdataSize,
558 macLength,
559 dst,
560 DEMO_AESCallback,
561 &msgQ );
562 if( aesResult != AES_RESULT_SUCCESS )
563 {
564 return aesResult;
565 }
566
567 aesResult = DEMO_WaitAes(&msgQ);
568 if( aesResult != AES_RESULT_SUCCESS )
569 {
570 return aesResult;
571 }
572 }
573
574 // Switch the output byte order, too
575 {
576 void* mac = (u8*)dst + pdataSize;
577 u32 macSize = AES_GetMacLengthValue(macLength);
578
579 AES_SwapEndianEach128(dst, dst, pdataSize); // Cdata
580 AES_ReverseBytes(mac, mac, macSize); // MAC
581 }
582
583 return AES_RESULT_SUCCESS;
584 }
585
586
587
588 /*---------------------------------------------------------------------------*
589 Name: DEMO_CcmDecryptCompatible
590
591 Description: There is no compatibility for output results between those of the TWL-SDK AES library and those of general AES libraries.
592
593 This function uses appropriate processing before and after AES processes to perform decryption compatible with general AES libraries.
594
595 However, there is a limitation compared to AES_CcmDecryptAndVerify: cdataSize must be a multiple of AES_BLOCK_SIZE (=16).
596
597 Also, the limit on adataSize is not a multiple of 16. In some cases it will be a multiple of 16 minus 2 or a multiple of 16 minus 4.
598
599
600 Arguments: pKey: Specifies the key to use.
601 pNonce: Specifies the nonce to use.
602 pWorkBuffer: Passes a pointer to the working buffer used by the function internally.
603
604 A size equivalent to [adataSize + pdataSize + DEMO_CalcAdataHeaderSize(adataSize) + AES_GetMacLengthValue(macLength)] is needed.
605
606
607
608 The pointer must be 4-byte aligned.
609 pAdata: Pointer to Adata
610 adataSize: Adata size.
611 Must be a multiple of 16 minus DEMO_CalcAdataHeaderSize(adataSize).
612
613 pPdata: Pointer to buffer where ciphertext and MAC are stored
614 pdataSize: Size of the ciphertext.
615 Must be a multiple of 16.
616 macLength: MAC size
617 dst: Pointer to the buffer where the ciphertext is written out.
618 The pointer must be 4-byte aligned.
619
620 Returns: Returns the processing result.
621 *---------------------------------------------------------------------------*/
DEMO_CcmDecryptCompatible(const AESKey * pKey,const AESNonce * pNonce,void * pWorkBuffer,const void * pAdata,u32 adataSize,const void * pCdata,u32 cdataSize,AESMacLength macLength,void * dst)622 AESResult DEMO_CcmDecryptCompatible(
623 const AESKey* pKey,
624 const AESNonce* pNonce,
625 void* pWorkBuffer,
626 const void* pAdata,
627 u32 adataSize,
628 const void* pCdata,
629 u32 cdataSize,
630 AESMacLength macLength,
631 void* dst )
632 {
633 const u32 headerSize = DEMO_CalcAdataHeaderSize(adataSize);
634 const u32 macSize = AES_GetMacLengthValue(macLength);
635 AESKey key;
636 AESNonce nonce;
637
638 SDK_POINTER_ASSERT(pKey);
639 SDK_POINTER_ASSERT(pNonce);
640 SDK_POINTER_ASSERT(pWorkBuffer);
641 SDK_POINTER_ASSERT(pAdata);
642 SDK_POINTER_ASSERT(pCdata);
643 SDK_POINTER_ASSERT(dst);
644 SDK_MAX_ASSERT( adataSize, AES_ADATA_SIZE_MAX );
645 SDK_MAX_ASSERT( cdataSize, AES_PDATA_SIZE_MAX );
646 SDK_ASSERT( (adataSize > DEMO_CCM_COMPATIBLE_2_MAX_ADATA_SIZE) || ((adataSize % 16) == 14) );
647 SDK_ASSERT( (adataSize <= DEMO_CCM_COMPATIBLE_2_MAX_ADATA_SIZE) || ((adataSize % 16) == 10) );
648 SDK_ASSERT( (cdataSize % 16) == 0 );
649
650 // Create the input data
651 {
652 const u32 offsetHeader = 0;
653 const u32 offsetAdata = offsetHeader + headerSize;
654 const u32 offsetCdata = offsetAdata + adataSize;
655
656 u8* pWork = (u8*)pWorkBuffer;
657 DEMO_MakeAdataHeader(pWork + offsetHeader, adataSize); // Adata size
658 MI_CpuCopy(pAdata, pWork + offsetAdata, adataSize); // Adata
659 MI_CpuCopy(pCdata, pWork + offsetCdata, cdataSize + macSize); // Cdata, MAC
660 }
661
662 // Switch the byte order of all input
663 {
664 const u32 workSize = headerSize + adataSize + cdataSize + macSize;
665
666 AES_ReverseBytes(pKey, &key, sizeof(key)); // Key
667 AES_ReverseBytes(pNonce, &nonce, sizeof(nonce)); // Nonce
668 AES_SwapEndianEach128(pWorkBuffer, pWorkBuffer, workSize); // Adata size, Adata, Cdata, MAC
669 }
670
671 // AES processing
672 {
673 OSMessageQueue msgQ;
674 OSMessage msgQBuffer[1];
675 AESResult aesResult;
676
677 OS_InitMessageQueue(&msgQ, msgQBuffer, sizeof(msgQBuffer)/sizeof(*msgQBuffer));
678
679 aesResult = AES_SetKey(&key);
680 if( aesResult != AES_RESULT_SUCCESS )
681 {
682 return aesResult;
683 }
684
685 aesResult = AES_CcmDecryptAndVerify(
686 &nonce,
687 pWorkBuffer,
688 adataSize + headerSize,
689 cdataSize,
690 macLength,
691 dst,
692 DEMO_AESCallback,
693 &msgQ );
694 if( aesResult != AES_RESULT_SUCCESS )
695 {
696 return aesResult;
697 }
698
699 aesResult = DEMO_WaitAes(&msgQ);
700 if( aesResult != AES_RESULT_SUCCESS )
701 {
702 return aesResult;
703 }
704 }
705
706 // Switch the output byte order, too
707 {
708 AES_SwapEndianEach128(dst, dst, cdataSize); // Pdata
709 }
710
711 return AES_RESULT_SUCCESS;
712 }
713
714
715
716 /*---------------------------------------------------------------------------*
717 Name: DEMO_LoadFile
718
719 Description: Allocates memory and loads a file.
720
721 Arguments: pSize: Pointer to the buffer that stores the size of the file that was loaded.
722 Specify NULL when size is unnecessary.
723 path: Path of the file to load
724
725 Returns: Returns a pointer to the buffer where the file content is stored.
726 This buffer must be deallocated with the OS_Free function when it is no longer needed.
727 Returns NULL if it failed to load.
728 *---------------------------------------------------------------------------*/
DEMO_LoadFile(u32 * pSize,const char * path)729 static void* DEMO_LoadFile(u32* pSize, const char* path)
730 {
731 BOOL bSuccess;
732 FSFile f;
733 u32 fileSize;
734 s32 readSize;
735 void* pBuffer;
736
737 FS_InitFile(&f);
738
739 bSuccess = FS_OpenFileEx(&f, path, FS_FILEMODE_R);
740 if( ! bSuccess )
741 {
742 OS_Warning("fail to FS_OpenFileEx(%s)\n", path);
743 return NULL;
744 }
745
746 fileSize = FS_GetFileLength(&f);
747 pBuffer = OS_Alloc(fileSize + 1);
748 if( pBuffer == NULL )
749 {
750 (void)FS_CloseFile(&f);
751 OS_Warning("fail to OS_Alloc(%d)\n", fileSize + 1);
752 return NULL;
753 }
754
755 readSize = FS_ReadFile(&f, pBuffer, (s32)fileSize);
756 if( readSize != fileSize )
757 {
758 OS_Free(pBuffer);
759 (void)FS_CloseFile(&f);
760 OS_Warning("fail to FS_ReadFile(%d)\n", fileSize + 1);
761 return NULL;
762 }
763
764 bSuccess = FS_CloseFile(&f);
765 SDK_ASSERT( bSuccess );
766
767 ((char*)pBuffer)[fileSize] = '\0';
768
769 if( pSize != NULL )
770 {
771 *pSize = fileSize;
772 }
773
774 return pBuffer;
775 }
776
777 /*---------------------------------------------------------------------------*
778 Name: DEMO_AESCallback
779
780 Description: This is the callback called at AES processing completion.
781 It is of type AESCallback.
782
783 Arguments: result: AES processing result
784 arg: Last argument passed in AES_Ctr
785
786 Returns: None.
787 *---------------------------------------------------------------------------*/
DEMO_AESCallback(AESResult result,void * arg)788 static void DEMO_AESCallback(AESResult result, void* arg)
789 {
790 OSMessageQueue* pQ = (OSMessageQueue*)arg;
791 (void)OS_SendMessage(pQ, (OSMessage)result, OS_MESSAGE_BLOCK);
792 }
793
794 /*---------------------------------------------------------------------------*
795 Name: DEMO_WaitAes
796
797 Description: Returns the result of awaiting AES completion.
798 DEMO_AESCallback must be specified in AES_Ctr.
799
800 Arguments: pQ: Message queue passed as the last AES_Ctr argument
801
802 Returns: AES processing result.
803 *---------------------------------------------------------------------------*/
DEMO_WaitAes(OSMessageQueue * pQ)804 static AESResult DEMO_WaitAes(OSMessageQueue* pQ)
805 {
806 OSMessage msg;
807 (void)OS_ReceiveMessage(pQ, &msg, OS_MESSAGE_BLOCK);
808 return (AESResult)msg;
809 }
810
811 /*---------------------------------------------------------------------------*
812 Name: DEMO_PrintText
813
814 Description: Prints a string of specified length to debug output.
815
816 Arguments: pvoid: Target string
817 size: Target string byte count
818
819 Returns: None.
820 *---------------------------------------------------------------------------*/
DEMO_PrintText(const void * pvoid,u32 size)821 static void DEMO_PrintText(const void* pvoid, u32 size)
822 {
823 static const u32 TMP_BUFFER_LEN = 128 - 1;
824 char tmp_buffer[TMP_BUFFER_LEN + 1];
825 const u8* p = (const u8*)pvoid;
826
827 while( size >= TMP_BUFFER_LEN )
828 {
829 MI_CpuCopy8(p, tmp_buffer, TMP_BUFFER_LEN);
830 tmp_buffer[TMP_BUFFER_LEN] = '\0';
831 OS_PutString(tmp_buffer);
832
833 size -= TMP_BUFFER_LEN;
834 p += TMP_BUFFER_LEN;
835 }
836
837 if( size > 0 )
838 {
839 MI_CpuCopy8(p, tmp_buffer, size);
840 tmp_buffer[size] = '\0';
841 OS_PutString(tmp_buffer);
842 }
843 }
844
845 /*---------------------------------------------------------------------------*
846 Name: DEMO_PrintBytes
847
848 Description: Outputs the specified binary array in hexadecimal to debug output.
849
850 Arguments: pvoid: Pointer to the target binary array
851 size: Number of bytes in the target binary array
852
853 Returns: None.
854 *---------------------------------------------------------------------------*/
DEMO_PrintBytes(const void * pvoid,u32 size)855 static void DEMO_PrintBytes(const void* pvoid, u32 size)
856 {
857 const u8* p = (const u8*)pvoid;
858 u32 i;
859
860 for( i = 0; i < size; ++i )
861 {
862 OS_TPrintf("%02X ", p[i]);
863 if( i % 16 == 15 )
864 {
865 OS_TPrintf("\n");
866 }
867 }
868
869 if( i % 16 != 0 )
870 {
871 OS_TPrintf("\n");
872 }
873 }
874
875 /*---------------------------------------------------------------------------*
876 Name: DEMO_InitInteruptSystem
877
878 Description: Initializes interrupts.
879
880 Arguments: None.
881
882 Returns: None.
883 *---------------------------------------------------------------------------*/
DEMO_InitInteruptSystem(void)884 static void DEMO_InitInteruptSystem(void)
885 {
886 // Enable master interrupt flag
887 (void)OS_EnableIrq();
888 }
889
890 /*---------------------------------------------------------------------------*
891 Name: DEMO_InitAllocSystem
892
893 Description: Creates a heap and makes OS_Alloc usable.
894
895 Arguments: None.
896
897 Returns: None.
898 *---------------------------------------------------------------------------*/
DEMO_InitAllocSystem(void)899 static void DEMO_InitAllocSystem(void)
900 {
901 void* newArenaLo;
902 OSHeapHandle hHeap;
903
904 // Initialize the main arena's allocation system
905 newArenaLo = OS_InitAlloc(OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi(), 1);
906 OS_SetMainArenaLo(newArenaLo);
907
908 // Create a heap in the main arena
909 hHeap = OS_CreateHeap(OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi());
910 (void)OS_SetCurrentHeap(OS_ARENA_MAIN, hHeap);
911 }
912
913 /*---------------------------------------------------------------------------*
914 Name: DEMO_InitFileSystem
915
916 Description: Initializes the file system and makes the ROM accessible.
917 The DEMO_InitInteruptSystem and DEMO_InitAllocSystem functions must have been called before calling this function.
918
919
920 Arguments: None.
921
922 Returns: None.
923 *---------------------------------------------------------------------------*/
DEMO_InitFileSystem(void)924 static void DEMO_InitFileSystem(void)
925 {
926 void* p_table;
927 u32 need_size;
928
929 // Enables interrupts for the communications FIFO with the ARM7
930 (void)OS_EnableIrqMask(OS_IE_SPFIFO_RECV);
931
932 // Initialize file system
933 FS_Init( FS_DMA_NOT_USE );
934
935 // File table cache
936 need_size = FS_GetTableSize();
937 p_table = OS_Alloc(need_size);
938 SDK_POINTER_ASSERT(p_table);
939 (void)FS_LoadTable(p_table, need_size);
940 }
941