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