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