/* * Copyright 2017-2020 NXP * All rights reserved. * * * SPDX-License-Identifier: BSD-3-Clause */ #include "fsl_cau3.h" /******************************************************************************* * Definitions ******************************************************************************/ /* Component ID definition, used by tools. */ #ifndef FSL_COMPONENT_ID #define FSL_COMPONENT_ID "platform.drivers.cau3" #endif /*! Compile time sizeof() check */ #define BUILD_ASSURE(condition, msg) extern int msg[1 - 2 * (!(condition))] __attribute__((unused)) #define CAU3_SR_TKCS_INITRUN 0x00000000U #define CAU3_SR_TKCS_RUN 0x00000100U #define CAU3_SR_TKCS_DBGHALT 0x00000200U #define CAU3_SR_TKCS_STOPNOERR 0x00000900U #define CAU3_SR_TKCS_STOPERROR 0x00000A00U #define CAU3_SR_TKCS_SECV 0x00000E00U #define CAU3_SR_TKCS_EXTSECV 0x00000F00U #define CAU3_DMEM_STK_BASE 0xfff003f8U #define CAU3_DMEM_AES_RCON 0xfff00A00U #define CAU3_TASK_SECV_INIT 0x00 * 4 #define CAU3_TASK_STOPERROR 0x01 * 4 #define CAU3_TASK_STOPNOERR 0x02 * 4 #define CAU3_TASK_NULL 0x02 * 4 #define CAU3_TASK_BLKLD_DMEM 0x03 * 4 #define CAU3_TASK_LD_KEYCTX 0x04 * 4 #define CAU3_TASK_LD_SP_KEYCTX 0x05 * 4 #define CAU3_TASK_CLR_KEYCTX 0x06 * 4 #define CAU3_TASK_LD_KEY 0x07 * 4 #define CAU3_TASK_LD_KEK 0x08 * 4 #define CAU3_TASK_LD_IV 0x09 * 4 #define CAU3_TASK_AES_KEY_SCH 0x0A * 4 #define CAU3_TASK_AES_ENCRYPT 0x0B * 4 #define CAU3_TASK_AES_DECRYPT 0x0C * 4 #define CAU3_TASK_AES128_ENCRYPT 0x0D * 4 #define CAU3_TASK_AES128_DECRYPT 0x0E * 4 #define CAU3_TASK_AES128_CMAC 0x0F * 4 #define CAU3_TASK_SHA256_INIT_STATE 0x10 * 4 #define CAU3_TASK_SHA256_UPDATE 0x11 * 4 #define CAU3_TASK_KEY_BLOB_UNWRAP 0x12 * 4 #define CAU3_TASK_SHA1_HASH 0x13 * 4 #define CAU3_TASK_SHA1_INIT_STATE 0x14 * 4 #define CAU3_TASK_SHA512_INIT_STATE 0x15 * 4 #define CAU3_TASK_SHA512_UPDATE 0x16 * 4 #define CAU3_TASK_3DES_CHECK_PARITY 0x17 * 4 #define CAU3_TASK_3DES_ENCRYPT 0x18 * 4 #define CAU3_TASK_3DES_DECRYPT 0x19 * 4 #define CAU3_TASK_CHA_POLY_ENCRYPT 0x1A * 4 #define CAU3_TASK_CHA_POLY_DECRYPT 0x1B * 4 #define CAU3_SEMA4_LOCK 0x80000000U #define CAU3_SEMA4_RELEASE 0x00000000U #define CAU3_SMOWNR_OWNED_BY_ME 0x00000001U #define CAU3_SMOWNR_UNLOCKED 0x80000000U /*! @brief keyContext structure in the CAU3's DataMemory */ typedef struct _cau3_key_context { uint32_t keySize; /*!< key size in bytes, 0 = invalid context */ uint32_t streamSize; /*!< rfu-firmware; stream length in bytes */ uint32_t *keySched; /*!< rfu-firmware; ptr to expanded key schedule */ uint32_t zeroFill; /*!< zero (unused) to keep 0-mod-4 alignment */ uint8_t iv[16]; /*!< initialization vector */ uint8_t key[32]; /*!< key for 3des, aes[128,192,256] */ } cau3_key_context_t; typedef enum _cau3_crypt { kCAU3_Encrypt = 0, kCAU3_Decrypt = 1, } cau3_crypt_t; #define cau3_memcpy memcpy /*! Internal states of the HASH creation process */ typedef enum _cau3_hash_algo_state { kCAU3_StateHashInit = 1u, /*!< Init state. */ kCAU3_StateHashUpdate, /*!< Update state. */ } cau3_hash_algo_state_t; /*! multiple of 64-byte block represented as byte array of 32-bit words */ typedef union _cau3_hash_block { uint32_t w[CAU3_HASH_BLOCK_SIZE / 4]; /*!< array of 32-bit words */ uint8_t b[CAU3_HASH_BLOCK_SIZE]; /*!< byte array */ } cau3_hash_block_t; /*! internal cau3_hash context structure */ typedef struct _cau3_hash_ctx_internal { cau3_hash_block_t blk; /*!< memory buffer. only full blocks are written to CAU3 during hash/cmac updates */ size_t blksz; /*!< number of valid bytes in memory buffer */ cau3_hash_algo_t algo; /*!< selected algorithm from the set of supported algorithms */ cau3_hash_algo_state_t state; /*!< finite machine state of the hash software process */ size_t fullMessageSize; /*!< track message size during CAU3_HASH_Update(). The value is used for padding. */ uint32_t runningHash[8]; } cau3_hash_ctx_internal_t; /*!< SHA-1/SHA-2 digest length in bytes */ enum _cau3_hash_digest_len { kCAU3_OutLenSha1 = 20u, kCAU3_OutLenSha256 = 32u, }; /*! 64-byte block represented as byte array of 16 32-bit words */ typedef union _cau3_sha_block { uint32_t w[64 / 4]; /*!< array of 32-bit words */ uint8_t b[64]; /*!< byte array */ } cau3_sha_block_t; /*! Full word representing the actual bit values for the CAU3 1.0 mode register. */ typedef uint32_t cau3_mode_t; #define CAU3_MDPK_ALG_PKHA (0x80U) /*!< Bit field value for CAU3_MDPK_ALG: PKHA */ #define CAU3_MD_ALG_SHIFT 16 typedef enum _cau3_algorithm { kCAU3_AlgorithmPKHA = CAU3_MDPK_ALG_PKHA << CAU3_MD_ALG_SHIFT, } cau3_algorithm_t; /*! @brief CAU3 status flags */ enum _cau3_status_flag { kCAU3_StatusPkhaBusy = 1U << CAU3_STA_PB_SHIFT, kCAU3_StatusDoneIsr = 1U << CAU3_STA_DI_SHIFT, kCAU3_StatusErrorIsr = 1U << CAU3_STA_EI_SHIFT, kCAU3_StatusPublicKeyPrime = 1U << CAU3_STA_PKP_SHIFT, kCAU3_StatusPublicKeyOpOne = 1U << CAU3_STA_PKO_SHIFT, kCAU3_StatusPublicKeyOpZero = 1U << CAU3_STA_PKZ_SHIFT, kCAU3_StatusAll = 0 | kCAU3_StatusDoneIsr | kCAU3_StatusErrorIsr | kCAU3_StatusPkhaBusy | kCAU3_StatusPublicKeyPrime | kCAU3_StatusPublicKeyOpOne | kCAU3_StatusPublicKeyOpZero }; /*! @brief CAU3 clear register */ typedef enum _cau3_clear_written { kCAU3_ClearMode = 1U << 0, kCAU3_ClearDataSize = 1U << 2, kCAU3_ClearPkhaSizeA = 1U << 12, kCAU3_ClearPkhaSizeB = 1U << 13, kCAU3_ClearPkhaSizeN = 1U << 14, kCAU3_ClearPkhaSizeE = 1U << 15, kCAU3_ClearAllSize = (int)kCAU3_ClearPkhaSizeA | kCAU3_ClearPkhaSizeB | kCAU3_ClearPkhaSizeN | kCAU3_ClearPkhaSizeE, kCAU3_ClearAll = (int)(kCAU3_ClearMode | kCAU3_ClearDataSize | kCAU3_ClearAllSize | 0) } cau3_clear_written_t; /*! @brief PKHA functions - arithmetic, copy/clear memory. */ typedef enum _cau3_pkha_func_t { kCAU3_PKHA_ClearMem = 1U, kCAU3_PKHA_ArithModAdd = 2U, /*!< (A + B) mod N */ kCAU3_PKHA_ArithModSub1 = 3U, /*!< (A - B) mod N */ kCAU3_PKHA_ArithModSub2 = 4U, /*!< (B - A) mod N */ kCAU3_PKHA_ArithModMul = 5U, /*!< (A x B) mod N */ kCAU3_PKHA_ArithModExp = 6U, /*!< (A^E) mod N */ kCAU3_PKHA_ArithModRed = 7U, /*!< (A) mod N */ kCAU3_PKHA_ArithModInv = 8U, /*!< (A^-1) mod N */ kCAU3_PKHA_ArithEccAdd = 9U, /*!< (P1 + P2) */ kCAU3_PKHA_ArithEccDouble = 10U, /*!< (P2 + P2) */ kCAU3_PKHA_ArithEccMul = 11U, /*!< (E x P(A0,A1) */ kCAU3_PKHA_ArithModR2 = 12U, /*!< (R^2 mod N) */ kCAU3_PKHA_ArithModRR = 13U, /*!< (RERP mod N) */ kCAU3_PKHA_ArithGcd = 14U, /*!< GCD (A, N) */ kCAU3_PKHA_ArithPrimalityTest = 15U, /*!< Miller-Rabin */ kCAU3_PKHA_CopyMemSizeN = 16U, kCAU3_PKHA_CopyMemSizeSrc = 17U, kCAU3_PKHA_ArithModSqrt = 0x17U, /*!< (B0 x B0) mod N = A mod N */ kCAU3_PKHA_ArithEcmMul = 0x4B, /*!< (E x P[A0]) */ kCAU3_PKHA_ArithEctAdd = 0x89, /*!< (P[A0,A1] + P[B1,B2]) */ kCAU3_PKHA_ArithEctMul = 0x8B, /*!< (E x P[A0,A1]) */ } cau3_pkha_func_t; /*! @brief Register areas for PKHA clear memory operations. */ typedef enum _cau3_pkha_reg_area { kCAU3_PKHA_RegA = 8U, kCAU3_PKHA_RegB = 4U, kCAU3_PKHA_RegE = 2U, kCAU3_PKHA_RegN = 1U, kCAU3_PKHA_RegAll = kCAU3_PKHA_RegA | kCAU3_PKHA_RegB | kCAU3_PKHA_RegE | kCAU3_PKHA_RegN, } cau3_pkha_reg_area_t; /*! @brief Quadrant areas for 2048-bit registers for PKHA copy memory * operations. */ typedef enum _cau3_pkha_quad_area_t { kCAU3_PKHA_Quad0 = 0U, kCAU3_PKHA_Quad1 = 1U, kCAU3_PKHA_Quad2 = 2U, kCAU3_PKHA_Quad3 = 3U, } cau3_pkha_quad_area_t; /*! @brief User-supplied (R^2 mod N) input or CAU3 should calculate. */ typedef enum _cau3_pkha_r2_t { kCAU3_PKHA_CalcR2 = 0U, /*!< Calculate (R^2 mod N) */ kCAU3_PKHA_InputR2 = 1U /*!< (R^2 mod N) supplied as input */ } cau3_pkha_r2_t; /*! @brief CAU3 PKHA parameters */ typedef struct _cau3_pkha_mode_params_t { cau3_pkha_func_t func; cau3_pkha_f2m_t arithType; cau3_pkha_montgomery_form_t montFormIn; cau3_pkha_montgomery_form_t montFormOut; cau3_pkha_reg_area_t srcReg; cau3_pkha_quad_area_t srcQuad; cau3_pkha_reg_area_t dstReg; cau3_pkha_quad_area_t dstQuad; cau3_pkha_timing_t equalTime; cau3_pkha_r2_t r2modn; } cau3_pkha_mode_params_t; /******************************************************************************* * Variables ******************************************************************************/ /******************************************************************************* * CAU3 Read-Only Data Constants and CryptoCore Code Image ******************************************************************************/ /* in the cau3's private, local data memory, there is a section for read-only */ /* constants associated with AES, SHA-1, SHA-256, SHA-384 and SHA-512. */ /* the memory organization and layout of this section is defined as: */ /* */ /* description size dmem_base description */ /* cau_dmem_aes_rcon 48 FFF00800 RO aes constants 10 x 32b */ /* cau_dmem_sha1_k 16 FFF00830 RO sha1 initial "k" 4 x 32b */ /* cau_dmem_sha1_init_h 32 FFF00840 RO sha1 initial state 5 x 32b */ /* cau_dmem_sha224_init_h 32 FFF00860 RO sha224 initial state 8 x 32b */ /* cau_dmem_sha256_init_h 32 FFF00880 RO sha256 initial state 8 x 32b */ /* cau_dmem_sha256_k 256 FFF008A0 RO sha256 initial "k" 64 x 32b */ /* cau_dmem_sha384_init_h 64 FFF009A0 RO sha384 initial state 16 x 32b */ /* cau_dmem_sha512_init_h 64 FFF009E0 RO sha512 initial state 16 x 32b */ /* cau_dmem_sha512_k 640 FFF00A20 RO sha512 initial "k" 160 x 32b */ /* */ /* data size allocation are rounded up to be modulo 16 bytes as required. */ /* */ static const uint32_t s_cau3ReadOnlyConstants[] __attribute__((aligned(16))) = { /* AES RCON[] */ 0x01000000U, 0x02000000U, 0x04000000U, 0x08000000U, 0x10000000U, 0x20000000U, 0x40000000U, 0x80000000U, 0x1b000000U, 0x36000000U, 0x00000000U, 0x00000000U, /* zero fill for 0-mod-16 alignment */ /* SHA1_K[] */ 0x5a827999U, 0x6ed9eba1U, 0x8f1bbcdcU, 0xca62c1d6U, /* SHA1_INIT_H[] */ 0x67452301U, 0xefcdab89U, 0x98badcfeU, 0x10325476U, 0xc3d2e1f0U, 0x00000000U, 0x00000000U, 0x00000000U, /* zero fill for 0-mod-16 alignemnt */ /* SHA224_INIT_H[] */ 0xc1059ed8U, 0x367cd507U, 0x3070dd17U, 0xf70e5939U, 0xffc00b31U, 0x68581511U, 0x64f98fa7U, 0xbefa4fa4U, /* SHA256_INIT_H[] */ /* As described in FIPS PUB 180-4 "Secure Hash Standard", the initial hash value */ /* for SHA-256 is obtained by taking the first thirty-two bits of the fractional */ /* parts of the square roots of the first eight prime numbers. */ 0x6a09e667U, 0xbb67ae85U, 0x3c6ef372U, 0xa54ff53aU, 0x510e527fU, 0x9b05688cU, 0x1f83d9abU, 0x5be0cd19U, /* SHA256_K[], also used as SHA224_K[] */ /* As described in FIPS PUB 180-4 "Secure Hash Standard", SHA-224 & SHA-256 use */ /* the same sequence of sixty-four constant 32-bit words (K[]), where the words */ /* represent the first thirty-two bits of the fractional parts of the cube roots */ /* of the first sixty-four prime numbers. */ 0x428a2f98U, 0x71374491U, 0xb5c0fbcfU, 0xe9b5dba5U, 0x3956c25bU, 0x59f111f1U, 0x923f82a4U, 0xab1c5ed5U, 0xd807aa98U, 0x12835b01U, 0x243185beU, 0x550c7dc3U, 0x72be5d74U, 0x80deb1feU, 0x9bdc06a7U, 0xc19bf174U, 0xe49b69c1U, 0xefbe4786U, 0x0fc19dc6U, 0x240ca1ccU, 0x2de92c6fU, 0x4a7484aaU, 0x5cb0a9dcU, 0x76f988daU, 0x983e5152U, 0xa831c66dU, 0xb00327c8U, 0xbf597fc7U, 0xc6e00bf3U, 0xd5a79147U, 0x06ca6351U, 0x14292967U, 0x27b70a85U, 0x2e1b2138U, 0x4d2c6dfcU, 0x53380d13U, 0x650a7354U, 0x766a0abbU, 0x81c2c92eU, 0x92722c85U, 0xa2bfe8a1U, 0xa81a664bU, 0xc24b8b70U, 0xc76c51a3U, 0xd192e819U, 0xd6990624U, 0xf40e3585U, 0x106aa070U, 0x19a4c116U, 0x1e376c08U, 0x2748774cU, 0x34b0bcb5U, 0x391c0cb3U, 0x4ed8aa4aU, 0x5b9cca4fU, 0x682e6ff3U, 0x748f82eeU, 0x78a5636fU, 0x84c87814U, 0x8cc70208U, 0x90befffaU, 0xa4506cebU, 0xbef9a3f7U, 0xc67178f2U, /* SHA384_INIT_H[] */ /* 8 x 64-bit words in little-endian format */ 0xc1059ed8U, 0xcbbb9d5dU, 0x367cd507U, 0x629a292aU, 0x3070dd17U, 0x9159015aU, 0xf70e5939U, 0x152fecd8U, 0xffc00b31U, 0x67332667U, 0x68581511U, 0x8eb44a87U, 0x64f98fa7U, 0xdb0c2e0dU, 0xbefa4fa4U, 0x47b5481dU, /* SHA512_INIT_H[] */ /* 8 x 64-bit words in little-endian format */ 0xf3bcc908U, 0x6a09e667U, 0x84caa73bU, 0xbb67ae85U, 0xfe94f82bU, 0x3c6ef372U, 0x5f1d36f1U, 0xa54ff53aU, 0xade682d1U, 0x510e527fU, 0x2b3e6c1fU, 0x9b05688cU, 0xfb41bd6bU, 0x1f83d9abU, 0x137e2179U, 0x5be0cd19U, /* SHA512_K[] */ /* 80 x 64-bit words in little-endian format */ 0xd728ae22U, 0x428a2f98U, 0x23ef65cdU, 0x71374491U, 0xec4d3b2fU, 0xb5c0fbcfU, 0x8189dbbcU, 0xe9b5dba5U, 0xf348b538U, 0x3956c25bU, 0xb605d019U, 0x59f111f1U, 0xaf194f9bU, 0x923f82a4U, 0xda6d8118U, 0xab1c5ed5U, 0xa3030242U, 0xd807aa98U, 0x45706fbeU, 0x12835b01U, 0x4ee4b28cU, 0x243185beU, 0xd5ffb4e2U, 0x550c7dc3U, 0xf27b896fU, 0x72be5d74U, 0x3b1696b1U, 0x80deb1feU, 0x25c71235U, 0x9bdc06a7U, 0xcf692694U, 0xc19bf174U, 0x9ef14ad2U, 0xe49b69c1U, 0x384f25e3U, 0xefbe4786U, 0x8b8cd5b5U, 0x0fc19dc6U, 0x77ac9c65U, 0x240ca1ccU, 0x592b0275U, 0x2de92c6fU, 0x6ea6e483U, 0x4a7484aaU, 0xbd41fbd4U, 0x5cb0a9dcU, 0x831153b5U, 0x76f988daU, 0xee66dfabU, 0x983e5152U, 0x2db43210U, 0xa831c66dU, 0x98fb213fU, 0xb00327c8U, 0xbeef0ee4U, 0xbf597fc7U, 0x3da88fc2U, 0xc6e00bf3U, 0x930aa725U, 0xd5a79147U, 0xe003826fU, 0x06ca6351U, 0x0a0e6e70U, 0x14292967U, 0x46d22ffcU, 0x27b70a85U, 0x5c26c926U, 0x2e1b2138U, 0x5ac42aedU, 0x4d2c6dfcU, 0x9d95b3dfU, 0x53380d13U, 0x8baf63deU, 0x650a7354U, 0x3c77b2a8U, 0x766a0abbU, 0x47edaee6U, 0x81c2c92eU, 0x1482353bU, 0x92722c85U, 0x4cf10364U, 0xa2bfe8a1U, 0xbc423001U, 0xa81a664bU, 0xd0f89791U, 0xc24b8b70U, 0x0654be30U, 0xc76c51a3U, 0xd6ef5218U, 0xd192e819U, 0x5565a910U, 0xd6990624U, 0x5771202aU, 0xf40e3585U, 0x32bbd1b8U, 0x106aa070U, 0xb8d2d0c8U, 0x19a4c116U, 0x5141ab53U, 0x1e376c08U, 0xdf8eeb99U, 0x2748774cU, 0xe19b48a8U, 0x34b0bcb5U, 0xc5c95a63U, 0x391c0cb3U, 0xe3418acbU, 0x4ed8aa4aU, 0x7763e373U, 0x5b9cca4fU, 0xd6b2b8a3U, 0x682e6ff3U, 0x5defb2fcU, 0x748f82eeU, 0x43172f60U, 0x78a5636fU, 0xa1f0ab72U, 0x84c87814U, 0x1a6439ecU, 0x8cc70208U, 0x23631e28U, 0x90befffaU, 0xde82bde9U, 0xa4506cebU, 0xb2c67915U, 0xbef9a3f7U, 0xe372532bU, 0xc67178f2U, 0xea26619cU, 0xca273eceU, 0x21c0c207U, 0xd186b8c7U, 0xcde0eb1eU, 0xeada7dd6U, 0xee6ed178U, 0xf57d4f7fU, 0x72176fbaU, 0x06f067aaU, 0xa2c898a6U, 0x0a637dc5U, 0xbef90daeU, 0x113f9804U, 0x131c471bU, 0x1b710b35U, 0x23047d84U, 0x28db77f5U, 0x40c72493U, 0x32caab7bU, 0x15c9bebcU, 0x3c9ebe0aU, 0x9c100d4cU, 0x431d67c4U, 0xcb3e42b6U, 0x4cc5d4beU, 0xfc657e2aU, 0x597f299cU, 0x3ad6faecU, 0x5fcb6fabU, 0x4a475817U, 0x6c44198cU, /* CHACHA_K[] */ 0x61707865U, 0x3320646eU, 0x79622d32U, 0x6b206574U}; static const uint32_t s_cau3ReadOnlyConstantsBytes = sizeof(s_cau3ReadOnlyConstants); static const uint32_t s_cau3ImemImage[] __attribute__((aligned(16))) = { 0x60C00000U, 0x54000040U, 0x54000020U, 0x60812760U, 0x608128C0U, 0x60812F00U, 0x60813640U, 0x608138C0U, 0x54000040U, 0x60813C20U, 0x60813F40U, 0x60802060U, 0x60803BC0U, 0x60805780U, 0x54000040U, 0x60806800U, 0x60808AA0U, 0x60808D00U, 0x60814120U, 0x6080C100U, 0x6080BF60U, 0x54000040U, 0x54000040U, 0x6080FB60U, 0x6080FE20U, 0x608112C0U, 0x608150C0U, 0x60815700U, 0x54000040U, 0x54000040U, 0x54000040U, 0x54000040U, 0x86000280U, 0x86002282U, 0x08C82236U, 0x2000C011U, 0x101FFE11U, 0x00405A31U, 0x20014015U, 0x101FFE15U, 0x00800004U, 0x00800425U, 0x00800846U, 0x00800C67U, 0xCE002220U, 0xCE002222U, 0x3C000192U, 0x66801420U, 0x63801400U, 0x86004284U, 0x86006286U, 0xCE002224U, 0xCE002226U, 0x08D020E8U, 0x01800108U, 0xAC0012A8U, 0x008C2000U, 0x008C0021U, 0x008C0442U, 0x008C0863U, 0xCE002220U, 0xCE002222U, 0x01800068U, 0x008C2084U, 0x008C10A5U, 0x008C14C6U, 0x008C18E7U, 0xCE002224U, 0xCE002226U, 0x08D020E8U, 0x01800108U, 0xAC0012A8U, 0x008C2000U, 0x008C0021U, 0x008C0442U, 0x008C0863U, 0xCE002220U, 0xCE002222U, 0x01800068U, 0x008C2084U, 0x008C10A5U, 0x008C14C6U, 0x008C18E7U, 0xCE002224U, 0xCE002226U, 0x08D020E8U, 0x01800108U, 0xAC0012A8U, 0x008C2000U, 0x008C0021U, 0x008C0442U, 0x008C0863U, 0xCE002220U, 0xCE002222U, 0x01800068U, 0x008C2084U, 0x008C10A5U, 0x008C14C6U, 0x008C18E7U, 0xCE002224U, 0xCE002226U, 0x08D020E8U, 0x01800108U, 0xAC0012A8U, 0x008C2000U, 0x008C0021U, 0x008C0442U, 0x008C0863U, 0xCE002220U, 0xCE002222U, 0x01800068U, 0x008C2084U, 0x008C10A5U, 0x008C14C6U, 0x008C18E7U, 0xCE002224U, 0xCE002226U, 0x08D020E8U, 0x01800108U, 0xAC0012A8U, 0x008C2000U, 0x008C0021U, 0x008C0442U, 0x008C0863U, 0xCE002220U, 0xCE002222U, 0x01800068U, 0x008C2084U, 0x008C10A5U, 0x008C14C6U, 0x008C18E7U, 0xCE002224U, 0xCE002226U, 0x08D020E8U, 0x01800108U, 0xAC0012A8U, 0x008C2000U, 0x008C0021U, 0x008C0442U, 0x008C0863U, 0xCE002220U, 0xCE002222U, 0x01800068U, 0x008C2084U, 0x008C10A5U, 0x008C14C6U, 0x008C18E7U, 0xCE002224U, 0xCE002226U, 0x08D020E8U, 0x01800108U, 0xAC0012A8U, 0x008C2000U, 0x008C0021U, 0x008C0442U, 0x008C0863U, 0xCE002220U, 0xCE002222U, 0x29FFE211U, 0x60801F80U, 0x54000040U, 0x08D02067U, 0x018000E7U, 0xAC0012A7U, 0x008C1C00U, 0x008C0021U, 0x008C0442U, 0x008C0863U, 0xCE002220U, 0xCE002222U, 0x08D02067U, 0x018000E7U, 0xAC0012A7U, 0x008C1C00U, 0x008C0021U, 0x008C0442U, 0x008C0863U, 0xCE002220U, 0xCE002222U, 0x08D02067U, 0x018000E7U, 0xAC0012A7U, 0x008C1C00U, 0x008C0021U, 0x008C0442U, 0x008C0863U, 0xCE002220U, 0xCE002222U, 0x08D02067U, 0x018000E7U, 0xAC0012A7U, 0x008C1C00U, 0x008C0021U, 0x008C0442U, 0x008C0863U, 0xCE002220U, 0xCE002222U, 0x08D02067U, 0x018000E7U, 0xAC0012A7U, 0x008C1C00U, 0x008C0021U, 0x008C0442U, 0x008C0863U, 0xCE002220U, 0xCE002222U, 0x08D02067U, 0x018000E7U, 0xAC0012A7U, 0x008C1C00U, 0x008C0021U, 0x008C0442U, 0x008C0863U, 0xCE002220U, 0xCE002222U, 0x08D02067U, 0x018000E7U, 0xAC0012A7U, 0x008C1C00U, 0x008C0021U, 0x008C0442U, 0x008C0863U, 0xCE002220U, 0xCE002222U, 0x08D02067U, 0x018000E7U, 0xAC0012A7U, 0x008C1C00U, 0x008C0021U, 0x008C0442U, 0x008C0863U, 0xCE002220U, 0xCE002222U, 0x08D02067U, 0x018000E7U, 0xAC0012A7U, 0x008C1C00U, 0x008C0021U, 0x008C0442U, 0x008C0863U, 0xCE002220U, 0xCE002222U, 0x08D02067U, 0x018000E7U, 0xAC0012A7U, 0x008C1C00U, 0x008C0021U, 0x008C0442U, 0x008C0863U, 0xCE002220U, 0xCE002222U, 0x29FFEA11U, 0x04807FFFU, 0xC4FFA291U, 0x63802000U, 0x7080001FU, 0x5C1FFFE0U, 0x581FFFE0U, 0x54000020U, 0x08800E31U, 0x08C81A20U, 0x2000A012U, 0x101FFE12U, 0x80000252U, 0x3C000312U, 0x668021A0U, 0x63802180U, 0x08501A52U, 0x08501A52U, 0x08501A52U, 0x08C82236U, 0x2000C011U, 0x101FFE11U, 0x00405A31U, 0x0C800E04U, 0x638029C0U, 0x3C000024U, 0x63802780U, 0x3C000044U, 0x63802540U, 0x94FFF605U, 0x08C860A0U, 0x94000605U, 0x08CC20A6U, 0x00881800U, 0x08C860A1U, 0x94001605U, 0x08CC20A6U, 0x00881821U, 0x08C860A2U, 0x94002605U, 0x08CC20A6U, 0x00881842U, 0x08C860A3U, 0x94003605U, 0x08CC20A6U, 0x00881863U, 0x60802A40U, 0x94FFFA05U, 0x08C840A0U, 0x94000A05U, 0x08CC40A6U, 0x00881800U, 0x08C840A1U, 0x94001A05U, 0x08CC40A6U, 0x00881821U, 0x08C840A2U, 0x94002A05U, 0x08CC40A6U, 0x00881842U, 0x08C840A3U, 0x94003A05U, 0x08CC40A6U, 0x00881863U, 0x60802A40U, 0x94FFFE05U, 0x08C820A0U, 0x94000E05U, 0x08CC60A6U, 0x00881800U, 0x08C820A1U, 0x94001E05U, 0x08CC60A6U, 0x00881821U, 0x08C820A2U, 0x94002E05U, 0x08CC60A6U, 0x00881842U, 0x08C820A3U, 0x94003E05U, 0x08CC60A6U, 0x00881863U, 0x60802A40U, 0x94000200U, 0x94001201U, 0x94002202U, 0x94003203U, 0xAC001220U, 0xAC001221U, 0xAC001222U, 0xAC001223U, 0x08500A48U, 0x08CC0508U, 0x01800000U, 0x01800021U, 0x01800042U, 0x01800063U, 0x01900000U, 0x8E002224U, 0x8E002226U, 0x01881000U, 0x01881421U, 0x01881842U, 0x01881C63U, 0x01800000U, 0x01800021U, 0x01800042U, 0x01800063U, 0x01900000U, 0x8E002224U, 0x8E002226U, 0x01881000U, 0x01881421U, 0x01881842U, 0x01881C63U, 0x60002B08U, 0x01800000U, 0x01800021U, 0x01800042U, 0x01800063U, 0x01900000U, 0x8E002224U, 0x8E002226U, 0x01881000U, 0x01881421U, 0x01881842U, 0x01881C63U, 0x01800000U, 0x01800021U, 0x01800042U, 0x01800063U, 0x01900000U, 0xAC001220U, 0xAC001221U, 0xAC001222U, 0xAC001223U, 0x0C800E64U, 0x63803A80U, 0x3C000024U, 0x63803760U, 0x3C000044U, 0x63803440U, 0x94FFF664U, 0x08CC2084U, 0x08C82084U, 0x08CC6005U, 0x008810A5U, 0xD4FFF665U, 0x08C82005U, 0x08CC6024U, 0x008810A5U, 0xD4000665U, 0x08C82025U, 0x08CC6044U, 0x008810A5U, 0xD4001665U, 0x08C82045U, 0x08CC6064U, 0x008810A5U, 0xD4002665U, 0x94003664U, 0x08C86084U, 0x08CC6084U, 0x08C82065U, 0x008810A5U, 0xD4003665U, 0x60803B00U, 0x94FFFA64U, 0x08CC4084U, 0x08C84084U, 0x08CC4005U, 0x008810A5U, 0xD4FFFA65U, 0x08C84005U, 0x08CC4024U, 0x008810A5U, 0xD4000A65U, 0x08C84025U, 0x08CC4044U, 0x008810A5U, 0xD4001A65U, 0x08C84045U, 0x08CC4064U, 0x008810A5U, 0xD4002A65U, 0x94003A64U, 0x08C84084U, 0x08CC4084U, 0x08C84065U, 0x008810A5U, 0xD4003A65U, 0x60803B00U, 0x94FFFE64U, 0x08CC6084U, 0x08C86084U, 0x08CC2005U, 0x008810A5U, 0xD4FFFE65U, 0x08C86005U, 0x08CC2024U, 0x008810A5U, 0xD4000E65U, 0x08C86025U, 0x08CC2044U, 0x008810A5U, 0xD4001E65U, 0x08C86045U, 0x08CC2064U, 0x008810A5U, 0xD4002E65U, 0x94003E64U, 0x08C82084U, 0x08CC2084U, 0x08C86065U, 0x008810A5U, 0xD4003E65U, 0x60803B00U, 0xD4000260U, 0xD4001261U, 0xD4002262U, 0xD4003263U, 0x04807FFFU, 0x63803B60U, 0x7080001FU, 0x5C1FFFE0U, 0x581FFFE0U, 0x54000020U, 0x08800E31U, 0x08C81A20U, 0x2000A012U, 0x101FFE12U, 0x80000252U, 0x3C000312U, 0x66803D00U, 0x63803CE0U, 0x08501A52U, 0x08501A52U, 0x08501A52U, 0x08C82236U, 0x2000C011U, 0x101FFE11U, 0x00405A31U, 0x0C800E04U, 0x63804520U, 0x3C000024U, 0x638042E0U, 0x3C000044U, 0x638040A0U, 0x94FFF605U, 0x08C860A0U, 0x94000605U, 0x08CC20A6U, 0x00881800U, 0x08C860A1U, 0x94001605U, 0x08CC20A6U, 0x00881821U, 0x08C860A2U, 0x94002605U, 0x08CC20A6U, 0x00881842U, 0x08C860A3U, 0x94003605U, 0x08CC20A6U, 0x00881863U, 0x608045A0U, 0x94FFFA05U, 0x08C840A0U, 0x94000A05U, 0x08CC40A6U, 0x00881800U, 0x08C840A1U, 0x94001A05U, 0x08CC40A6U, 0x00881821U, 0x08C840A2U, 0x94002A05U, 0x08CC40A6U, 0x00881842U, 0x08C840A3U, 0x94003A05U, 0x08CC40A6U, 0x00881863U, 0x608045A0U, 0x94FFFE05U, 0x08C820A0U, 0x94000E05U, 0x08CC60A6U, 0x00881800U, 0x08C820A1U, 0x94001E05U, 0x08CC60A6U, 0x00881821U, 0x08C820A2U, 0x94002E05U, 0x08CC60A6U, 0x00881842U, 0x08C820A3U, 0x94003E05U, 0x08CC60A6U, 0x00881863U, 0x608045A0U, 0x94000200U, 0x94001201U, 0x94002202U, 0x94003203U, 0x08C81259U, 0x00406631U, 0xA8003223U, 0xA8FFF222U, 0xA8FFF221U, 0xA8FFF220U, 0x08500A59U, 0x08CC0739U, 0x01940000U, 0x01840063U, 0x01840042U, 0x01840021U, 0x01840000U, 0x8AFFE23CU, 0x8AFFE23AU, 0x018C7463U, 0x018C7042U, 0x018C6C21U, 0x018C6800U, 0x01940000U, 0x01840063U, 0x01840042U, 0x01840021U, 0x01840000U, 0x8AFFE23CU, 0x8AFFE23AU, 0x018C7463U, 0x018C7042U, 0x018C6C21U, 0x018C6800U, 0x600046B9U, 0x01940000U, 0x01840063U, 0x01840042U, 0x01840021U, 0x01840000U, 0x8AFFE23CU, 0x8AFFE23AU, 0x018C7463U, 0x018C7042U, 0x018C6C21U, 0x018C6800U, 0x01940000U, 0x01840063U, 0x01840042U, 0x01840021U, 0x01840000U, 0xA8FFF223U, 0xA8FFF222U, 0xA8FFF221U, 0xA8FFF220U, 0x0C800E79U, 0x63805620U, 0x3C000039U, 0x63805300U, 0x3C000059U, 0x63804FE0U, 0x94FFF664U, 0x08CC2084U, 0x08C82084U, 0x08CC6005U, 0x008810A5U, 0xD4FFF665U, 0x08C82005U, 0x08CC6024U, 0x008810A5U, 0xD4000665U, 0x08C82025U, 0x08CC6044U, 0x008810A5U, 0xD4001665U, 0x08C82045U, 0x08CC6064U, 0x008810A5U, 0xD4002665U, 0x94003664U, 0x08C86084U, 0x08CC6084U, 0x08C82065U, 0x008810A5U, 0xD4003665U, 0x608056A0U, 0x94FFFA64U, 0x08CC4084U, 0x08C84084U, 0x08CC4005U, 0x008810A5U, 0xD4FFFA65U, 0x08C84005U, 0x08CC4024U, 0x008810A5U, 0xD4000A65U, 0x08C84025U, 0x08CC4044U, 0x008810A5U, 0xD4001A65U, 0x08C84045U, 0x08CC4064U, 0x008810A5U, 0xD4002A65U, 0x94003A64U, 0x08C84084U, 0x08CC4084U, 0x08C84065U, 0x008810A5U, 0xD4003A65U, 0x608056A0U, 0x94FFFE64U, 0x08CC6084U, 0x08C86084U, 0x08CC2005U, 0x008810A5U, 0xD4FFFE65U, 0x08C86005U, 0x08CC2024U, 0x008810A5U, 0xD4000E65U, 0x08C86025U, 0x08CC2044U, 0x008810A5U, 0xD4001E65U, 0x08C86045U, 0x08CC2064U, 0x008810A5U, 0xD4002E65U, 0x94003E64U, 0x08C82084U, 0x08CC2084U, 0x08C86065U, 0x008810A5U, 0xD4003E65U, 0x608056A0U, 0xD4003263U, 0xD4002262U, 0xD4001261U, 0xD4000260U, 0x04807FFFU, 0x63805700U, 0x7080001FU, 0x5C1FFFE0U, 0x581FFFE0U, 0x54000020U, 0x7080001FU, 0x08800E31U, 0x08C82236U, 0x2000C011U, 0x101FFE11U, 0x00405A31U, 0x94000200U, 0x94001201U, 0x94002202U, 0x94003203U, 0xAC001220U, 0xAC001221U, 0xAC001222U, 0xAC001223U, 0x01800000U, 0x01800021U, 0x01800042U, 0x01800063U, 0x01900000U, 0x8E002224U, 0x8E002226U, 0x01881000U, 0x01881421U, 0x01881842U, 0x01881C63U, 0x01800000U, 0x01800021U, 0x01800042U, 0x01800063U, 0x01900000U, 0x8E002224U, 0x8E002226U, 0x01881000U, 0x01881421U, 0x01881842U, 0x01881C63U, 0x01800000U, 0x01800021U, 0x01800042U, 0x01800063U, 0x01900000U, 0x8E002224U, 0x8E002226U, 0x01881000U, 0x01881421U, 0x01881842U, 0x01881C63U, 0x01800000U, 0x01800021U, 0x01800042U, 0x01800063U, 0x01900000U, 0x8E002224U, 0x8E002226U, 0x01881000U, 0x01881421U, 0x01881842U, 0x01881C63U, 0x01800000U, 0x01800021U, 0x01800042U, 0x01800063U, 0x01900000U, 0x8E002224U, 0x8E002226U, 0x01881000U, 0x01881421U, 0x01881842U, 0x01881C63U, 0x01800000U, 0x01800021U, 0x01800042U, 0x01800063U, 0x01900000U, 0x8E002224U, 0x8E002226U, 0x01881000U, 0x01881421U, 0x01881842U, 0x01881C63U, 0x01800000U, 0x01800021U, 0x01800042U, 0x01800063U, 0x01900000U, 0x8E002224U, 0x8E002226U, 0x01881000U, 0x01881421U, 0x01881842U, 0x01881C63U, 0x01800000U, 0x01800021U, 0x01800042U, 0x01800063U, 0x01900000U, 0x8E002224U, 0x8E002226U, 0x01881000U, 0x01881421U, 0x01881842U, 0x01881C63U, 0x01800000U, 0x01800021U, 0x01800042U, 0x01800063U, 0x01900000U, 0x8E002224U, 0x8E002226U, 0x01881000U, 0x01881421U, 0x01881842U, 0x01881C63U, 0x01800000U, 0x01800021U, 0x01800042U, 0x01800063U, 0x01900000U, 0xAC001220U, 0xAC001221U, 0xAC001222U, 0xAC001223U, 0xD4000260U, 0xD4001261U, 0xD4002262U, 0xD4003263U, 0x04807FFFU, 0x29FFEA11U, 0x638067A0U, 0x7080001FU, 0x5C1FFFE0U, 0x581FFFE0U, 0x54000020U, 0xC8FF03DEU, 0xC40013DFU, 0x2000A114U, 0x101FFE14U, 0x08C81A31U, 0x00405231U, 0x84000231U, 0x04804631U, 0x63006940U, 0x54000040U, 0x5C0001E0U, 0x700058BFU, 0x08CC7C04U, 0x04800000U, 0x04980063U, 0x04980042U, 0x04980021U, 0x04980000U, 0x60006A84U, 0x088E1C63U, 0xC40043C0U, 0xC40053C1U, 0xC40063C2U, 0xC40073C3U, 0x08CC7C04U, 0x04800000U, 0x04980063U, 0x04980042U, 0x04980021U, 0x04980000U, 0x60006C04U, 0x088E1C63U, 0xC40083C0U, 0xC40093C1U, 0xC400A3C2U, 0xC400B3C3U, 0x0C800E09U, 0x63806D20U, 0x08C80D2AU, 0x088C7D4BU, 0x2800002BU, 0x08403E4DU, 0x0CCC11ADU, 0x63006DE0U, 0x2000002DU, 0x2000000EU, 0x60806E80U, 0x0C803E4FU, 0x63806E60U, 0x2000000EU, 0x60806E80U, 0x2000002EU, 0x085005ADU, 0x08C811ACU, 0x0040418CU, 0x600072CEU, 0x0C800E09U, 0x638071A0U, 0x0050258CU, 0x9C001189U, 0x00C82920U, 0x9C001189U, 0x00CC2D39U, 0x00886400U, 0x00C82921U, 0x9C001189U, 0x00CC2D39U, 0x00886421U, 0x00C82922U, 0x9C001189U, 0x00CC2D39U, 0x00886442U, 0x00C82923U, 0x9C001189U, 0x00CC2D39U, 0x00886463U, 0x60807220U, 0x94000180U, 0x94001181U, 0x94002182U, 0x94003183U, 0xA40043C0U, 0xA40053C1U, 0xA40063C2U, 0xA40073C3U, 0x60808340U, 0x5C003E00U, 0x04803DEFU, 0x638077C0U, 0x0C800E09U, 0x63807680U, 0x0050258CU, 0x9C001189U, 0x00C82924U, 0x9C001189U, 0x00CC2D39U, 0x00886484U, 0x0C5015F8U, 0x658077C0U, 0x00C82925U, 0x9C001189U, 0x00CC2D39U, 0x008864A5U, 0x0C501318U, 0x658077C0U, 0x00C82926U, 0x9C001189U, 0x00CC2D39U, 0x008864C6U, 0x0C501318U, 0x658077C0U, 0x00C82927U, 0x9C001189U, 0x00CC2D39U, 0x008864E7U, 0x608077C0U, 0x94000184U, 0x0C5015E9U, 0x658077C0U, 0x94001185U, 0x0C501129U, 0x658077C0U, 0x94002186U, 0x0C501129U, 0x658077C0U, 0x94003187U, 0x2001E194U, 0x10000014U, 0x08C809EFU, 0x00403E9FU, 0x7080001FU, 0x60807A60U, 0x60807AC0U, 0x60807B60U, 0x60807C00U, 0x60807C80U, 0x60807CE0U, 0x60807D80U, 0x60807E20U, 0x60807EA0U, 0x60807F00U, 0x60807FA0U, 0x60808040U, 0x608080C0U, 0x60808120U, 0x608081C0U, 0x60808260U, 0x10100008U, 0x00882084U, 0x608082C0U, 0x101FE008U, 0x00802084U, 0x10001008U, 0x00882084U, 0x608082C0U, 0x101FFFE8U, 0x00802084U, 0x30100008U, 0x00882084U, 0x608082C0U, 0x31FFE008U, 0x00802084U, 0x088A0084U, 0x608082C0U, 0x10100008U, 0x008820A5U, 0x608082C0U, 0x101FE008U, 0x008020A5U, 0x10001008U, 0x008820A5U, 0x608082C0U, 0x101FFFE8U, 0x008020A5U, 0x30100008U, 0x008820A5U, 0x608082C0U, 0x31FFE008U, 0x008020A5U, 0x088A00A5U, 0x608082C0U, 0x10100008U, 0x008820C6U, 0x608082C0U, 0x101FE008U, 0x008020C6U, 0x10001008U, 0x008820C6U, 0x608082C0U, 0x101FFFE8U, 0x008020C6U, 0x30100008U, 0x008820C6U, 0x608082C0U, 0x31FFE008U, 0x008020C6U, 0x088A00C6U, 0x608082C0U, 0x10100008U, 0x008820E7U, 0x608082C0U, 0x101FE008U, 0x008020E7U, 0x10001008U, 0x008820E7U, 0x608082C0U, 0x101FFFE8U, 0x008020E7U, 0x30100008U, 0x008820E7U, 0x608082C0U, 0x31FFE008U, 0x008020E7U, 0x088A00E7U, 0x008C1000U, 0x008C1421U, 0x008C1842U, 0x008C1C63U, 0xC400C3C0U, 0xC400D3C1U, 0xC400E3C2U, 0xC400F3C3U, 0x5C0001E0U, 0x048035ADU, 0x63808880U, 0x0C800E09U, 0x638087A0U, 0x00502617U, 0x9C0012E9U, 0x00C82938U, 0x9C0012E9U, 0x00CC2D39U, 0x00886718U, 0x008C6000U, 0x00C82938U, 0x9C0012E9U, 0x00CC2D39U, 0x00886718U, 0x008C6021U, 0x00C82938U, 0x9C0012E9U, 0x00CC2D39U, 0x00886718U, 0x008C6042U, 0x00C82938U, 0x9C0012E9U, 0x00CC2D39U, 0x00886718U, 0x008C6063U, 0x700058BFU, 0x28000210U, 0x600084ADU, 0x60808880U, 0xB4000200U, 0xB4001201U, 0xB4002202U, 0xB4003203U, 0x700058BFU, 0x28000210U, 0x600087ADU, 0xA400C3C0U, 0xA400D3C1U, 0xA400E3C2U, 0xA400F3C3U, 0x700058BFU, 0xD4000260U, 0xD4001261U, 0xD4002262U, 0xD4003263U, 0x840013DFU, 0x840003DEU, 0x04807FFFU, 0x63808A40U, 0x7080001FU, 0x5C1FFFE0U, 0x581FFFE0U, 0x54000020U, 0x20015000U, 0x101FFE00U, 0x84000001U, 0x84001002U, 0x84002003U, 0x84003004U, 0x84004005U, 0x84005006U, 0x84006007U, 0x84007008U, 0xD40003A1U, 0xD40013A2U, 0xD40023A3U, 0xD40033A4U, 0xD40043A5U, 0xD40053A6U, 0xD40063A7U, 0xD40073A8U, 0x54000020U, 0xC8FF93DEU, 0xC40013DFU, 0x940003A1U, 0x940013A2U, 0x940023A3U, 0x940033A4U, 0x940043A5U, 0x940053A6U, 0x940063A7U, 0x940073A8U, 0xC40043DBU, 0x0C800F7AU, 0x63808F80U, 0x00506B7BU, 0x2800009BU, 0x08C80F5AU, 0xC40053DAU, 0x088C7F5AU, 0x2800003AU, 0xC40063DAU, 0x2001541AU, 0x101FFE1AU, 0xC40033DDU, 0xC40023DCU, 0x840043DFU, 0x0C800FFFU, 0x6380A8A0U, 0x94FFF37FU, 0x840053DCU, 0x00C873E9U, 0x9C00137FU, 0x840063DCU, 0x00CC73FDU, 0x00887529U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x840053DCU, 0x00C873E9U, 0x9C00137FU, 0x840063DCU, 0x00CC73FDU, 0x00887529U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x840053DCU, 0x00C873E9U, 0x9C00137FU, 0x840063DCU, 0x00CC73FDU, 0x00887529U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x840053DCU, 0x00C873E9U, 0x9C00137FU, 0x840063DCU, 0x00CC73FDU, 0x00887529U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x840053DCU, 0x00C873E9U, 0x9C00137FU, 0x840063DCU, 0x00CC73FDU, 0x00887529U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x840053DCU, 0x00C873E9U, 0x9C00137FU, 0x840063DCU, 0x00CC73FDU, 0x00887529U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x840053DCU, 0x00C873E9U, 0x9C00137FU, 0x840063DCU, 0x00CC73FDU, 0x00887529U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x840053DCU, 0x00C873E9U, 0x9C00137FU, 0x840063DCU, 0x00CC73FDU, 0x00887529U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x840053DCU, 0x00C873E9U, 0x9C00137FU, 0x840063DCU, 0x00CC73FDU, 0x00887529U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x840053DCU, 0x00C873E9U, 0x9C00137FU, 0x840063DCU, 0x00CC73FDU, 0x00887529U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x840053DCU, 0x00C873E9U, 0x9C00137FU, 0x840063DCU, 0x00CC73FDU, 0x00887529U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x840053DCU, 0x00C873E9U, 0x9C00137FU, 0x840063DCU, 0x00CC73FDU, 0x00887529U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x840053DCU, 0x00C873E9U, 0x9C00137FU, 0x840063DCU, 0x00CC73FDU, 0x00887529U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x840053DCU, 0x00C873E9U, 0x9C00137FU, 0x840063DCU, 0x00CC73FDU, 0x00887529U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x840053DCU, 0x00C873E9U, 0x9C00137FU, 0x840063DCU, 0x00CC73FDU, 0x00887529U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x840053DCU, 0x00C873E9U, 0x9C00137FU, 0x840063DCU, 0x00CC73FDU, 0x00887529U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x6080B6A0U, 0x9C001369U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x9C001369U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x9C001369U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x9C001369U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x9C001369U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x9C001369U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x9C001369U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x9C001369U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x9C001369U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x9C001369U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x9C001369U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x9C001369U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x9C001369U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x9C001369U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x9C001369U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x9C001369U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x2000019FU, 0x00406609U, 0x01E06169U, 0x8C001340U, 0x01E80120U, 0x01E41500U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x00406609U, 0x01E06169U, 0x8C001340U, 0x01E80120U, 0x01E41500U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x00406609U, 0x01E06169U, 0x8C001340U, 0x01E80120U, 0x01E41500U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x00406609U, 0x01E06169U, 0x8C001340U, 0x01E80120U, 0x01E41500U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x6000B6DFU, 0x840033DDU, 0x940003A0U, 0x00400021U, 0x940013A0U, 0x00400042U, 0x940023A0U, 0x00400063U, 0x940033A0U, 0x00400084U, 0x940043A0U, 0x004000A5U, 0x940053A0U, 0x004000C6U, 0x940063A0U, 0x004000E7U, 0x940073A0U, 0x00400108U, 0xD40003A1U, 0xD40013A2U, 0xD40023A3U, 0xD40033A4U, 0xD40043A5U, 0xD40053A6U, 0xD40063A7U, 0xD40073A8U, 0x29FFE01AU, 0x840023DCU, 0x60008FDCU, 0x840013DFU, 0x840003DEU, 0x04807FFFU, 0x6380BF00U, 0x7080001FU, 0x581FFFE0U, 0x5C1FFFE0U, 0x54000020U, 0x20014800U, 0x101FFE00U, 0x84000001U, 0x84001002U, 0x84002003U, 0x84003004U, 0x84004005U, 0xD40003A1U, 0xD40013A2U, 0xD40023A3U, 0xD40033A4U, 0xD40043A5U, 0x54000020U, 0xC8FF43DEU, 0xC40013DFU, 0xC40033DDU, 0x940003A1U, 0x940013A2U, 0x940023A3U, 0x940033A4U, 0x940043A5U, 0xC40043C1U, 0xC40053C2U, 0xC40063C3U, 0xC40073C4U, 0xC40083C5U, 0xC40093DBU, 0x0C800F7DU, 0x6380C3E0U, 0x0050777BU, 0x08C80FBFU, 0xC400A3DFU, 0x088C7FE7U, 0x28000027U, 0xC400B3C7U, 0x9C00137DU, 0xC40023DCU, 0x20014608U, 0x101FFE08U, 0x00800420U, 0x08D01400U, 0x84000108U, 0x840093DCU, 0x0C800F9CU, 0x6380DD60U, 0x8400A3DFU, 0x8400B3C7U, 0x01D41400U, 0x00402000U, 0x00C87FA9U, 0x9C00137DU, 0x00CC1FBCU, 0x00887129U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U, 0x00C87FA9U, 0x9C00137DU, 0x00CC1FBCU, 0x00887129U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U, 0x00C87FA9U, 0x9C00137DU, 0x00CC1FBCU, 0x00887129U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U, 0x00C87FA9U, 0x9C00137DU, 0x00CC1FBCU, 0x00887129U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U, 0x00C87FA9U, 0x9C00137DU, 0x00CC1FBCU, 0x00887129U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U, 0x00C87FA9U, 0x9C00137DU, 0x00CC1FBCU, 0x00887129U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U, 0x00C87FA9U, 0x9C00137DU, 0x00CC1FBCU, 0x00887129U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U, 0x00C87FA9U, 0x9C00137DU, 0x00CC1FBCU, 0x00887129U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U, 0x00C87FA9U, 0x9C00137DU, 0x00CC1FBCU, 0x00887129U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U, 0x00C87FA9U, 0x9C00137DU, 0x00CC1FBCU, 0x00887129U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U, 0x00C87FA9U, 0x9C00137DU, 0x00CC1FBCU, 0x00887129U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U, 0x00C87FA9U, 0x9C00137DU, 0x00CC1FBCU, 0x00887129U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U, 0x00C87FA9U, 0x9C00137DU, 0x00CC1FBCU, 0x00887129U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U, 0x00C87FA9U, 0x9C00137DU, 0x00CC1FBCU, 0x00887129U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U, 0x00C87FA9U, 0x9C00137DU, 0x00CC1FBCU, 0x00887129U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U, 0x00C87FA9U, 0x9C00137DU, 0x00CC1FBCU, 0x00887129U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x6080EF60U, 0x01D41400U, 0x00402000U, 0x9C001369U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U, 0x9C001369U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U, 0x9C001369U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U, 0x9C001369U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U, 0x9C001369U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U, 0x9C001369U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U, 0x9C001369U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U, 0x9C001369U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U, 0x9C001369U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U, 0x9C001369U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U, 0x9C001369U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U, 0x9C001369U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U, 0x9C001369U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U, 0x9C001369U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U, 0x9C001369U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U, 0x9C001369U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x2000009FU, 0x01D41400U, 0x00402000U, 0x00803189U, 0x008C4529U, 0x008C5D29U, 0x008C6529U, 0x08D00529U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x6000EF9FU, 0x2000029FU, 0x20014687U, 0x101FFE07U, 0x8C0010E8U, 0x01D01400U, 0x00402000U, 0x00803189U, 0x008C4529U, 0x008C5D29U, 0x008C6529U, 0x08D00529U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x6000F1DFU, 0x2000029FU, 0x8C0010E8U, 0x01D81400U, 0x00402000U, 0x00803189U, 0x008C4529U, 0x008C5D29U, 0x008C6529U, 0x08D00529U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x6000F3DFU, 0x2000029FU, 0x840000E8U, 0x01D01400U, 0x00402000U, 0x00803189U, 0x008C4529U, 0x008C5D29U, 0x008C6529U, 0x08D00529U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x6000F5DFU, 0x840043C0U, 0x00400021U, 0xC40043C1U, 0x840053C0U, 0x00400042U, 0xC40053C2U, 0x840063C0U, 0x00400063U, 0xC40063C3U, 0x840073C0U, 0x00400084U, 0xC40073C4U, 0x840083C0U, 0x004000A5U, 0xC40083C5U, 0x840023DCU, 0x6000C3FCU, 0x840033DDU, 0xDC0013A1U, 0xDC0013A2U, 0xDC0013A3U, 0xDC0013A4U, 0xDC0013A5U, 0x840013DFU, 0x840003DEU, 0x04807FFFU, 0x6380FB00U, 0x7080001FU, 0x5C1FFFE0U, 0x581FFFE0U, 0x54000020U, 0x08800E31U, 0x08C81A20U, 0x2000A412U, 0x101FFE12U, 0x00400251U, 0x84000220U, 0x84001221U, 0x01A42012U, 0x04804A52U, 0x6300FE00U, 0x84002220U, 0x84003221U, 0x01A42012U, 0x04804A52U, 0x6300FE00U, 0x84004220U, 0x84005221U, 0x01A42012U, 0x04804A52U, 0x6300FE00U, 0x54000020U, 0x54000040U, 0x08800E31U, 0x08C81A20U, 0x2000A412U, 0x101FFE12U, 0x00400251U, 0x84000220U, 0x84001221U, 0x0C800E07U, 0x63810380U, 0x3C000027U, 0x63810240U, 0x3C000047U, 0x63810100U, 0x94FFF607U, 0x08C860E2U, 0x94000607U, 0x08CC20E8U, 0x00882042U, 0x08C860E3U, 0x94001607U, 0x08CC20E8U, 0x00882063U, 0x608103C0U, 0x94FFFA07U, 0x08C840E2U, 0x94000A07U, 0x08CC40E8U, 0x00882042U, 0x08C840E3U, 0x94001A07U, 0x08CC40E8U, 0x00882063U, 0x608103C0U, 0x94FFFE07U, 0x08C820E2U, 0x94000E07U, 0x08CC60E8U, 0x00882042U, 0x08C820E3U, 0x94001E07U, 0x08CC60E8U, 0x00882063U, 0x608103C0U, 0x9C001202U, 0x94000203U, 0x01A40000U, 0x01A02000U, 0x01A00400U, 0x01A00400U, 0x01A00400U, 0x01A00400U, 0x01A00400U, 0x01A00400U, 0x01A00000U, 0x01A00400U, 0x01A00400U, 0x01A00400U, 0x01A00400U, 0x01A00400U, 0x01A00400U, 0x01A00000U, 0x01A01000U, 0x84002220U, 0x84003221U, 0x01A41000U, 0x01A02800U, 0x01A00C00U, 0x01A00C00U, 0x01A00C00U, 0x01A00C00U, 0x01A00C00U, 0x01A00C00U, 0x01A00800U, 0x01A00C00U, 0x01A00C00U, 0x01A00C00U, 0x01A00C00U, 0x01A00C00U, 0x01A00C00U, 0x01A00800U, 0x01A01000U, 0x84004220U, 0x84005221U, 0x01A40000U, 0x01A02000U, 0x01A00400U, 0x01A00400U, 0x01A00400U, 0x01A00400U, 0x01A00400U, 0x01A00400U, 0x01A00000U, 0x01A00400U, 0x01A00400U, 0x01A00400U, 0x01A00400U, 0x01A00400U, 0x01A00400U, 0x01A00000U, 0x01A01000U, 0x0C800E67U, 0x638111C0U, 0x3C000027U, 0x63810FA0U, 0x3C000047U, 0x63810D80U, 0x94FFF668U, 0x08CC2108U, 0x08C82108U, 0x08CC6047U, 0x008820E7U, 0xD4FFF667U, 0x08C82047U, 0x08CC6062U, 0x00881C42U, 0xD4000662U, 0x94001668U, 0x08C86108U, 0x08CC6108U, 0x08C82067U, 0x008820E7U, 0xD4001667U, 0x60811200U, 0x94FFFA68U, 0x08CC4108U, 0x08C84108U, 0x08CC4047U, 0x008820E7U, 0xD4FFFA67U, 0x08C84047U, 0x08CC4062U, 0x00881C42U, 0xD4000A62U, 0x94001A68U, 0x08C84108U, 0x08CC4108U, 0x08C84067U, 0x008820E7U, 0xD4001A67U, 0x60811200U, 0x94FFFE68U, 0x08CC6108U, 0x08C86108U, 0x08CC2047U, 0x008820E7U, 0xD4FFFE67U, 0x08C86047U, 0x08CC2062U, 0x00881C42U, 0xD4000E62U, 0x94001E68U, 0x08C82108U, 0x08CC2108U, 0x08C86067U, 0x008820E7U, 0xD4001E67U, 0x60811200U, 0xDC001262U, 0xD4000263U, 0x04807FFFU, 0x63811260U, 0x7080001FU, 0x5C1FFFE0U, 0x581FFFE0U, 0x54000020U, 0x08800E31U, 0x08C81A20U, 0x2000A412U, 0x101FFE12U, 0x00400251U, 0x84004220U, 0x84005221U, 0x0C800E07U, 0x63811820U, 0x3C000027U, 0x638116E0U, 0x3C000047U, 0x638115A0U, 0x94FFF607U, 0x08C860E2U, 0x94000607U, 0x08CC20E8U, 0x00882042U, 0x08C860E3U, 0x94001607U, 0x08CC20E8U, 0x00882063U, 0x60811860U, 0x94FFFA07U, 0x08C840E2U, 0x94000A07U, 0x08CC40E8U, 0x00882042U, 0x08C840E3U, 0x94001A07U, 0x08CC40E8U, 0x00882063U, 0x60811860U, 0x94FFFE07U, 0x08C820E2U, 0x94000E07U, 0x08CC60E8U, 0x00882042U, 0x08C820E3U, 0x94001E07U, 0x08CC60E8U, 0x00882063U, 0x60811860U, 0x9C001202U, 0x94000203U, 0x01A41000U, 0x01A02800U, 0x01A00C00U, 0x01A00C00U, 0x01A00C00U, 0x01A00C00U, 0x01A00C00U, 0x01A00C00U, 0x01A00800U, 0x01A00C00U, 0x01A00C00U, 0x01A00C00U, 0x01A00C00U, 0x01A00C00U, 0x01A00C00U, 0x01A00800U, 0x01A01000U, 0x84002220U, 0x84003221U, 0x01A40000U, 0x01A02000U, 0x01A00400U, 0x01A00400U, 0x01A00400U, 0x01A00400U, 0x01A00400U, 0x01A00400U, 0x01A00000U, 0x01A00400U, 0x01A00400U, 0x01A00400U, 0x01A00400U, 0x01A00400U, 0x01A00400U, 0x01A00000U, 0x01A01000U, 0x84000220U, 0x84001221U, 0x01A41000U, 0x01A02800U, 0x01A00C00U, 0x01A00C00U, 0x01A00C00U, 0x01A00C00U, 0x01A00C00U, 0x01A00C00U, 0x01A00800U, 0x01A00C00U, 0x01A00C00U, 0x01A00C00U, 0x01A00C00U, 0x01A00C00U, 0x01A00C00U, 0x01A00800U, 0x01A01000U, 0x0C800E67U, 0x63812660U, 0x3C000027U, 0x63812440U, 0x3C000047U, 0x63812220U, 0x94FFF668U, 0x08CC2108U, 0x08C82108U, 0x08CC6047U, 0x008820E7U, 0xD4FFF667U, 0x08C82047U, 0x08CC6062U, 0x00881C42U, 0xD4000662U, 0x94001668U, 0x08C86108U, 0x08CC6108U, 0x08C82067U, 0x008820E7U, 0xD4001667U, 0x608126A0U, 0x94FFFA68U, 0x08CC4108U, 0x08C84108U, 0x08CC4047U, 0x008820E7U, 0xD4FFFA67U, 0x08C84047U, 0x08CC4062U, 0x00881C42U, 0xD4000A62U, 0x94001A68U, 0x08C84108U, 0x08CC4108U, 0x08C84067U, 0x008820E7U, 0xD4001A67U, 0x608126A0U, 0x94FFFE68U, 0x08CC6108U, 0x08C86108U, 0x08CC2047U, 0x008820E7U, 0xD4FFFE67U, 0x08C86047U, 0x08CC2062U, 0x00881C42U, 0xD4000E62U, 0x94001E68U, 0x08C82108U, 0x08CC2108U, 0x08C86067U, 0x008820E7U, 0xD4001E67U, 0x608126A0U, 0xDC001262U, 0xD4000263U, 0x04807FFFU, 0x63812700U, 0x7080001FU, 0x5C1FFFE0U, 0x581FFFE0U, 0x54000020U, 0xC8FFE3DEU, 0x08CC1234U, 0x8C001200U, 0x8C001201U, 0x8C001202U, 0x8C001203U, 0xCE002240U, 0xCE002242U, 0x600127B4U, 0x840003DEU, 0x54000020U, 0xC8FFE3DEU, 0x5C001FE0U, 0x08800E31U, 0x0CC81A31U, 0x2000A012U, 0x101FFE12U, 0x00404652U, 0x8C004200U, 0x9C001204U, 0x9C001205U, 0x9C001206U, 0x9C001207U, 0xCE002240U, 0xCE002242U, 0xCE002244U, 0xCE002246U, 0x9C001200U, 0x9C001201U, 0x9C001202U, 0x9C001203U, 0x9C001204U, 0x9C001205U, 0x9C001206U, 0x9C001207U, 0xCE002240U, 0xCE002242U, 0xCE002244U, 0xCE002246U, 0x08510252U, 0x84000240U, 0x0880E000U, 0x3C000400U, 0x67812D00U, 0x20000400U, 0xC4000240U, 0x3C000100U, 0x08408254U, 0x00800012U, 0x08CC1A31U, 0x67812EA0U, 0x3C000300U, 0x66812E60U, 0x63812E40U, 0x08501A52U, 0x08501A52U, 0x08501A52U, 0x7000041FU, 0x5C1FFFE0U, 0x5801FFE0U, 0x54000020U, 0xC8FFE3DEU, 0x5C001FE0U, 0x08800E31U, 0x0CC81A31U, 0x2000A012U, 0x101FFE12U, 0x00404652U, 0x00804200U, 0xCE002240U, 0xCE002242U, 0x20D4D4C4U, 0x1014D4C4U, 0x20D4D4C5U, 0x1014D4C5U, 0xCE002244U, 0xCE002246U, 0x24000100U, 0x24000121U, 0x24000142U, 0x24000163U, 0x24000184U, 0x240001A5U, 0x240001C6U, 0x240001E7U, 0x00040000U, 0x00040021U, 0x00040042U, 0x00040063U, 0x00040084U, 0x000400A5U, 0x000400C6U, 0x000400E7U, 0xCE002240U, 0xCE002242U, 0xCE002244U, 0xCE002246U, 0x08510252U, 0x84000240U, 0x0880E000U, 0x3C000400U, 0x67813440U, 0x20000400U, 0xC4000240U, 0x3C000100U, 0x08408254U, 0x00800012U, 0x08CC1A31U, 0x678135E0U, 0x3C000300U, 0x668135A0U, 0x63813580U, 0x08501A52U, 0x08501A52U, 0x08501A52U, 0x7000041FU, 0x5C1FFFE0U, 0x5801FFE0U, 0x54000020U, 0x08800E31U, 0x08C81A31U, 0x2000A012U, 0x101FFE12U, 0x00404652U, 0x5C1FFFE0U, 0xCE002240U, 0xCE002242U, 0xCE002244U, 0xCE002246U, 0xCE002240U, 0xCE002242U, 0xCE002244U, 0xCE002246U, 0x5C1FFFE0U, 0x5801FFE0U, 0x04807FFFU, 0x638138A0U, 0x7080001FU, 0x54000020U, 0x0CCC7E48U, 0x63813940U, 0x088C7E52U, 0x28000032U, 0x08800E52U, 0x08C81A52U, 0x2000A013U, 0x101FFE13U, 0x00404A73U, 0xC4000271U, 0x28000413U, 0x0C800E21U, 0x08CC0A31U, 0x63813AA0U, 0x28000031U, 0x3C000008U, 0x63813B60U, 0x8C001201U, 0xCC001261U, 0x60013AF1U, 0x60813BC0U, 0x8C001201U, 0xDC001261U, 0x60013B71U, 0x5C1FFFE0U, 0x581FFFE0U, 0x54000020U, 0x0CCC7E28U, 0x63813CA0U, 0x088C7E31U, 0x28000031U, 0x08800E31U, 0x08C81A31U, 0x2000A212U, 0x101FFE12U, 0x00404652U, 0x8C001204U, 0x8C001205U, 0x8C001206U, 0x8C001207U, 0x3C000008U, 0x63813E60U, 0xCE002244U, 0xCE002246U, 0x60813EE0U, 0xDC001244U, 0xDC001245U, 0xDC001246U, 0xDC001247U, 0x5C1FFFE0U, 0x5801FFE0U, 0x54000020U, 0xC8FFE3DEU, 0x08800E31U, 0x08C81A20U, 0x2000A014U, 0x101FFE14U, 0x00400294U, 0x84000292U, 0x3C000312U, 0x668140C0U, 0x638140A0U, 0x08501A52U, 0x08501A52U, 0x08501A52U, 0x28000414U, 0x60800400U, 0x0C8013C6U, 0x638141C0U, 0xC8FEB3DEU, 0xC40013DFU, 0x60814200U, 0xC8FEC3DEU, 0xC40013DFU, 0x00804A55U, 0x00804636U, 0x00804E77U, 0x084006F4U, 0x3C000094U, 0x630142E0U, 0x20000034U, 0x3C000055U, 0x63814400U, 0x3C000095U, 0x63814400U, 0x3C000115U, 0x63814400U, 0x3C000095U, 0x67014B00U, 0x60814A80U, 0x08800EC6U, 0x08C818C6U, 0x2000A00CU, 0x101FFE0CU, 0x0040198CU, 0x8C004198U, 0x08800E31U, 0x08C82226U, 0x2000C011U, 0x101FFE11U, 0x00401A31U, 0x3C000318U, 0x66814600U, 0x63814A40U, 0x200001D2U, 0x60814620U, 0x20000152U, 0x2001D613U, 0x101FFE13U, 0x9C001200U, 0x9C001201U, 0x20000106U, 0x004078C6U, 0x008056AAU, 0x9C00120EU, 0x9C00120FU, 0xCE0020CEU, 0x6001470AU, 0x200000C9U, 0x008056AAU, 0x08500527U, 0x01001EA7U, 0x004028E6U, 0x008C1821U, 0x08C80D48U, 0x800023C2U, 0x08401108U, 0x800023C3U, 0x700045BFU, 0x08501108U, 0xC00023C2U, 0x08401108U, 0xC00023C3U, 0x6001480AU, 0x600147A9U, 0x8600018EU, 0x008C01CBU, 0x008C05E6U, 0x0488196BU, 0x63814BE0U, 0x3C000115U, 0x63814B00U, 0x00805EF1U, 0x7001365FU, 0x581FFFE0U, 0x54000040U, 0x00805EF1U, 0x0080529DU, 0x7001365FU, 0x008077B1U, 0x7001365FU, 0x581FFFE0U, 0x54000040U, 0x00805EE7U, 0x08800EF7U, 0x08C81AE6U, 0x2000A017U, 0x101FFE17U, 0x00401AF7U, 0x3C000055U, 0x63814D60U, 0x3C000095U, 0x63814D60U, 0x20000407U, 0x60814D80U, 0x08C80EA7U, 0xCC0082E7U, 0x20000106U, 0x004078C6U, 0x008056AAU, 0x3C000115U, 0x63814EC0U, 0x8E0020C0U, 0xCE0022E0U, 0x60014E4AU, 0x608150A0U, 0x0850114AU, 0x8E0020C0U, 0xCE0022E0U, 0x60014EEAU, 0x08800E94U, 0x08C81A87U, 0x2000A014U, 0x101FFE14U, 0x00401E94U, 0x2000008AU, 0x20000407U, 0xCC008287U, 0x8E0020C0U, 0xCE002280U, 0x6001504AU, 0x54000020U, 0xC4FFF3DFU, 0xC8FFE3DEU, 0x2001D600U, 0x101FFE00U, 0x700162BFU, 0x3C000017U, 0x63815600U, 0x0C800EFDU, 0x63015280U, 0xC40002E2U, 0xC40012E3U, 0xC40022E4U, 0xC40032E5U, 0x60815600U, 0x005076F7U, 0x08C80FBDU, 0x088C7FBCU, 0x2800003CU, 0x840002FAU, 0x00C8735FU, 0x00CC73FFU, 0x00C8745AU, 0x00887F5AU, 0xC40002FAU, 0x00CC705FU, 0x00C8747AU, 0x00887F5AU, 0xC40012FAU, 0x00CC707FU, 0x00C8749AU, 0x00887F5AU, 0xC40022FAU, 0x00CC709FU, 0x00C874BAU, 0x00887F5AU, 0xC40032FAU, 0x00CC70BFU, 0x840042FAU, 0x00CC775AU, 0x00C8775AU, 0x00887F5AU, 0xC40042FAU, 0x840013DFU, 0x04807FFFU, 0x638156A0U, 0x840003DEU, 0x7080001FU, 0x5C1FFFE0U, 0x581FFFE0U, 0x54000020U, 0xC4FFF3D5U, 0xC4FFE3D6U, 0xC4FFD3DFU, 0xC8FFC3DEU, 0x2001DE00U, 0x101FFE00U, 0x700162BFU, 0x84FFD3DFU, 0x20000033U, 0x3C000017U, 0x638161A0U, 0x0C800EFDU, 0x63015940U, 0x840002E6U, 0x840012E7U, 0x840022E8U, 0x840032E9U, 0x60815BE0U, 0x005076F7U, 0x08C80FBDU, 0x088C7FBCU, 0x2800003CU, 0x840002FAU, 0x00CC775FU, 0x840012FAU, 0x00C87346U, 0x00887CC6U, 0x00CC775FU, 0x840022FAU, 0x00C87347U, 0x00887CE7U, 0x00CC775FU, 0x840032FAU, 0x00C87348U, 0x00887D08U, 0x00CC775FU, 0x840042FAU, 0x00C87349U, 0x00887D29U, 0x008C1857U, 0x008C1C7AU, 0x00886AF7U, 0x008C209AU, 0x00886AF7U, 0x008C24BAU, 0x04886AF7U, 0x638161A0U, 0x20000053U, 0x840033D5U, 0x3C000015U, 0x638161A0U, 0x840023D6U, 0x0C800EDAU, 0x63816020U, 0x00506AD6U, 0x00406AB5U, 0x0C5012B5U, 0x2000001CU, 0x66015F20U, 0x840002DCU, 0x28000095U, 0x08C80EB5U, 0x00CC579CU, 0x00C8579CU, 0x20000015U, 0x08C80F5AU, 0x088C7F5AU, 0x2800003AU, 0x840002DBU, 0x00C86B7BU, 0x00CC6B7BU, 0x0088737BU, 0xCC0012DBU, 0x0CCC0ABBU, 0x638160C0U, 0x2000001AU, 0xCC0012DAU, 0x6001609BU, 0x0C800EBAU, 0x638161A0U, 0x08C80F5AU, 0x840002DBU, 0x00CC6B7BU, 0x00C86B7BU, 0xCC0012DBU, 0x840013DFU, 0x04807FFFU, 0x63816240U, 0x840003DEU, 0x7080001FU, 0x5C1FFFE0U, 0x581FFEE0U, 0x50000013U, 0x0C8013DAU, 0x63816320U, 0xCAFD13DEU, 0x60816340U, 0xCAFD23DEU, 0xC402D3C0U, 0xC402A3D3U, 0xC402B3D5U, 0x3C000011U, 0x0080463AU, 0x660165C0U, 0x20000015U, 0x20000011U, 0x088C0F5AU, 0x2800003AU, 0x08800F5AU, 0x08C81B5AU, 0x2000A41BU, 0x101FFE1BU, 0x00406B7AU, 0x8E002340U, 0x8E002342U, 0x8E002344U, 0x8E002346U, 0x60816840U, 0x08800F5AU, 0x08C81B5AU, 0x2000A011U, 0x101FFE11U, 0x00406A31U, 0x0C800E9CU, 0x00507294U, 0x08C80F9CU, 0x63816740U, 0x8C001290U, 0x00CC7210U, 0xC40263D0U, 0x08800EDDU, 0x005076D6U, 0x08C80FBDU, 0xC60243DCU, 0x20000019U, 0x3C000017U, 0x63817A80U, 0x7001B07FU, 0xC60023C0U, 0xC60043C2U, 0xC60063C4U, 0xC60083C6U, 0x08C81808U, 0x08CC1908U, 0x08CC6009U, 0x08C8203AU, 0x00886929U, 0x08CC0929U, 0x21FFE07AU, 0x10007FFAU, 0x00806929U, 0x08CC402AU, 0x08C8405AU, 0x0088694AU, 0x08CC114AU, 0x21F81FFAU, 0x10007FFAU, 0x0080694AU, 0x08CC204BU, 0x08C8607AU, 0x0088696BU, 0x08CC196BU, 0x2007FFFAU, 0x10007E1AU, 0x0080696BU, 0x08CC206CU, 0x08C8318CU, 0x08CC318CU, 0xC60103C8U, 0xC60123CAU, 0xC40143CCU, 0x860103C6U, 0x860123C8U, 0x840143CBU, 0x08C808ECU, 0x00401D8CU, 0x08C8090DU, 0x004021ADU, 0x08C8092EU, 0x004025CEU, 0x08C8096FU, 0x00402DEFU, 0xC60203CCU, 0xC60223CEU, 0x2000001AU, 0x2000001BU, 0xC600A3DAU, 0xC600C3DAU, 0xC400E3DAU, 0x3C000013U, 0x63817A80U, 0x00804A5CU, 0x0C800E5AU, 0x63017220U, 0x8402D3C8U, 0x08CC0A7BU, 0x0C800E7DU, 0x63816FE0U, 0x2800003BU, 0x3C000813U, 0x67817060U, 0x2000081BU, 0x08CC0B7BU, 0x8C001240U, 0xCC001100U, 0x6001707BU, 0x3C000813U, 0x67817800U, 0xC40153D3U, 0x20000813U, 0xC402C3D2U, 0x7001C1DFU, 0x840153D3U, 0x8402C3D2U, 0x2000081DU, 0x00507673U, 0x60816F40U, 0x20000038U, 0x08800E4AU, 0x08C80D4AU, 0x088C7D49U, 0x28000029U, 0x08800E7CU, 0x00406B9CU, 0x3C00009CU, 0x67817360U, 0x28000038U, 0x8402D3C8U, 0x00506A5AU, 0x08CC0A7BU, 0x0C800E7DU, 0x63817420U, 0x2800003BU, 0x3C000813U, 0x678174A0U, 0x2000081BU, 0x08CC0B7BU, 0x00806F7DU, 0x0040637BU, 0x8C001340U, 0x00CC2801U, 0x0850077BU, 0x00506FBDU, 0x8C001340U, 0x00C82402U, 0x00880442U, 0x00CC2801U, 0xCC001102U, 0x6001757BU, 0x3C00001DU, 0x63817680U, 0xCC001101U, 0x3C000813U, 0x67817800U, 0xC40153D3U, 0x20000813U, 0xC402C3D2U, 0x7001C1DFU, 0x840153D3U, 0x8402C3D2U, 0x2000081DU, 0x00507673U, 0x00407652U, 0x60816EE0U, 0x0C803E7DU, 0x63817A20U, 0x3C000011U, 0x638179E0U, 0x00507672U, 0x8402D3DDU, 0x00407652U, 0xC4FFF3DFU, 0xC8FFE3DEU, 0x7001F3DFU, 0x840013DFU, 0x840003DEU, 0x08CC1273U, 0x08C81273U, 0x28000213U, 0x7001C1DFU, 0x60817A80U, 0x3C000013U, 0x63817A80U, 0x7001C1DFU, 0x3C000015U, 0x6381AD40U, 0x860243DCU, 0x840263D0U, 0x840002DFU, 0x20000039U, 0x088C7FBBU, 0x2800003BU, 0x00C86FFFU, 0x00CC6FFFU, 0xC40273DFU, 0x7001B07FU, 0x840273DFU, 0x2001D61AU, 0x101FFE1AU, 0xC6000340U, 0xC6002342U, 0xC6004344U, 0xC6006346U, 0xC6008348U, 0xC600A34AU, 0xC600C34CU, 0xC600E34EU, 0x0C5102B5U, 0x860243DCU, 0x66819BC0U, 0x0C807F9CU, 0x63018020U, 0x8C001280U, 0x8C001281U, 0x8C001282U, 0x8C001283U, 0x8C001284U, 0x8C001285U, 0x8C001286U, 0x8C001287U, 0x8C001288U, 0x8C001289U, 0x8C00128AU, 0x8C00128BU, 0x8C00128CU, 0x8C00128DU, 0x8C00128EU, 0x8C00128FU, 0x60818880U, 0x088C7F9DU, 0x2800003DU, 0x8C00129BU, 0x00C8777AU, 0x00884340U, 0x00CC7370U, 0x8C00129BU, 0x00C8777AU, 0x00884341U, 0x00CC7370U, 0x8C00129BU, 0x00C8777AU, 0x00884342U, 0x00CC7370U, 0x8C00129BU, 0x00C8777AU, 0x00884343U, 0x00CC7370U, 0x8C00129BU, 0x00C8777AU, 0x00884344U, 0x00CC7370U, 0x8C00129BU, 0x00C8777AU, 0x00884345U, 0x00CC7370U, 0x8C00129BU, 0x00C8777AU, 0x00884346U, 0x00CC7370U, 0x8C00129BU, 0x00C8777AU, 0x00884347U, 0x00CC7370U, 0x8C00129BU, 0x00C8777AU, 0x00884348U, 0x00CC7370U, 0x8C00129BU, 0x00C8777AU, 0x00884349U, 0x00CC7370U, 0x8C00129BU, 0x00C8777AU, 0x0088434AU, 0x00CC7370U, 0x8C00129BU, 0x00C8777AU, 0x0088434BU, 0x00CC7370U, 0x8C00129BU, 0x00C8777AU, 0x0088434CU, 0x00CC7370U, 0x8C00129BU, 0x00C8777AU, 0x0088434DU, 0x00CC7370U, 0x8C00129BU, 0x00C8777AU, 0x0088434EU, 0x00CC7370U, 0x8C00129BU, 0x00C8777AU, 0x0088434FU, 0x00CC7370U, 0xC40263D0U, 0x3C000017U, 0x63818A00U, 0x2001DE12U, 0x101FFE12U, 0xC6000240U, 0xC6002242U, 0xC6004244U, 0xC6006246U, 0xC6008248U, 0xC600A24AU, 0xC600C24CU, 0xC600E24EU, 0x2001D61AU, 0x101FFE1AU, 0xA4000340U, 0xA4001341U, 0xA4002342U, 0xA4003343U, 0xA4004344U, 0xA4005345U, 0xA4006346U, 0xA4007347U, 0xA4008348U, 0xA4009349U, 0xA400A34AU, 0xA400B34BU, 0xA400C34CU, 0xA400D34DU, 0xA400E34EU, 0xA400F34FU, 0x63818F20U, 0xC6000340U, 0xC6002342U, 0xC6004344U, 0xC6006346U, 0xC6008348U, 0xC600A34AU, 0xC600C34CU, 0xC600E34EU, 0xC402C3DFU, 0x20000813U, 0x7001C1DFU, 0x8402C3DFU, 0x2001D61AU, 0x101FFE1AU, 0x86000340U, 0x86002342U, 0x86004344U, 0x86006346U, 0x86008348U, 0x8600A34AU, 0x8600C34CU, 0x8600E34EU, 0x860243DCU, 0x0C807FBDU, 0x63019200U, 0xCC0012C0U, 0xCC0012C1U, 0xCC0012C2U, 0xCC0012C3U, 0xCC0012C4U, 0xCC0012C5U, 0xCC0012C6U, 0xCC0012C7U, 0xCC0012C8U, 0xCC0012C9U, 0xCC0012CAU, 0xCC0012CBU, 0xCC0012CCU, 0xCC0012CDU, 0xCC0012CEU, 0xCC0012CFU, 0x3C000015U, 0x6381AD20U, 0x67017BC0U, 0x54000040U, 0x860243DCU, 0x088C7FBCU, 0x2800003CU, 0x00C8741BU, 0x00887F7BU, 0xCC0012DBU, 0x00CC701FU, 0x00C8743BU, 0x00887F7BU, 0xCC0012DBU, 0x00CC703FU, 0x00C8745BU, 0x00887F7BU, 0xCC0012DBU, 0x00CC705FU, 0x00C8747BU, 0x00887F7BU, 0xCC0012DBU, 0x00CC707FU, 0x00C8749BU, 0x00887F7BU, 0xCC0012DBU, 0x00CC709FU, 0x00C874BBU, 0x00887F7BU, 0xCC0012DBU, 0x00CC70BFU, 0x00C874DBU, 0x00887F7BU, 0xCC0012DBU, 0x00CC70DFU, 0x00C874FBU, 0x00887F7BU, 0xCC0012DBU, 0x00CC70FFU, 0x00C8751BU, 0x00887F7BU, 0xCC0012DBU, 0x00CC711FU, 0x00C8753BU, 0x00887F7BU, 0xCC0012DBU, 0x00CC713FU, 0x00C8755BU, 0x00887F7BU, 0xCC0012DBU, 0x00CC715FU, 0x00C8757BU, 0x00887F7BU, 0xCC0012DBU, 0x00CC717FU, 0x00C8759BU, 0x00887F7BU, 0xCC0012DBU, 0x00CC719FU, 0x00C875BBU, 0x00887F7BU, 0xCC0012DBU, 0x00CC71BFU, 0x00C875DBU, 0x00887F7BU, 0xCC0012DBU, 0x00CC71DFU, 0x00C875FBU, 0x00887F7BU, 0xCC0012DBU, 0x00CC71FFU, 0xC40273DFU, 0x3C000015U, 0x67017BC0U, 0x63819B00U, 0x54000040U, 0x840002DBU, 0x00CC777BU, 0x00C8777BU, 0x00887F7BU, 0xC40002DBU, 0x6081AD20U, 0x28000815U, 0x860243DCU, 0x2001D69DU, 0x101FFE1DU, 0x2001DE0DU, 0x101FFE0DU, 0x0C800EBCU, 0x08CC0ABBU, 0x63819D00U, 0x2800003BU, 0x840243DCU, 0x0C807F9CU, 0x63019E40U, 0x8C00129AU, 0xCC0011BAU, 0x008C6800U, 0xC4FFF3A0U, 0x8C0013A0U, 0x60019D7BU, 0x60819FA0U, 0x088C7F8BU, 0x2800002BU, 0x8C001281U, 0x00C82C3AU, 0x0088435AU, 0xCC0011BAU, 0x008C6800U, 0x00CC7030U, 0xC4FFF3A0U, 0x8C0013A0U, 0x60019E9BU, 0x3C000017U, 0x6381A180U, 0xC402C3DFU, 0x008056B3U, 0x0C803E7AU, 0x6381A140U, 0x00506A72U, 0x8402D3DAU, 0x00406A52U, 0x7001F3DFU, 0x08803E7AU, 0x00506A73U, 0x28000213U, 0x7001C1DFU, 0x8402C3DFU, 0x2001D61AU, 0x101FFE1AU, 0x860243DCU, 0x0C807FBDU, 0x6301A4C0U, 0x0CCC0ABBU, 0x6381A2C0U, 0x8C001340U, 0xCC0012C0U, 0x6001A27BU, 0x0C800EBBU, 0x6381AD20U, 0x8C000340U, 0x840002DCU, 0x08800EBDU, 0x08C80FBDU, 0x088C7FBBU, 0x2800003BU, 0x00C86C00U, 0x00CC6C00U, 0x00CC779CU, 0x00C8779CU, 0xC4001340U, 0x00887000U, 0xC40002C0U, 0x6081AD20U, 0x0CCC0AB0U, 0x6381A720U, 0x08CC0FBCU, 0x08800EABU, 0x0040716BU, 0x3C00008BU, 0x6781A5E0U, 0x28000030U, 0x0C800D6BU, 0x840273DFU, 0x088C7FBCU, 0x2800003CU, 0x8C001340U, 0x00C8741BU, 0x00887F7BU, 0xCC0012DBU, 0x00CC701FU, 0x6001A650U, 0x6301AB40U, 0x860243DCU, 0x088C7FBBU, 0x2800003BU, 0x8C00135CU, 0x00C87780U, 0x00887C00U, 0x00CC6F9FU, 0x840002DCU, 0x08CC0FABU, 0x08800EAAU, 0x00402D4AU, 0x3C00008AU, 0x6681A9A0U, 0x6381AB00U, 0xCC0012C0U, 0x840002DCU, 0x8C001340U, 0x00C87400U, 0x00887C00U, 0x08800D4AU, 0x08C80D4AU, 0x088C7D5BU, 0x2800003BU, 0x00C86C00U, 0x00CC6C00U, 0xC4001140U, 0x00CC2B9CU, 0x00C82B9CU, 0x00887000U, 0xC40002C0U, 0x6081AD20U, 0xC40002C0U, 0x6081AD20U, 0x08C80D6BU, 0x088C7D7CU, 0x2800003CU, 0x84000340U, 0x00C87400U, 0x00887C00U, 0x00C87000U, 0x00CC7000U, 0x00CC740AU, 0xC400134AU, 0x840002DBU, 0x00CC2F7BU, 0x00C82F7BU, 0x0088037BU, 0xC40002DBU, 0x008056B3U, 0x3C000017U, 0x6381AFE0U, 0x3C000011U, 0x6381AF60U, 0x2001DE12U, 0x101FFE12U, 0x8402A3DAU, 0x2000001BU, 0x8402B3DCU, 0x2000001DU, 0xC600025AU, 0xC600225CU, 0x20000213U, 0x7001C1FFU, 0x20000013U, 0x7001C1DFU, 0x6081AFE0U, 0x0C803E73U, 0x6301AFE0U, 0x20000013U, 0x7001C1DFU, 0x840013DFU, 0x04807FFFU, 0x840003DEU, 0x7080001FU, 0x2001D41AU, 0x101FFE1AU, 0x86000340U, 0x86002342U, 0x86008224U, 0x8600A226U, 0x8600C228U, 0x8600E22AU, 0x0080672CU, 0x8400422DU, 0x8400522EU, 0x8400622FU, 0x20000158U, 0x00401000U, 0x008C018CU, 0x08D0418CU, 0x00403108U, 0x008C2084U, 0x08D03084U, 0x00401000U, 0x008C018CU, 0x08D0218CU, 0x00403108U, 0x008C2084U, 0x08D01C84U, 0x00401421U, 0x008C05ADU, 0x08D041ADU, 0x00403529U, 0x008C24A5U, 0x08D030A5U, 0x00401421U, 0x008C05ADU, 0x08D021ADU, 0x00403529U, 0x008C24A5U, 0x08D01CA5U, 0x00401842U, 0x008C09CEU, 0x08D041CEU, 0x0040394AU, 0x008C28C6U, 0x08D030C6U, 0x00401842U, 0x008C09CEU, 0x08D021CEU, 0x0040394AU, 0x008C28C6U, 0x08D01CC6U, 0x00401C63U, 0x008C0DEFU, 0x08D041EFU, 0x00403D6BU, 0x008C2CE7U, 0x08D030E7U, 0x00401C63U, 0x008C0DEFU, 0x08D021EFU, 0x00403D6BU, 0x008C2CE7U, 0x08D01CE7U, 0x00401400U, 0x008C01EFU, 0x08D041EFU, 0x00403D4AU, 0x008C28A5U, 0x08D030A5U, 0x00401400U, 0x008C01EFU, 0x08D021EFU, 0x00403D4AU, 0x008C28A5U, 0x08D01CA5U, 0x00401821U, 0x008C058CU, 0x08D0418CU, 0x0040316BU, 0x008C2CC6U, 0x08D030C6U, 0x00401821U, 0x008C058CU, 0x08D0218CU, 0x0040316BU, 0x008C2CC6U, 0x08D01CC6U, 0x00401C42U, 0x008C09ADU, 0x08D041ADU, 0x00403508U, 0x008C20E7U, 0x08D030E7U, 0x00401C42U, 0x008C09ADU, 0x08D021ADU, 0x00403508U, 0x008C20E7U, 0x08D01CE7U, 0x00401063U, 0x008C0DCEU, 0x08D041CEU, 0x00403929U, 0x008C2484U, 0x08D03084U, 0x00401063U, 0x008C0DCEU, 0x08D021CEU, 0x00403929U, 0x008C2484U, 0x08D01C84U, 0x6001B218U, 0x2001D41AU, 0x101FFE1AU, 0x8600035CU, 0x00407000U, 0x00407421U, 0x8600235CU, 0x00407042U, 0x00407463U, 0x8600823AU, 0x8600A23CU, 0x00406884U, 0x00406CA5U, 0x004070C6U, 0x004074E7U, 0x8600C23AU, 0x8600E23CU, 0x00406908U, 0x00406D29U, 0x0040714AU, 0x0040756BU, 0x0040658CU, 0x8400423AU, 0x004069ADU, 0x8400523AU, 0x004069CEU, 0x8400623AU, 0x004069EFU, 0x28000039U, 0x7080001FU, 0x8402D3D2U, 0xC40263D0U, 0xC60283C0U, 0x8600A3C2U, 0x8600C3C4U, 0x8400E3CAU, 0x3C000013U, 0x6381E8A0U, 0x20000010U, 0x10002010U, 0x860103C6U, 0x860123C8U, 0x840143CBU, 0x860203CCU, 0x860223CEU, 0x0CCC1278U, 0x6381E7A0U, 0x8C00125DU, 0x08C81BBAU, 0x08CC1B5AU, 0x00406842U, 0x08CC63BAU, 0x8C00125DU, 0x08C823BBU, 0x00886F5AU, 0x08CC0B5AU, 0x08C81B5AU, 0x08CC1B5AU, 0x00406863U, 0x08CC43BAU, 0x8C00125DU, 0x08C843BBU, 0x00886F5AU, 0x08CC135AU, 0x08C81B5AU, 0x08CC1B5AU, 0x00406884U, 0x08CC23BAU, 0x8C00125DU, 0x08C863BBU, 0x00886F5AU, 0x08CC1B5AU, 0x08C81B5AU, 0x08CC1B5AU, 0x004068A5U, 0x08CC23BAU, 0x0088435AU, 0x0040694AU, 0x008C1840U, 0x08C47C00U, 0x008C0041U, 0x08CC7C00U, 0x00400021U, 0x03041820U, 0x0080001AU, 0x0080043BU, 0x008C3C60U, 0x08C47C00U, 0x008C0061U, 0x08CC7C00U, 0x00400021U, 0x03043C20U, 0x0440035AU, 0x0044077BU, 0x008C3880U, 0x08C47C00U, 0x008C0081U, 0x08CC7C00U, 0x00400021U, 0x03043820U, 0x0440035AU, 0x0044077BU, 0x008C34A0U, 0x08C47C00U, 0x008C00A1U, 0x08CC7C00U, 0x00400021U, 0x03043420U, 0x0440035AU, 0x0044077BU, 0x008C3140U, 0x08C47C00U, 0x008C0141U, 0x08CC7C00U, 0x00400021U, 0x03043020U, 0x0440035AU, 0x0044077BU, 0xC60163DAU, 0x008C1C40U, 0x08C47C00U, 0x008C0041U, 0x08CC7C00U, 0x00400021U, 0x03041C20U, 0x0080001AU, 0x0080043BU, 0x008C1860U, 0x08C47C00U, 0x008C0061U, 0x08CC7C00U, 0x00400021U, 0x03041820U, 0x0440035AU, 0x0044077BU, 0x008C3C80U, 0x08C47C00U, 0x008C0081U, 0x08CC7C00U, 0x00400021U, 0x03043C20U, 0x0440035AU, 0x0044077BU, 0x008C38A0U, 0x08C47C00U, 0x008C00A1U, 0x08CC7C00U, 0x00400021U, 0x03043820U, 0x0440035AU, 0x0044077BU, 0x008C3540U, 0x08C47C00U, 0x008C0141U, 0x08CC7C00U, 0x00400021U, 0x03043420U, 0x0440035AU, 0x0044077BU, 0xC60183DAU, 0x008C2040U, 0x08C47C00U, 0x008C0041U, 0x08CC7C00U, 0x00400021U, 0x03042020U, 0x0080001AU, 0x0080043BU, 0x008C1C60U, 0x08C47C00U, 0x008C0061U, 0x08CC7C00U, 0x00400021U, 0x03041C20U, 0x0440035AU, 0x0044077BU, 0x008C1880U, 0x08C47C00U, 0x008C0081U, 0x08CC7C00U, 0x00400021U, 0x03041820U, 0x0440035AU, 0x0044077BU, 0x008C3CA0U, 0x08C47C00U, 0x008C00A1U, 0x08CC7C00U, 0x00400021U, 0x03043C20U, 0x0440035AU, 0x0044077BU, 0x008C3940U, 0x08C47C00U, 0x008C0141U, 0x08CC7C00U, 0x00400021U, 0x03043820U, 0x0440035AU, 0x0044077BU, 0xC601A3DAU, 0x008C2440U, 0x08C47C00U, 0x008C0041U, 0x08CC7C00U, 0x00400021U, 0x03042420U, 0x0080001AU, 0x0080043BU, 0x008C2060U, 0x08C47C00U, 0x008C0061U, 0x08CC7C00U, 0x00400021U, 0x03042020U, 0x0440035AU, 0x0044077BU, 0x008C1C80U, 0x08C47C00U, 0x008C0081U, 0x08CC7C00U, 0x00400021U, 0x03041C20U, 0x0440035AU, 0x0044077BU, 0x008C18A0U, 0x08C47C00U, 0x008C00A1U, 0x08CC7C00U, 0x00400021U, 0x03041820U, 0x0440035AU, 0x0044077BU, 0x008C3D40U, 0x08C47C00U, 0x008C0141U, 0x08CC7C00U, 0x00400021U, 0x03043C20U, 0x0440035AU, 0x0044077BU, 0xC601C3DAU, 0x008C2C40U, 0x08C47C00U, 0x008C0041U, 0x08CC7C00U, 0x00400021U, 0x03042C20U, 0x0080001AU, 0x0080043BU, 0x008C2460U, 0x08C47C00U, 0x008C0061U, 0x08CC7C00U, 0x00400021U, 0x03042420U, 0x0440035AU, 0x0044077BU, 0x008C2080U, 0x08C47C00U, 0x008C0081U, 0x08CC7C00U, 0x00400021U, 0x03042020U, 0x0440035AU, 0x0044077BU, 0x008C1CA0U, 0x08C47C00U, 0x008C00A1U, 0x08CC7C00U, 0x00400021U, 0x03041C20U, 0x0440035AU, 0x0044077BU, 0x008C1940U, 0x08C47C00U, 0x008C0141U, 0x08CC7C00U, 0x00400021U, 0x03041820U, 0x0440035AU, 0x0044077BU, 0xC601E3DAU, 0x860163DAU, 0x08CC6B40U, 0x08C81B62U, 0x00880800U, 0x08C81B42U, 0x08CC1842U, 0x860183DAU, 0x0440035AU, 0x0844037BU, 0x08CC6B40U, 0x08C81B63U, 0x00880C00U, 0x08C81B43U, 0x08CC1863U, 0x8601A3DAU, 0x0440035AU, 0x0844037BU, 0x08CC6B40U, 0x08C81B64U, 0x00881000U, 0x08C81B44U, 0x08CC1884U, 0x8601C3DAU, 0x0440035AU, 0x0844037BU, 0x08CC6B40U, 0x08C81B65U, 0x00881400U, 0x08C81B45U, 0x08CC18A5U, 0x8601E3DAU, 0x0440035AU, 0x0844037BU, 0x08CC6B40U, 0x08C81B6AU, 0x00882800U, 0x08C81B4AU, 0x08CC194AU, 0x08C8081AU, 0x00406842U, 0x00400042U, 0x08CC6840U, 0x08C81842U, 0x08CC1842U, 0x00400063U, 0x6001C3F8U, 0x3C000010U, 0x6381E8A0U, 0x0C803E73U, 0x6381F2A0U, 0xC4FFF3DFU, 0xC8FFE3DEU, 0x7001F37FU, 0x840013DFU, 0x840003DEU, 0x20000010U, 0x20000038U, 0x6081C3E0U, 0x08CC6860U, 0x08C81863U, 0x08CC1863U, 0x00400084U, 0x08CC6880U, 0x08C81884U, 0x08CC1884U, 0x004000A5U, 0x08CC68A0U, 0x08C818A5U, 0x08CC18A5U, 0x0040014AU, 0x08CC6940U, 0x08C8194AU, 0x08CC194AU, 0x00400042U, 0x08C8081AU, 0x00406842U, 0x08CC6840U, 0x08C81842U, 0x08CC1842U, 0x00400063U, 0x00800846U, 0x280000A6U, 0x08CC68C0U, 0x08C818C6U, 0x08CC18C6U, 0x00400067U, 0x08CC68E0U, 0x08C818E7U, 0x08CC18E7U, 0x00400088U, 0x08CC6900U, 0x08C81908U, 0x08CC1908U, 0x004000A9U, 0x08CC6920U, 0x08C81929U, 0x08CC1929U, 0x0040014BU, 0x2000003AU, 0x08C86B5AU, 0x0050696BU, 0x08CC7D7AU, 0x0850075AU, 0x008068C6U, 0x008068E7U, 0x00806908U, 0x00806929U, 0x0080696BU, 0x2000001BU, 0x00506B7AU, 0x0850075AU, 0x00806842U, 0x00881842U, 0x00806863U, 0x00881C63U, 0x00806884U, 0x00882084U, 0x008068A5U, 0x008824A5U, 0x0080694AU, 0x00882D4AU, 0x08C8687BU, 0x00886C42U, 0x08CC1863U, 0x08C8509BU, 0x00886C63U, 0x08CC3084U, 0x08C838BBU, 0x00886C84U, 0x08CC48A5U, 0x08C8215BU, 0x00886CA5U, 0x860063DAU, 0x860083DCU, 0x04406842U, 0x04446C63U, 0x04447084U, 0x004474A5U, 0xC600A3C2U, 0xC600C3C4U, 0xC400E3CAU, 0x840263D0U, 0x860283C0U, 0x7080001FU, 0x20000020U, 0x0CCC0400U, 0x6081F3E0U, 0x04500000U, 0x8E00225AU, 0x8EFFE25CU, 0x08803E61U, 0x20000000U, 0x00500400U, 0x08C47C01U, 0x0080075AU, 0x28000080U, 0x08C47C01U, 0x0080077BU, 0x28000080U, 0x08C47C01U, 0x0080079CU, 0x28000080U, 0x08C47C01U, 0x008007BDU, 0xCE00225AU, 0xCEFFE25CU, 0x08800E7AU, 0x08C80F5AU, 0x20000000U, 0x08440000U, 0x00C86800U, 0x2000001CU, 0x00506B9AU, 0x00806B5CU, 0x08C47F9CU, 0x2800041AU, 0x00CC6B9CU, 0x0880327BU, 0x00404B7BU, 0x8400037DU, 0x008073BDU, 0x008803BDU, 0xC400037DU, 0x7080001FU, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U}; static const uint32_t s_cau3ImemBytes = sizeof(s_cau3ImemImage); /******************************************************************************* * Prototypes ******************************************************************************/ static status_t cau3_initialize_inst_memory(CAU3_Type *base, const uint32_t *cau3ImemImage, size_t cau3ImemBytes); static status_t cau3_initialize_data_memory(CAU3_Type *base, cau3_task_done_t taskDone); static status_t cau3_initialize_read_only_data_memory(CAU3_Type *base, const uint32_t *cau3ReadOnlyConstants, size_t cau3ReadOnlyConstantsBytes, cau3_task_done_t taskDone); static status_t cau3_load_key_context(CAU3_Type *base, cau3_key_context_t *cauKeyContext, cau3_key_slot_t keySlot, cau3_task_done_t taskDone); static status_t cau3_load_key( CAU3_Type *base, const uint8_t *key, size_t keySize, uint32_t keySlot, cau3_task_done_t taskDone); static status_t cau3_pkha_clear_regabne(CAU3_Type *base, bool A, bool B, bool N, bool E); #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) static status_t cau3_execute_null_task(CAU3_Type *base, cau3_task_done_t taskDone); static status_t cau3_lock_semaphore(CAU3_Type *base); static void cau3_release_semaphore(CAU3_Type *base); #endif /******************************************************************************* * Code ******************************************************************************/ static status_t cau3_process_task_completion(CAU3_Type *base, cau3_task_done_t taskDone) { status_t taskCompletionStatus; uint32_t tkcs; taskCompletionStatus = kStatus_Fail; /* assume an error completion status */ switch (((uint32_t)taskDone >> 16U) & 7U) { case 0: /* poll the cau3 status register */ tkcs = base->SR & CAU3_SR_TKCS_MASK; while (tkcs == CAU3_SR_TKCS_RUN) { tkcs = base->SR & CAU3_SR_TKCS_MASK; }; /* check the task completion status*/ if (tkcs == CAU3_SR_TKCS_STOPNOERR) { taskCompletionStatus = kStatus_Success; /* signal error-free completion status */ } break; case 2: /* task completion signaled by event_done */ do { __WFE(); /* cpu is waiting for cau3 event_done */ tkcs = base->SR & CAU3_SR_TKCS_MASK; } while (tkcs == CAU3_SR_TKCS_RUN); /* check the task completion status */ if (tkcs == CAU3_SR_TKCS_STOPNOERR) { taskCompletionStatus = kStatus_Success; /* signal error-free completion status */ } break; case 1: /* task completion signaled by irq */ /* TEMP FIX - for boot ROM with IRQ task completion, simply return */ case 4: /* task completion signaled by dma_req */ /* processing here is complete */ taskCompletionStatus = kStatus_Success; /* signal error-free completion status */ break; default: /* undefined taskDone specifier defaults to kStatus_Fail */ break; } /* end - switch (taskDone & 7U) */ return (taskCompletionStatus); } /*! * @brief Initialize the CAU3's Instruction Memory * * Initializes the CAU3, including configuring it to enable the execution of * crypto tasks, loading the CryptoCore's firmware image into the CAU3's * instruction memory, and then performing a simple read-verify of its contents. * NOTE: All the operations for this function are executed on the host processor. * * cau3_initialize_inst_memory * @param cau3ImemImage - binary firmware image for CryptoCore * @param cau3ImemBytes - size of the firmware image in bytes * * @retval status from the readVerify check: CAU_[OK (=0), ERROR (!0)] * if an error is signaled, the retval is 0xbad10000UU + i, where i is * the first miscompare word index location */ static status_t cau3_initialize_inst_memory(CAU3_Type *base, const uint32_t *cau3ImemImage, size_t cau3ImemBytes) { uint32_t i; /* enable the cau3 */ base->CR = 0U; /* poll if/while the cau3 is running initialization */ while ((base->SR & CAU3_SR_TKCS_MASK) == CAU3_SR_TKCS_INITRUN) { }; /* check for error-free stop state */ if ((base->SR & CAU3_SR_TKCS_MASK) != CAU3_SR_TKCS_STOPNOERR) { return (int32_t)(uint32_t)(0xbad00000U + (base->SR & CAU3_SR_TKCS_MASK)); /* exit with error */ } base->SR = CAU3_SR_TCIRQ_MASK; /* clear the TCIRQ interrupt flag */ /* write the code hex image into the cau3's imem * initialize the memory cmd and address registers */ base->DBGMCMD = 0xac000000U; /* wt=1, ia=1, imem=0 */ base->DBGMADR = 0U; /* imem starting address */ for (i = 0; i < cau3ImemBytes / 4U; i++) { base->DBGMDR = cau3ImemImage[i]; /* indirect write into cau3Imem */ } /* read-verify the cau3 imem code image * initialize the memory cmd and address registers */ base->DBGMCMD = 0x8c000000U; /* wt=0, ia=1, imem=0 */ base->DBGMADR = 0U; /* imem starting address */ for (i = 0; i < cau3ImemBytes / 4U; i++) { if (base->DBGMDR != cau3ImemImage[i]) /* indirect read from cau3Imem */ { return (int32_t)(uint32_t)(0xbad10000U + i); /* exit on miscompare */ } } /* this function does *not* disable reads/writes of the cau3 local memories * but, this operation is needed to "secure" (i.e., make private) the cau3 * local memories */ return 0; } /*! * @brief Initializes the CAU3's entire private Data Memory * * Initialize the CAU3's data memory, and then perform a read-verify versus a * precalculated "pseudo-hash" value. * * cau3_initialize_data_memory * @param taskDone indicates completion signal: CAU_[POLL, IRQ, EVENT, DMAREQ] * * @retval status from the readVerify check: CAU_[OK, ERROR] */ static status_t cau3_initialize_data_memory(CAU3_Type *base, cau3_task_done_t taskDone) { status_t completionStatus; /* execute the cau3 "security violation + data initialization" task */ base->CC_R30 = CAU3_DMEM_STK_BASE; /* initialize stack pointer (sp) */ base->CC_R31 = 0U; /* set LR = 0 to signal a host task */ base->CC_PC = CAU3_TASK_SECV_INIT; /* call cau_secv_init() */ base->CC_CMD = (uint32_t)taskDone; /* trigger cau3 execution */ /* process the cau3 task completion signal specified by taskDone */ completionStatus = cau3_process_task_completion(base, taskDone); return (completionStatus); } /*! * @brief Copies read-only constants from sysMemory to CAU3's DataMemory * * Initialize the read-only constants in the CAU3's data memory. This includes * the AES constants (RCON) and most of the constants used in the hash functions. * The constants associated with SHA-512 are NOT included and must be loaded * separately. * * cau3_initialize_read_only_data_memory * @param cauReadOnlyConstants - sysMemory table of constants needed by CAU3 * @param cauReadOnlyConstantsSize - size of read-only constants in bytes * @param taskDone indicates completion signal: CAU_[POLL, IRQ, EVENT, DMAREQ] * * @retval status check from task completion: CAU_[OK, ERROR] */ static status_t cau3_initialize_read_only_data_memory(CAU3_Type *base, const uint32_t *cau3ReadOnlyConstants, size_t cau3ReadOnlyConstantsBytes, cau3_task_done_t taskDone) { status_t completionStatus; /* execute the cau3 "initialize dmem read-only constants" task */ base->CC_R[16] = (uint32_t)s_cau3ReadOnlyConstants; /* pReadOnlyConstants */ base->CC_R[17] = s_cau3ReadOnlyConstantsBytes; /* byte count (0-mod-16) */ base->CC_R[18] = CAU3_DMEM_AES_RCON; /* pDMEM_AES_RCON constants base */ base->CC_R30 = CAU3_DMEM_STK_BASE; /* initialize stack pointer (sp) */ base->CC_R31 = 0U; /* set LR = 0 to signal a host task */ base->CC_PC = CAU3_TASK_BLKLD_DMEM; /* call cau_block_load_dmem task */ base->CC_CMD = (uint32_t)taskDone; /* trigger cau3 execution */ /* process the cau3 task completion signal specified by taskDone */ completionStatus = cau3_process_task_completion(base, taskDone); return (completionStatus); } /*! * brief Make the CAU3's local memories private * * Modify the CAU3's internal configuration so the local memories are private * and only accessible to the CAU3. This operation is typically performed after * the CAU_InitializeInstMemory(), * CAU_InitializeDataMemory(), and * CAU_InitializeReadOnlyDataMemory() functions have been performed. * * This configuration remains in effect until the next hardware reset. * * param taskDone indicates completion signal: CAU_[POLL, IRQ, EVENT, DMAREQ] * * retval status check from task completion: CAU_[OK, ERROR] */ status_t CAU3_MakeMemsPrivate(CAU3_Type *base, cau3_task_done_t taskDone) { #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) uint32_t completionStatus; completionStatus = cau3_lock_semaphore(base); if (kStatus_Success != completionStatus) { cau3_release_semaphore(base); return completionStatus; } #endif /* FSL_CAU3_USE_HW_SEMA */ /* making the xMEMs private involves setting DBGCSR[DDBGMC] = 1 */ base->DBGCSR = CAU3_DBGCSR_DDBGMC_MASK; /* set DBGCSR[DDBGMC] */ #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) cau3_release_semaphore(base); #endif return kStatus_Success; } #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) /*! * @brief Execute a CAU3 null task to "establish ownership" by host processor * * Execute a null task to claim ownership of the CAU3 by the host processor. * This is required for correct IRQ, EVT and DMA_REQ signaling by subsequent * PKHA operations. The CryptoCore task executes one instruction - a "stop". * * cau3_execute_null_task * @param taskDone indicates completion signal: CAU_[POLL, IRQ, EVENT, DMAREQ] * * @retval status check from task completion: CAU_[OK, ERROR] */ static status_t cau3_execute_null_task(CAU3_Type *base, cau3_task_done_t taskDone) { status_t completionStatus; /* execute the cau3 null task */ base->CC_R30 = CAU3_DMEM_STK_BASE; /* initialize stack pointer (sp) */ base->CC_R31 = 0; /* set LR = 0 to signal a host task */ base->CC_PC = CAU3_TASK_NULL; /* call cau_null() */ base->CC_CMD = taskDone; /* trigger cau3 execution */ /* process the cau3 task completion signal specified by taskDone */ completionStatus = cau3_process_task_completion(base, taskDone); return (completionStatus); } #endif /* FSL_CAU3_USE_HW_SEMA */ /*! * @brief Load a key into a key context * * Loads up to 32-byte key into the specified key slot. * There is support for a maximum of 4 key slots. * This does not do AES key expansion (as in cau3_load_key_context() case) so we use this one for loading TDES keys. * * @param key is the key pointer, ALIGNED ON A 0-MOD-4 ADDRESS * @param keySize is the size in bytes of the key * @param keySlot is the destination key context * @param taskDone indicates completion signal: CAU_[POLL, IRQ, EVENT, DMAREQ] * * @retval status check from task completion: CAU_[OK, ERROR] */ static status_t cau3_load_key( CAU3_Type *base, const uint8_t *key, size_t keySize, uint32_t keySlot, cau3_task_done_t taskDone) { status_t completionStatus; #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) completionStatus = cau3_lock_semaphore(base); if (kStatus_Success != completionStatus) { cau3_release_semaphore(base); return completionStatus; } #endif /* execute the cau3 "load initialization vector into key context" task */ base->CC_R[16] = (uintptr_t)key; /* pKey */ base->CC_R[17] = keySize; /* IV size */ base->CC_R[18] = keySlot; /* keySlot */ base->CC_R30 = CAU3_DMEM_STK_BASE; /* initialize stack pointer (sp) */ base->CC_R31 = 0U; /* set LR = 0 to signal a host task */ base->CC_PC = CAU3_TASK_LD_KEY; /* call cau_load_key() */ base->CC_CMD = (uint32_t)taskDone; /* trigger cau3 execution */ /* process the cau3 task completion signal specified by taskDone */ completionStatus = cau3_process_task_completion(base, taskDone); #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) cau3_release_semaphore(base); #endif return (completionStatus); } /*! * brief Encrypts AES on one 128-bit block. * * Encrypts AES. * The source plaintext and destination ciphertext can overlap in system memory. * * param base CAU3 peripheral base address * param handle Handle used for this request. * param plaintext Input plain text to encrypt * param[out] ciphertext Output cipher text * return Status from encrypt operation */ status_t CAU3_AES_Encrypt(CAU3_Type *base, cau3_handle_t *handle, const uint8_t plaintext[16], uint8_t ciphertext[16]) { status_t completionStatus; cau3_task_done_t taskDone; taskDone = handle->taskDone; #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) completionStatus = cau3_lock_semaphore(base); if (kStatus_Success != completionStatus) { cau3_release_semaphore(base); return completionStatus; } #endif /* execute the cau3 "aes_encrypt_ecb" task */ base->CC_R[16] = (uint32_t)plaintext; /* pPlainText */ base->CC_R[17] = (uint32_t)handle->keySlot; /* keySlot */ base->CC_R[19] = (uint32_t)ciphertext; /* pCipherText */ base->CC_R30 = CAU3_DMEM_STK_BASE; /* initialize stack pointer (sp) */ base->CC_R31 = 0U; /* set LR = 0 to signal a host task */ base->CC_PC = CAU3_TASK_AES_ENCRYPT; /* call cau_aes_encrypt() */ base->CC_CMD = (uint32_t)taskDone; /* trigger cau3 execution */ /* process the cau3 task completion signal specified by taskDone */ completionStatus = cau3_process_task_completion(base, taskDone); #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) cau3_release_semaphore(base); #endif return (completionStatus); } /*! * brief Decrypts AES on one 128-bit block. * * Decrypts AES. * The source ciphertext and destination plaintext can overlap in system memory. * * param base CAU3 peripheral base address * param handle Handle used for this request. * param ciphertext Input plain text to encrypt * param[out] plaintext Output cipher text * return Status from decrypt operation */ status_t CAU3_AES_Decrypt(CAU3_Type *base, cau3_handle_t *handle, const uint8_t ciphertext[16], uint8_t plaintext[16]) { status_t completionStatus; cau3_task_done_t taskDone; taskDone = handle->taskDone; #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) completionStatus = cau3_lock_semaphore(base); if (kStatus_Success != completionStatus) { cau3_release_semaphore(base); return completionStatus; } #endif /* execute the cau3 "aes_decrypt_ecb" task */ base->CC_R[16] = (uint32_t)ciphertext; /* pCipherText */ base->CC_R[17] = (uint32_t)handle->keySlot; /* keySlot */ base->CC_R[19] = (uint32_t)plaintext; /* pPlainText */ base->CC_R30 = CAU3_DMEM_STK_BASE; /* initialize stack pointer (sp) */ base->CC_R31 = 0U; /* set LR = 0 to signal a host task */ base->CC_PC = CAU3_TASK_AES_DECRYPT; /* call cau_aes_decrypt() */ base->CC_CMD = (uint32_t)taskDone; /* trigger cau3 execution */ /* process the cau3 task completion signal specified by taskDone */ completionStatus = cau3_process_task_completion(base, taskDone); #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) cau3_release_semaphore(base); #endif return (completionStatus); } /*! * brief Enables clock for CAU3 and loads image to memory * * Enable CAU3 clock and loads image to CryptoCore. * * param base CAU3 base address */ void CAU3_Init(CAU3_Type *base) { #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* ungate clock */ CLOCK_EnableClock(kCLOCK_Cau3); #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) CLOCK_EnableClock(FSL_CAU3_SEMA42_CLOCK_NAME); #endif /* FSL_CAU3_USE_HW_SEMA */ #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ base->CR = CAU3_CR_RSTSM4(1); base->CR = CAU3_CR_RSTSM4(2); (void)cau3_initialize_inst_memory(base, s_cau3ImemImage, s_cau3ImemBytes); (void)cau3_initialize_data_memory(base, kCAU3_TaskDonePoll); (void)cau3_initialize_read_only_data_memory(base, s_cau3ReadOnlyConstants, s_cau3ReadOnlyConstantsBytes, kCAU3_TaskDonePoll); } #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) static status_t cau3_lock_semaphore(CAU3_Type *base) { uint32_t processorNumber = 0; /* cm4 will be 1, cm0+ will be 2 */ /* This concept supports dual assymetric cores on K32W0 (dula core m4 and m0+) */ /* For next SoC, the processor number shall be defined in the SoC header file */ #if __CORTEX_M == 0U processorNumber++; #endif processorNumber++; while (processorNumber != SEMA42_GATEn(FSL_CAU3_SEMA42_BASE, 1)) { /* Wait for unlocked status. */ while (SEMA42_GATEn(FSL_CAU3_SEMA42_BASE, FSL_CAU3_SEMA42_GATE)) { } /* Lock the gate. */ SEMA42_GATEn(FSL_CAU3_SEMA42_BASE, FSL_CAU3_SEMA42_GATE) = processorNumber; } return cau3_execute_null_task(base, kCAU3_TaskDonePoll); } #endif /* FSL_CAU3_USE_HW_SEMA */ #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) static void cau3_release_semaphore(CAU3_Type *base) { /* unlock the semaphore */ SEMA42_GATEn(FSL_CAU3_SEMA42_BASE, FSL_CAU3_SEMA42_GATE) = 0; } #endif /* FSL_CAU3_USE_HW_SEMA */ /*! * @brief Load a 64-byte "key context" into the CAU3's private data memory * * Load the key context into the private DMEM. This includes size and config * information, a 16-byte initialization vector and a key of size [8,16,24,32] * bytes (for DES or AES-[128,192,256]). There is support for 4 "key slots" with * slot 0 typically used for the system key encryption key (KEK). * * See the GENERAL COMMENTS for more information on the keyContext structure. * * NOTE: This function also performs an AES key expansion if a keySize > 8 * is specified. * * cau3_load_key_context * @param cauKeyContext is pointer to key structure in sysMemory * @param keySlot is the destination key slot number [0-3] * @param taskDone indicates completion signal: CAU_[POLL, IRQ, EVENT, DMAREQ] * * @return status check from task completion: CAU_[OK, ERROR] */ static status_t cau3_load_key_context(CAU3_Type *base, cau3_key_context_t *cauKeyContext, cau3_key_slot_t keySlot, cau3_task_done_t taskDone) { status_t completionStatus; #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) completionStatus = cau3_lock_semaphore(base); if (kStatus_Success != completionStatus) { cau3_release_semaphore(base); return completionStatus; } #endif /* execute the cau3 "load key context" task */ base->CC_R[16] = (uint32_t)cauKeyContext; /* pKeyContext */ base->CC_R[17] = (uint32_t)keySlot; /* keySlot */ base->CC_R30 = CAU3_DMEM_STK_BASE; /* initialize stack pointer (sp) */ base->CC_R31 = 0U; /* set LR = 0 to signal a host task */ base->CC_PC = CAU3_TASK_LD_KEYCTX; /* call cau_load_key_context() */ base->CC_CMD = (uint32_t)taskDone; /* trigger cau3 execution */ /* process the cau3 task completion signal specified by taskDone */ completionStatus = cau3_process_task_completion(base, taskDone); #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) cau3_release_semaphore(base); #endif return (completionStatus); } /*! * brief Execute a CAU3 null task to signal error termination * * Execute a null task to signal error termination. * The CryptoCore task executes one instruction - a "stop with error". * * param base CAU3 base address * param taskDone indicates completion signal * * return status check from task completion */ status_t CAU3_ForceError(CAU3_Type *base, cau3_task_done_t taskDone) { status_t completionStatus; #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) completionStatus = cau3_lock_semaphore(base); if (kStatus_Success != completionStatus) { cau3_release_semaphore(base); return completionStatus; } #endif /* execute the cau3 null task */ base->CC_R30 = CAU3_DMEM_STK_BASE; /* initialize stack pointer (sp) */ base->CC_R31 = 0; /* set LR = 0 to signal a host task */ base->CC_PC = CAU3_TASK_STOPERROR; base->CC_CMD = (uint32_t)taskDone; /* trigger cau3 execution */ /* process the cau3 task completion signal specified by taskDone */ completionStatus = cau3_process_task_completion(base, taskDone); #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) cau3_release_semaphore(base); #endif return (completionStatus); } /*! * brief Load special hardware "key context" into the CAU3's data memory * * Load the special hardware key context into the private DMEM. This only * includes the complete 256-bit key which is then specified with a size of * [8,16,24,32] bytes (for DES or AES-[128,256]). It also loads the * default IV value specified in NIST/RFC2294 IV=0xa6a6a6a6a6a6a6a6. This operation typically * loads keySlot 0, which, by convention, is used for the system key encryption * key. * * See the GENERAL COMMENTS for more information on the keyContext structure. * * NOTE: This function also performs an AES key expansion if a keySize > 8 * is specified. * * param base CAU3 base address * param keySize is the logical key size in bytes [8,16,24,32] * param keySlot is the destination key slot number [0-3] * param taskDone indicates completion signal. * * return status check from task completion */ status_t CAU3_LoadSpecialKeyContext(CAU3_Type *base, size_t keySize, cau3_key_slot_t keySlot, cau3_task_done_t taskDone) { status_t completionStatus; #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) completionStatus = cau3_lock_semaphore(base); if (kStatus_Success != completionStatus) { cau3_release_semaphore(base); return completionStatus; } #endif /* execute the cau3 "load special key context" task */ base->CC_R[16] = keySize; /* keySize [8,16,24,32] */ base->CC_R[17] = (uint32_t)keySlot; /* keySlot */ base->CC_R30 = CAU3_DMEM_STK_BASE; /* initialize stack pointer (sp) */ base->CC_R31 = 0U; /* set LR = 0 to signal a host task */ base->CC_PC = CAU3_TASK_LD_SP_KEYCTX; /* call cau_load_special_key_context() */ base->CC_CMD = (uint32_t)taskDone; /* trigger cau3 execution */ /* process the cau3 task completion signal specified by taskDone */ completionStatus = cau3_process_task_completion(base, taskDone); #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) cau3_release_semaphore(base); #endif return (completionStatus); } /*! * brief Invalidate a 64-byte "key context" in the CAU3's private data memory * * Clears the key context in the private DMEM. There is support for four "key * slots" with slot 0 typically used for the system key encryption key. * * param base CAU3 base address * param keySlot is the key slot number [0-3] to invalidate * param taskDone indicates completion signal * * return status check from task completion */ status_t CAU3_ClearKeyContext(CAU3_Type *base, cau3_key_slot_t keySlot, cau3_task_done_t taskDone) { uint32_t completionStatus; #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) completionStatus = cau3_lock_semaphore(base); if (kStatus_Success != completionStatus) { cau3_release_semaphore(base); return completionStatus; } #endif /* execute the cau3 "clear key context" task */ base->CC_R[17] = (uint32_t)keySlot; /* keySlot */ base->CC_R30 = CAU3_DMEM_STK_BASE; /* initialize stack pointer (sp) */ base->CC_R31 = 0U; /* set LR = 0 to signal a host task */ base->CC_PC = CAU3_TASK_CLR_KEYCTX; /* call cau_clear_key_context() */ base->CC_CMD = (uint32_t)taskDone; /* trigger cau3 execution */ /* process the cau3 task completion signal specified by taskDone */ completionStatus = (uint32_t)cau3_process_task_completion(base, taskDone); #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) cau3_release_semaphore(base); #endif return ((int32_t)completionStatus); } /*! * brief Load an initialization vector into a key context * * Loads a 16-byte initialization vector (iv) into the specified key slot. * There is support for a maximum of 4 key slots. * The function is used internally for loading AEAD_CHACHA20_POY1305 nonce. * It can be also used for Alternative Initial Values for A[0] in RFC 3394. * * param base CAU3 base address * param iv The initialization vector, ALIGNED ON A 0-MOD-4 ADDRESS. * param keySlot is the destination key context * param taskDone indicates completion signal * * return status check from task completion */ status_t CAU3_LoadKeyInitVector(CAU3_Type *base, const uint8_t *iv, cau3_key_slot_t keySlot, cau3_task_done_t taskDone) { status_t completionStatus; #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) completionStatus = cau3_lock_semaphore(base); if (kStatus_Success != completionStatus) { cau3_release_semaphore(base); return completionStatus; } #endif /* execute the cau3 "load initialization vector into key context" task */ base->CC_R[16] = (uintptr_t)iv; /* pIv */ base->CC_R[17] = (uint32_t)keySlot; /* keySlot */ base->CC_R30 = CAU3_DMEM_STK_BASE; /* initialize stack pointer (sp) */ base->CC_R31 = 0U; /* set LR = 0 to signal a host task */ base->CC_PC = CAU3_TASK_LD_IV; /* call cau_load_iv() */ base->CC_CMD = (uint32_t)taskDone; /* trigger cau3 execution */ /* process the cau3 task completion signal specified by taskDone */ completionStatus = cau3_process_task_completion(base, taskDone); #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) cau3_release_semaphore(base); #endif return (completionStatus); } /*! * brief Perform an AES key expansion for specified key slot * * Performs an AES key expansion (aka schedule) on the specified key slot. It * uses the keySize information in the context to determine whether the key * expansion applies to a 128- or 256-bit AES key. * This function is primarily intended to be called after * key blob has been unwrapped by ref CAU3_KeyBlobUnwrap to destination key slot, so that the unwrapped key * can be used for AES encryption. * * param base CAU3 base address * param keySlot is the key context * param taskDone indicates completion signal * return status check from task completion */ status_t CAU3_AES_KeyExpansion(CAU3_Type *base, cau3_key_slot_t keySlot, cau3_task_done_t taskDone) { status_t completionStatus; #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) completionStatus = cau3_lock_semaphore(base); if (kStatus_Success != completionStatus) { cau3_release_semaphore(base); return completionStatus; } #endif /* execute the cau3 "aes_key_expansion" task */ base->CC_R[17] = (uint32_t)keySlot; /* keySlot */ base->CC_R30 = CAU3_DMEM_STK_BASE; /* initialize stack pointer (sp) */ base->CC_R31 = 0U; /* set LR = 0 to signal a host task */ base->CC_PC = CAU3_TASK_AES_KEY_SCH; /* call cau_aes_key_sched() */ base->CC_CMD = (uint32_t)taskDone; /* trigger cau3 execution */ /* process the cau3 task completion signal specified by taskDone */ completionStatus = cau3_process_task_completion(base, taskDone); #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) cau3_release_semaphore(base); #endif return (completionStatus); } /*! * brief Load AES key into CAU3 key slot. * * Load the key context into the private DMEM. This function also performs an AES key expansion. * For CAU3 AES encryption/decryption/cmac, users only need to call one of ref CAU3_AES_SetKey and ref * CAU3_LoadSpecialKeyContext. * * CAU3_AES_SetKey * param base CAU3 peripheral base address. * param handle Handle used for the request. * param key 0-mod-4 aligned pointer to AES key. * param keySize AES key size in bytes. Shall equal 16 or 32. * return status from set key operation */ status_t CAU3_AES_SetKey(CAU3_Type *base, cau3_handle_t *handle, const uint8_t *key, size_t keySize) { cau3_key_context_t cau3KeyCtx = {0}; /* only work with aligned key[] */ if (0U != (0x3U & (uintptr_t)key)) { return kStatus_InvalidArgument; } /* keySize must be 16 or 32. initial CAU3 firmware doesn't support 24 bytes. */ if ((keySize != 16U) && (keySize != 32U)) { return kStatus_InvalidArgument; } cau3KeyCtx.keySize = keySize; /* move the key by 32-bit words */ int i = 0; while (keySize != 0U) { keySize -= sizeof(uint32_t); ((uint32_t *)((uintptr_t)cau3KeyCtx.key))[i] = ((uint32_t *)(uintptr_t)key)[i]; i++; } return cau3_load_key_context(base, &cau3KeyCtx, handle->keySlot, handle->taskDone); } /*! * brief Perform an AES-128 cipher-based authentication code (CMAC) * * Performs an AES-128 cipher-based authentication code (CMAC) on a * message. RFC 4493. * * param base CAU3 peripheral base address * param handle Handle used for this request. * param message is source uint8_t array of data bytes, any alignment * param size Number of bytes in the message. * param mac is the output 16 bytes MAC, must be a 0-mod-4 aligned address * return status check from task completion */ status_t CAU3_AES_Cmac(CAU3_Type *base, cau3_handle_t *handle, const uint8_t *message, size_t size, uint8_t *mac) { status_t completionStatus; /* mac must be 0-mod-4 aligned */ if (0U != (0x3U & (uintptr_t)mac)) { return kStatus_InvalidArgument; } #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) completionStatus = cau3_lock_semaphore(base); if (kStatus_Success != completionStatus) { cau3_release_semaphore(base); return completionStatus; } #endif /* execute the cau3 "aes_cmac" task */ base->CC_R[16] = (uintptr_t)message; /* pMessage */ base->CC_R[17] = (uint32_t)handle->keySlot; /* keySlot */ base->CC_R[18] = size; /* messageSize */ base->CC_R[19] = (uintptr_t)mac; /* pMac */ base->CC_R30 = CAU3_DMEM_STK_BASE; /* initialize stack pointer (sp) */ base->CC_R31 = 0U; /* set LR = 0 to signal a host task */ base->CC_PC = CAU3_TASK_AES128_CMAC; /* call cau_aes128_cmac() */ base->CC_CMD = (uint32_t)handle->taskDone; /* trigger cau3 execution */ /* process the cau3 task completion signal specified by taskDone */ completionStatus = cau3_process_task_completion(base, handle->taskDone); #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) cau3_release_semaphore(base); #endif return (completionStatus); } /*! * @brief Check validity of algoritm. * * This function checks the validity of input argument. * * @param algo Tested algorithm value. * @return kStatus_Success if valid, kStatus_InvalidArgument otherwise. */ static status_t cau3_hash_check_input_alg(cau3_hash_algo_t algo) { if ((algo != kCAU3_Sha256) && (algo != kCAU3_Sha1)) { return kStatus_InvalidArgument; } return kStatus_Success; } /*! * @brief Check validity of input arguments. * * This function checks the validity of input arguments. * * @param base CAU3 peripheral base address. * @param ctx Memory buffer given by user application where the CAU3_HASH_Init/CAU3_HASH_Update/CAU3_HASH_Finish store * context. * @param algo Tested algorithm value. * @return kStatus_Success if valid, kStatus_InvalidArgument otherwise. */ static status_t cau3_hash_check_input_args(CAU3_Type *base, cau3_hash_ctx_t *ctx, cau3_hash_algo_t algo) { /* Check validity of input algorithm */ if (kStatus_Success != cau3_hash_check_input_alg(algo)) { return kStatus_InvalidArgument; } if ((NULL == ctx) || (NULL == base)) { return kStatus_InvalidArgument; } return kStatus_Success; } /*! * @brief Check validity of internal software context. * * This function checks if the internal context structure looks correct. * * @param ctxInternal Internal context. * @param message Input message address. * @return kStatus_Success if valid, kStatus_InvalidArgument otherwise. */ static status_t cau3_hash_check_context(cau3_hash_ctx_internal_t *ctxInternal, const uint8_t *message) { if ((NULL == message) || (NULL == ctxInternal) || (kStatus_Success != cau3_hash_check_input_alg(ctxInternal->algo))) { return kStatus_InvalidArgument; } return kStatus_Success; } /*! * @brief Initialize message digest output state for SHA-1 hash * * Initializes the message digest output state for a SHA-1 hash. * * @param sha1State is message digest output in sysMemory in BE format * @param taskDone indicates completion signal: CAU_[POLL, IRQ, EVENT, DMAREQ] * * @retval status check from task completion: CAU_[OK, ERROR] */ static status_t CAU3_Sha1InitializeOutput(CAU3_Type *base, uint32_t *sha1State, cau3_task_done_t taskDone) { status_t completionStatus; #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) completionStatus = cau3_lock_semaphore(base); if (kStatus_Success != completionStatus) { cau3_release_semaphore(base); return completionStatus; } #endif /* execute the cau3 "sha1_init_output" task */ base->CC_R[29] = (uintptr_t)sha1State; /* pSha1State */ base->CC_R30 = CAU3_DMEM_STK_BASE; /* initialize stack pointer (sp) */ base->CC_R31 = 0U; /* set LR = 0 to signal a host task */ base->CC_PC = CAU3_TASK_SHA1_INIT_STATE; /* call cau_sha1_init_state() */ base->CC_CMD = (uint32_t)taskDone; /* trigger cau3 execution */ /* process the cau3 task completion signal specified by taskDone */ completionStatus = cau3_process_task_completion(base, taskDone); #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) cau3_release_semaphore(base); #endif return (completionStatus); } /*! * @brief Perform a SHA-1 hash function over a message of "n" 64-byte blocks * * Perform a SHA-1 hash function over a message of "n" 64-byte data blocks, * returning an 8-word message digest (aka "state"). The input message must * be padded appropriately as defined by the SHA-1 algorithm. * * @param message is the uint8_t input message, any alignment * @param numberOfBlocks is the message length as multiple of 64-byte blocks * @param sha1State is uint32_t message digest output (state) in BE format * @param taskDone indicates completion signal: CAU_[POLL, IRQ, EVENT, DMAREQ] * * @retval status check from task completion: CAU_[OK, ERROR] */ static status_t CAU3_Sha1Update( CAU3_Type *base, const uint8_t *message, uint32_t numberOfBlocks, uint32_t *sha1State, cau3_task_done_t taskDone) { status_t completionStatus; #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) completionStatus = cau3_lock_semaphore(base); if (kStatus_Success != completionStatus) { cau3_release_semaphore(base); return completionStatus; } #endif /* execute the cau3 "sha1_update" task */ base->CC_R[27] = (uintptr_t)message; /* pMessage */ base->CC_R[28] = numberOfBlocks; /* n blocks */ base->CC_R[29] = (uintptr_t)sha1State; /* output */ base->CC_R30 = CAU3_DMEM_STK_BASE; /* initialize stack pointer (sp) */ base->CC_R31 = 0U; /* set LR = 0 to signal a host task */ base->CC_PC = CAU3_TASK_SHA1_HASH; /* call cau_sha1_hash_n() */ base->CC_CMD = (uint32_t)taskDone; /* trigger cau3 execution */ /* process the cau3 task completion signal specified by taskDone */ completionStatus = cau3_process_task_completion(base, taskDone); #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) cau3_release_semaphore(base); #endif return (completionStatus); } /*! * @brief Initialize message digest output state for SHA-256 hash * * Initializes the message digest output state for a SHA-256 hash. * * CAU3_Sha256InitializeOutput * @param sha256State is message digest output in sysMemory in BE format * @param taskDone indicates completion signal: CAU_[POLL, IRQ, EVENT, DMAREQ] * * @retval status check from task completion: CAU_[OK, ERROR] */ static status_t CAU3_Sha256InitializeOutput(CAU3_Type *base, uint32_t *sha256State, cau3_task_done_t taskDone) { status_t completionStatus; #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) completionStatus = cau3_lock_semaphore(base); if (kStatus_Success != completionStatus) { cau3_release_semaphore(base); return completionStatus; } #endif /* execute the cau3 "sha256_init_output" task */ base->CC_R[29] = (uint32_t)sha256State; /* pSha256State */ base->CC_R30 = CAU3_DMEM_STK_BASE; /* initialize stack pointer (sp) */ base->CC_R31 = 0U; /* set LR = 0 to signal a host task */ base->CC_PC = CAU3_TASK_SHA256_INIT_STATE; /* call cau_sha256_init_state() */ base->CC_CMD = (uint32_t)taskDone; /* trigger cau3 execution */ /* process the cau3 task completion signal specified by taskDone */ completionStatus = cau3_process_task_completion(base, taskDone); #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) cau3_release_semaphore(base); #endif return (completionStatus); } /*! * @brief Perform a SHA-256 hash function over a message of "n" 64-byte blocks * * Perform a SHA-256 hash function over a message of "n" 64-byte data blocks, * returning an 8-word message digest (aka "state"). The input message must * be padded appropriately as defined by the SHA-256 algorithm. * * CAU_Sha256Update * @param message is the uint8_t input message, LE, ANY ALIGNMENT * @param numberOfBlocks is the message length as multiple of 64-byte blocks * @param sha256State is uint32_t message digest output (state) in BE format * @param taskDone indicates completion signal: CAU_[POLL, IRQ, EVENT, DMAREQ] * * @retval status check from task completion: CAU_[OK, ERROR] */ static status_t CAU3_Sha256Update( CAU3_Type *base, const uint8_t *message, uint32_t numberOfBlocks, uint32_t *sha256State, cau3_task_done_t taskDone) { status_t completionStatus; #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) completionStatus = cau3_lock_semaphore(base); if (kStatus_Success != completionStatus) { cau3_release_semaphore(base); return completionStatus; } #endif /* execute the cau3 "sha256_update" task */ base->CC_R[27] = (uint32_t)message; /* pMessage */ base->CC_R[28] = numberOfBlocks; /* = (64*numberOfBlocks) bytes */ base->CC_R[29] = (uint32_t)sha256State; /* pSha256State */ base->CC_R30 = CAU3_DMEM_STK_BASE; /* initialize stack pointer (sp) */ base->CC_R31 = 0U; /* set LR = 0 to signal a host task */ base->CC_PC = CAU3_TASK_SHA256_UPDATE; /* call cau_sha256_update() */ base->CC_CMD = (uint32_t)taskDone; /* trigger cau3 execution */ /* process the cau3 task completion signal specified by taskDone */ completionStatus = cau3_process_task_completion(base, taskDone); #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) cau3_release_semaphore(base); #endif return (completionStatus); } /*! * @brief Initialize the SHA engine for new hash. * * This function sets NEW and MODE fields in SHA Control register to start new hash. * * @param base SHA peripheral base address. * @param ctxInternal Internal context. */ static status_t cau3_hash_engine_init(CAU3_Type *base, cau3_hash_ctx_internal_t *ctxInternal) { status_t status; status = kStatus_InvalidArgument; if (kCAU3_Sha256 == ctxInternal->algo) { status = CAU3_Sha256InitializeOutput(base, ctxInternal->runningHash, kCAU3_TaskDonePoll); } if (kCAU3_Sha1 == ctxInternal->algo) { status = CAU3_Sha1InitializeOutput(base, ctxInternal->runningHash, kCAU3_TaskDonePoll); } return status; } /*! * @brief Adds message to current hash. * * This function merges the message to fill the internal buffer, empties the internal buffer if * it becomes full, then process all remaining message data. * * * @param base CAU3 peripheral base address. * @param ctxInternal Internal context. * @param message Input message. * @param messageSize Size of input message in bytes. * @return kStatus_Success. */ static status_t cau3_hash_process_message_data(CAU3_Type *base, cau3_hash_ctx_internal_t *ctxInternal, const uint8_t *message, size_t messageSize) { status_t status; status_t (*funcUpdate)(CAU3_Type *cau3base, const uint8_t *msg, uint32_t numberOfBlocks, uint32_t *shaState, cau3_task_done_t taskDone); /* first fill the internal buffer to full block */ size_t toCopy = CAU3_HASH_BLOCK_SIZE - ctxInternal->blksz; (void)cau3_memcpy(&ctxInternal->blk.b[ctxInternal->blksz], message, toCopy); message += toCopy; messageSize -= toCopy; status = kStatus_InvalidArgument; funcUpdate = NULL; switch (ctxInternal->algo) { case kCAU3_Sha256: funcUpdate = CAU3_Sha256Update; break; case kCAU3_Sha1: funcUpdate = CAU3_Sha1Update; break; default: /* All the cases have been listed above, the default clause should not be reached. */ break; } if (NULL != funcUpdate) { /* process full internal block */ status = funcUpdate(base, &ctxInternal->blk.b[0], CAU3_HASH_BLOCK_SIZE / 64u, ctxInternal->runningHash, kCAU3_TaskDonePoll); if (kStatus_Success != status) { return status; } /* process all full blocks in message[] */ while (messageSize >= CAU3_HASH_BLOCK_SIZE) { status = funcUpdate(base, message, CAU3_HASH_BLOCK_SIZE / 64u, ctxInternal->runningHash, kCAU3_TaskDonePoll); if (kStatus_Success != status) { return status; } message += CAU3_HASH_BLOCK_SIZE; messageSize -= CAU3_HASH_BLOCK_SIZE; } /* copy last incomplete message bytes into internal block */ (void)cau3_memcpy(&ctxInternal->blk.b[0], message, messageSize); ctxInternal->blksz = messageSize; } return status; } /*! * @brief Finalize the running hash to make digest. * * This function empties the internal buffer, adds padding bits, and generates final digest. * * @param base SHA peripheral base address. * @param ctxInternal Internal context. * @return kStatus_Success. */ static status_t cau3_hash_finalize(CAU3_Type *base, cau3_hash_ctx_internal_t *ctxInternal) { cau3_sha_block_t lastBlock; status_t status; status_t (*funcUpdate)(CAU3_Type *cau3base, const uint8_t *msg, uint32_t numberOfBlocks, uint32_t *shaState, cau3_task_done_t taskDone); funcUpdate = NULL; switch (ctxInternal->algo) { case kCAU3_Sha256: funcUpdate = CAU3_Sha256Update; break; case kCAU3_Sha1: funcUpdate = CAU3_Sha1Update; break; default: /* All the cases have been listed above, the default clause should not be reached. */ break; } if (NULL == funcUpdate) { return kStatus_InvalidArgument; } (void)memset(&lastBlock, 0, sizeof(cau3_sha_block_t)); while (ctxInternal->blksz >= 64u) { status = funcUpdate(base, &ctxInternal->blk.b[0], 1, ctxInternal->runningHash, kCAU3_TaskDonePoll); if (kStatus_Success != status) { return status; } ctxInternal->blksz -= 64u; (void)memmove(&ctxInternal->blk.b[0], &ctxInternal->blk.b[64], ctxInternal->blksz); } /* this is last call, so need to flush buffered message bytes along with padding */ if (ctxInternal->blksz <= 55u) { /* last data is 440 bits or less. */ (void)cau3_memcpy(&lastBlock.b[0], &ctxInternal->blk.b[0], ctxInternal->blksz); lastBlock.b[ctxInternal->blksz] = (uint8_t)0x80U; lastBlock.w[15] = __REV(8u * ctxInternal->fullMessageSize); status = funcUpdate(base, &lastBlock.b[0], 1, ctxInternal->runningHash, kCAU3_TaskDonePoll); if (kStatus_Success != status) { return status; } } else { if (ctxInternal->blksz < 64u) { ctxInternal->blk.b[ctxInternal->blksz] = (uint8_t)0x80U; for (uint32_t i = ctxInternal->blksz + 1u; i < 64u; i++) { ctxInternal->blk.b[i] = 0; } } else { lastBlock.b[0] = (uint8_t)0x80U; } status = funcUpdate(base, &ctxInternal->blk.b[0], 1, ctxInternal->runningHash, kCAU3_TaskDonePoll); if (kStatus_Success != status) { return status; } lastBlock.w[15] = __REV(8u * ctxInternal->fullMessageSize); status = funcUpdate(base, &lastBlock.b[0], 1, ctxInternal->runningHash, kCAU3_TaskDonePoll); if (kStatus_Success != status) { return status; } } return status; } /*! * brief Initialize HASH context * * This function initializes the HASH. * * For blocking CAU3 HASH API, the HASH context contains all information required for context switch, * such as running hash. * * param base CAU3 peripheral base address * param[out] ctx Output hash context * param algo Underlaying algorithm to use for hash computation. * return Status of initialization */ status_t CAU3_HASH_Init(CAU3_Type *base, cau3_hash_ctx_t *ctx, cau3_hash_algo_t algo) { status_t status; cau3_hash_ctx_internal_t *ctxInternal; /* compile time check for the correct structure size */ BUILD_ASSURE(sizeof(cau3_hash_ctx_t) >= sizeof(cau3_hash_ctx_internal_t), cau3_hash_ctx_t_size); uint32_t i, j; status = cau3_hash_check_input_args(base, ctx, algo); if (status != kStatus_Success) { return status; } /* set algorithm in context struct for later use */ ctxInternal = (cau3_hash_ctx_internal_t *)(uint32_t)ctx; ctxInternal->algo = algo; ctxInternal->blksz = 0u; j = sizeof(ctxInternal->blk.w) / sizeof(ctxInternal->blk.w[0]); for (i = 0; i < j; i++) { ctxInternal->blk.w[0] = 0u; } ctxInternal->state = kCAU3_StateHashInit; ctxInternal->fullMessageSize = 0; return status; } /*! * brief Add data to current HASH * * Add data to current HASH. This can be called repeatedly with an arbitrary amount of data to be * hashed. The functions blocks. If it returns kStatus_Success, the running hash or mac * has been updated (CAU3 has processed the input data), so the memory at ref input pointer * can be released back to system. The context is updated with the running hash or mac * and with all necessary information to support possible context switch. * * param base CAU3 peripheral base address * param[in,out] ctx HASH context * param input Input data * param inputSize Size of input data in bytes * return Status of the hash update operation */ status_t CAU3_HASH_Update(CAU3_Type *base, cau3_hash_ctx_t *ctx, const uint8_t *input, size_t inputSize) { bool isUpdateState; status_t status; cau3_hash_ctx_internal_t *ctxInternal; size_t blockSize; if (inputSize == 0U) { return kStatus_Success; } ctxInternal = (cau3_hash_ctx_internal_t *)(uint32_t)ctx; status = cau3_hash_check_context(ctxInternal, input); if (kStatus_Success != status) { return status; } ctxInternal->fullMessageSize += inputSize; blockSize = CAU3_HASH_BLOCK_SIZE; /* if we are still less than CAU3_HASH_BLOCK_SIZE bytes, keep only in context */ if ((ctxInternal->blksz + inputSize) <= blockSize) { (void)cau3_memcpy((&ctxInternal->blk.b[0]) + ctxInternal->blksz, input, inputSize); ctxInternal->blksz += inputSize; return status; } else { isUpdateState = ctxInternal->state == kCAU3_StateHashUpdate; if (!isUpdateState) { /* start NEW hash */ status = cau3_hash_engine_init(base, ctxInternal); if (status != kStatus_Success) { return status; } ctxInternal->state = kCAU3_StateHashUpdate; } } /* process input data */ status = cau3_hash_process_message_data(base, ctxInternal, input, inputSize); return status; } /*! * brief Finalize hashing * * Outputs the final hash (computed by CAU3_HASH_Update()) and erases the context. * * param[in,out] ctx Input hash context * param[out] output Output hash data * param[out] outputSize Output parameter storing the size of the output hash in bytes * return Status of the hash finish operation */ status_t CAU3_HASH_Finish(CAU3_Type *base, cau3_hash_ctx_t *ctx, uint8_t *output, size_t *outputSize) { size_t algOutSize = 0; status_t status; cau3_hash_ctx_internal_t *ctxInternal; ctxInternal = (cau3_hash_ctx_internal_t *)(uint32_t)ctx; status = cau3_hash_check_context(ctxInternal, output); if (kStatus_Success != status) { return status; } if (ctxInternal->state == kCAU3_StateHashInit) { status = cau3_hash_engine_init(base, ctxInternal); if (status != kStatus_Success) { return status; } } size_t outSize = 0u; /* compute algorithm output length */ switch (ctxInternal->algo) { case kCAU3_Sha256: outSize = (uint32_t)kCAU3_OutLenSha256; break; case kCAU3_Sha1: outSize = (uint32_t)kCAU3_OutLenSha1; break; default: /* All the cases have been listed above, the default clause should not be reached. */ break; } algOutSize = outSize; /* flush message last incomplete block, if there is any, and add padding bits */ status = cau3_hash_finalize(base, ctxInternal); if (outputSize != NULL) { if (algOutSize < *outputSize) { *outputSize = algOutSize; } else { algOutSize = *outputSize; } } (void)cau3_memcpy(&output[0], (const uint8_t *)ctxInternal->runningHash, algOutSize); (void)memset(ctx, 0, sizeof(cau3_hash_ctx_t)); return status; } /*! * brief Create HASH on given data * * Perform the full SHA in one function call. The function is blocking. * * param base CAU3 peripheral base address * param algo Underlaying algorithm to use for hash computation. * param input Input data * param inputSize Size of input data in bytes * param[out] output Output hash data * param[out] outputSize Output parameter storing the size of the output hash in bytes * return Status of the one call hash operation. */ status_t CAU3_HASH( CAU3_Type *base, cau3_hash_algo_t algo, const uint8_t *input, size_t inputSize, uint8_t *output, size_t *outputSize) { cau3_hash_ctx_t hashCtx; status_t status; status = CAU3_HASH_Init(base, &hashCtx, algo); if (status != kStatus_Success) { return status; } status = CAU3_HASH_Update(base, &hashCtx, input, inputSize); if (status != kStatus_Success) { return status; } status = CAU3_HASH_Finish(base, &hashCtx, output, outputSize); return status; } /*! @brief CAU3 driver wait mechanism. */ static status_t cau3_wait(CAU3_Type *base) { status_t status; bool error = false; bool done = false; /* Wait for 'done' or 'error' flag. */ while ((!error) && (!done)) { uint32_t temp32 = base->STA; error = (bool)(temp32 & (uint32_t)kCAU3_StatusErrorIsr); done = (bool)(temp32 & (uint32_t)kCAU3_StatusDoneIsr); } if (error) { base->COM = CAU3_COM_ALL_MASK; /* Reset all engine to clear the error flag */ status = kStatus_Fail; } else /* 'done' */ { status = kStatus_Success; base->CW = (uint32_t)kCAU3_ClearDataSize; /* Clear 'done' interrupt status. This also clears the mode register. */ base->STA = (uint32_t)kCAU3_StatusDoneIsr; } return status; } /*! * @brief Clears the CAU3 module. * This function can be used to clear all sensitive data from theCAU3 module, such as private keys. It is called * internally by the CAU3 driver in case of an error or operation complete. * @param base CAU3 peripheral base address * @param pkha Include CAU3 PKHA register clear. If there is no PKHA, the argument is ignored. */ static void cau3_clear_all(CAU3_Type *base, bool addPKHA) { base->CW = (uint32_t)kCAU3_ClearAll; if (addPKHA) { (void)cau3_pkha_clear_regabne(base, true, true, true, true); } } /*! * @brief Reads an unaligned word. * * This function creates a 32-bit word from an input array of four bytes. * * @param src Input array of four bytes. The array can start at any address in memory. * @return 32-bit unsigned int created from the input byte array. */ static inline uint32_t cau3_get_word_from_unaligned(const uint8_t *srcAddr) { #if (!(defined(__CORTEX_M)) || (defined(__CORTEX_M) && (__CORTEX_M == 0))) register const uint8_t *src = srcAddr; /* Cortex M0 does not support misaligned loads */ if (0U != ((uint32_t)src & 0x3u)) { union _align_bytes_t { uint32_t word; uint8_t byte[sizeof(uint32_t)]; } my_bytes; my_bytes.byte[0] = *src; my_bytes.byte[1] = *(src + 1); my_bytes.byte[2] = *(src + 2); my_bytes.byte[3] = *(src + 3); return my_bytes.word; } else { /* addr aligned to 0-modulo-4 so it is safe to type cast */ return *((const uint32_t *)(uintptr_t)src); } #elif defined(__CC_ARM) || defined(__ARMCC_VERSION) /* -O3 optimization in Keil Compiler 5 uses LDM instruction here (LDM r4!, {r0}) * which is wrong, because srcAddr might be unaligned. * LDM on unaligned address causes hard-fault. so use memcpy() */ uint32_t ret; memcpy(&ret, srcAddr, sizeof(uint32_t)); return ret; #else return *((const uint32_t *)(uintptr_t)srcAddr); #endif } /******************************************************************************* * PKHA Code static ******************************************************************************/ static status_t cau3_pkha_clear_regabne(CAU3_Type *base, bool A, bool B, bool N, bool E) { cau3_mode_t mode; /* Set the PKHA algorithm and the appropriate function. */ mode = (uint32_t)kCAU3_AlgorithmPKHA | 1U; /* Set ram area to clear. Clear all. */ if (A) { mode |= ((uint32_t)1U << 19U); } if (B) { mode |= ((uint32_t)1U << 18U); } if (N) { mode |= ((uint32_t)1U << 16U); } if (E) { mode |= ((uint32_t)1U << 17U); } /* Write the mode register to the hardware. * NOTE: This will begin the operation. */ base->MDPK = mode; /* Wait for 'done' */ return cau3_wait(base); } static void cau3_pkha_default_parms(cau3_pkha_mode_params_t *params) { params->func = (cau3_pkha_func_t)0; params->arithType = kCAU3_PKHA_IntegerArith; params->montFormIn = kCAU3_PKHA_NormalValue; params->montFormOut = kCAU3_PKHA_NormalValue; params->srcReg = kCAU3_PKHA_RegAll; params->srcQuad = kCAU3_PKHA_Quad0; params->dstReg = kCAU3_PKHA_RegAll; params->dstQuad = kCAU3_PKHA_Quad0; params->equalTime = kCAU3_PKHA_NoTimingEqualized; params->r2modn = kCAU3_PKHA_CalcR2; } static void cau3_pkha_write_word(CAU3_Type *base, cau3_pkha_reg_area_t reg, uint8_t index, uint32_t data) { __IO uint32_t *pka = base->PKA0; __IO uint32_t *pkb = base->PKB0; __IO uint32_t *pkn = base->PKN0; switch (reg) { case kCAU3_PKHA_RegA: pka[index] = data; break; case kCAU3_PKHA_RegB: pkb[index] = data; break; case kCAU3_PKHA_RegN: pkn[index] = data; break; case kCAU3_PKHA_RegE: base->PKE[index] = data; break; default: /* All the cases have been listed above, the default clause should not be reached. */ break; } } static uint32_t cau3_pkha_read_word(CAU3_Type *base, cau3_pkha_reg_area_t reg, uint8_t index) { uint32_t retval; __IO uint32_t *pka = base->PKA0; __IO uint32_t *pkb = base->PKB0; __IO uint32_t *pkn = base->PKN0; switch (reg) { case kCAU3_PKHA_RegA: retval = pka[index]; break; case kCAU3_PKHA_RegB: retval = pkb[index]; break; case kCAU3_PKHA_RegN: retval = pkn[index]; break; default: retval = 0; break; } return retval; } static status_t cau3_pkha_write_reg( CAU3_Type *base, cau3_pkha_reg_area_t reg, uint8_t quad, const uint8_t *data, size_t dataSize) { /* Select the word-based start index for each quadrant of 128 bytes. */ uint8_t startIndex = (quad * 32u); uint32_t outWord; while (dataSize > 0U) { if (dataSize >= sizeof(uint32_t)) { cau3_pkha_write_word(base, reg, startIndex++, cau3_get_word_from_unaligned(data)); dataSize -= sizeof(uint32_t); data += sizeof(uint32_t); } else /* (dataSize > 0) && (dataSize < 4) */ { outWord = 0; (void)cau3_memcpy(&outWord, (const uint32_t *)(uintptr_t)data, dataSize); cau3_pkha_write_word(base, reg, startIndex, outWord); dataSize = 0; } } return kStatus_Success; } static void cau3_pkha_read_reg(CAU3_Type *base, cau3_pkha_reg_area_t reg, uint8_t quad, uint8_t *data, size_t dataSize) { /* Select the word-based start index for each quadrant of 128 bytes. */ uint8_t startIndex = (quad * 32u); size_t calcSize; uint32_t word; while (dataSize > 0U) { word = cau3_pkha_read_word(base, reg, startIndex++); calcSize = (dataSize >= sizeof(uint32_t)) ? sizeof(uint32_t) : dataSize; (void)cau3_memcpy(data, (const uint8_t *)&word, calcSize); data += calcSize; dataSize -= calcSize; } } static void cau3_pkha_init_data(CAU3_Type *base, const uint8_t *A, size_t sizeA, const uint8_t *B, size_t sizeB, const uint8_t *N, size_t sizeN, const uint8_t *E, size_t sizeE) { uint32_t clearMask = (uint32_t)kCAU3_ClearMode; /* clear Mode Register */ /* Clear internal register states. */ if (sizeA != 0U) { clearMask |= (uint32_t)kCAU3_ClearPkhaSizeA; } if (sizeB != 0U) { clearMask |= (uint32_t)kCAU3_ClearPkhaSizeB; } if (sizeN != 0U) { clearMask |= (uint32_t)kCAU3_ClearPkhaSizeN; } if (sizeE != 0U) { clearMask |= (uint32_t)kCAU3_ClearPkhaSizeE; } base->CW = clearMask; base->STA = (uint32_t)kCAU3_StatusDoneIsr; (void)cau3_pkha_clear_regabne(base, (bool)(uintptr_t)A, (bool)(uintptr_t)B, (bool)(uintptr_t)N, (bool)(uintptr_t)E); /* Write register sizes. */ /* Write modulus (N) and A and B register arguments. */ if (sizeN != 0U) { base->PKNSZ = sizeN; if (N != NULL) { (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegN, 0, N, sizeN); } } if (sizeA != 0U) { base->PKASZ = sizeA; if (A != NULL) { (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegA, 0, A, sizeA); } } if (sizeB != 0U) { base->PKBSZ = sizeB; if (B != NULL) { (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegB, 0, B, sizeB); } } if (sizeE != 0U) { base->PKESZ = sizeE; if (E != NULL) { (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegE, 0, E, sizeE); } } } static void cau3_pkha_mode_set_src_reg_copy(cau3_mode_t *outMode, cau3_pkha_reg_area_t reg) { int i = 0; do { reg = (cau3_pkha_reg_area_t)(uint32_t)((uint32_t)reg >> 1u); i++; } while ((uint32_t)reg != 0U); i = 4 - i; /* Source register must not be E. */ if (i != 2) { *outMode |= ((uint32_t)i << 17u); } } static void cau3_pkha_mode_set_dst_reg_copy(cau3_mode_t *outMode, cau3_pkha_reg_area_t reg) { int i = 0; do { reg = (cau3_pkha_reg_area_t)(uint32_t)(((uint32_t)reg) >> 1u); i++; } while ((uint32_t)reg != 0U); i = 4 - i; *outMode |= ((uint32_t)i << 10u); } static void cau3_pkha_mode_set_src_seg_copy(cau3_mode_t *outMode, const cau3_pkha_quad_area_t quad) { *outMode |= ((uint32_t)quad << 8u); } static void cau3_pkha_mode_set_dst_seg_copy(cau3_mode_t *outMode, const cau3_pkha_quad_area_t quad) { *outMode |= ((uint32_t)quad << 6u); } /*! * @brief Starts the PKHA operation. * * This function starts an operation configured by the params parameter. * * @param base CAU3 peripheral base address * @param params Configuration structure containing all settings required for PKHA operation. */ static status_t cau3_pkha_init_mode(CAU3_Type *base, const cau3_pkha_mode_params_t *params) { cau3_mode_t modeReg; status_t retval; /* Set the PKHA algorithm and the appropriate function. */ modeReg = (uint32_t)kCAU3_AlgorithmPKHA; modeReg |= (uint32_t)params->func; if ((params->func == kCAU3_PKHA_CopyMemSizeN) || (params->func == kCAU3_PKHA_CopyMemSizeSrc)) { /* Set source and destination registers and quads. */ cau3_pkha_mode_set_src_reg_copy(&modeReg, params->srcReg); cau3_pkha_mode_set_dst_reg_copy(&modeReg, params->dstReg); cau3_pkha_mode_set_src_seg_copy(&modeReg, params->srcQuad); cau3_pkha_mode_set_dst_seg_copy(&modeReg, params->dstQuad); } else { /* Set the arithmetic type - integer or binary polynomial (F2m). */ modeReg |= ((uint32_t)params->arithType << 17u); /* Set to use Montgomery form of inputs and/or outputs. */ modeReg |= ((uint32_t)params->montFormIn << 19u); modeReg |= ((uint32_t)params->montFormOut << 18u); /* Set to use pre-computed R2modN */ modeReg |= ((uint32_t)params->r2modn << 16u); } modeReg |= ((uint32_t)params->equalTime << 10u); /* Write the mode register to the hardware. * NOTE: This will begin the operation. */ base->MDPK = modeReg; retval = cau3_wait(base); return (retval); } static status_t cau3_pkha_modR2( CAU3_Type *base, const uint8_t *N, size_t sizeN, uint8_t *result, size_t *resultSize, cau3_pkha_f2m_t arithType) { status_t status; cau3_pkha_mode_params_t params; cau3_pkha_default_parms(¶ms); params.func = kCAU3_PKHA_ArithModR2; params.arithType = arithType; cau3_pkha_init_data(base, NULL, 0, NULL, 0, N, sizeN, NULL, 0); status = cau3_pkha_init_mode(base, ¶ms); if (status == kStatus_Success) { /* Read the result and size from register B0. */ if ((resultSize != NULL) && (result != NULL)) { *resultSize = base->PKBSZ; /* Read the data from the result register into place. */ cau3_pkha_read_reg(base, kCAU3_PKHA_RegB, 0, result, *resultSize); } } return status; } static status_t cau3_pkha_modmul(CAU3_Type *base, const uint8_t *A, size_t sizeA, const uint8_t *B, size_t sizeB, const uint8_t *N, size_t sizeN, uint8_t *result, size_t *resultSize, cau3_pkha_f2m_t arithType, cau3_pkha_montgomery_form_t montIn, cau3_pkha_montgomery_form_t montOut, cau3_pkha_timing_t equalTime) { cau3_pkha_mode_params_t params; status_t status; if (arithType == kCAU3_PKHA_IntegerArith) { if (CAU3_PKHA_CompareBigNum(A, sizeA, N, sizeN) >= 0) { return (kStatus_InvalidArgument); } if (CAU3_PKHA_CompareBigNum(B, sizeB, N, sizeN) >= 0) { return (kStatus_InvalidArgument); } } cau3_pkha_default_parms(¶ms); params.func = kCAU3_PKHA_ArithModMul; params.arithType = arithType; params.montFormIn = montIn; params.montFormOut = montOut; params.equalTime = equalTime; cau3_pkha_init_data(base, A, sizeA, B, sizeB, N, sizeN, NULL, 0); status = cau3_pkha_init_mode(base, ¶ms); if (status == kStatus_Success) { /* Read the result and size from register B0. */ if ((resultSize != NULL) && (result != NULL)) { *resultSize = base->PKBSZ; /* Read the data from the result register into place. */ cau3_pkha_read_reg(base, kCAU3_PKHA_RegB, 0, result, *resultSize); } } return status; } /******************************************************************************* * PKHA Code public ******************************************************************************/ /*! * addtogroup cau3_driver_pkha * { */ int CAU3_PKHA_CompareBigNum(const uint8_t *a, size_t sizeA, const uint8_t *b, size_t sizeB) { int retval = 0; /* skip zero msbytes - integer a */ while ((sizeA != 0U) && (0u == a[sizeA - 1U])) { sizeA--; } /* skip zero msbytes - integer b */ while ((sizeB != 0U) && (0u == b[sizeB - 1U])) { sizeB--; } if (sizeA > sizeB) { retval = 1; } /* int a has more non-zero bytes, thus it is bigger than b */ else if (sizeA < sizeB) { retval = -1; } /* int b has more non-zero bytes, thus it is bigger than a */ else if (sizeA == 0U) { retval = 0; } /* sizeA = sizeB = 0 */ else { int n; int i; int val; uint32_t equal; n = (int32_t)((int32_t)sizeA - 1); i = 0; equal = 0; while (n >= 0) { uint32_t chXor = ((uint32_t)a[i] ^ (uint32_t)b[i]); equal |= chXor; val = (int)chXor * ((int32_t)a[i] - (int32_t)b[i]); if (val < 0) { retval = -1; } if (val > 0) { retval = 1; } if (val == 0) { val = 1; } if (0 != val) { i++; n--; } } if (0U == equal) { retval = 0; } } return (retval); } /*! * brief Converts from integer to Montgomery format. * * This function computes R2 mod N and optionally converts A or B into Montgomery format of A or B. * * param base CAU3 peripheral base address * param N modulus * param sizeN size of N in bytes * param[in,out] A The first input in non-Montgomery format. Output Montgomery format of the first input. * param[in,out] sizeA pointer to size variable. On input it holds size of input A in bytes. On output it holds size of * Montgomery format of A in bytes. * param[in,out] B Second input in non-Montgomery format. Output Montgomery format of the second input. * param[in,out] sizeB pointer to size variable. On input it holds size of input B in bytes. On output it holds size of * Montgomery format of B in bytes. * param[out] R2 Output Montgomery factor R2 mod N. * param[out] sizeR2 pointer to size variable. On output it holds size of Montgomery factor R2 mod N in bytes. * param equalTime Run the function time equalized or no timing equalization. * param arithType Type of arithmetic to perform (integer or F2m) * return Operation status. */ status_t CAU3_PKHA_NormalToMontgomery(CAU3_Type *base, const uint8_t *N, size_t sizeN, uint8_t *A, size_t *sizeA, uint8_t *B, size_t *sizeB, uint8_t *R2, size_t *sizeR2, cau3_pkha_timing_t equalTime, cau3_pkha_f2m_t arithType) { status_t status; #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) status = cau3_lock_semaphore(base); if (kStatus_Success != status) { cau3_release_semaphore(base); return status; } #endif /* need to convert our Integer inputs into Montgomery format */ if ((N != NULL) && (sizeN != 0U) && (R2 != NULL) && (sizeR2 != NULL)) { /* 1. R2 = MOD_R2(N) */ status = cau3_pkha_modR2(base, N, sizeN, R2, sizeR2, arithType); if (status != kStatus_Success) { #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) cau3_release_semaphore(base); #endif return status; } /* 2. A(Montgomery) = MOD_MUL_IM_OM(A, R2, N) */ if ((A != NULL) && (sizeA != NULL)) { status = cau3_pkha_modmul(base, A, *sizeA, R2, *sizeR2, N, sizeN, A, sizeA, arithType, kCAU3_PKHA_MontgomeryFormat, kCAU3_PKHA_MontgomeryFormat, equalTime); if (status != kStatus_Success) { #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) cau3_release_semaphore(base); #endif return status; } } /* 2. B(Montgomery) = MOD_MUL_IM_OM(B, R2, N) */ if ((B != NULL) && (sizeB != NULL)) { status = cau3_pkha_modmul(base, B, *sizeB, R2, *sizeR2, N, sizeN, B, sizeB, arithType, kCAU3_PKHA_MontgomeryFormat, kCAU3_PKHA_MontgomeryFormat, equalTime); if (status != kStatus_Success) { #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) cau3_release_semaphore(base); #endif return status; } } cau3_clear_all(base, true); } else { status = kStatus_InvalidArgument; } #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) cau3_release_semaphore(base); #endif return status; } /*! * brief Converts from Montgomery format to int. * * This function converts Montgomery format of A or B into int A or B. * * param base CAU3 peripheral base address * param N modulus. * param sizeN size of N modulus in bytes. * param[in,out] A Input first number in Montgomery format. Output is non-Montgomery format. * param[in,out] sizeA pointer to size variable. On input it holds size of the input A in bytes. On output it holds * size of non-Montgomery A in bytes. * param[in,out] B Input first number in Montgomery format. Output is non-Montgomery format. * param[in,out] sizeB pointer to size variable. On input it holds size of the input B in bytes. On output it holds * size of non-Montgomery B in bytes. * param equalTime Run the function time equalized or no timing equalization. * param arithType Type of arithmetic to perform (integer or F2m) * return Operation status. */ status_t CAU3_PKHA_MontgomeryToNormal(CAU3_Type *base, const uint8_t *N, size_t sizeN, uint8_t *A, size_t *sizeA, uint8_t *B, size_t *sizeB, cau3_pkha_timing_t equalTime, cau3_pkha_f2m_t arithType) { uint8_t one = 1; status_t status = kStatus_InvalidArgument; #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) status = cau3_lock_semaphore(base); if (kStatus_Success != status) { cau3_release_semaphore(base); return status; } #endif /* A = MOD_MUL_IM_OM(A(Montgomery), 1, N) */ if ((A != NULL) && (sizeA != NULL)) { status = cau3_pkha_modmul(base, A, *sizeA, &one, sizeof(one), N, sizeN, A, sizeA, arithType, kCAU3_PKHA_MontgomeryFormat, kCAU3_PKHA_MontgomeryFormat, equalTime); if (kStatus_Success != status) { #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) cau3_release_semaphore(base); #endif return status; } } /* B = MOD_MUL_IM_OM(B(Montgomery), 1, N) */ if ((B != NULL) && (sizeB != NULL)) { status = cau3_pkha_modmul(base, B, *sizeB, &one, sizeof(one), N, sizeN, B, sizeB, arithType, kCAU3_PKHA_MontgomeryFormat, kCAU3_PKHA_MontgomeryFormat, equalTime); if (kStatus_Success != status) { #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) cau3_release_semaphore(base); #endif return status; } } cau3_clear_all(base, true); #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) cau3_release_semaphore(base); #endif return status; } /*! * brief Performs modular addition - (A + B) mod N. * * This function performs modular addition of (A + B) mod N, with either * integer or binary polynomial (F2m) inputs. In the F2m form, this function is * equivalent to a bitwise XOR and it is functionally the same as subtraction. * * param base CAU3 peripheral base address * param A first addend (integer or binary polynomial) * param sizeA Size of A in bytes * param B second addend (integer or binary polynomial) * param sizeB Size of B in bytes * param N modulus. * param sizeN Size of N in bytes. * param[out] result Output array to store result of operation * param[out] resultSize Output size of operation in bytes * param arithType Type of arithmetic to perform (integer or F2m) * return Operation status. */ status_t CAU3_PKHA_ModAdd(CAU3_Type *base, const uint8_t *A, size_t sizeA, const uint8_t *B, size_t sizeB, const uint8_t *N, size_t sizeN, uint8_t *result, size_t *resultSize, cau3_pkha_f2m_t arithType) { cau3_pkha_mode_params_t params; status_t status; if (arithType == kCAU3_PKHA_IntegerArith) { if (CAU3_PKHA_CompareBigNum(A, sizeA, N, sizeN) >= 0) { return (kStatus_InvalidArgument); } if (CAU3_PKHA_CompareBigNum(B, sizeB, N, sizeN) >= 0) { return (kStatus_InvalidArgument); } } #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) status = cau3_lock_semaphore(base); if (kStatus_Success != status) { cau3_release_semaphore(base); return status; } #endif cau3_pkha_default_parms(¶ms); params.func = kCAU3_PKHA_ArithModAdd; params.arithType = arithType; cau3_pkha_init_data(base, A, sizeA, B, sizeB, N, sizeN, NULL, 0); status = cau3_pkha_init_mode(base, ¶ms); if (status == kStatus_Success) { /* Read the result and size from register B0. */ if ((resultSize != NULL) && (result != NULL)) { *resultSize = base->PKBSZ; /* Read the data from the result register into place. */ cau3_pkha_read_reg(base, kCAU3_PKHA_RegB, 0, result, *resultSize); } } cau3_clear_all(base, true); #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) cau3_release_semaphore(base); #endif return status; } /*! * brief Performs modular subtraction - (A - B) mod N. * * This function performs modular subtraction of (A - B) mod N with * integer inputs. * * param base CAU3 peripheral base address * param A first addend (integer or binary polynomial) * param sizeA Size of A in bytes * param B second addend (integer or binary polynomial) * param sizeB Size of B in bytes * param N modulus * param sizeN Size of N in bytes * param[out] result Output array to store result of operation * param[out] resultSize Output size of operation in bytes * return Operation status. */ status_t CAU3_PKHA_ModSub1(CAU3_Type *base, const uint8_t *A, size_t sizeA, const uint8_t *B, size_t sizeB, const uint8_t *N, size_t sizeN, uint8_t *result, size_t *resultSize) { cau3_pkha_mode_params_t params; status_t status; if (CAU3_PKHA_CompareBigNum(A, sizeA, N, sizeN) >= 0) { return (kStatus_InvalidArgument); } if (CAU3_PKHA_CompareBigNum(B, sizeB, N, sizeN) >= 0) { return (kStatus_InvalidArgument); } #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) status = cau3_lock_semaphore(base); if (kStatus_Success != status) { cau3_release_semaphore(base); return status; } #endif cau3_pkha_default_parms(¶ms); params.func = kCAU3_PKHA_ArithModSub1; cau3_pkha_init_data(base, A, sizeA, B, sizeB, N, sizeN, NULL, 0); status = cau3_pkha_init_mode(base, ¶ms); if (status == kStatus_Success) { /* Read the result and size from register B0. */ if ((resultSize != NULL) && (result != NULL)) { *resultSize = base->PKBSZ; /* Read the data from the result register into place. */ cau3_pkha_read_reg(base, kCAU3_PKHA_RegB, 0, result, *resultSize); } } cau3_clear_all(base, true); #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) cau3_release_semaphore(base); #endif return status; } /*! * brief Performs modular subtraction - (B - A) mod N. * * This function performs modular subtraction of (B - A) mod N, * with integer inputs. * * param base CAU3 peripheral base address * param A first addend (integer or binary polynomial) * param sizeA Size of A in bytes * param B second addend (integer or binary polynomial) * param sizeB Size of B in bytes * param N modulus * param sizeN Size of N in bytes * param[out] result Output array to store result of operation * param[out] resultSize Output size of operation in bytes * return Operation status. */ status_t CAU3_PKHA_ModSub2(CAU3_Type *base, const uint8_t *A, size_t sizeA, const uint8_t *B, size_t sizeB, const uint8_t *N, size_t sizeN, uint8_t *result, size_t *resultSize) { cau3_pkha_mode_params_t params; status_t status; #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) status = cau3_lock_semaphore(base); if (kStatus_Success != status) { cau3_release_semaphore(base); return status; } #endif cau3_pkha_default_parms(¶ms); params.func = kCAU3_PKHA_ArithModSub2; cau3_pkha_init_data(base, A, sizeA, B, sizeB, N, sizeN, NULL, 0); status = cau3_pkha_init_mode(base, ¶ms); if (status == kStatus_Success) { /* Read the result and size from register B0. */ if ((resultSize != NULL) && (result != NULL)) { *resultSize = base->PKBSZ; /* Read the data from the result register into place. */ cau3_pkha_read_reg(base, kCAU3_PKHA_RegB, 0, result, *resultSize); } } cau3_clear_all(base, true); #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) cau3_release_semaphore(base); #endif return status; } /*! * brief Performs modular multiplication - (A x B) mod N. * * This function performs modular multiplication with either integer or * binary polynomial (F2m) inputs. It can optionally specify whether inputs * and/or outputs will be in Montgomery form or not. * * param base CAU3 peripheral base address * param A first addend (integer or binary polynomial) * param sizeA Size of A in bytes * param B second addend (integer or binary polynomial) * param sizeB Size of B in bytes * param N modulus. * param sizeN Size of N in bytes * param[out] result Output array to store result of operation * param[out] resultSize Output size of operation in bytes * param arithType Type of arithmetic to perform (integer or F2m) * param montIn Format of inputs * param montOut Format of output * param equalTime Run the function time equalized or no timing equalization. This argument is ignored for F2m modular * multiplication. * return Operation status. */ status_t CAU3_PKHA_ModMul(CAU3_Type *base, const uint8_t *A, size_t sizeA, const uint8_t *B, size_t sizeB, const uint8_t *N, size_t sizeN, uint8_t *result, size_t *resultSize, cau3_pkha_f2m_t arithType, cau3_pkha_montgomery_form_t montIn, cau3_pkha_montgomery_form_t montOut, cau3_pkha_timing_t equalTime) { status_t status; #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) status = cau3_lock_semaphore(base); if (kStatus_Success != status) { cau3_release_semaphore(base); return status; } #endif status = cau3_pkha_modmul(base, A, sizeA, B, sizeB, N, sizeN, result, resultSize, arithType, montIn, montOut, equalTime); cau3_clear_all(base, true); #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) cau3_release_semaphore(base); #endif return status; } /*! * brief Performs modular exponentiation - (A^E) mod N. * * This function performs modular exponentiation with either integer or * binary polynomial (F2m) inputs. * * param base CAU3 peripheral base address * param A first addend (integer or binary polynomial) * param sizeA Size of A in bytes * param N modulus * param sizeN Size of N in bytes * param E exponent * param sizeE Size of E in bytes * param[out] result Output array to store result of operation * param[out] resultSize Output size of operation in bytes * param montIn Format of A input (normal or Montgomery) * param arithType Type of arithmetic to perform (integer or F2m) * param equalTime Run the function time equalized or no timing equalization. * return Operation status. */ status_t CAU3_PKHA_ModExp(CAU3_Type *base, const uint8_t *A, size_t sizeA, const uint8_t *N, size_t sizeN, const uint8_t *E, size_t sizeE, uint8_t *result, size_t *resultSize, cau3_pkha_f2m_t arithType, cau3_pkha_montgomery_form_t montIn, cau3_pkha_timing_t equalTime) { cau3_pkha_mode_params_t params; status_t status; if (arithType == kCAU3_PKHA_IntegerArith) { if (CAU3_PKHA_CompareBigNum(A, sizeA, N, sizeN) >= 0) { return (kStatus_InvalidArgument); } } #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) status = cau3_lock_semaphore(base); if (kStatus_Success != status) { cau3_release_semaphore(base); return status; } #endif cau3_pkha_default_parms(¶ms); params.func = kCAU3_PKHA_ArithModExp; params.arithType = arithType; params.montFormIn = montIn; params.equalTime = equalTime; cau3_pkha_init_data(base, A, sizeA, NULL, 0, N, sizeN, E, sizeE); status = cau3_pkha_init_mode(base, ¶ms); if (status == kStatus_Success) { /* Read the result and size from register B0. */ if ((resultSize != NULL) && (result != NULL)) { *resultSize = base->PKBSZ; /* Read the data from the result register into place. */ cau3_pkha_read_reg(base, kCAU3_PKHA_RegB, 0, result, *resultSize); } } cau3_clear_all(base, true); #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) cau3_release_semaphore(base); #endif return status; } /*! * brief Performs Modular Square Root. * * This function performs modular square root with integer inputs. * The modular square root function computes output result B, such that ( B x B ) mod N = input A. * If no such B result exists, the result will be set to 0 and the PKHA "prime" flag * will be set. Input values A and B are limited to a maximum size of 128 bytes. Note that * two such square root values may exist. This algorithm will find either one of them, if any * exist. The second possible square root (B') can be found by calculating B' = N - B. * * param base CAU3 peripheral base address * param A input value, for which a square root is to be calculated * param sizeA Size of A in bytes * param N modulus * param sizeN Size of N in bytes * param[out] result Output array to store result of operation * param[out] resultSize Output size of operation in bytes * return Operation status. */ status_t CAU3_PKHA_ModSqrt(CAU3_Type *base, const uint8_t *A, size_t sizeA, const uint8_t *N, size_t sizeN, uint8_t *result, size_t *resultSize) { cau3_pkha_mode_params_t params; status_t status; /* A < N */ if (CAU3_PKHA_CompareBigNum(A, sizeA, N, sizeN) >= 0) { return (kStatus_InvalidArgument); } #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) status = cau3_lock_semaphore(base); if (kStatus_Success != status) { cau3_release_semaphore(base); return status; } #endif cau3_pkha_default_parms(¶ms); params.func = kCAU3_PKHA_ArithModSqrt; cau3_pkha_init_data(base, A, sizeA, NULL, 0, N, sizeN, NULL, 0); status = cau3_pkha_init_mode(base, ¶ms); if (status == kStatus_Success) { /* Read the result and size from register B0. */ if ((resultSize != NULL) && (result != NULL)) { *resultSize = base->PKBSZ; /* Read the data from the result register into place. */ cau3_pkha_read_reg(base, kCAU3_PKHA_RegB, 0, result, *resultSize); } } cau3_clear_all(base, true); #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) cau3_release_semaphore(base); #endif return status; } /*! * brief Performs modular reduction - (A) mod N. * * This function performs modular reduction with either integer or * binary polynomial (F2m) inputs. * * param base CAU3 peripheral base address * param A first addend (integer or binary polynomial) * param sizeA Size of A in bytes * param N modulus * param sizeN Size of N in bytes * param[out] result Output array to store result of operation * param[out] resultSize Output size of operation in bytes * param arithType Type of arithmetic to perform (integer or F2m) * return Operation status. */ status_t CAU3_PKHA_ModRed(CAU3_Type *base, const uint8_t *A, size_t sizeA, const uint8_t *N, size_t sizeN, uint8_t *result, size_t *resultSize, cau3_pkha_f2m_t arithType) { cau3_pkha_mode_params_t params; status_t status; #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) status = cau3_lock_semaphore(base); if (kStatus_Success != status) { cau3_release_semaphore(base); return status; } #endif cau3_pkha_default_parms(¶ms); params.func = kCAU3_PKHA_ArithModRed; params.arithType = arithType; cau3_pkha_init_data(base, A, sizeA, NULL, 0, N, sizeN, NULL, 0); status = cau3_pkha_init_mode(base, ¶ms); if (status == kStatus_Success) { /* Read the result and size from register B0. */ if ((resultSize != NULL) && (result != NULL)) { *resultSize = base->PKBSZ; /* Read the data from the result register into place. */ cau3_pkha_read_reg(base, kCAU3_PKHA_RegB, 0, result, *resultSize); } } cau3_clear_all(base, true); #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) cau3_release_semaphore(base); #endif return status; } /*! * brief Performs modular inversion - (A^-1) mod N. * * This function performs modular inversion with either integer or * binary polynomial (F2m) inputs. * * param base CAU3 peripheral base address * param A first addend (integer or binary polynomial) * param sizeA Size of A in bytes * param N modulus * param sizeN Size of N in bytes * param[out] result Output array to store result of operation * param[out] resultSize Output size of operation in bytes * param arithType Type of arithmetic to perform (integer or F2m) * return Operation status. */ status_t CAU3_PKHA_ModInv(CAU3_Type *base, const uint8_t *A, size_t sizeA, const uint8_t *N, size_t sizeN, uint8_t *result, size_t *resultSize, cau3_pkha_f2m_t arithType) { cau3_pkha_mode_params_t params; status_t status; /* A must be less than N -> CAU3_PKHA_CompareBigNum() must return -1 */ if (arithType == kCAU3_PKHA_IntegerArith) { if (CAU3_PKHA_CompareBigNum(A, sizeA, N, sizeN) >= 0) { return (kStatus_InvalidArgument); } } #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) status = cau3_lock_semaphore(base); if (kStatus_Success != status) { cau3_release_semaphore(base); return status; } #endif cau3_pkha_default_parms(¶ms); params.func = kCAU3_PKHA_ArithModInv; params.arithType = arithType; cau3_pkha_init_data(base, A, sizeA, NULL, 0, N, sizeN, NULL, 0); status = cau3_pkha_init_mode(base, ¶ms); if (status == kStatus_Success) { /* Read the result and size from register B0. */ if ((resultSize != NULL) && (result != NULL)) { *resultSize = base->PKBSZ; /* Read the data from the result register into place. */ cau3_pkha_read_reg(base, kCAU3_PKHA_RegB, 0, result, *resultSize); } } cau3_clear_all(base, true); #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) cau3_release_semaphore(base); #endif return status; } /*! * brief Computes integer Montgomery factor R^2 mod N. * * This function computes a constant to assist in converting operands * into the Montgomery residue system representation. * * param base CAU3 peripheral base address * param N modulus * param sizeN Size of N in bytes * param[out] result Output array to store result of operation * param[out] resultSize Output size of operation in bytes * param arithType Type of arithmetic to perform (integer or F2m) * return Operation status. */ status_t CAU3_PKHA_ModR2( CAU3_Type *base, const uint8_t *N, size_t sizeN, uint8_t *result, size_t *resultSize, cau3_pkha_f2m_t arithType) { status_t status; #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) status = cau3_lock_semaphore(base); if (kStatus_Success != status) { cau3_release_semaphore(base); return status; } #endif status = cau3_pkha_modR2(base, N, sizeN, result, resultSize, arithType); cau3_clear_all(base, true); #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) cau3_release_semaphore(base); #endif return status; } /*! * brief Performs Integer RERP mod P. * * This function is used to compute a constant to assist in converting operands into the * Montgomery residue system representation specifically for Chinese Remainder Theorem * while performing RSA with a CRT implementation where a modulus E=P x Q, and P and * Q are prime numbers. Although labeled RERP mod P, this routine (function) can also * compute RERQ mod Q. * * param base CAU3 peripheral base address * param P modulus P or Q of CRT, an odd integer * param sizeP Size of P in bytes * param sizeE Number of bytes of E = P x Q (this size must be given, though content of E itself is not used). * param[out] result Output array to store result of operation * param[out] resultSize Output size of operation in bytes * return Operation status. */ status_t CAU3_PKHA_ModRR( CAU3_Type *base, const uint8_t *P, size_t sizeP, size_t sizeE, uint8_t *result, size_t *resultSize) { status_t status; cau3_pkha_mode_params_t params; #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) status = cau3_lock_semaphore(base); if (kStatus_Success != status) { cau3_release_semaphore(base); return status; } #endif cau3_pkha_default_parms(¶ms); params.func = kCAU3_PKHA_ArithModRR; cau3_pkha_init_data(base, NULL, 0, NULL, 0, P, sizeP, NULL, sizeE); status = cau3_pkha_init_mode(base, ¶ms); if (status == kStatus_Success) { /* Read the result and size from register B0. */ if ((resultSize != NULL) && (result != NULL)) { *resultSize = base->PKBSZ; /* Read the data from the result register into place. */ cau3_pkha_read_reg(base, kCAU3_PKHA_RegB, 0, result, *resultSize); } } #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) cau3_release_semaphore(base); #endif return status; } /*! * brief Calculates the greatest common divisor - GCD (A, N). * * This function calculates the greatest common divisor of two inputs with * either integer or binary polynomial (F2m) inputs. * * param base CAU3 peripheral base address * param A first value (must be smaller than or equal to N) * param sizeA Size of A in bytes * param N second value (must be non-zero) * param sizeN Size of N in bytes * param[out] result Output array to store result of operation * param[out] resultSize Output size of operation in bytes * param arithType Type of arithmetic to perform (integer or F2m) * return Operation status. */ status_t CAU3_PKHA_ModGcd(CAU3_Type *base, const uint8_t *A, size_t sizeA, const uint8_t *N, size_t sizeN, uint8_t *result, size_t *resultSize, cau3_pkha_f2m_t arithType) { cau3_pkha_mode_params_t params; status_t status; #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) status = cau3_lock_semaphore(base); if (kStatus_Success != status) { cau3_release_semaphore(base); return status; } #endif cau3_pkha_default_parms(¶ms); params.func = kCAU3_PKHA_ArithGcd; params.arithType = arithType; cau3_pkha_init_data(base, A, sizeA, NULL, 0, N, sizeN, NULL, 0); status = cau3_pkha_init_mode(base, ¶ms); if (status == kStatus_Success) { /* Read the result and size from register B0. */ if ((resultSize != NULL) && (result != NULL)) { *resultSize = base->PKBSZ; /* Read the data from the result register into place. */ cau3_pkha_read_reg(base, kCAU3_PKHA_RegB, 0, result, *resultSize); } } cau3_clear_all(base, true); #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) cau3_release_semaphore(base); #endif return status; } /*! * brief Executes Miller-Rabin primality test. * * This function calculates whether or not a candidate prime number is likely * to be a prime. * * param base CAU3 peripheral base address * param A initial random seed * param sizeA Size of A in bytes * param B number of trial runs * param sizeB Size of B in bytes * param N candidate prime integer * param sizeN Size of N in bytes * param[out] res True if the value is likely prime or false otherwise * return Operation status. */ status_t CAU3_PKHA_PrimalityTest(CAU3_Type *base, const uint8_t *A, size_t sizeA, const uint8_t *B, size_t sizeB, const uint8_t *N, size_t sizeN, bool *res) { uint8_t result; cau3_pkha_mode_params_t params; status_t status; #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) status = cau3_lock_semaphore(base); if (kStatus_Success != status) { cau3_release_semaphore(base); return status; } #endif cau3_pkha_default_parms(¶ms); params.func = kCAU3_PKHA_ArithPrimalityTest; cau3_pkha_init_data(base, A, sizeA, B, sizeB, N, sizeN, NULL, 0); status = cau3_pkha_init_mode(base, ¶ms); if (status == kStatus_Success) { /* Read the data from the result register into place. */ cau3_pkha_read_reg(base, kCAU3_PKHA_RegB, 0, &result, 1); *res = (bool)result; } cau3_clear_all(base, true); #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) cau3_release_semaphore(base); #endif return status; } /*! * brief Adds elliptic curve points - A + B. * * This function performs ECC point addition over a prime field (Fp) or binary field (F2m) using * affine coordinates. * * param base CAU3 peripheral base address * param A Left-hand point * param B Right-hand point * param N Prime modulus of the field * param R2modN NULL (the function computes R2modN internally) or pointer to pre-computed R2modN (obtained from * CAU3_PKHA_ModR2() function). * param aCurveParam A parameter from curve equation * param bCurveParam B parameter from curve equation (constant) * param size Size in bytes of curve points and parameters * param arithType Type of arithmetic to perform (integer or F2m) * param[out] result Result point * return Operation status. */ status_t CAU3_PKHA_ECC_PointAdd(CAU3_Type *base, const cau3_pkha_ecc_point_t *A, const cau3_pkha_ecc_point_t *B, const uint8_t *N, const uint8_t *R2modN, const uint8_t *aCurveParam, const uint8_t *bCurveParam, size_t size, cau3_pkha_f2m_t arithType, cau3_pkha_ecc_point_t *result) { cau3_pkha_mode_params_t params; uint32_t clearMask; status_t status; #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) status = cau3_lock_semaphore(base); if (kStatus_Success != status) { cau3_release_semaphore(base); return status; } #endif cau3_pkha_default_parms(¶ms); params.func = kCAU3_PKHA_ArithEccAdd; params.arithType = arithType; params.r2modn = (R2modN != NULL) ? kCAU3_PKHA_InputR2 : kCAU3_PKHA_CalcR2; clearMask = (uint32_t)kCAU3_ClearMode; /* Clear internal register states. */ clearMask |= (uint32_t)kCAU3_ClearPkhaSizeA; clearMask |= (uint32_t)kCAU3_ClearPkhaSizeB; clearMask |= (uint32_t)kCAU3_ClearPkhaSizeN; clearMask |= (uint32_t)kCAU3_ClearPkhaSizeE; base->CW = clearMask; base->STA = (uint32_t)kCAU3_StatusDoneIsr; (void)cau3_pkha_clear_regabne(base, true, true, true, false); /* sizeN should be less than 64 bytes. */ base->PKNSZ = size; (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegN, 0, N, size); base->PKASZ = size; (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegA, 0, A->X, size); (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegA, 1, A->Y, size); (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegA, 3, aCurveParam, size); base->PKBSZ = size; (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegB, 0, bCurveParam, size); (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegB, 1, B->X, size); (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegB, 2, B->Y, size); if (R2modN != NULL) { (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegB, 3, R2modN, size); } status = cau3_pkha_init_mode(base, ¶ms); if (status == kStatus_Success) { /* Read the data from the result register into place. */ cau3_pkha_read_reg(base, kCAU3_PKHA_RegB, 1, result->X, size); cau3_pkha_read_reg(base, kCAU3_PKHA_RegB, 2, result->Y, size); } cau3_clear_all(base, true); #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) cau3_release_semaphore(base); #endif return status; } /*! * brief Doubles elliptic curve points - B + B. * * This function performs ECC point doubling over a prime field (Fp) or binary field (F2m) using * affine coordinates. * * param base CAU3 peripheral base address * param B Point to double * param N Prime modulus of the field * param aCurveParam A parameter from curve equation * param bCurveParam B parameter from curve equation (constant) * param size Size in bytes of curve points and parameters * param arithType Type of arithmetic to perform (integer or F2m) * param[out] result Result point * return Operation status. */ status_t CAU3_PKHA_ECC_PointDouble(CAU3_Type *base, const cau3_pkha_ecc_point_t *B, const uint8_t *N, const uint8_t *aCurveParam, const uint8_t *bCurveParam, size_t size, cau3_pkha_f2m_t arithType, cau3_pkha_ecc_point_t *result) { cau3_pkha_mode_params_t params; uint32_t clearMask; status_t status; #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) status = cau3_lock_semaphore(base); if (kStatus_Success != status) { cau3_release_semaphore(base); return status; } #endif cau3_pkha_default_parms(¶ms); params.func = kCAU3_PKHA_ArithEccDouble; params.arithType = arithType; clearMask = (uint32_t)kCAU3_ClearMode; /* Clear internal register states. */ clearMask |= (uint32_t)kCAU3_ClearPkhaSizeA; clearMask |= (uint32_t)kCAU3_ClearPkhaSizeB; clearMask |= (uint32_t)kCAU3_ClearPkhaSizeN; clearMask |= (uint32_t)kCAU3_ClearPkhaSizeE; base->CW = clearMask; base->STA = (uint32_t)kCAU3_StatusDoneIsr; (void)cau3_pkha_clear_regabne(base, true, true, true, false); /* sizeN should be less than 64 bytes. */ base->PKNSZ = size; (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegN, 0, N, size); base->PKASZ = size; (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegA, 3, aCurveParam, size); base->PKBSZ = size; (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegB, 0, bCurveParam, size); (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegB, 1, B->X, size); (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegB, 2, B->Y, size); status = cau3_pkha_init_mode(base, ¶ms); if (status == kStatus_Success) { /* Read the data from the result register into place. */ cau3_pkha_read_reg(base, kCAU3_PKHA_RegB, 1, result->X, size); cau3_pkha_read_reg(base, kCAU3_PKHA_RegB, 2, result->Y, size); } cau3_clear_all(base, true); #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) cau3_release_semaphore(base); #endif return status; } /*! * brief Multiplies an elliptic curve point by a scalar - E x (A0, A1). * * This function performs ECC point multiplication to multiply an ECC point by * a scalar integer multiplier over a prime field (Fp) or a binary field (F2m). * * param base CAU3 peripheral base address * param A Point as multiplicand * param E Scalar multiple * param sizeE The size of E, in bytes * param N Modulus, a prime number for the Fp field or Irreducible polynomial for F2m field. * param R2modN NULL (the function computes R2modN internally) or pointer to pre-computed R2modN (obtained from * CAU3_PKHA_ModR2() function). * param aCurveParam A parameter from curve equation * param bCurveParam B parameter from curve equation (C parameter for operation over F2m). * param size Size in bytes of curve points and parameters * param equalTime Run the function time equalized or no timing equalization. * param arithType Type of arithmetic to perform (integer or F2m) * param[out] result Result point * return Operation status. */ status_t CAU3_PKHA_ECC_PointMul(CAU3_Type *base, const cau3_pkha_ecc_point_t *A, const uint8_t *E, size_t sizeE, const uint8_t *N, const uint8_t *R2modN, const uint8_t *aCurveParam, const uint8_t *bCurveParam, size_t size, cau3_pkha_timing_t equalTime, cau3_pkha_f2m_t arithType, cau3_pkha_ecc_point_t *result) { cau3_pkha_mode_params_t params; uint32_t clearMask; status_t status; #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) status = cau3_lock_semaphore(base); if (kStatus_Success != status) { cau3_release_semaphore(base); return status; } #endif cau3_pkha_default_parms(¶ms); params.func = kCAU3_PKHA_ArithEccMul; params.equalTime = equalTime; params.arithType = arithType; params.r2modn = (R2modN != NULL) ? kCAU3_PKHA_InputR2 : kCAU3_PKHA_CalcR2; clearMask = (uint32_t)kCAU3_ClearMode; /* Clear internal register states. */ clearMask |= (uint32_t)kCAU3_ClearPkhaSizeA; clearMask |= (uint32_t)kCAU3_ClearPkhaSizeB; clearMask |= (uint32_t)kCAU3_ClearPkhaSizeN; clearMask |= (uint32_t)kCAU3_ClearPkhaSizeE; base->CW = clearMask; base->STA = (uint32_t)kCAU3_StatusDoneIsr; (void)cau3_pkha_clear_regabne(base, true, true, true, true); /* sizeN should be less than 64 bytes. */ base->PKNSZ = size; (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegN, 0, N, size); base->PKESZ = sizeE; (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegE, 0, E, sizeE); base->PKASZ = size; (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegA, 0, A->X, size); (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegA, 1, A->Y, size); (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegA, 3, aCurveParam, size); base->PKBSZ = size; (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegB, 0, bCurveParam, size); if (R2modN != NULL) { (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegB, 1, R2modN, size); } status = cau3_pkha_init_mode(base, ¶ms); if (status == kStatus_Success) { /* Read the data from the result register into place. */ cau3_pkha_read_reg(base, kCAU3_PKHA_RegB, 1, result->X, size); cau3_pkha_read_reg(base, kCAU3_PKHA_RegB, 2, result->Y, size); } cau3_clear_all(base, true); #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) cau3_release_semaphore(base); #endif return status; } /*! * brief Computes scalar multiplication of a point on an elliptic curve in Montgomery form. * * This function computes the scalar multiplication of a point on an elliptic curve in * Montgomery form. The input and output are just the x coordinates of the points. * The points on a curve are defined by the equation E: B*y^2 = x^3 + A*x^2 + x mod p * This function computes a point multiplication on a Montgomery curve, using * Montgomery values, by means of a Montgomery ladder. At the end of the ladder, P2 = P3 + P1, * where P1 is the input and P3 is the result. * * param base CAU3 peripheral base address * param E Scalar multiplier, any integer * param sizeE The size of E, in bytes * param inputCoordinate Point as multiplicand, an input point's affine x coordinate * param A24 elliptic curve a24 parameter, that is, (A+2)/4 * param N Modulus, a prime number. * param R2modN NULL (the function computes R2modN internally) or pointer to pre-computed R2modN (obtained from * ref CAU3_PKHA_ModR2() function). * param size Size in bytes of curve points and parameters * param equalTime Run the function time equalized or no timing equalization. * param[out] outputCoordinate Resulting poin's x affine coordinate. * return Operation status. */ status_t CAU3_PKHA_ECM_PointMul(CAU3_Type *base, const uint8_t *E, size_t sizeE, const uint8_t *inputCoordinate, const uint8_t *A24, const uint8_t *N, const uint8_t *R2modN, size_t size, cau3_pkha_timing_t equalTime, uint8_t *outputCoordinate) { cau3_pkha_mode_params_t params; uint32_t clearMask; status_t status; #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) status = cau3_lock_semaphore(base); if (kStatus_Success != status) { cau3_release_semaphore(base); return status; } #endif cau3_pkha_default_parms(¶ms); params.func = kCAU3_PKHA_ArithEcmMul; params.equalTime = equalTime; params.r2modn = (R2modN != NULL) ? kCAU3_PKHA_InputR2 : kCAU3_PKHA_CalcR2; clearMask = (uint32_t)kCAU3_ClearMode; /* Clear internal register states. */ clearMask |= (uint32_t)kCAU3_ClearPkhaSizeA; clearMask |= (uint32_t)kCAU3_ClearPkhaSizeB; clearMask |= (uint32_t)kCAU3_ClearPkhaSizeN; clearMask |= (uint32_t)kCAU3_ClearPkhaSizeE; base->CW = clearMask; base->STA = (uint32_t)kCAU3_StatusDoneIsr; (void)cau3_pkha_clear_regabne(base, true, true, true, true); base->PKNSZ = size; (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegN, 0, N, size); base->PKESZ = sizeE; (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegE, 0, E, sizeE); base->PKASZ = size; (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegA, 0, inputCoordinate, size); (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegA, 3, A24, size); if (R2modN != NULL) { base->PKBSZ = size; (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegB, 1, R2modN, size); } status = cau3_pkha_init_mode(base, ¶ms); if (status == kStatus_Success) { /* Read the data from the result register into place. */ (void)cau3_pkha_read_reg(base, kCAU3_PKHA_RegB, 1, outputCoordinate, size); } cau3_clear_all(base, true); #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) cau3_release_semaphore(base); #endif return status; } /*! * brief Multiplies an Edwards-form elliptic curve point by a scalar - E x (A0, A1). * * This function performs scalar multiplication of an Edwards-form elliptic curve point * in affine coordinates. * The points on a curve are defined by the equation E: a*X^2 + d^2 = 1 + D^2*X^2*Y^2 mod N * * param base CAU3 peripheral base address * param A Point as multiplicand * param E Scalar multiple * param sizeE The size of E, in bytes * param N Modulus, a prime number for the Fp field. * param R2modN NULL (the function computes R2modN internally) or pointer to pre-computed R2modN (obtained from * ref CAU3_PKHA_ModR2() function). * param aCurveParam A parameter from curve equation * param dCurveParam D parameter from curve equation. * param size Size in bytes of curve points and parameters * param equalTime Run the function time equalized or no timing equalization. * param[out] result Result point * return Operation status. */ status_t CAU3_PKHA_ECT_PointMul(CAU3_Type *base, const cau3_pkha_ecc_point_t *A, const uint8_t *E, size_t sizeE, const uint8_t *N, const uint8_t *R2modN, const uint8_t *aCurveParam, const uint8_t *dCurveParam, size_t size, cau3_pkha_timing_t equalTime, cau3_pkha_ecc_point_t *result) { cau3_pkha_mode_params_t params; uint32_t clearMask; status_t status; #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) status = cau3_lock_semaphore(base); if (kStatus_Success != status) { cau3_release_semaphore(base); return status; } #endif cau3_pkha_default_parms(¶ms); params.func = kCAU3_PKHA_ArithEctMul; params.equalTime = equalTime; params.r2modn = (R2modN != NULL) ? kCAU3_PKHA_InputR2 : kCAU3_PKHA_CalcR2; clearMask = (uint32_t)kCAU3_ClearMode; /* Clear internal register states. */ clearMask |= (uint32_t)kCAU3_ClearPkhaSizeA; clearMask |= (uint32_t)kCAU3_ClearPkhaSizeB; clearMask |= (uint32_t)kCAU3_ClearPkhaSizeN; clearMask |= (uint32_t)kCAU3_ClearPkhaSizeE; base->CW = clearMask; base->STA = (uint32_t)kCAU3_StatusDoneIsr; (void)cau3_pkha_clear_regabne(base, true, true, true, true); base->PKNSZ = size; (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegN, 0, N, size); base->PKESZ = sizeE; (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegE, 0, E, sizeE); base->PKASZ = size; (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegA, 0, A->X, size); (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegA, 1, A->Y, size); (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegA, 3, aCurveParam, size); base->PKBSZ = size; (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegB, 0, dCurveParam, size); if (R2modN != NULL) { (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegB, 1, R2modN, size); } status = cau3_pkha_init_mode(base, ¶ms); if (status == kStatus_Success) { /* Read the data from the result register into place. */ cau3_pkha_read_reg(base, kCAU3_PKHA_RegB, 1, result->X, size); cau3_pkha_read_reg(base, kCAU3_PKHA_RegB, 2, result->Y, size); } cau3_clear_all(base, true); #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) cau3_release_semaphore(base); #endif return status; } /*! * brief Adds an Edwards-form elliptic curve points - A + B. * * This function performs Edwards-form elliptic curve point addition over a prime field (Fp) using affine coordinates. * The points on a curve are defined by the equation E: a*X^2 + Y^2 = 1 + d^2*X^2*Y^2 mod N * * param base CAU3 peripheral base address * param A Left-hand point * param B Right-hand point * param N Prime modulus of the field * param R2modN NULL (the function computes R2modN internally) or pointer to pre-computed R2modN (obtained from * ref CAU3_PKHA_ModR2() function). * param aCurveParam A parameter from curve equation * param dCurveParam D parameter from curve equation * param size Size in bytes of curve points and parameters * param[out] result Result point * return Operation status. */ status_t CAU3_PKHA_ECT_PointAdd(CAU3_Type *base, const cau3_pkha_ecc_point_t *A, const cau3_pkha_ecc_point_t *B, const uint8_t *N, const uint8_t *R2modN, const uint8_t *aCurveParam, const uint8_t *dCurveParam, size_t size, cau3_pkha_ecc_point_t *result) { cau3_pkha_mode_params_t params; uint32_t clearMask; status_t status; #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) status = cau3_lock_semaphore(base); if (kStatus_Success != status) { cau3_release_semaphore(base); return status; } #endif cau3_pkha_default_parms(¶ms); params.func = kCAU3_PKHA_ArithEctAdd; params.r2modn = (R2modN != NULL) ? kCAU3_PKHA_InputR2 : kCAU3_PKHA_CalcR2; clearMask = (uint32_t)kCAU3_ClearMode; /* Clear internal register states. */ clearMask |= (uint32_t)kCAU3_ClearPkhaSizeA; clearMask |= (uint32_t)kCAU3_ClearPkhaSizeB; clearMask |= (uint32_t)kCAU3_ClearPkhaSizeN; clearMask |= (uint32_t)kCAU3_ClearPkhaSizeE; base->CW = clearMask; base->STA = (uint32_t)kCAU3_StatusDoneIsr; (void)cau3_pkha_clear_regabne(base, true, true, true, false); /* sizeN should be less than 64 bytes. */ base->PKNSZ = size; (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegN, 0, N, size); base->PKASZ = size; (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegA, 0, A->X, size); (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegA, 1, A->Y, size); (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegA, 3, aCurveParam, size); base->PKBSZ = size; (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegB, 0, dCurveParam, size); (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegB, 1, B->X, size); (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegB, 2, B->Y, size); if (R2modN != NULL) { (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegB, 3, R2modN, size); } status = cau3_pkha_init_mode(base, ¶ms); if (status == kStatus_Success) { /* Read the data from the result register into place. */ cau3_pkha_read_reg(base, kCAU3_PKHA_RegB, 1, result->X, size); cau3_pkha_read_reg(base, kCAU3_PKHA_RegB, 2, result->Y, size); } cau3_clear_all(base, true); #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) cau3_release_semaphore(base); #endif return status; } /*! * brief Perform a 3DES key parity check * * Performs a 3DES key parity check on three 8-byte keys. * The function is blocking. * * param base CAU3 peripheral base address * param keySlot defines the key context to be used in the parity check * * return status check from task completion */ status_t CAU3_TDES_CheckParity(CAU3_Type *base, cau3_key_slot_t keySlot) { status_t completionStatus; cau3_task_done_t taskDone; #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) completionStatus = cau3_lock_semaphore(base); if (kStatus_Success != completionStatus) { cau3_release_semaphore(base); return completionStatus; } #endif taskDone = kCAU3_TaskDonePoll; /* execute the cau3 "3des_check_parity" task */ base->CC_R[17] = (uint32_t)keySlot; /* keySlot */ base->CC_R30 = CAU3_DMEM_STK_BASE; /* initialize stack pointer (sp) */ base->CC_R31 = 0U; /* set LR = 0 to signal a host task */ base->CC_PC = CAU3_TASK_3DES_CHECK_PARITY; /* call cau_3des_chk_parity() */ base->CC_CMD = (uint32_t)taskDone; /* trigger cau3 execution */ /* process the cau3 task completion signal specified by taskDone */ completionStatus = cau3_process_task_completion(base, taskDone); #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) cau3_release_semaphore(base); #endif return (completionStatus); } /*! * brief Load DES key into CAU3 key slot. * * Load the key context into the private DMEM. * * param base CAU3 peripheral base address. * param handle Handle used for the request. * param key 0-mod-4 aligned pointer to 3DES key. * param keySize 3DES key size in bytes. Shall equal 24. * return status from set key operation */ status_t CAU3_TDES_SetKey(CAU3_Type *base, cau3_handle_t *handle, const uint8_t *key, size_t keySize) { /* only work with aligned key[] */ if (0U != (0x3U & (uintptr_t)key)) { return kStatus_InvalidArgument; } /* keySize must be 24. */ if (keySize != 24U) { return kStatus_InvalidArgument; } return cau3_load_key(base, key, keySize, (uint32_t)handle->keySlot, handle->taskDone); } /*! * brief Perform a 3DES encryption * * Performs a 3DES "electronic code book" encryption on one 8-byte data block. * The source plaintext and destination ciphertext can overlap in system memory. * Supports both blocking and non-blocking task completion. * * param base CAU3 peripheral base address. * param handle Handle used for this request. * param plaintext is source uint8_t array of data bytes, any alignment * param ciphertext is destination uint8_t array of data byte, any alignment * * return status check from task completion */ status_t CAU3_TDES_Encrypt(CAU3_Type *base, cau3_handle_t *handle, const uint8_t *plaintext, uint8_t *ciphertext) { status_t completionStatus; #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) completionStatus = cau3_lock_semaphore(base); if (kStatus_Success != completionStatus) { cau3_release_semaphore(base); return completionStatus; } #endif /* execute the cau3 "3des_encrypt_ecb" task */ base->CC_R[16] = (uintptr_t)plaintext; /* pPlainText */ base->CC_R[17] = (uint32_t)handle->keySlot; /* keySlot */ base->CC_R[19] = (uintptr_t)ciphertext; /* pCipherText */ base->CC_R30 = CAU3_DMEM_STK_BASE; /* initialize stack pointer (sp) */ base->CC_R31 = 0U; /* set LR = 0 to signal a host task */ base->CC_PC = CAU3_TASK_3DES_ENCRYPT; /* call cau_3des_encrypt() */ base->CC_CMD = (uint32_t)handle->taskDone; /* trigger cau3 execution */ /* process the cau3 task completion signal specified by taskDone */ completionStatus = cau3_process_task_completion(base, handle->taskDone); #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) cau3_release_semaphore(base); #endif return (completionStatus); } /*! * brief Perform a 3DES decryption * * Performs a 3DES "electronic code book" decryption on one 8-byte data block. * The source ciphertext and destination plaintext can overlap in sysMemory. * Supports both blocking and non-blocking task completion. * * param base CAU3 peripheral base address. * param handle Handle used for this request. * param ciphertext is destination uint8_t array of data byte, any alignment * param plaintext is source uint8_t array of data bytes, any alignment * return status check from task completion */ status_t CAU3_TDES_Decrypt(CAU3_Type *base, cau3_handle_t *handle, const uint8_t *ciphertext, uint8_t *plaintext) { status_t completionStatus; #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) completionStatus = cau3_lock_semaphore(base); if (kStatus_Success != completionStatus) { cau3_release_semaphore(base); return completionStatus; } #endif /* execute the cau3 "3des_decrypt_ecb" task */ base->CC_R[16] = (uintptr_t)ciphertext; /* pCipherText */ base->CC_R[17] = (uint32_t)handle->keySlot; /* keySlot */ base->CC_R[19] = (uintptr_t)plaintext; /* pPlainText */ base->CC_R30 = CAU3_DMEM_STK_BASE; /* initialize stack pointer (sp) */ base->CC_R31 = 0U; /* set LR = 0 to signal a host task */ base->CC_PC = CAU3_TASK_3DES_DECRYPT; /* call cau_3des_decrypt() */ base->CC_CMD = (uint32_t)handle->taskDone; /* trigger cau3 execution */ /* process the cau3 task completion signal specified by taskDone */ completionStatus = cau3_process_task_completion(base, handle->taskDone); #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) cau3_release_semaphore(base); #endif return (completionStatus); } /*! * brief Load 256-bit key into CAU3 key context (in key slot). * * Load the key context into the private DMEM for CHACHA20_POLY1305 AEAD. * * param base CAU3 peripheral base address. * param handle Handle used for the request. * param key 0-mod-4 aligned pointer to CHACHA20_POLY1305 256-bit key. * param keySize Size of the key in bytes. Shall be 32. * return status from set key operation */ status_t CAU3_CHACHA20_POLY1305_SetKey(CAU3_Type *base, cau3_handle_t *handle, const uint8_t *key, size_t keySize) { /* only work with aligned key[] */ if (0U != (0x3U & (uintptr_t)key)) { return kStatus_InvalidArgument; } /* keySize must be 32. */ if (keySize != 32U) { return kStatus_InvalidArgument; } union { uint8_t b[32]; uint32_t w[8]; } tempKey; for (uint32_t i = 0; i < ARRAY_SIZE(tempKey.w); i++) { tempKey.w[i] = __REV(((const uint32_t *)(uintptr_t)key)[i]); } return cau3_load_key(base, tempKey.b, keySize, (uint32_t)handle->keySlot, handle->taskDone); } static status_t cau3_load_nonce(CAU3_Type *base, const uint8_t *nonce, cau3_key_slot_t keySlot) { union { uint8_t b[16]; uint32_t w[4]; } tempIv; (void)memset(&tempIv, 0, sizeof(tempIv)); /* set nonce to keySlot */ (void)memcpy(tempIv.b, nonce, 12); /* swap bytes */ tempIv.w[0] = __REV(tempIv.w[0]); tempIv.w[1] = __REV(tempIv.w[1]); tempIv.w[2] = __REV(tempIv.w[2]); return CAU3_LoadKeyInitVector(base, tempIv.b, keySlot, kCAU3_TaskDonePoll); } /*! * brief Perform ChaCha-Poly encryption/authentication * * Perform ChaCha encryption over a message of "n" bytes, and authentication * over the encrypted data plus an additional authenticated data, * returning encrypted data + a message digest. * * param base CAU3 peripheral base address * param handle Handle used for this request. The keySlot member specifies key context with key and IV. * param plaintext The uint8_t source message to be encrypted, any alignment * param[out] ciphertext is a pointer to the output encrypted message, any aligment * param size The length of the plaintext and ciphertext in bytes * param aad A pointer to the additional authenticated data, any alignment * param aadLen Length of additional authenticated data in bytes * param nonce 0-mod-4 aligned pointer to CHACHA20_POLY1305 96-bit nonce. * param[out] tag A pointer to the 128-bit message digest output, any alignment * * return status check from task completion */ status_t CAU3_CHACHA20_POLY1305_Encrypt(CAU3_Type *base, cau3_handle_t *handle, const uint8_t *plaintext, uint8_t *ciphertext, size_t size, const uint8_t *aad, size_t aadLen, const uint8_t *nonce, uint8_t *tag) { status_t completionStatus; completionStatus = cau3_load_nonce(base, nonce, handle->keySlot); if (kStatus_Success != completionStatus) { return completionStatus; } #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) completionStatus = cau3_lock_semaphore(base); if (kStatus_Success != completionStatus) { cau3_release_semaphore(base); return completionStatus; } #endif base->CC_R[17] = (uint32_t)handle->keySlot; /* key/iv slot */ base->CC_R[18] = (uintptr_t)aad; /* AAD pointer */ base->CC_R[19] = aadLen; /* AAD length (bytes) */ base->CC_R[20] = (uintptr_t)plaintext; /* Plaintext pointer */ base->CC_R[21] = size; /* Plaintext length */ base->CC_R[22] = (uintptr_t)ciphertext; /* Ciphertext pointer */ base->CC_R[23] = (uintptr_t)tag; /* Tag pointer */ base->CC_R30 = CAU3_DMEM_STK_BASE; /* initialize stack pointer (sp) */ base->CC_R31 = 0U; /* set LR = 0 to signal a host task */ base->CC_PC = CAU3_TASK_CHA_POLY_ENCRYPT; /* ChaChaPoly encrypt vector */ base->CC_CMD = (uint32_t)handle->taskDone; /* trigger cau3 execution */ /* process the cau3 task completion signal specified by taskDone */ completionStatus = cau3_process_task_completion(base, handle->taskDone); #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) cau3_release_semaphore(base); #endif return (completionStatus); } /*! * brief Perform ChaCha-Poly decryption/authentication check * * Perform ChaCha decryption over a message of "n" bytes, and checks * authentication over the encrypted data plus an additional authenticated data, * returning decrypted data. IF the tag authentication fails, the task terminates with error and * the output is forced to zero. * * param base CAU3 peripheral base address * param handle Handle used for this request. The keySlot member specifies key context with key and IV. * param ciphertext The uint8_t source msg to be decrypted, any alignment * param[out] plaintext A pointer to the output decrypted message, any alignment * param size Length of the plaintext and ciphertext in bytes * param aad A pointer to the additional authenticated data, any alignment * param aadLen Length of additional authenticated data in bytes * param nonce 0-mod-4 aligned pointer to CHACHA20_POLY1305 96-bit nonce. * param tag A pointer to the 128-bit msg digest input to be checked, any alignment * * return status check from task completion * */ status_t CAU3_CHACHA20_POLY1305_Decrypt(CAU3_Type *base, cau3_handle_t *handle, const uint8_t *ciphertext, uint8_t *plaintext, size_t size, const uint8_t *aad, size_t aadLen, const uint8_t *nonce, const uint8_t *tag) { status_t completionStatus; completionStatus = cau3_load_nonce(base, nonce, handle->keySlot); if (kStatus_Success != completionStatus) { return completionStatus; } #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) completionStatus = cau3_lock_semaphore(base); if (kStatus_Success != completionStatus) { cau3_release_semaphore(base); return completionStatus; } #endif base->CC_R[17] = (uint32_t)handle->keySlot; /* key/iv slot */ base->CC_R[18] = (uintptr_t)aad; /* AAD pointer */ base->CC_R[19] = aadLen; /* AAD length (bytes) */ base->CC_R[20] = (uintptr_t)ciphertext; /* Ciphertext pointer */ base->CC_R[21] = size; /* Cyphertext length */ base->CC_R[22] = (uintptr_t)plaintext; /* Plaintext pointer */ base->CC_R[23] = (uintptr_t)tag; /* Tag pointer */ base->CC_R30 = CAU3_DMEM_STK_BASE; /* initialize stack pointer (sp) */ base->CC_R31 = 0U; /* set LR = 0 to signal a host task */ base->CC_PC = CAU3_TASK_CHA_POLY_DECRYPT; /* ChaChaPoly decrypt vector */ base->CC_CMD = (uint32_t)handle->taskDone; /* trigger cau3 execution */ /* process the cau3 task completion signal specified by taskDone */ completionStatus = cau3_process_task_completion(base, handle->taskDone); #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) cau3_release_semaphore(base); #endif return (completionStatus); } /*! * brief Perform an RFC3394 key blob unwrap * * Perform an RFC3394 unwrap of an AES encrypted key blob. The unwrapped * key blob is loaded into the specified key slot [1-3]. The initial * special hardware KEK contained in key slot 0 is typically used for the * unwrapping operation. The destination context number must be different than * the keySlot used for unwrapping. * Implements the algorithm at RFC 3394 to AES key unwrap. The * current implementation allows to unwrap up to 512 bits, * with the restriction of nblocks=2 or =4 or n=8(means it * unwraps only 128bits, 256bits or two 256 bits keys (512)). It * is allowed input key of 128 and 256bits only (passed using * the keyslot). The function also assumes the * ref CAU3_LoadSpecialKeyContext was called before. * It returns error and clear the destination context in case * parameters are not inside aceptable values. * In case n>4 && n!=8 it clears both destination contexts (the * dstContext and the adjacent/next context) * In case of n=8, the first unwraped key will be stored in the * dstContext slot, and the second key will be saved in the next * context (E.g: if dstContext=1, then first key goes to slot 1 * and second key to slot 2. If dstContext=3 then first key goes * to slot 3 and second key goes to slot 1). * Examples of n usage. * E.g.: n = 2 means a unwraped key of 128 bits (2 * 64) * E.g.: n = 4 means a unwraped key of 256 bits (4 * 64) * E.g.: n = 8 means two unwraped keys of 256 bits (8 * 64) * * The function is blocking, it uses the polling task done signaling. * * param base CAU3 peripheral base address * param keySlot is the key used to unwrap the key blob [0-3] * param keyBlob 0-mod-4 aligned pointer is the RFC3394 wrapped key blob. * param numberOfBlocks is the unwrapped keyBlob length as multiple of 64-bit blocks * param dstContext is the destination key context for unwrapped blob [0-3] * retval status check from task completion */ status_t CAU3_KeyBlobUnwrap(CAU3_Type *base, cau3_key_slot_t keySlot, const uint8_t *keyBlob, uint32_t numberOfBlocks, cau3_key_slot_t dstContext) { status_t completionStatus; cau3_task_done_t taskDone; if (0U != (0x3U & (uintptr_t)keyBlob)) { return kStatus_InvalidArgument; } #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) completionStatus = cau3_lock_semaphore(base); if (kStatus_Success != completionStatus) { cau3_release_semaphore(base); return completionStatus; } #endif taskDone = kCAU3_TaskDonePoll; /* execute the cau3 "key blob unwrap" task */ base->CC_R[16] = (uintptr_t)keyBlob; /* pKeyBlob */ base->CC_R[17] = (uint32_t)keySlot; /* keySlot */ base->CC_R[18] = numberOfBlocks; /* numberOfBlocks */ base->CC_R[19] = (uint32_t)dstContext; /* destination key context */ base->CC_R30 = CAU3_DMEM_STK_BASE; /* initialize stack pointer (sp) */ base->CC_R31 = 0U; /* set LR = 0 to signal a host task */ base->CC_PC = CAU3_TASK_KEY_BLOB_UNWRAP; /* call cau_key_blob_unwrap() */ base->CC_CMD = (uint32_t)taskDone; /* trigger cau3 execution */ /* process the cau3 task completion signal specified by taskDone */ completionStatus = cau3_process_task_completion(base, taskDone); #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0) cau3_release_semaphore(base); #endif return (completionStatus); }