1 /*
2  * Copyright 2017-2020 NXP
3  * All rights reserved.
4  *
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_cau3.h"
10 
11 /*******************************************************************************
12  * Definitions
13  ******************************************************************************/
14 
15 /* Component ID definition, used by tools. */
16 #ifndef FSL_COMPONENT_ID
17 #define FSL_COMPONENT_ID "platform.drivers.cau3"
18 #endif
19 
20 /*! Compile time sizeof() check */
21 #define BUILD_ASSURE(condition, msg) extern int msg[1 - 2 * (!(condition))] __attribute__((unused))
22 
23 #define CAU3_SR_TKCS_INITRUN   0x00000000U
24 #define CAU3_SR_TKCS_RUN       0x00000100U
25 #define CAU3_SR_TKCS_DBGHALT   0x00000200U
26 #define CAU3_SR_TKCS_STOPNOERR 0x00000900U
27 #define CAU3_SR_TKCS_STOPERROR 0x00000A00U
28 #define CAU3_SR_TKCS_SECV      0x00000E00U
29 #define CAU3_SR_TKCS_EXTSECV   0x00000F00U
30 
31 #define CAU3_DMEM_STK_BASE 0xfff003f8U
32 #define CAU3_DMEM_AES_RCON 0xfff00A00U
33 
34 #define CAU3_TASK_SECV_INIT         0x00 * 4
35 #define CAU3_TASK_STOPERROR         0x01 * 4
36 #define CAU3_TASK_STOPNOERR         0x02 * 4
37 #define CAU3_TASK_NULL              0x02 * 4
38 #define CAU3_TASK_BLKLD_DMEM        0x03 * 4
39 #define CAU3_TASK_LD_KEYCTX         0x04 * 4
40 #define CAU3_TASK_LD_SP_KEYCTX      0x05 * 4
41 #define CAU3_TASK_CLR_KEYCTX        0x06 * 4
42 #define CAU3_TASK_LD_KEY            0x07 * 4
43 #define CAU3_TASK_LD_KEK            0x08 * 4
44 #define CAU3_TASK_LD_IV             0x09 * 4
45 #define CAU3_TASK_AES_KEY_SCH       0x0A * 4
46 #define CAU3_TASK_AES_ENCRYPT       0x0B * 4
47 #define CAU3_TASK_AES_DECRYPT       0x0C * 4
48 #define CAU3_TASK_AES128_ENCRYPT    0x0D * 4
49 #define CAU3_TASK_AES128_DECRYPT    0x0E * 4
50 #define CAU3_TASK_AES128_CMAC       0x0F * 4
51 #define CAU3_TASK_SHA256_INIT_STATE 0x10 * 4
52 #define CAU3_TASK_SHA256_UPDATE     0x11 * 4
53 #define CAU3_TASK_KEY_BLOB_UNWRAP   0x12 * 4
54 #define CAU3_TASK_SHA1_HASH         0x13 * 4
55 #define CAU3_TASK_SHA1_INIT_STATE   0x14 * 4
56 #define CAU3_TASK_SHA512_INIT_STATE 0x15 * 4
57 #define CAU3_TASK_SHA512_UPDATE     0x16 * 4
58 #define CAU3_TASK_3DES_CHECK_PARITY 0x17 * 4
59 #define CAU3_TASK_3DES_ENCRYPT      0x18 * 4
60 #define CAU3_TASK_3DES_DECRYPT      0x19 * 4
61 #define CAU3_TASK_CHA_POLY_ENCRYPT  0x1A * 4
62 #define CAU3_TASK_CHA_POLY_DECRYPT  0x1B * 4
63 
64 #define CAU3_SEMA4_LOCK         0x80000000U
65 #define CAU3_SEMA4_RELEASE      0x00000000U
66 #define CAU3_SMOWNR_OWNED_BY_ME 0x00000001U
67 #define CAU3_SMOWNR_UNLOCKED    0x80000000U
68 
69 /*! @brief keyContext structure in the CAU3's DataMemory */
70 typedef struct _cau3_key_context
71 {
72     uint32_t keySize;    /*!< key size in bytes, 0 = invalid context */
73     uint32_t streamSize; /*!< rfu-firmware; stream length in bytes */
74     uint32_t *keySched;  /*!< rfu-firmware; ptr to expanded key schedule */
75     uint32_t zeroFill;   /*!< zero (unused) to keep 0-mod-4 alignment */
76     uint8_t iv[16];      /*!< initialization vector */
77     uint8_t key[32];     /*!< key for 3des, aes[128,192,256] */
78 } cau3_key_context_t;
79 
80 typedef enum _cau3_crypt
81 {
82     kCAU3_Encrypt = 0,
83     kCAU3_Decrypt = 1,
84 } cau3_crypt_t;
85 
86 #define cau3_memcpy memcpy
87 
88 /*! Internal states of the HASH creation process */
89 typedef enum _cau3_hash_algo_state
90 {
91     kCAU3_StateHashInit = 1u, /*!< Init state. */
92     kCAU3_StateHashUpdate,    /*!< Update state. */
93 } cau3_hash_algo_state_t;
94 
95 /*! multiple of 64-byte block represented as byte array of 32-bit words */
96 typedef union _cau3_hash_block
97 {
98     uint32_t w[CAU3_HASH_BLOCK_SIZE / 4]; /*!< array of 32-bit words */
99     uint8_t b[CAU3_HASH_BLOCK_SIZE];      /*!< byte array */
100 } cau3_hash_block_t;
101 
102 /*! internal cau3_hash context structure */
103 typedef struct _cau3_hash_ctx_internal
104 {
105     cau3_hash_block_t blk;        /*!< memory buffer. only full blocks are written to CAU3 during hash/cmac updates */
106     size_t blksz;                 /*!< number of valid bytes in memory buffer */
107     cau3_hash_algo_t algo;        /*!< selected algorithm from the set of supported algorithms */
108     cau3_hash_algo_state_t state; /*!< finite machine state of the hash software process */
109     size_t fullMessageSize;       /*!< track message size during CAU3_HASH_Update(). The value is used for padding. */
110     uint32_t runningHash[8];
111 } cau3_hash_ctx_internal_t;
112 
113 /*!< SHA-1/SHA-2 digest length in bytes  */
114 enum _cau3_hash_digest_len
115 {
116     kCAU3_OutLenSha1   = 20u,
117     kCAU3_OutLenSha256 = 32u,
118 };
119 
120 /*! 64-byte block represented as byte array of 16 32-bit words */
121 typedef union _cau3_sha_block
122 {
123     uint32_t w[64 / 4]; /*!< array of 32-bit words */
124     uint8_t b[64];      /*!< byte array */
125 } cau3_sha_block_t;
126 
127 /*! Full word representing the actual bit values for the CAU3 1.0 mode register. */
128 typedef uint32_t cau3_mode_t;
129 
130 #define CAU3_MDPK_ALG_PKHA (0x80U) /*!< Bit field value for CAU3_MDPK_ALG: PKHA */
131 #define CAU3_MD_ALG_SHIFT  16
132 
133 typedef enum _cau3_algorithm
134 {
135     kCAU3_AlgorithmPKHA = CAU3_MDPK_ALG_PKHA << CAU3_MD_ALG_SHIFT,
136 } cau3_algorithm_t;
137 
138 /*! @brief CAU3 status flags */
139 enum _cau3_status_flag
140 {
141     kCAU3_StatusPkhaBusy        = 1U << CAU3_STA_PB_SHIFT,
142     kCAU3_StatusDoneIsr         = 1U << CAU3_STA_DI_SHIFT,
143     kCAU3_StatusErrorIsr        = 1U << CAU3_STA_EI_SHIFT,
144     kCAU3_StatusPublicKeyPrime  = 1U << CAU3_STA_PKP_SHIFT,
145     kCAU3_StatusPublicKeyOpOne  = 1U << CAU3_STA_PKO_SHIFT,
146     kCAU3_StatusPublicKeyOpZero = 1U << CAU3_STA_PKZ_SHIFT,
147     kCAU3_StatusAll             = 0 | kCAU3_StatusDoneIsr | kCAU3_StatusErrorIsr | kCAU3_StatusPkhaBusy |
148                       kCAU3_StatusPublicKeyPrime | kCAU3_StatusPublicKeyOpOne | kCAU3_StatusPublicKeyOpZero
149 };
150 
151 /*! @brief CAU3 clear register */
152 typedef enum _cau3_clear_written
153 {
154     kCAU3_ClearMode      = 1U << 0,
155     kCAU3_ClearDataSize  = 1U << 2,
156     kCAU3_ClearPkhaSizeA = 1U << 12,
157     kCAU3_ClearPkhaSizeB = 1U << 13,
158     kCAU3_ClearPkhaSizeN = 1U << 14,
159     kCAU3_ClearPkhaSizeE = 1U << 15,
160     kCAU3_ClearAllSize = (int)kCAU3_ClearPkhaSizeA | kCAU3_ClearPkhaSizeB | kCAU3_ClearPkhaSizeN | kCAU3_ClearPkhaSizeE,
161     kCAU3_ClearAll     = (int)(kCAU3_ClearMode | kCAU3_ClearDataSize | kCAU3_ClearAllSize | 0)
162 } cau3_clear_written_t;
163 
164 /*! @brief PKHA functions - arithmetic, copy/clear memory. */
165 typedef enum _cau3_pkha_func_t
166 {
167     kCAU3_PKHA_ClearMem           = 1U,
168     kCAU3_PKHA_ArithModAdd        = 2U,  /*!< (A + B) mod N */
169     kCAU3_PKHA_ArithModSub1       = 3U,  /*!< (A - B) mod N */
170     kCAU3_PKHA_ArithModSub2       = 4U,  /*!< (B - A) mod N */
171     kCAU3_PKHA_ArithModMul        = 5U,  /*!< (A x B) mod N */
172     kCAU3_PKHA_ArithModExp        = 6U,  /*!< (A^E) mod N */
173     kCAU3_PKHA_ArithModRed        = 7U,  /*!< (A) mod N */
174     kCAU3_PKHA_ArithModInv        = 8U,  /*!< (A^-1) mod N */
175     kCAU3_PKHA_ArithEccAdd        = 9U,  /*!< (P1 + P2) */
176     kCAU3_PKHA_ArithEccDouble     = 10U, /*!< (P2 + P2) */
177     kCAU3_PKHA_ArithEccMul        = 11U, /*!< (E x P(A0,A1) */
178     kCAU3_PKHA_ArithModR2         = 12U, /*!< (R^2 mod N) */
179     kCAU3_PKHA_ArithModRR         = 13U, /*!< (RERP mod N) */
180     kCAU3_PKHA_ArithGcd           = 14U, /*!< GCD (A, N) */
181     kCAU3_PKHA_ArithPrimalityTest = 15U, /*!< Miller-Rabin */
182     kCAU3_PKHA_CopyMemSizeN       = 16U,
183     kCAU3_PKHA_CopyMemSizeSrc     = 17U,
184     kCAU3_PKHA_ArithModSqrt       = 0x17U, /*!< (B0 x B0) mod N = A mod N */
185     kCAU3_PKHA_ArithEcmMul        = 0x4B,  /*!< (E x P[A0]) */
186     kCAU3_PKHA_ArithEctAdd        = 0x89,  /*!< (P[A0,A1] + P[B1,B2]) */
187     kCAU3_PKHA_ArithEctMul        = 0x8B,  /*!< (E x P[A0,A1]) */
188 } cau3_pkha_func_t;
189 
190 /*! @brief Register areas for PKHA clear memory operations. */
191 typedef enum _cau3_pkha_reg_area
192 {
193     kCAU3_PKHA_RegA   = 8U,
194     kCAU3_PKHA_RegB   = 4U,
195     kCAU3_PKHA_RegE   = 2U,
196     kCAU3_PKHA_RegN   = 1U,
197     kCAU3_PKHA_RegAll = kCAU3_PKHA_RegA | kCAU3_PKHA_RegB | kCAU3_PKHA_RegE | kCAU3_PKHA_RegN,
198 } cau3_pkha_reg_area_t;
199 
200 /*! @brief Quadrant areas for 2048-bit registers for PKHA copy memory
201  * operations. */
202 typedef enum _cau3_pkha_quad_area_t
203 {
204     kCAU3_PKHA_Quad0 = 0U,
205     kCAU3_PKHA_Quad1 = 1U,
206     kCAU3_PKHA_Quad2 = 2U,
207     kCAU3_PKHA_Quad3 = 3U,
208 } cau3_pkha_quad_area_t;
209 
210 /*! @brief User-supplied (R^2 mod N) input or CAU3 should calculate. */
211 typedef enum _cau3_pkha_r2_t
212 {
213     kCAU3_PKHA_CalcR2  = 0U, /*!< Calculate (R^2 mod N) */
214     kCAU3_PKHA_InputR2 = 1U  /*!< (R^2 mod N) supplied as input */
215 } cau3_pkha_r2_t;
216 
217 /*! @brief CAU3 PKHA parameters */
218 typedef struct _cau3_pkha_mode_params_t
219 {
220     cau3_pkha_func_t func;
221     cau3_pkha_f2m_t arithType;
222     cau3_pkha_montgomery_form_t montFormIn;
223     cau3_pkha_montgomery_form_t montFormOut;
224     cau3_pkha_reg_area_t srcReg;
225     cau3_pkha_quad_area_t srcQuad;
226     cau3_pkha_reg_area_t dstReg;
227     cau3_pkha_quad_area_t dstQuad;
228     cau3_pkha_timing_t equalTime;
229     cau3_pkha_r2_t r2modn;
230 } cau3_pkha_mode_params_t;
231 
232 /*******************************************************************************
233  * Variables
234  ******************************************************************************/
235 /*******************************************************************************
236  * CAU3 Read-Only Data Constants and CryptoCore Code Image
237  ******************************************************************************/
238 
239 /*  in the cau3's private, local data memory, there is a section for read-only  */
240 /*  constants associated with AES, SHA-1, SHA-256, SHA-384 and SHA-512.  */
241 /*  the memory organization and layout of this section is defined as:  */
242 /*   */
243 /*  description            size dmem_base       description  */
244 /*  cau_dmem_aes_rcon        48  FFF00800       RO aes constants        10 x 32b  */
245 /*  cau_dmem_sha1_k          16  FFF00830       RO sha1 initial "k"      4 x 32b              */
246 /*  cau_dmem_sha1_init_h     32  FFF00840       RO sha1 initial state    5 x 32b  */
247 /*  cau_dmem_sha224_init_h   32  FFF00860       RO sha224 initial state  8 x 32b              */
248 /*  cau_dmem_sha256_init_h   32  FFF00880       RO sha256 initial state  8 x 32b              */
249 /*  cau_dmem_sha256_k       256  FFF008A0       RO sha256 initial "k"   64 x 32b  */
250 /*  cau_dmem_sha384_init_h   64  FFF009A0       RO sha384 initial state 16 x 32b  */
251 /*  cau_dmem_sha512_init_h   64  FFF009E0       RO sha512 initial state 16 x 32b  */
252 /*  cau_dmem_sha512_k       640  FFF00A20       RO sha512 initial "k"   160 x 32b  */
253 /*   */
254 /*  data size allocation are rounded up to be modulo 16 bytes as required.  */
255 /*   */
256 
257 static const uint32_t s_cau3ReadOnlyConstants[] __attribute__((aligned(16))) = {
258     /*  AES RCON[]  */
259     0x01000000U, 0x02000000U, 0x04000000U, 0x08000000U, 0x10000000U, 0x20000000U, 0x40000000U, 0x80000000U, 0x1b000000U,
260     0x36000000U, 0x00000000U, 0x00000000U, /*  zero fill for 0-mod-16 alignment  */
261 
262     /*  SHA1_K[]  */
263     0x5a827999U, 0x6ed9eba1U, 0x8f1bbcdcU, 0xca62c1d6U,
264 
265     /*  SHA1_INIT_H[]  */
266     0x67452301U, 0xefcdab89U, 0x98badcfeU, 0x10325476U, 0xc3d2e1f0U, 0x00000000U, 0x00000000U,
267     0x00000000U, /*  zero fill for 0-mod-16 alignemnt  */
268 
269     /*  SHA224_INIT_H[]  */
270     0xc1059ed8U, 0x367cd507U, 0x3070dd17U, 0xf70e5939U, 0xffc00b31U, 0x68581511U, 0x64f98fa7U, 0xbefa4fa4U,
271 
272     /*  SHA256_INIT_H[]  */
273     /*  As described in FIPS PUB 180-4 "Secure Hash Standard", the initial hash value  */
274     /*  for SHA-256 is obtained by taking the first thirty-two bits of the fractional  */
275     /*  parts of the square roots of the first eight prime numbers.  */
276     0x6a09e667U, 0xbb67ae85U, 0x3c6ef372U, 0xa54ff53aU, 0x510e527fU, 0x9b05688cU, 0x1f83d9abU, 0x5be0cd19U,
277 
278     /*  SHA256_K[], also used as SHA224_K[]  */
279     /*  As described in FIPS PUB 180-4 "Secure Hash Standard", SHA-224 & SHA-256 use  */
280     /*  the same sequence of sixty-four constant 32-bit words (K[]), where the words  */
281     /*  represent the first thirty-two bits of the fractional parts of the cube roots  */
282     /*  of the first sixty-four prime numbers.  */
283 
284     0x428a2f98U, 0x71374491U, 0xb5c0fbcfU, 0xe9b5dba5U, 0x3956c25bU, 0x59f111f1U, 0x923f82a4U, 0xab1c5ed5U, 0xd807aa98U,
285     0x12835b01U, 0x243185beU, 0x550c7dc3U, 0x72be5d74U, 0x80deb1feU, 0x9bdc06a7U, 0xc19bf174U, 0xe49b69c1U, 0xefbe4786U,
286     0x0fc19dc6U, 0x240ca1ccU, 0x2de92c6fU, 0x4a7484aaU, 0x5cb0a9dcU, 0x76f988daU, 0x983e5152U, 0xa831c66dU, 0xb00327c8U,
287     0xbf597fc7U, 0xc6e00bf3U, 0xd5a79147U, 0x06ca6351U, 0x14292967U, 0x27b70a85U, 0x2e1b2138U, 0x4d2c6dfcU, 0x53380d13U,
288     0x650a7354U, 0x766a0abbU, 0x81c2c92eU, 0x92722c85U, 0xa2bfe8a1U, 0xa81a664bU, 0xc24b8b70U, 0xc76c51a3U, 0xd192e819U,
289     0xd6990624U, 0xf40e3585U, 0x106aa070U, 0x19a4c116U, 0x1e376c08U, 0x2748774cU, 0x34b0bcb5U, 0x391c0cb3U, 0x4ed8aa4aU,
290     0x5b9cca4fU, 0x682e6ff3U, 0x748f82eeU, 0x78a5636fU, 0x84c87814U, 0x8cc70208U, 0x90befffaU, 0xa4506cebU, 0xbef9a3f7U,
291     0xc67178f2U,
292 
293     /*  SHA384_INIT_H[]  */
294     /*  8 x 64-bit words in little-endian format  */
295     0xc1059ed8U, 0xcbbb9d5dU, 0x367cd507U, 0x629a292aU, 0x3070dd17U, 0x9159015aU, 0xf70e5939U, 0x152fecd8U, 0xffc00b31U,
296     0x67332667U, 0x68581511U, 0x8eb44a87U, 0x64f98fa7U, 0xdb0c2e0dU, 0xbefa4fa4U, 0x47b5481dU,
297 
298     /*  SHA512_INIT_H[]  */
299     /*  8 x 64-bit words in little-endian format  */
300     0xf3bcc908U, 0x6a09e667U, 0x84caa73bU, 0xbb67ae85U, 0xfe94f82bU, 0x3c6ef372U, 0x5f1d36f1U, 0xa54ff53aU, 0xade682d1U,
301     0x510e527fU, 0x2b3e6c1fU, 0x9b05688cU, 0xfb41bd6bU, 0x1f83d9abU, 0x137e2179U, 0x5be0cd19U,
302 
303     /*  SHA512_K[]  */
304     /*  80 x 64-bit words in little-endian format  */
305     0xd728ae22U, 0x428a2f98U, 0x23ef65cdU, 0x71374491U, 0xec4d3b2fU, 0xb5c0fbcfU, 0x8189dbbcU, 0xe9b5dba5U, 0xf348b538U,
306     0x3956c25bU, 0xb605d019U, 0x59f111f1U, 0xaf194f9bU, 0x923f82a4U, 0xda6d8118U, 0xab1c5ed5U, 0xa3030242U, 0xd807aa98U,
307     0x45706fbeU, 0x12835b01U, 0x4ee4b28cU, 0x243185beU, 0xd5ffb4e2U, 0x550c7dc3U, 0xf27b896fU, 0x72be5d74U, 0x3b1696b1U,
308     0x80deb1feU, 0x25c71235U, 0x9bdc06a7U, 0xcf692694U, 0xc19bf174U, 0x9ef14ad2U, 0xe49b69c1U, 0x384f25e3U, 0xefbe4786U,
309     0x8b8cd5b5U, 0x0fc19dc6U, 0x77ac9c65U, 0x240ca1ccU, 0x592b0275U, 0x2de92c6fU, 0x6ea6e483U, 0x4a7484aaU, 0xbd41fbd4U,
310     0x5cb0a9dcU, 0x831153b5U, 0x76f988daU, 0xee66dfabU, 0x983e5152U, 0x2db43210U, 0xa831c66dU, 0x98fb213fU, 0xb00327c8U,
311     0xbeef0ee4U, 0xbf597fc7U, 0x3da88fc2U, 0xc6e00bf3U, 0x930aa725U, 0xd5a79147U, 0xe003826fU, 0x06ca6351U, 0x0a0e6e70U,
312     0x14292967U, 0x46d22ffcU, 0x27b70a85U, 0x5c26c926U, 0x2e1b2138U, 0x5ac42aedU, 0x4d2c6dfcU, 0x9d95b3dfU, 0x53380d13U,
313     0x8baf63deU, 0x650a7354U, 0x3c77b2a8U, 0x766a0abbU, 0x47edaee6U, 0x81c2c92eU, 0x1482353bU, 0x92722c85U, 0x4cf10364U,
314     0xa2bfe8a1U, 0xbc423001U, 0xa81a664bU, 0xd0f89791U, 0xc24b8b70U, 0x0654be30U, 0xc76c51a3U, 0xd6ef5218U, 0xd192e819U,
315     0x5565a910U, 0xd6990624U, 0x5771202aU, 0xf40e3585U, 0x32bbd1b8U, 0x106aa070U, 0xb8d2d0c8U, 0x19a4c116U, 0x5141ab53U,
316     0x1e376c08U, 0xdf8eeb99U, 0x2748774cU, 0xe19b48a8U, 0x34b0bcb5U, 0xc5c95a63U, 0x391c0cb3U, 0xe3418acbU, 0x4ed8aa4aU,
317     0x7763e373U, 0x5b9cca4fU, 0xd6b2b8a3U, 0x682e6ff3U, 0x5defb2fcU, 0x748f82eeU, 0x43172f60U, 0x78a5636fU, 0xa1f0ab72U,
318     0x84c87814U, 0x1a6439ecU, 0x8cc70208U, 0x23631e28U, 0x90befffaU, 0xde82bde9U, 0xa4506cebU, 0xb2c67915U, 0xbef9a3f7U,
319     0xe372532bU, 0xc67178f2U, 0xea26619cU, 0xca273eceU, 0x21c0c207U, 0xd186b8c7U, 0xcde0eb1eU, 0xeada7dd6U, 0xee6ed178U,
320     0xf57d4f7fU, 0x72176fbaU, 0x06f067aaU, 0xa2c898a6U, 0x0a637dc5U, 0xbef90daeU, 0x113f9804U, 0x131c471bU, 0x1b710b35U,
321     0x23047d84U, 0x28db77f5U, 0x40c72493U, 0x32caab7bU, 0x15c9bebcU, 0x3c9ebe0aU, 0x9c100d4cU, 0x431d67c4U, 0xcb3e42b6U,
322     0x4cc5d4beU, 0xfc657e2aU, 0x597f299cU, 0x3ad6faecU, 0x5fcb6fabU, 0x4a475817U, 0x6c44198cU,
323     /*  CHACHA_K[]  */
324     0x61707865U, 0x3320646eU, 0x79622d32U, 0x6b206574U};
325 
326 static const uint32_t s_cau3ReadOnlyConstantsBytes = sizeof(s_cau3ReadOnlyConstants);
327 
328 static const uint32_t s_cau3ImemImage[] __attribute__((aligned(16))) = {
329     0x60C00000U, 0x54000040U, 0x54000020U, 0x60812760U, 0x608128C0U, 0x60812F00U, 0x60813640U, 0x608138C0U, 0x54000040U,
330     0x60813C20U, 0x60813F40U, 0x60802060U, 0x60803BC0U, 0x60805780U, 0x54000040U, 0x60806800U, 0x60808AA0U, 0x60808D00U,
331     0x60814120U, 0x6080C100U, 0x6080BF60U, 0x54000040U, 0x54000040U, 0x6080FB60U, 0x6080FE20U, 0x608112C0U, 0x608150C0U,
332     0x60815700U, 0x54000040U, 0x54000040U, 0x54000040U, 0x54000040U, 0x86000280U, 0x86002282U, 0x08C82236U, 0x2000C011U,
333     0x101FFE11U, 0x00405A31U, 0x20014015U, 0x101FFE15U, 0x00800004U, 0x00800425U, 0x00800846U, 0x00800C67U, 0xCE002220U,
334     0xCE002222U, 0x3C000192U, 0x66801420U, 0x63801400U, 0x86004284U, 0x86006286U, 0xCE002224U, 0xCE002226U, 0x08D020E8U,
335     0x01800108U, 0xAC0012A8U, 0x008C2000U, 0x008C0021U, 0x008C0442U, 0x008C0863U, 0xCE002220U, 0xCE002222U, 0x01800068U,
336     0x008C2084U, 0x008C10A5U, 0x008C14C6U, 0x008C18E7U, 0xCE002224U, 0xCE002226U, 0x08D020E8U, 0x01800108U, 0xAC0012A8U,
337     0x008C2000U, 0x008C0021U, 0x008C0442U, 0x008C0863U, 0xCE002220U, 0xCE002222U, 0x01800068U, 0x008C2084U, 0x008C10A5U,
338     0x008C14C6U, 0x008C18E7U, 0xCE002224U, 0xCE002226U, 0x08D020E8U, 0x01800108U, 0xAC0012A8U, 0x008C2000U, 0x008C0021U,
339     0x008C0442U, 0x008C0863U, 0xCE002220U, 0xCE002222U, 0x01800068U, 0x008C2084U, 0x008C10A5U, 0x008C14C6U, 0x008C18E7U,
340     0xCE002224U, 0xCE002226U, 0x08D020E8U, 0x01800108U, 0xAC0012A8U, 0x008C2000U, 0x008C0021U, 0x008C0442U, 0x008C0863U,
341     0xCE002220U, 0xCE002222U, 0x01800068U, 0x008C2084U, 0x008C10A5U, 0x008C14C6U, 0x008C18E7U, 0xCE002224U, 0xCE002226U,
342     0x08D020E8U, 0x01800108U, 0xAC0012A8U, 0x008C2000U, 0x008C0021U, 0x008C0442U, 0x008C0863U, 0xCE002220U, 0xCE002222U,
343     0x01800068U, 0x008C2084U, 0x008C10A5U, 0x008C14C6U, 0x008C18E7U, 0xCE002224U, 0xCE002226U, 0x08D020E8U, 0x01800108U,
344     0xAC0012A8U, 0x008C2000U, 0x008C0021U, 0x008C0442U, 0x008C0863U, 0xCE002220U, 0xCE002222U, 0x01800068U, 0x008C2084U,
345     0x008C10A5U, 0x008C14C6U, 0x008C18E7U, 0xCE002224U, 0xCE002226U, 0x08D020E8U, 0x01800108U, 0xAC0012A8U, 0x008C2000U,
346     0x008C0021U, 0x008C0442U, 0x008C0863U, 0xCE002220U, 0xCE002222U, 0x29FFE211U, 0x60801F80U, 0x54000040U, 0x08D02067U,
347     0x018000E7U, 0xAC0012A7U, 0x008C1C00U, 0x008C0021U, 0x008C0442U, 0x008C0863U, 0xCE002220U, 0xCE002222U, 0x08D02067U,
348     0x018000E7U, 0xAC0012A7U, 0x008C1C00U, 0x008C0021U, 0x008C0442U, 0x008C0863U, 0xCE002220U, 0xCE002222U, 0x08D02067U,
349     0x018000E7U, 0xAC0012A7U, 0x008C1C00U, 0x008C0021U, 0x008C0442U, 0x008C0863U, 0xCE002220U, 0xCE002222U, 0x08D02067U,
350     0x018000E7U, 0xAC0012A7U, 0x008C1C00U, 0x008C0021U, 0x008C0442U, 0x008C0863U, 0xCE002220U, 0xCE002222U, 0x08D02067U,
351     0x018000E7U, 0xAC0012A7U, 0x008C1C00U, 0x008C0021U, 0x008C0442U, 0x008C0863U, 0xCE002220U, 0xCE002222U, 0x08D02067U,
352     0x018000E7U, 0xAC0012A7U, 0x008C1C00U, 0x008C0021U, 0x008C0442U, 0x008C0863U, 0xCE002220U, 0xCE002222U, 0x08D02067U,
353     0x018000E7U, 0xAC0012A7U, 0x008C1C00U, 0x008C0021U, 0x008C0442U, 0x008C0863U, 0xCE002220U, 0xCE002222U, 0x08D02067U,
354     0x018000E7U, 0xAC0012A7U, 0x008C1C00U, 0x008C0021U, 0x008C0442U, 0x008C0863U, 0xCE002220U, 0xCE002222U, 0x08D02067U,
355     0x018000E7U, 0xAC0012A7U, 0x008C1C00U, 0x008C0021U, 0x008C0442U, 0x008C0863U, 0xCE002220U, 0xCE002222U, 0x08D02067U,
356     0x018000E7U, 0xAC0012A7U, 0x008C1C00U, 0x008C0021U, 0x008C0442U, 0x008C0863U, 0xCE002220U, 0xCE002222U, 0x29FFEA11U,
357     0x04807FFFU, 0xC4FFA291U, 0x63802000U, 0x7080001FU, 0x5C1FFFE0U, 0x581FFFE0U, 0x54000020U, 0x08800E31U, 0x08C81A20U,
358     0x2000A012U, 0x101FFE12U, 0x80000252U, 0x3C000312U, 0x668021A0U, 0x63802180U, 0x08501A52U, 0x08501A52U, 0x08501A52U,
359     0x08C82236U, 0x2000C011U, 0x101FFE11U, 0x00405A31U, 0x0C800E04U, 0x638029C0U, 0x3C000024U, 0x63802780U, 0x3C000044U,
360     0x63802540U, 0x94FFF605U, 0x08C860A0U, 0x94000605U, 0x08CC20A6U, 0x00881800U, 0x08C860A1U, 0x94001605U, 0x08CC20A6U,
361     0x00881821U, 0x08C860A2U, 0x94002605U, 0x08CC20A6U, 0x00881842U, 0x08C860A3U, 0x94003605U, 0x08CC20A6U, 0x00881863U,
362     0x60802A40U, 0x94FFFA05U, 0x08C840A0U, 0x94000A05U, 0x08CC40A6U, 0x00881800U, 0x08C840A1U, 0x94001A05U, 0x08CC40A6U,
363     0x00881821U, 0x08C840A2U, 0x94002A05U, 0x08CC40A6U, 0x00881842U, 0x08C840A3U, 0x94003A05U, 0x08CC40A6U, 0x00881863U,
364     0x60802A40U, 0x94FFFE05U, 0x08C820A0U, 0x94000E05U, 0x08CC60A6U, 0x00881800U, 0x08C820A1U, 0x94001E05U, 0x08CC60A6U,
365     0x00881821U, 0x08C820A2U, 0x94002E05U, 0x08CC60A6U, 0x00881842U, 0x08C820A3U, 0x94003E05U, 0x08CC60A6U, 0x00881863U,
366     0x60802A40U, 0x94000200U, 0x94001201U, 0x94002202U, 0x94003203U, 0xAC001220U, 0xAC001221U, 0xAC001222U, 0xAC001223U,
367     0x08500A48U, 0x08CC0508U, 0x01800000U, 0x01800021U, 0x01800042U, 0x01800063U, 0x01900000U, 0x8E002224U, 0x8E002226U,
368     0x01881000U, 0x01881421U, 0x01881842U, 0x01881C63U, 0x01800000U, 0x01800021U, 0x01800042U, 0x01800063U, 0x01900000U,
369     0x8E002224U, 0x8E002226U, 0x01881000U, 0x01881421U, 0x01881842U, 0x01881C63U, 0x60002B08U, 0x01800000U, 0x01800021U,
370     0x01800042U, 0x01800063U, 0x01900000U, 0x8E002224U, 0x8E002226U, 0x01881000U, 0x01881421U, 0x01881842U, 0x01881C63U,
371     0x01800000U, 0x01800021U, 0x01800042U, 0x01800063U, 0x01900000U, 0xAC001220U, 0xAC001221U, 0xAC001222U, 0xAC001223U,
372     0x0C800E64U, 0x63803A80U, 0x3C000024U, 0x63803760U, 0x3C000044U, 0x63803440U, 0x94FFF664U, 0x08CC2084U, 0x08C82084U,
373     0x08CC6005U, 0x008810A5U, 0xD4FFF665U, 0x08C82005U, 0x08CC6024U, 0x008810A5U, 0xD4000665U, 0x08C82025U, 0x08CC6044U,
374     0x008810A5U, 0xD4001665U, 0x08C82045U, 0x08CC6064U, 0x008810A5U, 0xD4002665U, 0x94003664U, 0x08C86084U, 0x08CC6084U,
375     0x08C82065U, 0x008810A5U, 0xD4003665U, 0x60803B00U, 0x94FFFA64U, 0x08CC4084U, 0x08C84084U, 0x08CC4005U, 0x008810A5U,
376     0xD4FFFA65U, 0x08C84005U, 0x08CC4024U, 0x008810A5U, 0xD4000A65U, 0x08C84025U, 0x08CC4044U, 0x008810A5U, 0xD4001A65U,
377     0x08C84045U, 0x08CC4064U, 0x008810A5U, 0xD4002A65U, 0x94003A64U, 0x08C84084U, 0x08CC4084U, 0x08C84065U, 0x008810A5U,
378     0xD4003A65U, 0x60803B00U, 0x94FFFE64U, 0x08CC6084U, 0x08C86084U, 0x08CC2005U, 0x008810A5U, 0xD4FFFE65U, 0x08C86005U,
379     0x08CC2024U, 0x008810A5U, 0xD4000E65U, 0x08C86025U, 0x08CC2044U, 0x008810A5U, 0xD4001E65U, 0x08C86045U, 0x08CC2064U,
380     0x008810A5U, 0xD4002E65U, 0x94003E64U, 0x08C82084U, 0x08CC2084U, 0x08C86065U, 0x008810A5U, 0xD4003E65U, 0x60803B00U,
381     0xD4000260U, 0xD4001261U, 0xD4002262U, 0xD4003263U, 0x04807FFFU, 0x63803B60U, 0x7080001FU, 0x5C1FFFE0U, 0x581FFFE0U,
382     0x54000020U, 0x08800E31U, 0x08C81A20U, 0x2000A012U, 0x101FFE12U, 0x80000252U, 0x3C000312U, 0x66803D00U, 0x63803CE0U,
383     0x08501A52U, 0x08501A52U, 0x08501A52U, 0x08C82236U, 0x2000C011U, 0x101FFE11U, 0x00405A31U, 0x0C800E04U, 0x63804520U,
384     0x3C000024U, 0x638042E0U, 0x3C000044U, 0x638040A0U, 0x94FFF605U, 0x08C860A0U, 0x94000605U, 0x08CC20A6U, 0x00881800U,
385     0x08C860A1U, 0x94001605U, 0x08CC20A6U, 0x00881821U, 0x08C860A2U, 0x94002605U, 0x08CC20A6U, 0x00881842U, 0x08C860A3U,
386     0x94003605U, 0x08CC20A6U, 0x00881863U, 0x608045A0U, 0x94FFFA05U, 0x08C840A0U, 0x94000A05U, 0x08CC40A6U, 0x00881800U,
387     0x08C840A1U, 0x94001A05U, 0x08CC40A6U, 0x00881821U, 0x08C840A2U, 0x94002A05U, 0x08CC40A6U, 0x00881842U, 0x08C840A3U,
388     0x94003A05U, 0x08CC40A6U, 0x00881863U, 0x608045A0U, 0x94FFFE05U, 0x08C820A0U, 0x94000E05U, 0x08CC60A6U, 0x00881800U,
389     0x08C820A1U, 0x94001E05U, 0x08CC60A6U, 0x00881821U, 0x08C820A2U, 0x94002E05U, 0x08CC60A6U, 0x00881842U, 0x08C820A3U,
390     0x94003E05U, 0x08CC60A6U, 0x00881863U, 0x608045A0U, 0x94000200U, 0x94001201U, 0x94002202U, 0x94003203U, 0x08C81259U,
391     0x00406631U, 0xA8003223U, 0xA8FFF222U, 0xA8FFF221U, 0xA8FFF220U, 0x08500A59U, 0x08CC0739U, 0x01940000U, 0x01840063U,
392     0x01840042U, 0x01840021U, 0x01840000U, 0x8AFFE23CU, 0x8AFFE23AU, 0x018C7463U, 0x018C7042U, 0x018C6C21U, 0x018C6800U,
393     0x01940000U, 0x01840063U, 0x01840042U, 0x01840021U, 0x01840000U, 0x8AFFE23CU, 0x8AFFE23AU, 0x018C7463U, 0x018C7042U,
394     0x018C6C21U, 0x018C6800U, 0x600046B9U, 0x01940000U, 0x01840063U, 0x01840042U, 0x01840021U, 0x01840000U, 0x8AFFE23CU,
395     0x8AFFE23AU, 0x018C7463U, 0x018C7042U, 0x018C6C21U, 0x018C6800U, 0x01940000U, 0x01840063U, 0x01840042U, 0x01840021U,
396     0x01840000U, 0xA8FFF223U, 0xA8FFF222U, 0xA8FFF221U, 0xA8FFF220U, 0x0C800E79U, 0x63805620U, 0x3C000039U, 0x63805300U,
397     0x3C000059U, 0x63804FE0U, 0x94FFF664U, 0x08CC2084U, 0x08C82084U, 0x08CC6005U, 0x008810A5U, 0xD4FFF665U, 0x08C82005U,
398     0x08CC6024U, 0x008810A5U, 0xD4000665U, 0x08C82025U, 0x08CC6044U, 0x008810A5U, 0xD4001665U, 0x08C82045U, 0x08CC6064U,
399     0x008810A5U, 0xD4002665U, 0x94003664U, 0x08C86084U, 0x08CC6084U, 0x08C82065U, 0x008810A5U, 0xD4003665U, 0x608056A0U,
400     0x94FFFA64U, 0x08CC4084U, 0x08C84084U, 0x08CC4005U, 0x008810A5U, 0xD4FFFA65U, 0x08C84005U, 0x08CC4024U, 0x008810A5U,
401     0xD4000A65U, 0x08C84025U, 0x08CC4044U, 0x008810A5U, 0xD4001A65U, 0x08C84045U, 0x08CC4064U, 0x008810A5U, 0xD4002A65U,
402     0x94003A64U, 0x08C84084U, 0x08CC4084U, 0x08C84065U, 0x008810A5U, 0xD4003A65U, 0x608056A0U, 0x94FFFE64U, 0x08CC6084U,
403     0x08C86084U, 0x08CC2005U, 0x008810A5U, 0xD4FFFE65U, 0x08C86005U, 0x08CC2024U, 0x008810A5U, 0xD4000E65U, 0x08C86025U,
404     0x08CC2044U, 0x008810A5U, 0xD4001E65U, 0x08C86045U, 0x08CC2064U, 0x008810A5U, 0xD4002E65U, 0x94003E64U, 0x08C82084U,
405     0x08CC2084U, 0x08C86065U, 0x008810A5U, 0xD4003E65U, 0x608056A0U, 0xD4003263U, 0xD4002262U, 0xD4001261U, 0xD4000260U,
406     0x04807FFFU, 0x63805700U, 0x7080001FU, 0x5C1FFFE0U, 0x581FFFE0U, 0x54000020U, 0x7080001FU, 0x08800E31U, 0x08C82236U,
407     0x2000C011U, 0x101FFE11U, 0x00405A31U, 0x94000200U, 0x94001201U, 0x94002202U, 0x94003203U, 0xAC001220U, 0xAC001221U,
408     0xAC001222U, 0xAC001223U, 0x01800000U, 0x01800021U, 0x01800042U, 0x01800063U, 0x01900000U, 0x8E002224U, 0x8E002226U,
409     0x01881000U, 0x01881421U, 0x01881842U, 0x01881C63U, 0x01800000U, 0x01800021U, 0x01800042U, 0x01800063U, 0x01900000U,
410     0x8E002224U, 0x8E002226U, 0x01881000U, 0x01881421U, 0x01881842U, 0x01881C63U, 0x01800000U, 0x01800021U, 0x01800042U,
411     0x01800063U, 0x01900000U, 0x8E002224U, 0x8E002226U, 0x01881000U, 0x01881421U, 0x01881842U, 0x01881C63U, 0x01800000U,
412     0x01800021U, 0x01800042U, 0x01800063U, 0x01900000U, 0x8E002224U, 0x8E002226U, 0x01881000U, 0x01881421U, 0x01881842U,
413     0x01881C63U, 0x01800000U, 0x01800021U, 0x01800042U, 0x01800063U, 0x01900000U, 0x8E002224U, 0x8E002226U, 0x01881000U,
414     0x01881421U, 0x01881842U, 0x01881C63U, 0x01800000U, 0x01800021U, 0x01800042U, 0x01800063U, 0x01900000U, 0x8E002224U,
415     0x8E002226U, 0x01881000U, 0x01881421U, 0x01881842U, 0x01881C63U, 0x01800000U, 0x01800021U, 0x01800042U, 0x01800063U,
416     0x01900000U, 0x8E002224U, 0x8E002226U, 0x01881000U, 0x01881421U, 0x01881842U, 0x01881C63U, 0x01800000U, 0x01800021U,
417     0x01800042U, 0x01800063U, 0x01900000U, 0x8E002224U, 0x8E002226U, 0x01881000U, 0x01881421U, 0x01881842U, 0x01881C63U,
418     0x01800000U, 0x01800021U, 0x01800042U, 0x01800063U, 0x01900000U, 0x8E002224U, 0x8E002226U, 0x01881000U, 0x01881421U,
419     0x01881842U, 0x01881C63U, 0x01800000U, 0x01800021U, 0x01800042U, 0x01800063U, 0x01900000U, 0xAC001220U, 0xAC001221U,
420     0xAC001222U, 0xAC001223U, 0xD4000260U, 0xD4001261U, 0xD4002262U, 0xD4003263U, 0x04807FFFU, 0x29FFEA11U, 0x638067A0U,
421     0x7080001FU, 0x5C1FFFE0U, 0x581FFFE0U, 0x54000020U, 0xC8FF03DEU, 0xC40013DFU, 0x2000A114U, 0x101FFE14U, 0x08C81A31U,
422     0x00405231U, 0x84000231U, 0x04804631U, 0x63006940U, 0x54000040U, 0x5C0001E0U, 0x700058BFU, 0x08CC7C04U, 0x04800000U,
423     0x04980063U, 0x04980042U, 0x04980021U, 0x04980000U, 0x60006A84U, 0x088E1C63U, 0xC40043C0U, 0xC40053C1U, 0xC40063C2U,
424     0xC40073C3U, 0x08CC7C04U, 0x04800000U, 0x04980063U, 0x04980042U, 0x04980021U, 0x04980000U, 0x60006C04U, 0x088E1C63U,
425     0xC40083C0U, 0xC40093C1U, 0xC400A3C2U, 0xC400B3C3U, 0x0C800E09U, 0x63806D20U, 0x08C80D2AU, 0x088C7D4BU, 0x2800002BU,
426     0x08403E4DU, 0x0CCC11ADU, 0x63006DE0U, 0x2000002DU, 0x2000000EU, 0x60806E80U, 0x0C803E4FU, 0x63806E60U, 0x2000000EU,
427     0x60806E80U, 0x2000002EU, 0x085005ADU, 0x08C811ACU, 0x0040418CU, 0x600072CEU, 0x0C800E09U, 0x638071A0U, 0x0050258CU,
428     0x9C001189U, 0x00C82920U, 0x9C001189U, 0x00CC2D39U, 0x00886400U, 0x00C82921U, 0x9C001189U, 0x00CC2D39U, 0x00886421U,
429     0x00C82922U, 0x9C001189U, 0x00CC2D39U, 0x00886442U, 0x00C82923U, 0x9C001189U, 0x00CC2D39U, 0x00886463U, 0x60807220U,
430     0x94000180U, 0x94001181U, 0x94002182U, 0x94003183U, 0xA40043C0U, 0xA40053C1U, 0xA40063C2U, 0xA40073C3U, 0x60808340U,
431     0x5C003E00U, 0x04803DEFU, 0x638077C0U, 0x0C800E09U, 0x63807680U, 0x0050258CU, 0x9C001189U, 0x00C82924U, 0x9C001189U,
432     0x00CC2D39U, 0x00886484U, 0x0C5015F8U, 0x658077C0U, 0x00C82925U, 0x9C001189U, 0x00CC2D39U, 0x008864A5U, 0x0C501318U,
433     0x658077C0U, 0x00C82926U, 0x9C001189U, 0x00CC2D39U, 0x008864C6U, 0x0C501318U, 0x658077C0U, 0x00C82927U, 0x9C001189U,
434     0x00CC2D39U, 0x008864E7U, 0x608077C0U, 0x94000184U, 0x0C5015E9U, 0x658077C0U, 0x94001185U, 0x0C501129U, 0x658077C0U,
435     0x94002186U, 0x0C501129U, 0x658077C0U, 0x94003187U, 0x2001E194U, 0x10000014U, 0x08C809EFU, 0x00403E9FU, 0x7080001FU,
436     0x60807A60U, 0x60807AC0U, 0x60807B60U, 0x60807C00U, 0x60807C80U, 0x60807CE0U, 0x60807D80U, 0x60807E20U, 0x60807EA0U,
437     0x60807F00U, 0x60807FA0U, 0x60808040U, 0x608080C0U, 0x60808120U, 0x608081C0U, 0x60808260U, 0x10100008U, 0x00882084U,
438     0x608082C0U, 0x101FE008U, 0x00802084U, 0x10001008U, 0x00882084U, 0x608082C0U, 0x101FFFE8U, 0x00802084U, 0x30100008U,
439     0x00882084U, 0x608082C0U, 0x31FFE008U, 0x00802084U, 0x088A0084U, 0x608082C0U, 0x10100008U, 0x008820A5U, 0x608082C0U,
440     0x101FE008U, 0x008020A5U, 0x10001008U, 0x008820A5U, 0x608082C0U, 0x101FFFE8U, 0x008020A5U, 0x30100008U, 0x008820A5U,
441     0x608082C0U, 0x31FFE008U, 0x008020A5U, 0x088A00A5U, 0x608082C0U, 0x10100008U, 0x008820C6U, 0x608082C0U, 0x101FE008U,
442     0x008020C6U, 0x10001008U, 0x008820C6U, 0x608082C0U, 0x101FFFE8U, 0x008020C6U, 0x30100008U, 0x008820C6U, 0x608082C0U,
443     0x31FFE008U, 0x008020C6U, 0x088A00C6U, 0x608082C0U, 0x10100008U, 0x008820E7U, 0x608082C0U, 0x101FE008U, 0x008020E7U,
444     0x10001008U, 0x008820E7U, 0x608082C0U, 0x101FFFE8U, 0x008020E7U, 0x30100008U, 0x008820E7U, 0x608082C0U, 0x31FFE008U,
445     0x008020E7U, 0x088A00E7U, 0x008C1000U, 0x008C1421U, 0x008C1842U, 0x008C1C63U, 0xC400C3C0U, 0xC400D3C1U, 0xC400E3C2U,
446     0xC400F3C3U, 0x5C0001E0U, 0x048035ADU, 0x63808880U, 0x0C800E09U, 0x638087A0U, 0x00502617U, 0x9C0012E9U, 0x00C82938U,
447     0x9C0012E9U, 0x00CC2D39U, 0x00886718U, 0x008C6000U, 0x00C82938U, 0x9C0012E9U, 0x00CC2D39U, 0x00886718U, 0x008C6021U,
448     0x00C82938U, 0x9C0012E9U, 0x00CC2D39U, 0x00886718U, 0x008C6042U, 0x00C82938U, 0x9C0012E9U, 0x00CC2D39U, 0x00886718U,
449     0x008C6063U, 0x700058BFU, 0x28000210U, 0x600084ADU, 0x60808880U, 0xB4000200U, 0xB4001201U, 0xB4002202U, 0xB4003203U,
450     0x700058BFU, 0x28000210U, 0x600087ADU, 0xA400C3C0U, 0xA400D3C1U, 0xA400E3C2U, 0xA400F3C3U, 0x700058BFU, 0xD4000260U,
451     0xD4001261U, 0xD4002262U, 0xD4003263U, 0x840013DFU, 0x840003DEU, 0x04807FFFU, 0x63808A40U, 0x7080001FU, 0x5C1FFFE0U,
452     0x581FFFE0U, 0x54000020U, 0x20015000U, 0x101FFE00U, 0x84000001U, 0x84001002U, 0x84002003U, 0x84003004U, 0x84004005U,
453     0x84005006U, 0x84006007U, 0x84007008U, 0xD40003A1U, 0xD40013A2U, 0xD40023A3U, 0xD40033A4U, 0xD40043A5U, 0xD40053A6U,
454     0xD40063A7U, 0xD40073A8U, 0x54000020U, 0xC8FF93DEU, 0xC40013DFU, 0x940003A1U, 0x940013A2U, 0x940023A3U, 0x940033A4U,
455     0x940043A5U, 0x940053A6U, 0x940063A7U, 0x940073A8U, 0xC40043DBU, 0x0C800F7AU, 0x63808F80U, 0x00506B7BU, 0x2800009BU,
456     0x08C80F5AU, 0xC40053DAU, 0x088C7F5AU, 0x2800003AU, 0xC40063DAU, 0x2001541AU, 0x101FFE1AU, 0xC40033DDU, 0xC40023DCU,
457     0x840043DFU, 0x0C800FFFU, 0x6380A8A0U, 0x94FFF37FU, 0x840053DCU, 0x00C873E9U, 0x9C00137FU, 0x840063DCU, 0x00CC73FDU,
458     0x00887529U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x840053DCU, 0x00C873E9U,
459     0x9C00137FU, 0x840063DCU, 0x00CC73FDU, 0x00887529U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U,
460     0x41FFFEFFU, 0x840053DCU, 0x00C873E9U, 0x9C00137FU, 0x840063DCU, 0x00CC73FDU, 0x00887529U, 0x8C001340U, 0x01E80100U,
461     0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x840053DCU, 0x00C873E9U, 0x9C00137FU, 0x840063DCU, 0x00CC73FDU,
462     0x00887529U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x840053DCU, 0x00C873E9U,
463     0x9C00137FU, 0x840063DCU, 0x00CC73FDU, 0x00887529U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U,
464     0x41FFFEFFU, 0x840053DCU, 0x00C873E9U, 0x9C00137FU, 0x840063DCU, 0x00CC73FDU, 0x00887529U, 0x8C001340U, 0x01E80100U,
465     0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x840053DCU, 0x00C873E9U, 0x9C00137FU, 0x840063DCU, 0x00CC73FDU,
466     0x00887529U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x840053DCU, 0x00C873E9U,
467     0x9C00137FU, 0x840063DCU, 0x00CC73FDU, 0x00887529U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U,
468     0x41FFFEFFU, 0x840053DCU, 0x00C873E9U, 0x9C00137FU, 0x840063DCU, 0x00CC73FDU, 0x00887529U, 0x8C001340U, 0x01E80100U,
469     0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x840053DCU, 0x00C873E9U, 0x9C00137FU, 0x840063DCU, 0x00CC73FDU,
470     0x00887529U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x840053DCU, 0x00C873E9U,
471     0x9C00137FU, 0x840063DCU, 0x00CC73FDU, 0x00887529U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U,
472     0x41FFFEFFU, 0x840053DCU, 0x00C873E9U, 0x9C00137FU, 0x840063DCU, 0x00CC73FDU, 0x00887529U, 0x8C001340U, 0x01E80100U,
473     0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x840053DCU, 0x00C873E9U, 0x9C00137FU, 0x840063DCU, 0x00CC73FDU,
474     0x00887529U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x840053DCU, 0x00C873E9U,
475     0x9C00137FU, 0x840063DCU, 0x00CC73FDU, 0x00887529U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U,
476     0x41FFFEFFU, 0x840053DCU, 0x00C873E9U, 0x9C00137FU, 0x840063DCU, 0x00CC73FDU, 0x00887529U, 0x8C001340U, 0x01E80100U,
477     0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x840053DCU, 0x00C873E9U, 0x9C00137FU, 0x840063DCU, 0x00CC73FDU,
478     0x00887529U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x6080B6A0U, 0x9C001369U,
479     0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x9C001369U, 0x8C001340U, 0x01E80100U,
480     0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x9C001369U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U,
481     0x01EC0020U, 0x41FFFEFFU, 0x9C001369U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU,
482     0x9C001369U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x9C001369U, 0x8C001340U,
483     0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x9C001369U, 0x8C001340U, 0x01E80100U, 0x01E41520U,
484     0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x9C001369U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U,
485     0x41FFFEFFU, 0x9C001369U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x9C001369U,
486     0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x9C001369U, 0x8C001340U, 0x01E80100U,
487     0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x9C001369U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U,
488     0x01EC0020U, 0x41FFFEFFU, 0x9C001369U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU,
489     0x9C001369U, 0x8C001340U, 0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x9C001369U, 0x8C001340U,
490     0x01E80100U, 0x01E41520U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x9C001369U, 0x8C001340U, 0x01E80100U, 0x01E41520U,
491     0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x2000019FU, 0x00406609U, 0x01E06169U, 0x8C001340U, 0x01E80120U, 0x01E41500U,
492     0x00400084U, 0x01EC0020U, 0x41FFFEFFU, 0x00406609U, 0x01E06169U, 0x8C001340U, 0x01E80120U, 0x01E41500U, 0x00400084U,
493     0x01EC0020U, 0x41FFFEFFU, 0x00406609U, 0x01E06169U, 0x8C001340U, 0x01E80120U, 0x01E41500U, 0x00400084U, 0x01EC0020U,
494     0x41FFFEFFU, 0x00406609U, 0x01E06169U, 0x8C001340U, 0x01E80120U, 0x01E41500U, 0x00400084U, 0x01EC0020U, 0x41FFFEFFU,
495     0x6000B6DFU, 0x840033DDU, 0x940003A0U, 0x00400021U, 0x940013A0U, 0x00400042U, 0x940023A0U, 0x00400063U, 0x940033A0U,
496     0x00400084U, 0x940043A0U, 0x004000A5U, 0x940053A0U, 0x004000C6U, 0x940063A0U, 0x004000E7U, 0x940073A0U, 0x00400108U,
497     0xD40003A1U, 0xD40013A2U, 0xD40023A3U, 0xD40033A4U, 0xD40043A5U, 0xD40053A6U, 0xD40063A7U, 0xD40073A8U, 0x29FFE01AU,
498     0x840023DCU, 0x60008FDCU, 0x840013DFU, 0x840003DEU, 0x04807FFFU, 0x6380BF00U, 0x7080001FU, 0x581FFFE0U, 0x5C1FFFE0U,
499     0x54000020U, 0x20014800U, 0x101FFE00U, 0x84000001U, 0x84001002U, 0x84002003U, 0x84003004U, 0x84004005U, 0xD40003A1U,
500     0xD40013A2U, 0xD40023A3U, 0xD40033A4U, 0xD40043A5U, 0x54000020U, 0xC8FF43DEU, 0xC40013DFU, 0xC40033DDU, 0x940003A1U,
501     0x940013A2U, 0x940023A3U, 0x940033A4U, 0x940043A5U, 0xC40043C1U, 0xC40053C2U, 0xC40063C3U, 0xC40073C4U, 0xC40083C5U,
502     0xC40093DBU, 0x0C800F7DU, 0x6380C3E0U, 0x0050777BU, 0x08C80FBFU, 0xC400A3DFU, 0x088C7FE7U, 0x28000027U, 0xC400B3C7U,
503     0x9C00137DU, 0xC40023DCU, 0x20014608U, 0x101FFE08U, 0x00800420U, 0x08D01400U, 0x84000108U, 0x840093DCU, 0x0C800F9CU,
504     0x6380DD60U, 0x8400A3DFU, 0x8400B3C7U, 0x01D41400U, 0x00402000U, 0x00C87FA9U, 0x9C00137DU, 0x00CC1FBCU, 0x00887129U,
505     0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U, 0x00C87FA9U,
506     0x9C00137DU, 0x00CC1FBCU, 0x00887129U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U,
507     0x01D41400U, 0x00402000U, 0x00C87FA9U, 0x9C00137DU, 0x00CC1FBCU, 0x00887129U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU,
508     0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U, 0x00C87FA9U, 0x9C00137DU, 0x00CC1FBCU, 0x00887129U,
509     0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U, 0x00C87FA9U,
510     0x9C00137DU, 0x00CC1FBCU, 0x00887129U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U,
511     0x01D41400U, 0x00402000U, 0x00C87FA9U, 0x9C00137DU, 0x00CC1FBCU, 0x00887129U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU,
512     0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U, 0x00C87FA9U, 0x9C00137DU, 0x00CC1FBCU, 0x00887129U,
513     0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U, 0x00C87FA9U,
514     0x9C00137DU, 0x00CC1FBCU, 0x00887129U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U,
515     0x01D41400U, 0x00402000U, 0x00C87FA9U, 0x9C00137DU, 0x00CC1FBCU, 0x00887129U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU,
516     0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U, 0x00C87FA9U, 0x9C00137DU, 0x00CC1FBCU, 0x00887129U,
517     0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U, 0x00C87FA9U,
518     0x9C00137DU, 0x00CC1FBCU, 0x00887129U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U,
519     0x01D41400U, 0x00402000U, 0x00C87FA9U, 0x9C00137DU, 0x00CC1FBCU, 0x00887129U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU,
520     0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U, 0x00C87FA9U, 0x9C00137DU, 0x00CC1FBCU, 0x00887129U,
521     0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U, 0x00C87FA9U,
522     0x9C00137DU, 0x00CC1FBCU, 0x00887129U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U,
523     0x01D41400U, 0x00402000U, 0x00C87FA9U, 0x9C00137DU, 0x00CC1FBCU, 0x00887129U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU,
524     0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U, 0x00C87FA9U, 0x9C00137DU, 0x00CC1FBCU, 0x00887129U,
525     0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x6080EF60U, 0x01D41400U, 0x00402000U,
526     0x9C001369U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U,
527     0x9C001369U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U,
528     0x9C001369U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U,
529     0x9C001369U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U,
530     0x9C001369U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U,
531     0x9C001369U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U,
532     0x9C001369U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U,
533     0x9C001369U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U,
534     0x9C001369U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U,
535     0x9C001369U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U,
536     0x9C001369U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U,
537     0x9C001369U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U,
538     0x9C001369U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U,
539     0x9C001369U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U,
540     0x9C001369U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x01D41400U, 0x00402000U,
541     0x9C001369U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x2000009FU, 0x01D41400U,
542     0x00402000U, 0x00803189U, 0x008C4529U, 0x008C5D29U, 0x008C6529U, 0x08D00529U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU,
543     0x4000001BU, 0x00806B43U, 0x08D01400U, 0x6000EF9FU, 0x2000029FU, 0x20014687U, 0x101FFE07U, 0x8C0010E8U, 0x01D01400U,
544     0x00402000U, 0x00803189U, 0x008C4529U, 0x008C5D29U, 0x008C6529U, 0x08D00529U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU,
545     0x4000001BU, 0x00806B43U, 0x08D01400U, 0x6000F1DFU, 0x2000029FU, 0x8C0010E8U, 0x01D81400U, 0x00402000U, 0x00803189U,
546     0x008C4529U, 0x008C5D29U, 0x008C6529U, 0x08D00529U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U,
547     0x08D01400U, 0x6000F3DFU, 0x2000029FU, 0x840000E8U, 0x01D01400U, 0x00402000U, 0x00803189U, 0x008C4529U, 0x008C5D29U,
548     0x008C6529U, 0x08D00529U, 0x00402400U, 0x41FFFE00U, 0x08D0785AU, 0x4000001BU, 0x00806B43U, 0x08D01400U, 0x6000F5DFU,
549     0x840043C0U, 0x00400021U, 0xC40043C1U, 0x840053C0U, 0x00400042U, 0xC40053C2U, 0x840063C0U, 0x00400063U, 0xC40063C3U,
550     0x840073C0U, 0x00400084U, 0xC40073C4U, 0x840083C0U, 0x004000A5U, 0xC40083C5U, 0x840023DCU, 0x6000C3FCU, 0x840033DDU,
551     0xDC0013A1U, 0xDC0013A2U, 0xDC0013A3U, 0xDC0013A4U, 0xDC0013A5U, 0x840013DFU, 0x840003DEU, 0x04807FFFU, 0x6380FB00U,
552     0x7080001FU, 0x5C1FFFE0U, 0x581FFFE0U, 0x54000020U, 0x08800E31U, 0x08C81A20U, 0x2000A412U, 0x101FFE12U, 0x00400251U,
553     0x84000220U, 0x84001221U, 0x01A42012U, 0x04804A52U, 0x6300FE00U, 0x84002220U, 0x84003221U, 0x01A42012U, 0x04804A52U,
554     0x6300FE00U, 0x84004220U, 0x84005221U, 0x01A42012U, 0x04804A52U, 0x6300FE00U, 0x54000020U, 0x54000040U, 0x08800E31U,
555     0x08C81A20U, 0x2000A412U, 0x101FFE12U, 0x00400251U, 0x84000220U, 0x84001221U, 0x0C800E07U, 0x63810380U, 0x3C000027U,
556     0x63810240U, 0x3C000047U, 0x63810100U, 0x94FFF607U, 0x08C860E2U, 0x94000607U, 0x08CC20E8U, 0x00882042U, 0x08C860E3U,
557     0x94001607U, 0x08CC20E8U, 0x00882063U, 0x608103C0U, 0x94FFFA07U, 0x08C840E2U, 0x94000A07U, 0x08CC40E8U, 0x00882042U,
558     0x08C840E3U, 0x94001A07U, 0x08CC40E8U, 0x00882063U, 0x608103C0U, 0x94FFFE07U, 0x08C820E2U, 0x94000E07U, 0x08CC60E8U,
559     0x00882042U, 0x08C820E3U, 0x94001E07U, 0x08CC60E8U, 0x00882063U, 0x608103C0U, 0x9C001202U, 0x94000203U, 0x01A40000U,
560     0x01A02000U, 0x01A00400U, 0x01A00400U, 0x01A00400U, 0x01A00400U, 0x01A00400U, 0x01A00400U, 0x01A00000U, 0x01A00400U,
561     0x01A00400U, 0x01A00400U, 0x01A00400U, 0x01A00400U, 0x01A00400U, 0x01A00000U, 0x01A01000U, 0x84002220U, 0x84003221U,
562     0x01A41000U, 0x01A02800U, 0x01A00C00U, 0x01A00C00U, 0x01A00C00U, 0x01A00C00U, 0x01A00C00U, 0x01A00C00U, 0x01A00800U,
563     0x01A00C00U, 0x01A00C00U, 0x01A00C00U, 0x01A00C00U, 0x01A00C00U, 0x01A00C00U, 0x01A00800U, 0x01A01000U, 0x84004220U,
564     0x84005221U, 0x01A40000U, 0x01A02000U, 0x01A00400U, 0x01A00400U, 0x01A00400U, 0x01A00400U, 0x01A00400U, 0x01A00400U,
565     0x01A00000U, 0x01A00400U, 0x01A00400U, 0x01A00400U, 0x01A00400U, 0x01A00400U, 0x01A00400U, 0x01A00000U, 0x01A01000U,
566     0x0C800E67U, 0x638111C0U, 0x3C000027U, 0x63810FA0U, 0x3C000047U, 0x63810D80U, 0x94FFF668U, 0x08CC2108U, 0x08C82108U,
567     0x08CC6047U, 0x008820E7U, 0xD4FFF667U, 0x08C82047U, 0x08CC6062U, 0x00881C42U, 0xD4000662U, 0x94001668U, 0x08C86108U,
568     0x08CC6108U, 0x08C82067U, 0x008820E7U, 0xD4001667U, 0x60811200U, 0x94FFFA68U, 0x08CC4108U, 0x08C84108U, 0x08CC4047U,
569     0x008820E7U, 0xD4FFFA67U, 0x08C84047U, 0x08CC4062U, 0x00881C42U, 0xD4000A62U, 0x94001A68U, 0x08C84108U, 0x08CC4108U,
570     0x08C84067U, 0x008820E7U, 0xD4001A67U, 0x60811200U, 0x94FFFE68U, 0x08CC6108U, 0x08C86108U, 0x08CC2047U, 0x008820E7U,
571     0xD4FFFE67U, 0x08C86047U, 0x08CC2062U, 0x00881C42U, 0xD4000E62U, 0x94001E68U, 0x08C82108U, 0x08CC2108U, 0x08C86067U,
572     0x008820E7U, 0xD4001E67U, 0x60811200U, 0xDC001262U, 0xD4000263U, 0x04807FFFU, 0x63811260U, 0x7080001FU, 0x5C1FFFE0U,
573     0x581FFFE0U, 0x54000020U, 0x08800E31U, 0x08C81A20U, 0x2000A412U, 0x101FFE12U, 0x00400251U, 0x84004220U, 0x84005221U,
574     0x0C800E07U, 0x63811820U, 0x3C000027U, 0x638116E0U, 0x3C000047U, 0x638115A0U, 0x94FFF607U, 0x08C860E2U, 0x94000607U,
575     0x08CC20E8U, 0x00882042U, 0x08C860E3U, 0x94001607U, 0x08CC20E8U, 0x00882063U, 0x60811860U, 0x94FFFA07U, 0x08C840E2U,
576     0x94000A07U, 0x08CC40E8U, 0x00882042U, 0x08C840E3U, 0x94001A07U, 0x08CC40E8U, 0x00882063U, 0x60811860U, 0x94FFFE07U,
577     0x08C820E2U, 0x94000E07U, 0x08CC60E8U, 0x00882042U, 0x08C820E3U, 0x94001E07U, 0x08CC60E8U, 0x00882063U, 0x60811860U,
578     0x9C001202U, 0x94000203U, 0x01A41000U, 0x01A02800U, 0x01A00C00U, 0x01A00C00U, 0x01A00C00U, 0x01A00C00U, 0x01A00C00U,
579     0x01A00C00U, 0x01A00800U, 0x01A00C00U, 0x01A00C00U, 0x01A00C00U, 0x01A00C00U, 0x01A00C00U, 0x01A00C00U, 0x01A00800U,
580     0x01A01000U, 0x84002220U, 0x84003221U, 0x01A40000U, 0x01A02000U, 0x01A00400U, 0x01A00400U, 0x01A00400U, 0x01A00400U,
581     0x01A00400U, 0x01A00400U, 0x01A00000U, 0x01A00400U, 0x01A00400U, 0x01A00400U, 0x01A00400U, 0x01A00400U, 0x01A00400U,
582     0x01A00000U, 0x01A01000U, 0x84000220U, 0x84001221U, 0x01A41000U, 0x01A02800U, 0x01A00C00U, 0x01A00C00U, 0x01A00C00U,
583     0x01A00C00U, 0x01A00C00U, 0x01A00C00U, 0x01A00800U, 0x01A00C00U, 0x01A00C00U, 0x01A00C00U, 0x01A00C00U, 0x01A00C00U,
584     0x01A00C00U, 0x01A00800U, 0x01A01000U, 0x0C800E67U, 0x63812660U, 0x3C000027U, 0x63812440U, 0x3C000047U, 0x63812220U,
585     0x94FFF668U, 0x08CC2108U, 0x08C82108U, 0x08CC6047U, 0x008820E7U, 0xD4FFF667U, 0x08C82047U, 0x08CC6062U, 0x00881C42U,
586     0xD4000662U, 0x94001668U, 0x08C86108U, 0x08CC6108U, 0x08C82067U, 0x008820E7U, 0xD4001667U, 0x608126A0U, 0x94FFFA68U,
587     0x08CC4108U, 0x08C84108U, 0x08CC4047U, 0x008820E7U, 0xD4FFFA67U, 0x08C84047U, 0x08CC4062U, 0x00881C42U, 0xD4000A62U,
588     0x94001A68U, 0x08C84108U, 0x08CC4108U, 0x08C84067U, 0x008820E7U, 0xD4001A67U, 0x608126A0U, 0x94FFFE68U, 0x08CC6108U,
589     0x08C86108U, 0x08CC2047U, 0x008820E7U, 0xD4FFFE67U, 0x08C86047U, 0x08CC2062U, 0x00881C42U, 0xD4000E62U, 0x94001E68U,
590     0x08C82108U, 0x08CC2108U, 0x08C86067U, 0x008820E7U, 0xD4001E67U, 0x608126A0U, 0xDC001262U, 0xD4000263U, 0x04807FFFU,
591     0x63812700U, 0x7080001FU, 0x5C1FFFE0U, 0x581FFFE0U, 0x54000020U, 0xC8FFE3DEU, 0x08CC1234U, 0x8C001200U, 0x8C001201U,
592     0x8C001202U, 0x8C001203U, 0xCE002240U, 0xCE002242U, 0x600127B4U, 0x840003DEU, 0x54000020U, 0xC8FFE3DEU, 0x5C001FE0U,
593     0x08800E31U, 0x0CC81A31U, 0x2000A012U, 0x101FFE12U, 0x00404652U, 0x8C004200U, 0x9C001204U, 0x9C001205U, 0x9C001206U,
594     0x9C001207U, 0xCE002240U, 0xCE002242U, 0xCE002244U, 0xCE002246U, 0x9C001200U, 0x9C001201U, 0x9C001202U, 0x9C001203U,
595     0x9C001204U, 0x9C001205U, 0x9C001206U, 0x9C001207U, 0xCE002240U, 0xCE002242U, 0xCE002244U, 0xCE002246U, 0x08510252U,
596     0x84000240U, 0x0880E000U, 0x3C000400U, 0x67812D00U, 0x20000400U, 0xC4000240U, 0x3C000100U, 0x08408254U, 0x00800012U,
597     0x08CC1A31U, 0x67812EA0U, 0x3C000300U, 0x66812E60U, 0x63812E40U, 0x08501A52U, 0x08501A52U, 0x08501A52U, 0x7000041FU,
598     0x5C1FFFE0U, 0x5801FFE0U, 0x54000020U, 0xC8FFE3DEU, 0x5C001FE0U, 0x08800E31U, 0x0CC81A31U, 0x2000A012U, 0x101FFE12U,
599     0x00404652U, 0x00804200U, 0xCE002240U, 0xCE002242U, 0x20D4D4C4U, 0x1014D4C4U, 0x20D4D4C5U, 0x1014D4C5U, 0xCE002244U,
600     0xCE002246U, 0x24000100U, 0x24000121U, 0x24000142U, 0x24000163U, 0x24000184U, 0x240001A5U, 0x240001C6U, 0x240001E7U,
601     0x00040000U, 0x00040021U, 0x00040042U, 0x00040063U, 0x00040084U, 0x000400A5U, 0x000400C6U, 0x000400E7U, 0xCE002240U,
602     0xCE002242U, 0xCE002244U, 0xCE002246U, 0x08510252U, 0x84000240U, 0x0880E000U, 0x3C000400U, 0x67813440U, 0x20000400U,
603     0xC4000240U, 0x3C000100U, 0x08408254U, 0x00800012U, 0x08CC1A31U, 0x678135E0U, 0x3C000300U, 0x668135A0U, 0x63813580U,
604     0x08501A52U, 0x08501A52U, 0x08501A52U, 0x7000041FU, 0x5C1FFFE0U, 0x5801FFE0U, 0x54000020U, 0x08800E31U, 0x08C81A31U,
605     0x2000A012U, 0x101FFE12U, 0x00404652U, 0x5C1FFFE0U, 0xCE002240U, 0xCE002242U, 0xCE002244U, 0xCE002246U, 0xCE002240U,
606     0xCE002242U, 0xCE002244U, 0xCE002246U, 0x5C1FFFE0U, 0x5801FFE0U, 0x04807FFFU, 0x638138A0U, 0x7080001FU, 0x54000020U,
607     0x0CCC7E48U, 0x63813940U, 0x088C7E52U, 0x28000032U, 0x08800E52U, 0x08C81A52U, 0x2000A013U, 0x101FFE13U, 0x00404A73U,
608     0xC4000271U, 0x28000413U, 0x0C800E21U, 0x08CC0A31U, 0x63813AA0U, 0x28000031U, 0x3C000008U, 0x63813B60U, 0x8C001201U,
609     0xCC001261U, 0x60013AF1U, 0x60813BC0U, 0x8C001201U, 0xDC001261U, 0x60013B71U, 0x5C1FFFE0U, 0x581FFFE0U, 0x54000020U,
610     0x0CCC7E28U, 0x63813CA0U, 0x088C7E31U, 0x28000031U, 0x08800E31U, 0x08C81A31U, 0x2000A212U, 0x101FFE12U, 0x00404652U,
611     0x8C001204U, 0x8C001205U, 0x8C001206U, 0x8C001207U, 0x3C000008U, 0x63813E60U, 0xCE002244U, 0xCE002246U, 0x60813EE0U,
612     0xDC001244U, 0xDC001245U, 0xDC001246U, 0xDC001247U, 0x5C1FFFE0U, 0x5801FFE0U, 0x54000020U, 0xC8FFE3DEU, 0x08800E31U,
613     0x08C81A20U, 0x2000A014U, 0x101FFE14U, 0x00400294U, 0x84000292U, 0x3C000312U, 0x668140C0U, 0x638140A0U, 0x08501A52U,
614     0x08501A52U, 0x08501A52U, 0x28000414U, 0x60800400U, 0x0C8013C6U, 0x638141C0U, 0xC8FEB3DEU, 0xC40013DFU, 0x60814200U,
615     0xC8FEC3DEU, 0xC40013DFU, 0x00804A55U, 0x00804636U, 0x00804E77U, 0x084006F4U, 0x3C000094U, 0x630142E0U, 0x20000034U,
616     0x3C000055U, 0x63814400U, 0x3C000095U, 0x63814400U, 0x3C000115U, 0x63814400U, 0x3C000095U, 0x67014B00U, 0x60814A80U,
617     0x08800EC6U, 0x08C818C6U, 0x2000A00CU, 0x101FFE0CU, 0x0040198CU, 0x8C004198U, 0x08800E31U, 0x08C82226U, 0x2000C011U,
618     0x101FFE11U, 0x00401A31U, 0x3C000318U, 0x66814600U, 0x63814A40U, 0x200001D2U, 0x60814620U, 0x20000152U, 0x2001D613U,
619     0x101FFE13U, 0x9C001200U, 0x9C001201U, 0x20000106U, 0x004078C6U, 0x008056AAU, 0x9C00120EU, 0x9C00120FU, 0xCE0020CEU,
620     0x6001470AU, 0x200000C9U, 0x008056AAU, 0x08500527U, 0x01001EA7U, 0x004028E6U, 0x008C1821U, 0x08C80D48U, 0x800023C2U,
621     0x08401108U, 0x800023C3U, 0x700045BFU, 0x08501108U, 0xC00023C2U, 0x08401108U, 0xC00023C3U, 0x6001480AU, 0x600147A9U,
622     0x8600018EU, 0x008C01CBU, 0x008C05E6U, 0x0488196BU, 0x63814BE0U, 0x3C000115U, 0x63814B00U, 0x00805EF1U, 0x7001365FU,
623     0x581FFFE0U, 0x54000040U, 0x00805EF1U, 0x0080529DU, 0x7001365FU, 0x008077B1U, 0x7001365FU, 0x581FFFE0U, 0x54000040U,
624     0x00805EE7U, 0x08800EF7U, 0x08C81AE6U, 0x2000A017U, 0x101FFE17U, 0x00401AF7U, 0x3C000055U, 0x63814D60U, 0x3C000095U,
625     0x63814D60U, 0x20000407U, 0x60814D80U, 0x08C80EA7U, 0xCC0082E7U, 0x20000106U, 0x004078C6U, 0x008056AAU, 0x3C000115U,
626     0x63814EC0U, 0x8E0020C0U, 0xCE0022E0U, 0x60014E4AU, 0x608150A0U, 0x0850114AU, 0x8E0020C0U, 0xCE0022E0U, 0x60014EEAU,
627     0x08800E94U, 0x08C81A87U, 0x2000A014U, 0x101FFE14U, 0x00401E94U, 0x2000008AU, 0x20000407U, 0xCC008287U, 0x8E0020C0U,
628     0xCE002280U, 0x6001504AU, 0x54000020U, 0xC4FFF3DFU, 0xC8FFE3DEU, 0x2001D600U, 0x101FFE00U, 0x700162BFU, 0x3C000017U,
629     0x63815600U, 0x0C800EFDU, 0x63015280U, 0xC40002E2U, 0xC40012E3U, 0xC40022E4U, 0xC40032E5U, 0x60815600U, 0x005076F7U,
630     0x08C80FBDU, 0x088C7FBCU, 0x2800003CU, 0x840002FAU, 0x00C8735FU, 0x00CC73FFU, 0x00C8745AU, 0x00887F5AU, 0xC40002FAU,
631     0x00CC705FU, 0x00C8747AU, 0x00887F5AU, 0xC40012FAU, 0x00CC707FU, 0x00C8749AU, 0x00887F5AU, 0xC40022FAU, 0x00CC709FU,
632     0x00C874BAU, 0x00887F5AU, 0xC40032FAU, 0x00CC70BFU, 0x840042FAU, 0x00CC775AU, 0x00C8775AU, 0x00887F5AU, 0xC40042FAU,
633     0x840013DFU, 0x04807FFFU, 0x638156A0U, 0x840003DEU, 0x7080001FU, 0x5C1FFFE0U, 0x581FFFE0U, 0x54000020U, 0xC4FFF3D5U,
634     0xC4FFE3D6U, 0xC4FFD3DFU, 0xC8FFC3DEU, 0x2001DE00U, 0x101FFE00U, 0x700162BFU, 0x84FFD3DFU, 0x20000033U, 0x3C000017U,
635     0x638161A0U, 0x0C800EFDU, 0x63015940U, 0x840002E6U, 0x840012E7U, 0x840022E8U, 0x840032E9U, 0x60815BE0U, 0x005076F7U,
636     0x08C80FBDU, 0x088C7FBCU, 0x2800003CU, 0x840002FAU, 0x00CC775FU, 0x840012FAU, 0x00C87346U, 0x00887CC6U, 0x00CC775FU,
637     0x840022FAU, 0x00C87347U, 0x00887CE7U, 0x00CC775FU, 0x840032FAU, 0x00C87348U, 0x00887D08U, 0x00CC775FU, 0x840042FAU,
638     0x00C87349U, 0x00887D29U, 0x008C1857U, 0x008C1C7AU, 0x00886AF7U, 0x008C209AU, 0x00886AF7U, 0x008C24BAU, 0x04886AF7U,
639     0x638161A0U, 0x20000053U, 0x840033D5U, 0x3C000015U, 0x638161A0U, 0x840023D6U, 0x0C800EDAU, 0x63816020U, 0x00506AD6U,
640     0x00406AB5U, 0x0C5012B5U, 0x2000001CU, 0x66015F20U, 0x840002DCU, 0x28000095U, 0x08C80EB5U, 0x00CC579CU, 0x00C8579CU,
641     0x20000015U, 0x08C80F5AU, 0x088C7F5AU, 0x2800003AU, 0x840002DBU, 0x00C86B7BU, 0x00CC6B7BU, 0x0088737BU, 0xCC0012DBU,
642     0x0CCC0ABBU, 0x638160C0U, 0x2000001AU, 0xCC0012DAU, 0x6001609BU, 0x0C800EBAU, 0x638161A0U, 0x08C80F5AU, 0x840002DBU,
643     0x00CC6B7BU, 0x00C86B7BU, 0xCC0012DBU, 0x840013DFU, 0x04807FFFU, 0x63816240U, 0x840003DEU, 0x7080001FU, 0x5C1FFFE0U,
644     0x581FFEE0U, 0x50000013U, 0x0C8013DAU, 0x63816320U, 0xCAFD13DEU, 0x60816340U, 0xCAFD23DEU, 0xC402D3C0U, 0xC402A3D3U,
645     0xC402B3D5U, 0x3C000011U, 0x0080463AU, 0x660165C0U, 0x20000015U, 0x20000011U, 0x088C0F5AU, 0x2800003AU, 0x08800F5AU,
646     0x08C81B5AU, 0x2000A41BU, 0x101FFE1BU, 0x00406B7AU, 0x8E002340U, 0x8E002342U, 0x8E002344U, 0x8E002346U, 0x60816840U,
647     0x08800F5AU, 0x08C81B5AU, 0x2000A011U, 0x101FFE11U, 0x00406A31U, 0x0C800E9CU, 0x00507294U, 0x08C80F9CU, 0x63816740U,
648     0x8C001290U, 0x00CC7210U, 0xC40263D0U, 0x08800EDDU, 0x005076D6U, 0x08C80FBDU, 0xC60243DCU, 0x20000019U, 0x3C000017U,
649     0x63817A80U, 0x7001B07FU, 0xC60023C0U, 0xC60043C2U, 0xC60063C4U, 0xC60083C6U, 0x08C81808U, 0x08CC1908U, 0x08CC6009U,
650     0x08C8203AU, 0x00886929U, 0x08CC0929U, 0x21FFE07AU, 0x10007FFAU, 0x00806929U, 0x08CC402AU, 0x08C8405AU, 0x0088694AU,
651     0x08CC114AU, 0x21F81FFAU, 0x10007FFAU, 0x0080694AU, 0x08CC204BU, 0x08C8607AU, 0x0088696BU, 0x08CC196BU, 0x2007FFFAU,
652     0x10007E1AU, 0x0080696BU, 0x08CC206CU, 0x08C8318CU, 0x08CC318CU, 0xC60103C8U, 0xC60123CAU, 0xC40143CCU, 0x860103C6U,
653     0x860123C8U, 0x840143CBU, 0x08C808ECU, 0x00401D8CU, 0x08C8090DU, 0x004021ADU, 0x08C8092EU, 0x004025CEU, 0x08C8096FU,
654     0x00402DEFU, 0xC60203CCU, 0xC60223CEU, 0x2000001AU, 0x2000001BU, 0xC600A3DAU, 0xC600C3DAU, 0xC400E3DAU, 0x3C000013U,
655     0x63817A80U, 0x00804A5CU, 0x0C800E5AU, 0x63017220U, 0x8402D3C8U, 0x08CC0A7BU, 0x0C800E7DU, 0x63816FE0U, 0x2800003BU,
656     0x3C000813U, 0x67817060U, 0x2000081BU, 0x08CC0B7BU, 0x8C001240U, 0xCC001100U, 0x6001707BU, 0x3C000813U, 0x67817800U,
657     0xC40153D3U, 0x20000813U, 0xC402C3D2U, 0x7001C1DFU, 0x840153D3U, 0x8402C3D2U, 0x2000081DU, 0x00507673U, 0x60816F40U,
658     0x20000038U, 0x08800E4AU, 0x08C80D4AU, 0x088C7D49U, 0x28000029U, 0x08800E7CU, 0x00406B9CU, 0x3C00009CU, 0x67817360U,
659     0x28000038U, 0x8402D3C8U, 0x00506A5AU, 0x08CC0A7BU, 0x0C800E7DU, 0x63817420U, 0x2800003BU, 0x3C000813U, 0x678174A0U,
660     0x2000081BU, 0x08CC0B7BU, 0x00806F7DU, 0x0040637BU, 0x8C001340U, 0x00CC2801U, 0x0850077BU, 0x00506FBDU, 0x8C001340U,
661     0x00C82402U, 0x00880442U, 0x00CC2801U, 0xCC001102U, 0x6001757BU, 0x3C00001DU, 0x63817680U, 0xCC001101U, 0x3C000813U,
662     0x67817800U, 0xC40153D3U, 0x20000813U, 0xC402C3D2U, 0x7001C1DFU, 0x840153D3U, 0x8402C3D2U, 0x2000081DU, 0x00507673U,
663     0x00407652U, 0x60816EE0U, 0x0C803E7DU, 0x63817A20U, 0x3C000011U, 0x638179E0U, 0x00507672U, 0x8402D3DDU, 0x00407652U,
664     0xC4FFF3DFU, 0xC8FFE3DEU, 0x7001F3DFU, 0x840013DFU, 0x840003DEU, 0x08CC1273U, 0x08C81273U, 0x28000213U, 0x7001C1DFU,
665     0x60817A80U, 0x3C000013U, 0x63817A80U, 0x7001C1DFU, 0x3C000015U, 0x6381AD40U, 0x860243DCU, 0x840263D0U, 0x840002DFU,
666     0x20000039U, 0x088C7FBBU, 0x2800003BU, 0x00C86FFFU, 0x00CC6FFFU, 0xC40273DFU, 0x7001B07FU, 0x840273DFU, 0x2001D61AU,
667     0x101FFE1AU, 0xC6000340U, 0xC6002342U, 0xC6004344U, 0xC6006346U, 0xC6008348U, 0xC600A34AU, 0xC600C34CU, 0xC600E34EU,
668     0x0C5102B5U, 0x860243DCU, 0x66819BC0U, 0x0C807F9CU, 0x63018020U, 0x8C001280U, 0x8C001281U, 0x8C001282U, 0x8C001283U,
669     0x8C001284U, 0x8C001285U, 0x8C001286U, 0x8C001287U, 0x8C001288U, 0x8C001289U, 0x8C00128AU, 0x8C00128BU, 0x8C00128CU,
670     0x8C00128DU, 0x8C00128EU, 0x8C00128FU, 0x60818880U, 0x088C7F9DU, 0x2800003DU, 0x8C00129BU, 0x00C8777AU, 0x00884340U,
671     0x00CC7370U, 0x8C00129BU, 0x00C8777AU, 0x00884341U, 0x00CC7370U, 0x8C00129BU, 0x00C8777AU, 0x00884342U, 0x00CC7370U,
672     0x8C00129BU, 0x00C8777AU, 0x00884343U, 0x00CC7370U, 0x8C00129BU, 0x00C8777AU, 0x00884344U, 0x00CC7370U, 0x8C00129BU,
673     0x00C8777AU, 0x00884345U, 0x00CC7370U, 0x8C00129BU, 0x00C8777AU, 0x00884346U, 0x00CC7370U, 0x8C00129BU, 0x00C8777AU,
674     0x00884347U, 0x00CC7370U, 0x8C00129BU, 0x00C8777AU, 0x00884348U, 0x00CC7370U, 0x8C00129BU, 0x00C8777AU, 0x00884349U,
675     0x00CC7370U, 0x8C00129BU, 0x00C8777AU, 0x0088434AU, 0x00CC7370U, 0x8C00129BU, 0x00C8777AU, 0x0088434BU, 0x00CC7370U,
676     0x8C00129BU, 0x00C8777AU, 0x0088434CU, 0x00CC7370U, 0x8C00129BU, 0x00C8777AU, 0x0088434DU, 0x00CC7370U, 0x8C00129BU,
677     0x00C8777AU, 0x0088434EU, 0x00CC7370U, 0x8C00129BU, 0x00C8777AU, 0x0088434FU, 0x00CC7370U, 0xC40263D0U, 0x3C000017U,
678     0x63818A00U, 0x2001DE12U, 0x101FFE12U, 0xC6000240U, 0xC6002242U, 0xC6004244U, 0xC6006246U, 0xC6008248U, 0xC600A24AU,
679     0xC600C24CU, 0xC600E24EU, 0x2001D61AU, 0x101FFE1AU, 0xA4000340U, 0xA4001341U, 0xA4002342U, 0xA4003343U, 0xA4004344U,
680     0xA4005345U, 0xA4006346U, 0xA4007347U, 0xA4008348U, 0xA4009349U, 0xA400A34AU, 0xA400B34BU, 0xA400C34CU, 0xA400D34DU,
681     0xA400E34EU, 0xA400F34FU, 0x63818F20U, 0xC6000340U, 0xC6002342U, 0xC6004344U, 0xC6006346U, 0xC6008348U, 0xC600A34AU,
682     0xC600C34CU, 0xC600E34EU, 0xC402C3DFU, 0x20000813U, 0x7001C1DFU, 0x8402C3DFU, 0x2001D61AU, 0x101FFE1AU, 0x86000340U,
683     0x86002342U, 0x86004344U, 0x86006346U, 0x86008348U, 0x8600A34AU, 0x8600C34CU, 0x8600E34EU, 0x860243DCU, 0x0C807FBDU,
684     0x63019200U, 0xCC0012C0U, 0xCC0012C1U, 0xCC0012C2U, 0xCC0012C3U, 0xCC0012C4U, 0xCC0012C5U, 0xCC0012C6U, 0xCC0012C7U,
685     0xCC0012C8U, 0xCC0012C9U, 0xCC0012CAU, 0xCC0012CBU, 0xCC0012CCU, 0xCC0012CDU, 0xCC0012CEU, 0xCC0012CFU, 0x3C000015U,
686     0x6381AD20U, 0x67017BC0U, 0x54000040U, 0x860243DCU, 0x088C7FBCU, 0x2800003CU, 0x00C8741BU, 0x00887F7BU, 0xCC0012DBU,
687     0x00CC701FU, 0x00C8743BU, 0x00887F7BU, 0xCC0012DBU, 0x00CC703FU, 0x00C8745BU, 0x00887F7BU, 0xCC0012DBU, 0x00CC705FU,
688     0x00C8747BU, 0x00887F7BU, 0xCC0012DBU, 0x00CC707FU, 0x00C8749BU, 0x00887F7BU, 0xCC0012DBU, 0x00CC709FU, 0x00C874BBU,
689     0x00887F7BU, 0xCC0012DBU, 0x00CC70BFU, 0x00C874DBU, 0x00887F7BU, 0xCC0012DBU, 0x00CC70DFU, 0x00C874FBU, 0x00887F7BU,
690     0xCC0012DBU, 0x00CC70FFU, 0x00C8751BU, 0x00887F7BU, 0xCC0012DBU, 0x00CC711FU, 0x00C8753BU, 0x00887F7BU, 0xCC0012DBU,
691     0x00CC713FU, 0x00C8755BU, 0x00887F7BU, 0xCC0012DBU, 0x00CC715FU, 0x00C8757BU, 0x00887F7BU, 0xCC0012DBU, 0x00CC717FU,
692     0x00C8759BU, 0x00887F7BU, 0xCC0012DBU, 0x00CC719FU, 0x00C875BBU, 0x00887F7BU, 0xCC0012DBU, 0x00CC71BFU, 0x00C875DBU,
693     0x00887F7BU, 0xCC0012DBU, 0x00CC71DFU, 0x00C875FBU, 0x00887F7BU, 0xCC0012DBU, 0x00CC71FFU, 0xC40273DFU, 0x3C000015U,
694     0x67017BC0U, 0x63819B00U, 0x54000040U, 0x840002DBU, 0x00CC777BU, 0x00C8777BU, 0x00887F7BU, 0xC40002DBU, 0x6081AD20U,
695     0x28000815U, 0x860243DCU, 0x2001D69DU, 0x101FFE1DU, 0x2001DE0DU, 0x101FFE0DU, 0x0C800EBCU, 0x08CC0ABBU, 0x63819D00U,
696     0x2800003BU, 0x840243DCU, 0x0C807F9CU, 0x63019E40U, 0x8C00129AU, 0xCC0011BAU, 0x008C6800U, 0xC4FFF3A0U, 0x8C0013A0U,
697     0x60019D7BU, 0x60819FA0U, 0x088C7F8BU, 0x2800002BU, 0x8C001281U, 0x00C82C3AU, 0x0088435AU, 0xCC0011BAU, 0x008C6800U,
698     0x00CC7030U, 0xC4FFF3A0U, 0x8C0013A0U, 0x60019E9BU, 0x3C000017U, 0x6381A180U, 0xC402C3DFU, 0x008056B3U, 0x0C803E7AU,
699     0x6381A140U, 0x00506A72U, 0x8402D3DAU, 0x00406A52U, 0x7001F3DFU, 0x08803E7AU, 0x00506A73U, 0x28000213U, 0x7001C1DFU,
700     0x8402C3DFU, 0x2001D61AU, 0x101FFE1AU, 0x860243DCU, 0x0C807FBDU, 0x6301A4C0U, 0x0CCC0ABBU, 0x6381A2C0U, 0x8C001340U,
701     0xCC0012C0U, 0x6001A27BU, 0x0C800EBBU, 0x6381AD20U, 0x8C000340U, 0x840002DCU, 0x08800EBDU, 0x08C80FBDU, 0x088C7FBBU,
702     0x2800003BU, 0x00C86C00U, 0x00CC6C00U, 0x00CC779CU, 0x00C8779CU, 0xC4001340U, 0x00887000U, 0xC40002C0U, 0x6081AD20U,
703     0x0CCC0AB0U, 0x6381A720U, 0x08CC0FBCU, 0x08800EABU, 0x0040716BU, 0x3C00008BU, 0x6781A5E0U, 0x28000030U, 0x0C800D6BU,
704     0x840273DFU, 0x088C7FBCU, 0x2800003CU, 0x8C001340U, 0x00C8741BU, 0x00887F7BU, 0xCC0012DBU, 0x00CC701FU, 0x6001A650U,
705     0x6301AB40U, 0x860243DCU, 0x088C7FBBU, 0x2800003BU, 0x8C00135CU, 0x00C87780U, 0x00887C00U, 0x00CC6F9FU, 0x840002DCU,
706     0x08CC0FABU, 0x08800EAAU, 0x00402D4AU, 0x3C00008AU, 0x6681A9A0U, 0x6381AB00U, 0xCC0012C0U, 0x840002DCU, 0x8C001340U,
707     0x00C87400U, 0x00887C00U, 0x08800D4AU, 0x08C80D4AU, 0x088C7D5BU, 0x2800003BU, 0x00C86C00U, 0x00CC6C00U, 0xC4001140U,
708     0x00CC2B9CU, 0x00C82B9CU, 0x00887000U, 0xC40002C0U, 0x6081AD20U, 0xC40002C0U, 0x6081AD20U, 0x08C80D6BU, 0x088C7D7CU,
709     0x2800003CU, 0x84000340U, 0x00C87400U, 0x00887C00U, 0x00C87000U, 0x00CC7000U, 0x00CC740AU, 0xC400134AU, 0x840002DBU,
710     0x00CC2F7BU, 0x00C82F7BU, 0x0088037BU, 0xC40002DBU, 0x008056B3U, 0x3C000017U, 0x6381AFE0U, 0x3C000011U, 0x6381AF60U,
711     0x2001DE12U, 0x101FFE12U, 0x8402A3DAU, 0x2000001BU, 0x8402B3DCU, 0x2000001DU, 0xC600025AU, 0xC600225CU, 0x20000213U,
712     0x7001C1FFU, 0x20000013U, 0x7001C1DFU, 0x6081AFE0U, 0x0C803E73U, 0x6301AFE0U, 0x20000013U, 0x7001C1DFU, 0x840013DFU,
713     0x04807FFFU, 0x840003DEU, 0x7080001FU, 0x2001D41AU, 0x101FFE1AU, 0x86000340U, 0x86002342U, 0x86008224U, 0x8600A226U,
714     0x8600C228U, 0x8600E22AU, 0x0080672CU, 0x8400422DU, 0x8400522EU, 0x8400622FU, 0x20000158U, 0x00401000U, 0x008C018CU,
715     0x08D0418CU, 0x00403108U, 0x008C2084U, 0x08D03084U, 0x00401000U, 0x008C018CU, 0x08D0218CU, 0x00403108U, 0x008C2084U,
716     0x08D01C84U, 0x00401421U, 0x008C05ADU, 0x08D041ADU, 0x00403529U, 0x008C24A5U, 0x08D030A5U, 0x00401421U, 0x008C05ADU,
717     0x08D021ADU, 0x00403529U, 0x008C24A5U, 0x08D01CA5U, 0x00401842U, 0x008C09CEU, 0x08D041CEU, 0x0040394AU, 0x008C28C6U,
718     0x08D030C6U, 0x00401842U, 0x008C09CEU, 0x08D021CEU, 0x0040394AU, 0x008C28C6U, 0x08D01CC6U, 0x00401C63U, 0x008C0DEFU,
719     0x08D041EFU, 0x00403D6BU, 0x008C2CE7U, 0x08D030E7U, 0x00401C63U, 0x008C0DEFU, 0x08D021EFU, 0x00403D6BU, 0x008C2CE7U,
720     0x08D01CE7U, 0x00401400U, 0x008C01EFU, 0x08D041EFU, 0x00403D4AU, 0x008C28A5U, 0x08D030A5U, 0x00401400U, 0x008C01EFU,
721     0x08D021EFU, 0x00403D4AU, 0x008C28A5U, 0x08D01CA5U, 0x00401821U, 0x008C058CU, 0x08D0418CU, 0x0040316BU, 0x008C2CC6U,
722     0x08D030C6U, 0x00401821U, 0x008C058CU, 0x08D0218CU, 0x0040316BU, 0x008C2CC6U, 0x08D01CC6U, 0x00401C42U, 0x008C09ADU,
723     0x08D041ADU, 0x00403508U, 0x008C20E7U, 0x08D030E7U, 0x00401C42U, 0x008C09ADU, 0x08D021ADU, 0x00403508U, 0x008C20E7U,
724     0x08D01CE7U, 0x00401063U, 0x008C0DCEU, 0x08D041CEU, 0x00403929U, 0x008C2484U, 0x08D03084U, 0x00401063U, 0x008C0DCEU,
725     0x08D021CEU, 0x00403929U, 0x008C2484U, 0x08D01C84U, 0x6001B218U, 0x2001D41AU, 0x101FFE1AU, 0x8600035CU, 0x00407000U,
726     0x00407421U, 0x8600235CU, 0x00407042U, 0x00407463U, 0x8600823AU, 0x8600A23CU, 0x00406884U, 0x00406CA5U, 0x004070C6U,
727     0x004074E7U, 0x8600C23AU, 0x8600E23CU, 0x00406908U, 0x00406D29U, 0x0040714AU, 0x0040756BU, 0x0040658CU, 0x8400423AU,
728     0x004069ADU, 0x8400523AU, 0x004069CEU, 0x8400623AU, 0x004069EFU, 0x28000039U, 0x7080001FU, 0x8402D3D2U, 0xC40263D0U,
729     0xC60283C0U, 0x8600A3C2U, 0x8600C3C4U, 0x8400E3CAU, 0x3C000013U, 0x6381E8A0U, 0x20000010U, 0x10002010U, 0x860103C6U,
730     0x860123C8U, 0x840143CBU, 0x860203CCU, 0x860223CEU, 0x0CCC1278U, 0x6381E7A0U, 0x8C00125DU, 0x08C81BBAU, 0x08CC1B5AU,
731     0x00406842U, 0x08CC63BAU, 0x8C00125DU, 0x08C823BBU, 0x00886F5AU, 0x08CC0B5AU, 0x08C81B5AU, 0x08CC1B5AU, 0x00406863U,
732     0x08CC43BAU, 0x8C00125DU, 0x08C843BBU, 0x00886F5AU, 0x08CC135AU, 0x08C81B5AU, 0x08CC1B5AU, 0x00406884U, 0x08CC23BAU,
733     0x8C00125DU, 0x08C863BBU, 0x00886F5AU, 0x08CC1B5AU, 0x08C81B5AU, 0x08CC1B5AU, 0x004068A5U, 0x08CC23BAU, 0x0088435AU,
734     0x0040694AU, 0x008C1840U, 0x08C47C00U, 0x008C0041U, 0x08CC7C00U, 0x00400021U, 0x03041820U, 0x0080001AU, 0x0080043BU,
735     0x008C3C60U, 0x08C47C00U, 0x008C0061U, 0x08CC7C00U, 0x00400021U, 0x03043C20U, 0x0440035AU, 0x0044077BU, 0x008C3880U,
736     0x08C47C00U, 0x008C0081U, 0x08CC7C00U, 0x00400021U, 0x03043820U, 0x0440035AU, 0x0044077BU, 0x008C34A0U, 0x08C47C00U,
737     0x008C00A1U, 0x08CC7C00U, 0x00400021U, 0x03043420U, 0x0440035AU, 0x0044077BU, 0x008C3140U, 0x08C47C00U, 0x008C0141U,
738     0x08CC7C00U, 0x00400021U, 0x03043020U, 0x0440035AU, 0x0044077BU, 0xC60163DAU, 0x008C1C40U, 0x08C47C00U, 0x008C0041U,
739     0x08CC7C00U, 0x00400021U, 0x03041C20U, 0x0080001AU, 0x0080043BU, 0x008C1860U, 0x08C47C00U, 0x008C0061U, 0x08CC7C00U,
740     0x00400021U, 0x03041820U, 0x0440035AU, 0x0044077BU, 0x008C3C80U, 0x08C47C00U, 0x008C0081U, 0x08CC7C00U, 0x00400021U,
741     0x03043C20U, 0x0440035AU, 0x0044077BU, 0x008C38A0U, 0x08C47C00U, 0x008C00A1U, 0x08CC7C00U, 0x00400021U, 0x03043820U,
742     0x0440035AU, 0x0044077BU, 0x008C3540U, 0x08C47C00U, 0x008C0141U, 0x08CC7C00U, 0x00400021U, 0x03043420U, 0x0440035AU,
743     0x0044077BU, 0xC60183DAU, 0x008C2040U, 0x08C47C00U, 0x008C0041U, 0x08CC7C00U, 0x00400021U, 0x03042020U, 0x0080001AU,
744     0x0080043BU, 0x008C1C60U, 0x08C47C00U, 0x008C0061U, 0x08CC7C00U, 0x00400021U, 0x03041C20U, 0x0440035AU, 0x0044077BU,
745     0x008C1880U, 0x08C47C00U, 0x008C0081U, 0x08CC7C00U, 0x00400021U, 0x03041820U, 0x0440035AU, 0x0044077BU, 0x008C3CA0U,
746     0x08C47C00U, 0x008C00A1U, 0x08CC7C00U, 0x00400021U, 0x03043C20U, 0x0440035AU, 0x0044077BU, 0x008C3940U, 0x08C47C00U,
747     0x008C0141U, 0x08CC7C00U, 0x00400021U, 0x03043820U, 0x0440035AU, 0x0044077BU, 0xC601A3DAU, 0x008C2440U, 0x08C47C00U,
748     0x008C0041U, 0x08CC7C00U, 0x00400021U, 0x03042420U, 0x0080001AU, 0x0080043BU, 0x008C2060U, 0x08C47C00U, 0x008C0061U,
749     0x08CC7C00U, 0x00400021U, 0x03042020U, 0x0440035AU, 0x0044077BU, 0x008C1C80U, 0x08C47C00U, 0x008C0081U, 0x08CC7C00U,
750     0x00400021U, 0x03041C20U, 0x0440035AU, 0x0044077BU, 0x008C18A0U, 0x08C47C00U, 0x008C00A1U, 0x08CC7C00U, 0x00400021U,
751     0x03041820U, 0x0440035AU, 0x0044077BU, 0x008C3D40U, 0x08C47C00U, 0x008C0141U, 0x08CC7C00U, 0x00400021U, 0x03043C20U,
752     0x0440035AU, 0x0044077BU, 0xC601C3DAU, 0x008C2C40U, 0x08C47C00U, 0x008C0041U, 0x08CC7C00U, 0x00400021U, 0x03042C20U,
753     0x0080001AU, 0x0080043BU, 0x008C2460U, 0x08C47C00U, 0x008C0061U, 0x08CC7C00U, 0x00400021U, 0x03042420U, 0x0440035AU,
754     0x0044077BU, 0x008C2080U, 0x08C47C00U, 0x008C0081U, 0x08CC7C00U, 0x00400021U, 0x03042020U, 0x0440035AU, 0x0044077BU,
755     0x008C1CA0U, 0x08C47C00U, 0x008C00A1U, 0x08CC7C00U, 0x00400021U, 0x03041C20U, 0x0440035AU, 0x0044077BU, 0x008C1940U,
756     0x08C47C00U, 0x008C0141U, 0x08CC7C00U, 0x00400021U, 0x03041820U, 0x0440035AU, 0x0044077BU, 0xC601E3DAU, 0x860163DAU,
757     0x08CC6B40U, 0x08C81B62U, 0x00880800U, 0x08C81B42U, 0x08CC1842U, 0x860183DAU, 0x0440035AU, 0x0844037BU, 0x08CC6B40U,
758     0x08C81B63U, 0x00880C00U, 0x08C81B43U, 0x08CC1863U, 0x8601A3DAU, 0x0440035AU, 0x0844037BU, 0x08CC6B40U, 0x08C81B64U,
759     0x00881000U, 0x08C81B44U, 0x08CC1884U, 0x8601C3DAU, 0x0440035AU, 0x0844037BU, 0x08CC6B40U, 0x08C81B65U, 0x00881400U,
760     0x08C81B45U, 0x08CC18A5U, 0x8601E3DAU, 0x0440035AU, 0x0844037BU, 0x08CC6B40U, 0x08C81B6AU, 0x00882800U, 0x08C81B4AU,
761     0x08CC194AU, 0x08C8081AU, 0x00406842U, 0x00400042U, 0x08CC6840U, 0x08C81842U, 0x08CC1842U, 0x00400063U, 0x6001C3F8U,
762     0x3C000010U, 0x6381E8A0U, 0x0C803E73U, 0x6381F2A0U, 0xC4FFF3DFU, 0xC8FFE3DEU, 0x7001F37FU, 0x840013DFU, 0x840003DEU,
763     0x20000010U, 0x20000038U, 0x6081C3E0U, 0x08CC6860U, 0x08C81863U, 0x08CC1863U, 0x00400084U, 0x08CC6880U, 0x08C81884U,
764     0x08CC1884U, 0x004000A5U, 0x08CC68A0U, 0x08C818A5U, 0x08CC18A5U, 0x0040014AU, 0x08CC6940U, 0x08C8194AU, 0x08CC194AU,
765     0x00400042U, 0x08C8081AU, 0x00406842U, 0x08CC6840U, 0x08C81842U, 0x08CC1842U, 0x00400063U, 0x00800846U, 0x280000A6U,
766     0x08CC68C0U, 0x08C818C6U, 0x08CC18C6U, 0x00400067U, 0x08CC68E0U, 0x08C818E7U, 0x08CC18E7U, 0x00400088U, 0x08CC6900U,
767     0x08C81908U, 0x08CC1908U, 0x004000A9U, 0x08CC6920U, 0x08C81929U, 0x08CC1929U, 0x0040014BU, 0x2000003AU, 0x08C86B5AU,
768     0x0050696BU, 0x08CC7D7AU, 0x0850075AU, 0x008068C6U, 0x008068E7U, 0x00806908U, 0x00806929U, 0x0080696BU, 0x2000001BU,
769     0x00506B7AU, 0x0850075AU, 0x00806842U, 0x00881842U, 0x00806863U, 0x00881C63U, 0x00806884U, 0x00882084U, 0x008068A5U,
770     0x008824A5U, 0x0080694AU, 0x00882D4AU, 0x08C8687BU, 0x00886C42U, 0x08CC1863U, 0x08C8509BU, 0x00886C63U, 0x08CC3084U,
771     0x08C838BBU, 0x00886C84U, 0x08CC48A5U, 0x08C8215BU, 0x00886CA5U, 0x860063DAU, 0x860083DCU, 0x04406842U, 0x04446C63U,
772     0x04447084U, 0x004474A5U, 0xC600A3C2U, 0xC600C3C4U, 0xC400E3CAU, 0x840263D0U, 0x860283C0U, 0x7080001FU, 0x20000020U,
773     0x0CCC0400U, 0x6081F3E0U, 0x04500000U, 0x8E00225AU, 0x8EFFE25CU, 0x08803E61U, 0x20000000U, 0x00500400U, 0x08C47C01U,
774     0x0080075AU, 0x28000080U, 0x08C47C01U, 0x0080077BU, 0x28000080U, 0x08C47C01U, 0x0080079CU, 0x28000080U, 0x08C47C01U,
775     0x008007BDU, 0xCE00225AU, 0xCEFFE25CU, 0x08800E7AU, 0x08C80F5AU, 0x20000000U, 0x08440000U, 0x00C86800U, 0x2000001CU,
776     0x00506B9AU, 0x00806B5CU, 0x08C47F9CU, 0x2800041AU, 0x00CC6B9CU, 0x0880327BU, 0x00404B7BU, 0x8400037DU, 0x008073BDU,
777     0x008803BDU, 0xC400037DU, 0x7080001FU, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U,
778     0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U,
779     0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U,
780     0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U,
781     0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U,
782     0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U,
783     0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U,
784     0x00000000U};
785 
786 static const uint32_t s_cau3ImemBytes = sizeof(s_cau3ImemImage);
787 
788 /*******************************************************************************
789  * Prototypes
790  ******************************************************************************/
791 
792 static status_t cau3_initialize_inst_memory(CAU3_Type *base, const uint32_t *cau3ImemImage, size_t cau3ImemBytes);
793 static status_t cau3_initialize_data_memory(CAU3_Type *base, cau3_task_done_t taskDone);
794 static status_t cau3_initialize_read_only_data_memory(CAU3_Type *base,
795                                                       const uint32_t *cau3ReadOnlyConstants,
796                                                       size_t cau3ReadOnlyConstantsBytes,
797                                                       cau3_task_done_t taskDone);
798 static status_t cau3_load_key_context(CAU3_Type *base,
799                                       cau3_key_context_t *cauKeyContext,
800                                       cau3_key_slot_t keySlot,
801                                       cau3_task_done_t taskDone);
802 static status_t cau3_load_key(
803     CAU3_Type *base, const uint8_t *key, size_t keySize, uint32_t keySlot, cau3_task_done_t taskDone);
804 static status_t cau3_pkha_clear_regabne(CAU3_Type *base, bool A, bool B, bool N, bool E);
805 
806 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
807 static status_t cau3_execute_null_task(CAU3_Type *base, cau3_task_done_t taskDone);
808 static status_t cau3_lock_semaphore(CAU3_Type *base);
809 static void cau3_release_semaphore(CAU3_Type *base);
810 #endif
811 
812 /*******************************************************************************
813  * Code
814  ******************************************************************************/
815 
cau3_process_task_completion(CAU3_Type * base,cau3_task_done_t taskDone)816 static status_t cau3_process_task_completion(CAU3_Type *base, cau3_task_done_t taskDone)
817 {
818     status_t taskCompletionStatus;
819     uint32_t tkcs;
820 
821     taskCompletionStatus = kStatus_Fail; /* assume an error completion status */
822 
823     switch (((uint32_t)taskDone >> 16U) & 7U)
824     {
825         case 0: /* poll the cau3 status register */
826             tkcs = base->SR & CAU3_SR_TKCS_MASK;
827             while (tkcs == CAU3_SR_TKCS_RUN)
828             {
829                 tkcs = base->SR & CAU3_SR_TKCS_MASK;
830             };
831 
832             /* check the task completion status*/
833             if (tkcs == CAU3_SR_TKCS_STOPNOERR)
834             {
835                 taskCompletionStatus = kStatus_Success; /* signal error-free completion status */
836             }
837 
838             break;
839 
840         case 2: /* task completion signaled by event_done */
841             do
842             {
843                 __WFE(); /* cpu is waiting for cau3 event_done */
844                 tkcs = base->SR & CAU3_SR_TKCS_MASK;
845             } while (tkcs == CAU3_SR_TKCS_RUN);
846 
847             /* check the task completion status */
848             if (tkcs == CAU3_SR_TKCS_STOPNOERR)
849             {
850                 taskCompletionStatus = kStatus_Success; /* signal error-free completion status */
851             }
852             break;
853 
854         case 1: /* task completion signaled by irq */
855         /* TEMP FIX - for boot ROM with IRQ task completion, simply return */
856         case 4: /* task completion signaled by dma_req */
857             /* processing here is complete */
858             taskCompletionStatus = kStatus_Success; /* signal error-free completion status */
859             break;
860 
861         default: /* undefined taskDone specifier defaults to kStatus_Fail */
862             break;
863     }            /* end - switch (taskDone & 7U) */
864 
865     return (taskCompletionStatus);
866 }
867 
868 /*!
869  * @brief   Initialize the CAU3's Instruction Memory
870  *
871  * Initializes the CAU3, including configuring it to enable the execution of
872  * crypto tasks, loading the CryptoCore's firmware image into the CAU3's
873  * instruction memory, and then performing a simple read-verify of its contents.
874  * NOTE: All the operations for this function are executed on the host processor.
875  *
876  * cau3_initialize_inst_memory
877  * @param   cau3ImemImage - binary firmware image for CryptoCore
878  * @param   cau3ImemBytes - size of the firmware image in bytes
879  *
880  * @retval  status from the readVerify check: CAU_[OK (=0), ERROR (!0)]
881  *          if an error is signaled, the retval is 0xbad10000UU + i, where i is
882  *          the first miscompare word index location
883  */
cau3_initialize_inst_memory(CAU3_Type * base,const uint32_t * cau3ImemImage,size_t cau3ImemBytes)884 static status_t cau3_initialize_inst_memory(CAU3_Type *base, const uint32_t *cau3ImemImage, size_t cau3ImemBytes)
885 {
886     uint32_t i;
887 
888     /* enable the cau3 */
889     base->CR = 0U;
890 
891     /* poll if/while the cau3 is running initialization */
892     while ((base->SR & CAU3_SR_TKCS_MASK) == CAU3_SR_TKCS_INITRUN)
893     {
894     };
895 
896     /* check for error-free stop state */
897     if ((base->SR & CAU3_SR_TKCS_MASK) != CAU3_SR_TKCS_STOPNOERR)
898     {
899         return (int32_t)(uint32_t)(0xbad00000U + (base->SR & CAU3_SR_TKCS_MASK)); /* exit with error */
900     }
901 
902     base->SR = CAU3_SR_TCIRQ_MASK; /* clear the TCIRQ interrupt flag */
903 
904     /* write the code hex image into the cau3's imem
905      * initialize the memory cmd and address registers */
906     base->DBGMCMD = 0xac000000U; /* wt=1, ia=1, imem=0 */
907     base->DBGMADR = 0U;          /* imem starting address */
908     for (i = 0; i < cau3ImemBytes / 4U; i++)
909     {
910         base->DBGMDR = cau3ImemImage[i]; /* indirect write into cau3Imem */
911     }
912 
913     /* read-verify the cau3 imem code image
914      * initialize the memory cmd and address registers */
915     base->DBGMCMD = 0x8c000000U; /* wt=0, ia=1, imem=0 */
916     base->DBGMADR = 0U;          /* imem starting address */
917     for (i = 0; i < cau3ImemBytes / 4U; i++)
918     {
919         if (base->DBGMDR != cau3ImemImage[i])            /* indirect read from cau3Imem */
920         {
921             return (int32_t)(uint32_t)(0xbad10000U + i); /* exit on miscompare */
922         }
923     }
924 
925     /* this function does *not* disable reads/writes of the cau3 local memories
926      * but, this operation is needed to "secure" (i.e., make private) the cau3
927      * local memories */
928 
929     return 0;
930 }
931 
932 /*!
933  * @brief   Initializes the CAU3's entire private Data Memory
934  *
935  * Initialize the CAU3's data memory, and then perform a read-verify versus a
936  * precalculated "pseudo-hash" value.
937  *
938  * cau3_initialize_data_memory
939  * @param   taskDone indicates completion signal: CAU_[POLL, IRQ, EVENT, DMAREQ]
940  *
941  * @retval  status from the readVerify check: CAU_[OK, ERROR]
942  */
cau3_initialize_data_memory(CAU3_Type * base,cau3_task_done_t taskDone)943 static status_t cau3_initialize_data_memory(CAU3_Type *base, cau3_task_done_t taskDone)
944 {
945     status_t completionStatus;
946 
947     /* execute the cau3 "security violation + data initialization" task */
948     base->CC_R30 = CAU3_DMEM_STK_BASE;  /* initialize stack pointer (sp) */
949     base->CC_R31 = 0U;                  /* set LR = 0 to signal a host task */
950     base->CC_PC  = CAU3_TASK_SECV_INIT; /* call cau_secv_init() */
951     base->CC_CMD = (uint32_t)taskDone;  /* trigger cau3 execution */
952 
953     /* process the cau3 task completion signal specified by taskDone */
954     completionStatus = cau3_process_task_completion(base, taskDone);
955     return (completionStatus);
956 }
957 
958 /*!
959  * @brief   Copies read-only constants from sysMemory to CAU3's DataMemory
960  *
961  * Initialize the read-only constants in the CAU3's data memory. This includes
962  * the AES constants (RCON) and most of the constants used in the hash functions.
963  * The constants associated with SHA-512 are NOT included and must be loaded
964  * separately.
965  *
966  * cau3_initialize_read_only_data_memory
967  * @param   cauReadOnlyConstants - sysMemory table of constants needed by CAU3
968  * @param   cauReadOnlyConstantsSize - size of read-only constants in bytes
969  * @param   taskDone indicates completion signal: CAU_[POLL, IRQ, EVENT, DMAREQ]
970  *
971  * @retval  status check from task completion: CAU_[OK, ERROR]
972  */
cau3_initialize_read_only_data_memory(CAU3_Type * base,const uint32_t * cau3ReadOnlyConstants,size_t cau3ReadOnlyConstantsBytes,cau3_task_done_t taskDone)973 static status_t cau3_initialize_read_only_data_memory(CAU3_Type *base,
974                                                       const uint32_t *cau3ReadOnlyConstants,
975                                                       size_t cau3ReadOnlyConstantsBytes,
976                                                       cau3_task_done_t taskDone)
977 {
978     status_t completionStatus;
979 
980     /* execute the cau3 "initialize dmem read-only constants" task */
981     base->CC_R[16] = (uint32_t)s_cau3ReadOnlyConstants; /* pReadOnlyConstants */
982     base->CC_R[17] = s_cau3ReadOnlyConstantsBytes;      /* byte count (0-mod-16) */
983     base->CC_R[18] = CAU3_DMEM_AES_RCON;                /* pDMEM_AES_RCON constants base */
984     base->CC_R30   = CAU3_DMEM_STK_BASE;                /* initialize stack pointer (sp) */
985     base->CC_R31   = 0U;                                /* set LR = 0 to signal a host task */
986     base->CC_PC    = CAU3_TASK_BLKLD_DMEM;              /* call cau_block_load_dmem task */
987     base->CC_CMD   = (uint32_t)taskDone;                /* trigger cau3 execution */
988 
989     /* process the cau3 task completion signal specified by taskDone */
990     completionStatus = cau3_process_task_completion(base, taskDone);
991     return (completionStatus);
992 }
993 
994 /*!
995  * brief   Make the CAU3's local memories private
996  *
997  * Modify the CAU3's internal configuration so the local memories are private
998  * and only accessible to the CAU3. This operation is typically performed after
999  * the CAU_InitializeInstMemory(),
1000  *     CAU_InitializeDataMemory(), and
1001  *     CAU_InitializeReadOnlyDataMemory() functions have been performed.
1002  *
1003  * This configuration remains in effect until the next hardware reset.
1004  *
1005  * param   taskDone indicates completion signal: CAU_[POLL, IRQ, EVENT, DMAREQ]
1006  *
1007  * retval  status check from task completion: CAU_[OK, ERROR]
1008  */
CAU3_MakeMemsPrivate(CAU3_Type * base,cau3_task_done_t taskDone)1009 status_t CAU3_MakeMemsPrivate(CAU3_Type *base, cau3_task_done_t taskDone)
1010 {
1011 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
1012     uint32_t completionStatus;
1013     completionStatus = cau3_lock_semaphore(base);
1014     if (kStatus_Success != completionStatus)
1015     {
1016         cau3_release_semaphore(base);
1017         return completionStatus;
1018     }
1019 #endif /* FSL_CAU3_USE_HW_SEMA */
1020 
1021     /* making the xMEMs private involves setting DBGCSR[DDBGMC] = 1 */
1022     base->DBGCSR = CAU3_DBGCSR_DDBGMC_MASK; /* set DBGCSR[DDBGMC] */
1023 
1024 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
1025     cau3_release_semaphore(base);
1026 #endif
1027     return kStatus_Success;
1028 }
1029 
1030 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
1031 /*!
1032  * @brief   Execute a CAU3 null task to "establish ownership" by host processor
1033  *
1034  * Execute a null task to claim ownership of the CAU3 by the host processor.
1035  * This is required for correct IRQ, EVT and DMA_REQ signaling by subsequent
1036  * PKHA operations. The CryptoCore task executes one instruction - a "stop".
1037  *
1038  * cau3_execute_null_task
1039  * @param   taskDone indicates completion signal: CAU_[POLL, IRQ, EVENT, DMAREQ]
1040  *
1041  * @retval  status check from task completion: CAU_[OK, ERROR]
1042  */
cau3_execute_null_task(CAU3_Type * base,cau3_task_done_t taskDone)1043 static status_t cau3_execute_null_task(CAU3_Type *base, cau3_task_done_t taskDone)
1044 {
1045     status_t completionStatus;
1046 
1047     /* execute the cau3 null task */
1048     base->CC_R30 = CAU3_DMEM_STK_BASE; /* initialize stack pointer (sp) */
1049     base->CC_R31 = 0;                  /* set LR = 0 to signal a host task */
1050     base->CC_PC  = CAU3_TASK_NULL;     /* call cau_null() */
1051     base->CC_CMD = taskDone;           /* trigger cau3 execution */
1052 
1053     /* process the cau3 task completion signal specified by taskDone */
1054     completionStatus = cau3_process_task_completion(base, taskDone);
1055     return (completionStatus);
1056 }
1057 #endif /* FSL_CAU3_USE_HW_SEMA */
1058 
1059 /*!
1060  * @brief   Load a key into a key context
1061  *
1062  * Loads up to 32-byte key into the specified key slot.
1063  * There is support for a maximum of 4 key slots.
1064  * This does not do AES key expansion (as in cau3_load_key_context() case) so we use this one for loading TDES keys.
1065  *
1066  * @param   key is the key pointer, ALIGNED ON A 0-MOD-4 ADDRESS
1067  * @param   keySize is the size in bytes of the key
1068  * @param   keySlot is the destination key context
1069  * @param   taskDone indicates completion signal: CAU_[POLL, IRQ, EVENT, DMAREQ]
1070  *
1071  * @retval  status check from task completion: CAU_[OK, ERROR]
1072  */
cau3_load_key(CAU3_Type * base,const uint8_t * key,size_t keySize,uint32_t keySlot,cau3_task_done_t taskDone)1073 static status_t cau3_load_key(
1074     CAU3_Type *base, const uint8_t *key, size_t keySize, uint32_t keySlot, cau3_task_done_t taskDone)
1075 {
1076     status_t completionStatus;
1077 
1078 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
1079     completionStatus = cau3_lock_semaphore(base);
1080     if (kStatus_Success != completionStatus)
1081     {
1082         cau3_release_semaphore(base);
1083         return completionStatus;
1084     }
1085 #endif
1086 
1087     /*  execute the cau3 "load initialization vector into key context" task  */
1088     base->CC_R[16] = (uintptr_t)key;     /*  pKey  */
1089     base->CC_R[17] = keySize;            /*  IV size  */
1090     base->CC_R[18] = keySlot;            /*  keySlot  */
1091     base->CC_R30   = CAU3_DMEM_STK_BASE; /*  initialize stack pointer (sp)  */
1092     base->CC_R31   = 0U;                 /*  set LR = 0 to signal a host task  */
1093     base->CC_PC    = CAU3_TASK_LD_KEY;   /*  call cau_load_key()  */
1094     base->CC_CMD   = (uint32_t)taskDone; /*  trigger cau3 execution  */
1095 
1096     /*  process the cau3 task completion signal specified by taskDone  */
1097     completionStatus = cau3_process_task_completion(base, taskDone);
1098 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
1099     cau3_release_semaphore(base);
1100 #endif
1101     return (completionStatus);
1102 }
1103 
1104 /*!
1105  * brief Encrypts AES on one 128-bit block.
1106  *
1107  * Encrypts AES.
1108  * The source plaintext and destination ciphertext can overlap in system memory.
1109  *
1110  * param base CAU3 peripheral base address
1111  * param handle Handle used for this request.
1112  * param plaintext Input plain text to encrypt
1113  * param[out] ciphertext Output cipher text
1114  * return Status from encrypt operation
1115  */
CAU3_AES_Encrypt(CAU3_Type * base,cau3_handle_t * handle,const uint8_t plaintext[16],uint8_t ciphertext[16])1116 status_t CAU3_AES_Encrypt(CAU3_Type *base, cau3_handle_t *handle, const uint8_t plaintext[16], uint8_t ciphertext[16])
1117 {
1118     status_t completionStatus;
1119     cau3_task_done_t taskDone;
1120 
1121     taskDone = handle->taskDone;
1122 
1123 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
1124     completionStatus = cau3_lock_semaphore(base);
1125     if (kStatus_Success != completionStatus)
1126     {
1127         cau3_release_semaphore(base);
1128         return completionStatus;
1129     }
1130 #endif
1131 
1132     /* execute the cau3 "aes_encrypt_ecb" task */
1133     base->CC_R[16] = (uint32_t)plaintext;       /* pPlainText */
1134     base->CC_R[17] = (uint32_t)handle->keySlot; /* keySlot */
1135     base->CC_R[19] = (uint32_t)ciphertext;      /* pCipherText */
1136     base->CC_R30   = CAU3_DMEM_STK_BASE;        /* initialize stack pointer (sp) */
1137     base->CC_R31   = 0U;                        /* set LR = 0 to signal a host task */
1138     base->CC_PC    = CAU3_TASK_AES_ENCRYPT;     /* call cau_aes_encrypt() */
1139     base->CC_CMD   = (uint32_t)taskDone;        /* trigger cau3 execution */
1140 
1141     /* process the cau3 task completion signal specified by taskDone */
1142     completionStatus = cau3_process_task_completion(base, taskDone);
1143 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
1144     cau3_release_semaphore(base);
1145 #endif
1146     return (completionStatus);
1147 }
1148 
1149 /*!
1150  * brief Decrypts AES on one 128-bit block.
1151  *
1152  * Decrypts AES.
1153  * The source ciphertext and destination plaintext can overlap in system memory.
1154  *
1155  * param base CAU3 peripheral base address
1156  * param handle Handle used for this request.
1157  * param ciphertext Input plain text to encrypt
1158  * param[out] plaintext Output cipher text
1159  * return Status from decrypt operation
1160  */
CAU3_AES_Decrypt(CAU3_Type * base,cau3_handle_t * handle,const uint8_t ciphertext[16],uint8_t plaintext[16])1161 status_t CAU3_AES_Decrypt(CAU3_Type *base, cau3_handle_t *handle, const uint8_t ciphertext[16], uint8_t plaintext[16])
1162 {
1163     status_t completionStatus;
1164     cau3_task_done_t taskDone;
1165 
1166     taskDone = handle->taskDone;
1167 
1168 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
1169     completionStatus = cau3_lock_semaphore(base);
1170     if (kStatus_Success != completionStatus)
1171     {
1172         cau3_release_semaphore(base);
1173         return completionStatus;
1174     }
1175 #endif
1176 
1177     /* execute the cau3 "aes_decrypt_ecb" task */
1178     base->CC_R[16] = (uint32_t)ciphertext;      /* pCipherText */
1179     base->CC_R[17] = (uint32_t)handle->keySlot; /* keySlot */
1180     base->CC_R[19] = (uint32_t)plaintext;       /* pPlainText */
1181     base->CC_R30   = CAU3_DMEM_STK_BASE;        /* initialize stack pointer (sp) */
1182     base->CC_R31   = 0U;                        /* set LR = 0 to signal a host task */
1183     base->CC_PC    = CAU3_TASK_AES_DECRYPT;     /* call cau_aes_decrypt() */
1184     base->CC_CMD   = (uint32_t)taskDone;        /* trigger cau3 execution */
1185 
1186     /* process the cau3 task completion signal specified by taskDone */
1187     completionStatus = cau3_process_task_completion(base, taskDone);
1188 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
1189     cau3_release_semaphore(base);
1190 #endif
1191     return (completionStatus);
1192 }
1193 
1194 /*!
1195  * brief   Enables clock for CAU3 and loads image to memory
1196  *
1197  * Enable CAU3 clock and loads image to CryptoCore.
1198  *
1199  * param base CAU3 base address
1200  */
CAU3_Init(CAU3_Type * base)1201 void CAU3_Init(CAU3_Type *base)
1202 {
1203 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
1204     /* ungate clock */
1205     CLOCK_EnableClock(kCLOCK_Cau3);
1206 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
1207     CLOCK_EnableClock(FSL_CAU3_SEMA42_CLOCK_NAME);
1208 #endif /* FSL_CAU3_USE_HW_SEMA */
1209 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
1210 
1211     base->CR = CAU3_CR_RSTSM4(1);
1212     base->CR = CAU3_CR_RSTSM4(2);
1213     (void)cau3_initialize_inst_memory(base, s_cau3ImemImage, s_cau3ImemBytes);
1214     (void)cau3_initialize_data_memory(base, kCAU3_TaskDonePoll);
1215     (void)cau3_initialize_read_only_data_memory(base, s_cau3ReadOnlyConstants, s_cau3ReadOnlyConstantsBytes,
1216                                                 kCAU3_TaskDonePoll);
1217 }
1218 
1219 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
cau3_lock_semaphore(CAU3_Type * base)1220 static status_t cau3_lock_semaphore(CAU3_Type *base)
1221 {
1222     uint32_t processorNumber = 0;
1223 
1224 /* cm4 will be 1, cm0+ will be 2 */
1225 /* This concept supports dual assymetric cores on K32W0 (dula core m4 and m0+) */
1226 /* For next SoC, the processor number shall be defined in the SoC header file */
1227 #if __CORTEX_M == 0U
1228     processorNumber++;
1229 #endif
1230     processorNumber++;
1231 
1232     while (processorNumber != SEMA42_GATEn(FSL_CAU3_SEMA42_BASE, 1))
1233     {
1234         /* Wait for unlocked status. */
1235         while (SEMA42_GATEn(FSL_CAU3_SEMA42_BASE, FSL_CAU3_SEMA42_GATE))
1236         {
1237         }
1238 
1239         /* Lock the gate. */
1240         SEMA42_GATEn(FSL_CAU3_SEMA42_BASE, FSL_CAU3_SEMA42_GATE) = processorNumber;
1241     }
1242 
1243     return cau3_execute_null_task(base, kCAU3_TaskDonePoll);
1244 }
1245 #endif /* FSL_CAU3_USE_HW_SEMA */
1246 
1247 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
cau3_release_semaphore(CAU3_Type * base)1248 static void cau3_release_semaphore(CAU3_Type *base)
1249 {
1250     /* unlock the semaphore */
1251     SEMA42_GATEn(FSL_CAU3_SEMA42_BASE, FSL_CAU3_SEMA42_GATE) = 0;
1252 }
1253 #endif /* FSL_CAU3_USE_HW_SEMA */
1254 
1255 /*!
1256  * @brief   Load a 64-byte "key context" into the CAU3's private data memory
1257  *
1258  * Load the key context into the private DMEM. This includes size and config
1259  * information, a 16-byte initialization vector and a key of size [8,16,24,32]
1260  * bytes (for DES or AES-[128,192,256]). There is support for 4 "key slots" with
1261  * slot 0 typically used for the system key encryption key (KEK).
1262  *
1263  * See the GENERAL COMMENTS for more information on the keyContext structure.
1264  *
1265  * NOTE: This function also performs an AES key expansion if a keySize > 8
1266  * is specified.
1267  *
1268  * cau3_load_key_context
1269  * @param   cauKeyContext is pointer to key structure in sysMemory
1270  * @param   keySlot is the destination key slot number [0-3]
1271  * @param   taskDone indicates completion signal: CAU_[POLL, IRQ, EVENT, DMAREQ]
1272  *
1273  * @return  status check from task completion: CAU_[OK, ERROR]
1274  */
cau3_load_key_context(CAU3_Type * base,cau3_key_context_t * cauKeyContext,cau3_key_slot_t keySlot,cau3_task_done_t taskDone)1275 static status_t cau3_load_key_context(CAU3_Type *base,
1276                                       cau3_key_context_t *cauKeyContext,
1277                                       cau3_key_slot_t keySlot,
1278                                       cau3_task_done_t taskDone)
1279 {
1280     status_t completionStatus;
1281 
1282 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
1283     completionStatus = cau3_lock_semaphore(base);
1284     if (kStatus_Success != completionStatus)
1285     {
1286         cau3_release_semaphore(base);
1287         return completionStatus;
1288     }
1289 #endif
1290 
1291     /* execute the cau3 "load key context" task */
1292     base->CC_R[16] = (uint32_t)cauKeyContext; /* pKeyContext */
1293     base->CC_R[17] = (uint32_t)keySlot;       /* keySlot */
1294     base->CC_R30   = CAU3_DMEM_STK_BASE;      /* initialize stack pointer (sp) */
1295     base->CC_R31   = 0U;                      /* set LR = 0 to signal a host task */
1296     base->CC_PC    = CAU3_TASK_LD_KEYCTX;     /* call cau_load_key_context() */
1297     base->CC_CMD   = (uint32_t)taskDone;      /* trigger cau3 execution */
1298 
1299     /* process the cau3 task completion signal specified by taskDone */
1300     completionStatus = cau3_process_task_completion(base, taskDone);
1301 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
1302     cau3_release_semaphore(base);
1303 #endif
1304     return (completionStatus);
1305 }
1306 
1307 /*!
1308  * brief   Execute a CAU3 null task to signal error termination
1309  *
1310  * Execute a null task to signal error termination.
1311  * The CryptoCore task executes one instruction - a "stop with error".
1312  *
1313  * param base CAU3 base address
1314  * param taskDone indicates completion signal
1315  *
1316  * return status check from task completion
1317  */
CAU3_ForceError(CAU3_Type * base,cau3_task_done_t taskDone)1318 status_t CAU3_ForceError(CAU3_Type *base, cau3_task_done_t taskDone)
1319 {
1320     status_t completionStatus;
1321 
1322 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
1323     completionStatus = cau3_lock_semaphore(base);
1324     if (kStatus_Success != completionStatus)
1325     {
1326         cau3_release_semaphore(base);
1327         return completionStatus;
1328     }
1329 #endif
1330 
1331     /*  execute the cau3 null task  */
1332     base->CC_R30 = CAU3_DMEM_STK_BASE; /*  initialize stack pointer (sp)  */
1333     base->CC_R31 = 0;                  /*  set LR = 0 to signal a host task  */
1334     base->CC_PC  = CAU3_TASK_STOPERROR;
1335     base->CC_CMD = (uint32_t)taskDone; /*  trigger cau3 execution  */
1336 
1337     /*  process the cau3 task completion signal specified by taskDone  */
1338     completionStatus = cau3_process_task_completion(base, taskDone);
1339 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
1340     cau3_release_semaphore(base);
1341 #endif
1342     return (completionStatus);
1343 }
1344 
1345 /*!
1346  * brief   Load special hardware "key context" into the CAU3's data memory
1347  *
1348  * Load the special hardware key context into the private DMEM. This only
1349  * includes the complete 256-bit key which is then specified with a size of
1350  * [8,16,24,32] bytes (for DES or AES-[128,256]).  It also loads the
1351  * default IV value specified in NIST/RFC2294 IV=0xa6a6a6a6a6a6a6a6. This operation typically
1352  * loads keySlot 0, which, by convention, is used for the system key encryption
1353  * key.
1354  *
1355  * See the GENERAL COMMENTS for more information on the keyContext structure.
1356  *
1357  * NOTE: This function also performs an AES key expansion if a keySize > 8
1358  * is specified.
1359  *
1360  * param base CAU3 base address
1361  * param   keySize is the logical key size in bytes [8,16,24,32]
1362  * param   keySlot is the destination key slot number [0-3]
1363  * param   taskDone indicates completion signal.
1364  *
1365  * return  status check from task completion
1366  */
CAU3_LoadSpecialKeyContext(CAU3_Type * base,size_t keySize,cau3_key_slot_t keySlot,cau3_task_done_t taskDone)1367 status_t CAU3_LoadSpecialKeyContext(CAU3_Type *base, size_t keySize, cau3_key_slot_t keySlot, cau3_task_done_t taskDone)
1368 {
1369     status_t completionStatus;
1370 
1371 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
1372     completionStatus = cau3_lock_semaphore(base);
1373     if (kStatus_Success != completionStatus)
1374     {
1375         cau3_release_semaphore(base);
1376         return completionStatus;
1377     }
1378 #endif
1379 
1380     /*  execute the cau3 "load special key context" task  */
1381     base->CC_R[16] = keySize;                /*  keySize [8,16,24,32]  */
1382     base->CC_R[17] = (uint32_t)keySlot;      /*  keySlot  */
1383     base->CC_R30   = CAU3_DMEM_STK_BASE;     /*  initialize stack pointer (sp)  */
1384     base->CC_R31   = 0U;                     /*  set LR = 0 to signal a host task  */
1385     base->CC_PC    = CAU3_TASK_LD_SP_KEYCTX; /*  call cau_load_special_key_context()  */
1386     base->CC_CMD   = (uint32_t)taskDone;     /*  trigger cau3 execution  */
1387 
1388     /*  process the cau3 task completion signal specified by taskDone  */
1389     completionStatus = cau3_process_task_completion(base, taskDone);
1390 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
1391     cau3_release_semaphore(base);
1392 #endif
1393     return (completionStatus);
1394 }
1395 
1396 /*!
1397  * brief   Invalidate a 64-byte "key context" in the CAU3's private data memory
1398  *
1399  * Clears the key context in the private DMEM. There is support for four "key
1400  * slots" with slot 0 typically used for the system key encryption key.
1401  *
1402  * param base CAU3 base address
1403  * param   keySlot is the key slot number [0-3] to invalidate
1404  * param   taskDone indicates completion signal *
1405  * return  status check from task completion
1406  */
CAU3_ClearKeyContext(CAU3_Type * base,cau3_key_slot_t keySlot,cau3_task_done_t taskDone)1407 status_t CAU3_ClearKeyContext(CAU3_Type *base, cau3_key_slot_t keySlot, cau3_task_done_t taskDone)
1408 {
1409     uint32_t completionStatus;
1410 
1411 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
1412     completionStatus = cau3_lock_semaphore(base);
1413     if (kStatus_Success != completionStatus)
1414     {
1415         cau3_release_semaphore(base);
1416         return completionStatus;
1417     }
1418 #endif
1419 
1420     /*  execute the cau3 "clear key context" task  */
1421     base->CC_R[17] = (uint32_t)keySlot;    /*  keySlot  */
1422     base->CC_R30   = CAU3_DMEM_STK_BASE;   /*  initialize stack pointer (sp)  */
1423     base->CC_R31   = 0U;                   /*  set LR = 0 to signal a host task  */
1424     base->CC_PC    = CAU3_TASK_CLR_KEYCTX; /*  call cau_clear_key_context()  */
1425     base->CC_CMD   = (uint32_t)taskDone;   /*  trigger cau3 execution  */
1426 
1427     /*  process the cau3 task completion signal specified by taskDone  */
1428     completionStatus = (uint32_t)cau3_process_task_completion(base, taskDone);
1429 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
1430     cau3_release_semaphore(base);
1431 #endif
1432     return ((int32_t)completionStatus);
1433 }
1434 
1435 /*!
1436  * brief   Load an initialization vector into a key context
1437  *
1438  * Loads a 16-byte initialization vector (iv) into the specified key slot.
1439  * There is support for a maximum of 4 key slots.
1440  * The function is used internally for loading AEAD_CHACHA20_POY1305 nonce.
1441  * It can be also used for Alternative Initial Values for A[0] in RFC 3394.
1442  *
1443  * param base CAU3 base address
1444  * param iv The initialization vector, ALIGNED ON A 0-MOD-4 ADDRESS.
1445  * param keySlot is the destination key context
1446  * param taskDone indicates completion signal
1447  *
1448  * return  status check from task completion
1449  */
CAU3_LoadKeyInitVector(CAU3_Type * base,const uint8_t * iv,cau3_key_slot_t keySlot,cau3_task_done_t taskDone)1450 status_t CAU3_LoadKeyInitVector(CAU3_Type *base, const uint8_t *iv, cau3_key_slot_t keySlot, cau3_task_done_t taskDone)
1451 {
1452     status_t completionStatus;
1453 
1454 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
1455     completionStatus = cau3_lock_semaphore(base);
1456     if (kStatus_Success != completionStatus)
1457     {
1458         cau3_release_semaphore(base);
1459         return completionStatus;
1460     }
1461 #endif
1462 
1463     /*  execute the cau3 "load initialization vector into key context" task  */
1464     base->CC_R[16] = (uintptr_t)iv;      /*  pIv  */
1465     base->CC_R[17] = (uint32_t)keySlot;  /*  keySlot  */
1466     base->CC_R30   = CAU3_DMEM_STK_BASE; /*  initialize stack pointer (sp)  */
1467     base->CC_R31   = 0U;                 /*  set LR = 0 to signal a host task  */
1468     base->CC_PC    = CAU3_TASK_LD_IV;    /*  call cau_load_iv()  */
1469     base->CC_CMD   = (uint32_t)taskDone; /*  trigger cau3 execution  */
1470 
1471     /*  process the cau3 task completion signal specified by taskDone  */
1472     completionStatus = cau3_process_task_completion(base, taskDone);
1473 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
1474     cau3_release_semaphore(base);
1475 #endif
1476     return (completionStatus);
1477 }
1478 
1479 /*!
1480  * brief   Perform an AES key expansion for specified key slot
1481  *
1482  * Performs an AES key expansion (aka schedule) on the specified key slot. It
1483  * uses the keySize information in the context to determine whether the key
1484  * expansion applies to a 128- or 256-bit AES key.
1485  * This function is primarily intended to be called after
1486  * key blob has been unwrapped by ref CAU3_KeyBlobUnwrap to destination key slot, so that the unwrapped key
1487  * can be used for AES encryption.
1488  *
1489  * param base CAU3 base address
1490  * param keySlot is the key context
1491  * param taskDone indicates completion signal
1492  * return status check from task completion
1493  */
CAU3_AES_KeyExpansion(CAU3_Type * base,cau3_key_slot_t keySlot,cau3_task_done_t taskDone)1494 status_t CAU3_AES_KeyExpansion(CAU3_Type *base, cau3_key_slot_t keySlot, cau3_task_done_t taskDone)
1495 {
1496     status_t completionStatus;
1497 
1498 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
1499     completionStatus = cau3_lock_semaphore(base);
1500     if (kStatus_Success != completionStatus)
1501     {
1502         cau3_release_semaphore(base);
1503         return completionStatus;
1504     }
1505 #endif
1506 
1507     /* execute the cau3 "aes_key_expansion" task */
1508     base->CC_R[17] = (uint32_t)keySlot;     /* keySlot */
1509     base->CC_R30   = CAU3_DMEM_STK_BASE;    /* initialize stack pointer (sp) */
1510     base->CC_R31   = 0U;                    /* set LR = 0 to signal a host task */
1511     base->CC_PC    = CAU3_TASK_AES_KEY_SCH; /* call cau_aes_key_sched() */
1512     base->CC_CMD   = (uint32_t)taskDone;    /* trigger cau3 execution */
1513 
1514     /* process the cau3 task completion signal specified by taskDone */
1515     completionStatus = cau3_process_task_completion(base, taskDone);
1516 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
1517     cau3_release_semaphore(base);
1518 #endif
1519     return (completionStatus);
1520 }
1521 
1522 /*!
1523  * brief Load AES key into CAU3 key slot.
1524  *
1525  * Load the key context into the private DMEM. This function also performs an AES key expansion.
1526  * For CAU3 AES encryption/decryption/cmac, users only need to call one of ref CAU3_AES_SetKey and ref
1527  * CAU3_LoadSpecialKeyContext.
1528  *
1529  * CAU3_AES_SetKey
1530  * param   base CAU3 peripheral base address.
1531  * param   handle Handle used for the request.
1532  * param   key 0-mod-4 aligned pointer to AES key.
1533  * param   keySize AES key size in bytes. Shall equal 16 or 32.
1534  * return  status from set key operation
1535  */
CAU3_AES_SetKey(CAU3_Type * base,cau3_handle_t * handle,const uint8_t * key,size_t keySize)1536 status_t CAU3_AES_SetKey(CAU3_Type *base, cau3_handle_t *handle, const uint8_t *key, size_t keySize)
1537 {
1538     cau3_key_context_t cau3KeyCtx = {0};
1539 
1540     /* only work with aligned key[] */
1541     if (0U != (0x3U & (uintptr_t)key))
1542     {
1543         return kStatus_InvalidArgument;
1544     }
1545 
1546     /* keySize must be 16 or 32. initial CAU3 firmware doesn't support 24 bytes. */
1547     if ((keySize != 16U) && (keySize != 32U))
1548     {
1549         return kStatus_InvalidArgument;
1550     }
1551 
1552     cau3KeyCtx.keySize = keySize;
1553 
1554     /* move the key by 32-bit words */
1555     int i = 0;
1556     while (keySize != 0U)
1557     {
1558         keySize -= sizeof(uint32_t);
1559         ((uint32_t *)((uintptr_t)cau3KeyCtx.key))[i] = ((uint32_t *)(uintptr_t)key)[i];
1560         i++;
1561     }
1562 
1563     return cau3_load_key_context(base, &cau3KeyCtx, handle->keySlot, handle->taskDone);
1564 }
1565 
1566 /*!
1567  * brief   Perform an AES-128 cipher-based authentication code (CMAC)
1568  *
1569  * Performs an AES-128 cipher-based authentication code (CMAC) on a
1570  * message. RFC 4493.
1571  *
1572  * param base CAU3 peripheral base address
1573  * param handle Handle used for this request.
1574  * param message is source uint8_t array of data bytes, any alignment
1575  * param size Number of bytes in the message.
1576  * param mac is the output 16 bytes MAC, must be a 0-mod-4 aligned address
1577  * return  status check from task completion
1578  */
CAU3_AES_Cmac(CAU3_Type * base,cau3_handle_t * handle,const uint8_t * message,size_t size,uint8_t * mac)1579 status_t CAU3_AES_Cmac(CAU3_Type *base, cau3_handle_t *handle, const uint8_t *message, size_t size, uint8_t *mac)
1580 {
1581     status_t completionStatus;
1582 
1583     /* mac must be 0-mod-4 aligned */
1584     if (0U != (0x3U & (uintptr_t)mac))
1585     {
1586         return kStatus_InvalidArgument;
1587     }
1588 
1589 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
1590     completionStatus = cau3_lock_semaphore(base);
1591     if (kStatus_Success != completionStatus)
1592     {
1593         cau3_release_semaphore(base);
1594         return completionStatus;
1595     }
1596 #endif
1597 
1598     /*  execute the cau3 "aes_cmac" task  */
1599     base->CC_R[16] = (uintptr_t)message;         /*  pMessage  */
1600     base->CC_R[17] = (uint32_t)handle->keySlot;  /*  keySlot  */
1601     base->CC_R[18] = size;                       /*  messageSize  */
1602     base->CC_R[19] = (uintptr_t)mac;             /*  pMac  */
1603     base->CC_R30   = CAU3_DMEM_STK_BASE;         /*  initialize stack pointer (sp)  */
1604     base->CC_R31   = 0U;                         /*  set LR = 0 to signal a host task  */
1605     base->CC_PC    = CAU3_TASK_AES128_CMAC;      /*  call cau_aes128_cmac()  */
1606     base->CC_CMD   = (uint32_t)handle->taskDone; /*  trigger cau3 execution  */
1607 
1608     /*  process the cau3 task completion signal specified by taskDone  */
1609     completionStatus = cau3_process_task_completion(base, handle->taskDone);
1610 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
1611     cau3_release_semaphore(base);
1612 #endif
1613     return (completionStatus);
1614 }
1615 
1616 /*!
1617  * @brief Check validity of algoritm.
1618  *
1619  * This function checks the validity of input argument.
1620  *
1621  * @param algo Tested algorithm value.
1622  * @return kStatus_Success if valid, kStatus_InvalidArgument otherwise.
1623  */
cau3_hash_check_input_alg(cau3_hash_algo_t algo)1624 static status_t cau3_hash_check_input_alg(cau3_hash_algo_t algo)
1625 {
1626     if ((algo != kCAU3_Sha256) && (algo != kCAU3_Sha1))
1627     {
1628         return kStatus_InvalidArgument;
1629     }
1630     return kStatus_Success;
1631 }
1632 
1633 /*!
1634  * @brief Check validity of input arguments.
1635  *
1636  * This function checks the validity of input arguments.
1637  *
1638  * @param base CAU3 peripheral base address.
1639  * @param ctx Memory buffer given by user application where the CAU3_HASH_Init/CAU3_HASH_Update/CAU3_HASH_Finish store
1640  * context.
1641  * @param algo Tested algorithm value.
1642  * @return kStatus_Success if valid, kStatus_InvalidArgument otherwise.
1643  */
cau3_hash_check_input_args(CAU3_Type * base,cau3_hash_ctx_t * ctx,cau3_hash_algo_t algo)1644 static status_t cau3_hash_check_input_args(CAU3_Type *base, cau3_hash_ctx_t *ctx, cau3_hash_algo_t algo)
1645 {
1646     /* Check validity of input algorithm */
1647     if (kStatus_Success != cau3_hash_check_input_alg(algo))
1648     {
1649         return kStatus_InvalidArgument;
1650     }
1651 
1652     if ((NULL == ctx) || (NULL == base))
1653     {
1654         return kStatus_InvalidArgument;
1655     }
1656 
1657     return kStatus_Success;
1658 }
1659 
1660 /*!
1661  * @brief Check validity of internal software context.
1662  *
1663  * This function checks if the internal context structure looks correct.
1664  *
1665  * @param ctxInternal Internal context.
1666  * @param message Input message address.
1667  * @return kStatus_Success if valid, kStatus_InvalidArgument otherwise.
1668  */
cau3_hash_check_context(cau3_hash_ctx_internal_t * ctxInternal,const uint8_t * message)1669 static status_t cau3_hash_check_context(cau3_hash_ctx_internal_t *ctxInternal, const uint8_t *message)
1670 {
1671     if ((NULL == message) || (NULL == ctxInternal) || (kStatus_Success != cau3_hash_check_input_alg(ctxInternal->algo)))
1672     {
1673         return kStatus_InvalidArgument;
1674     }
1675     return kStatus_Success;
1676 }
1677 
1678 /*!
1679  * @brief   Initialize message digest output state for SHA-1 hash
1680  *
1681  * Initializes the message digest output state for a SHA-1 hash.
1682  *
1683  * @param   sha1State is message digest output in sysMemory in BE format
1684  * @param   taskDone indicates completion signal: CAU_[POLL, IRQ, EVENT, DMAREQ]
1685  *
1686  * @retval  status check from task completion: CAU_[OK, ERROR]
1687  */
1688 
CAU3_Sha1InitializeOutput(CAU3_Type * base,uint32_t * sha1State,cau3_task_done_t taskDone)1689 static status_t CAU3_Sha1InitializeOutput(CAU3_Type *base, uint32_t *sha1State, cau3_task_done_t taskDone)
1690 {
1691     status_t completionStatus;
1692 
1693 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
1694     completionStatus = cau3_lock_semaphore(base);
1695     if (kStatus_Success != completionStatus)
1696     {
1697         cau3_release_semaphore(base);
1698         return completionStatus;
1699     }
1700 #endif
1701 
1702     /*  execute the cau3 "sha1_init_output" task  */
1703     base->CC_R[29] = (uintptr_t)sha1State;      /*  pSha1State  */
1704     base->CC_R30   = CAU3_DMEM_STK_BASE;        /*  initialize stack pointer (sp)  */
1705     base->CC_R31   = 0U;                        /*  set LR = 0 to signal a host task  */
1706     base->CC_PC    = CAU3_TASK_SHA1_INIT_STATE; /*  call cau_sha1_init_state()  */
1707     base->CC_CMD   = (uint32_t)taskDone;        /*  trigger cau3 execution  */
1708 
1709     /*  process the cau3 task completion signal specified by taskDone  */
1710     completionStatus = cau3_process_task_completion(base, taskDone);
1711 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
1712     cau3_release_semaphore(base);
1713 #endif
1714     return (completionStatus);
1715 }
1716 
1717 /*!
1718  * @brief   Perform a SHA-1 hash function over a message of "n" 64-byte blocks
1719  *
1720  * Perform a SHA-1 hash function over a message of "n" 64-byte data blocks,
1721  * returning an 8-word message digest (aka "state"). The input message must
1722  * be padded appropriately as defined by the SHA-1 algorithm.
1723  *
1724  * @param   message is the uint8_t input message, any alignment
1725  * @param   numberOfBlocks is the message length as multiple of 64-byte blocks
1726  * @param   sha1State is uint32_t message digest output (state) in BE format
1727  * @param   taskDone indicates completion signal: CAU_[POLL, IRQ, EVENT, DMAREQ]
1728  *
1729  * @retval  status check from task completion: CAU_[OK, ERROR]
1730  */
1731 
CAU3_Sha1Update(CAU3_Type * base,const uint8_t * message,uint32_t numberOfBlocks,uint32_t * sha1State,cau3_task_done_t taskDone)1732 static status_t CAU3_Sha1Update(
1733     CAU3_Type *base, const uint8_t *message, uint32_t numberOfBlocks, uint32_t *sha1State, cau3_task_done_t taskDone)
1734 {
1735     status_t completionStatus;
1736 
1737 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
1738     completionStatus = cau3_lock_semaphore(base);
1739     if (kStatus_Success != completionStatus)
1740     {
1741         cau3_release_semaphore(base);
1742         return completionStatus;
1743     }
1744 #endif
1745 
1746     /*  execute the cau3 "sha1_update" task  */
1747     base->CC_R[27] = (uintptr_t)message;   /*  pMessage  */
1748     base->CC_R[28] = numberOfBlocks;       /*  n blocks  */
1749     base->CC_R[29] = (uintptr_t)sha1State; /*  output  */
1750     base->CC_R30   = CAU3_DMEM_STK_BASE;   /*  initialize stack pointer (sp)  */
1751     base->CC_R31   = 0U;                   /*  set LR = 0 to signal a host task  */
1752     base->CC_PC    = CAU3_TASK_SHA1_HASH;  /*  call cau_sha1_hash_n()  */
1753     base->CC_CMD   = (uint32_t)taskDone;   /*  trigger cau3 execution  */
1754 
1755     /*  process the cau3 task completion signal specified by taskDone  */
1756     completionStatus = cau3_process_task_completion(base, taskDone);
1757 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
1758     cau3_release_semaphore(base);
1759 #endif
1760     return (completionStatus);
1761 }
1762 
1763 /*!
1764  * @brief   Initialize message digest output state for SHA-256 hash
1765  *
1766  * Initializes the message digest output state for a SHA-256 hash.
1767  *
1768  * CAU3_Sha256InitializeOutput
1769  * @param   sha256State is message digest output in sysMemory in BE format
1770  * @param   taskDone indicates completion signal: CAU_[POLL, IRQ, EVENT, DMAREQ]
1771  *
1772  * @retval  status check from task completion: CAU_[OK, ERROR]
1773  */
1774 
CAU3_Sha256InitializeOutput(CAU3_Type * base,uint32_t * sha256State,cau3_task_done_t taskDone)1775 static status_t CAU3_Sha256InitializeOutput(CAU3_Type *base, uint32_t *sha256State, cau3_task_done_t taskDone)
1776 {
1777     status_t completionStatus;
1778 
1779 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
1780     completionStatus = cau3_lock_semaphore(base);
1781     if (kStatus_Success != completionStatus)
1782     {
1783         cau3_release_semaphore(base);
1784         return completionStatus;
1785     }
1786 #endif
1787 
1788     /* execute the cau3 "sha256_init_output" task */
1789     base->CC_R[29] = (uint32_t)sha256State;       /* pSha256State */
1790     base->CC_R30   = CAU3_DMEM_STK_BASE;          /* initialize stack pointer (sp) */
1791     base->CC_R31   = 0U;                          /* set LR = 0 to signal a host task */
1792     base->CC_PC    = CAU3_TASK_SHA256_INIT_STATE; /* call cau_sha256_init_state() */
1793     base->CC_CMD   = (uint32_t)taskDone;          /* trigger cau3 execution */
1794 
1795     /* process the cau3 task completion signal specified by taskDone */
1796     completionStatus = cau3_process_task_completion(base, taskDone);
1797 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
1798     cau3_release_semaphore(base);
1799 #endif
1800     return (completionStatus);
1801 }
1802 
1803 /*!
1804  * @brief   Perform a SHA-256 hash function over a message of "n" 64-byte blocks
1805  *
1806  * Perform a SHA-256 hash function over a message of "n" 64-byte data blocks,
1807  * returning an 8-word message digest (aka "state"). The input message must
1808  * be padded appropriately as defined by the SHA-256 algorithm.
1809  *
1810  * CAU_Sha256Update
1811  * @param   message is the uint8_t input message, LE, ANY ALIGNMENT
1812  * @param   numberOfBlocks is the message length as multiple of 64-byte blocks
1813  * @param   sha256State is uint32_t message digest output (state) in BE format
1814  * @param   taskDone indicates completion signal: CAU_[POLL, IRQ, EVENT, DMAREQ]
1815  *
1816  * @retval  status check from task completion: CAU_[OK, ERROR]
1817  */
1818 
CAU3_Sha256Update(CAU3_Type * base,const uint8_t * message,uint32_t numberOfBlocks,uint32_t * sha256State,cau3_task_done_t taskDone)1819 static status_t CAU3_Sha256Update(
1820     CAU3_Type *base, const uint8_t *message, uint32_t numberOfBlocks, uint32_t *sha256State, cau3_task_done_t taskDone)
1821 {
1822     status_t completionStatus;
1823 
1824 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
1825     completionStatus = cau3_lock_semaphore(base);
1826     if (kStatus_Success != completionStatus)
1827     {
1828         cau3_release_semaphore(base);
1829         return completionStatus;
1830     }
1831 #endif
1832 
1833     /* execute the cau3 "sha256_update" task */
1834     base->CC_R[27] = (uint32_t)message;       /* pMessage */
1835     base->CC_R[28] = numberOfBlocks;          /* = (64*numberOfBlocks) bytes */
1836     base->CC_R[29] = (uint32_t)sha256State;   /* pSha256State */
1837     base->CC_R30   = CAU3_DMEM_STK_BASE;      /* initialize stack pointer (sp) */
1838     base->CC_R31   = 0U;                      /* set LR = 0 to signal a host task */
1839     base->CC_PC    = CAU3_TASK_SHA256_UPDATE; /* call cau_sha256_update() */
1840     base->CC_CMD   = (uint32_t)taskDone;      /* trigger cau3 execution */
1841 
1842     /* process the cau3 task completion signal specified by taskDone */
1843     completionStatus = cau3_process_task_completion(base, taskDone);
1844 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
1845     cau3_release_semaphore(base);
1846 #endif
1847     return (completionStatus);
1848 }
1849 
1850 /*!
1851  * @brief Initialize the SHA engine for new hash.
1852  *
1853  * This function sets NEW and MODE fields in SHA Control register to start new hash.
1854  *
1855  * @param base SHA peripheral base address.
1856  * @param ctxInternal Internal context.
1857  */
cau3_hash_engine_init(CAU3_Type * base,cau3_hash_ctx_internal_t * ctxInternal)1858 static status_t cau3_hash_engine_init(CAU3_Type *base, cau3_hash_ctx_internal_t *ctxInternal)
1859 {
1860     status_t status;
1861 
1862     status = kStatus_InvalidArgument;
1863 
1864     if (kCAU3_Sha256 == ctxInternal->algo)
1865     {
1866         status = CAU3_Sha256InitializeOutput(base, ctxInternal->runningHash, kCAU3_TaskDonePoll);
1867     }
1868 
1869     if (kCAU3_Sha1 == ctxInternal->algo)
1870     {
1871         status = CAU3_Sha1InitializeOutput(base, ctxInternal->runningHash, kCAU3_TaskDonePoll);
1872     }
1873 
1874     return status;
1875 }
1876 
1877 /*!
1878  * @brief Adds message to current hash.
1879  *
1880  * This function merges the message to fill the internal buffer, empties the internal buffer if
1881  * it becomes full, then process all remaining message data.
1882  *
1883  *
1884  * @param base CAU3 peripheral base address.
1885  * @param ctxInternal Internal context.
1886  * @param message Input message.
1887  * @param messageSize Size of input message in bytes.
1888  * @return kStatus_Success.
1889  */
cau3_hash_process_message_data(CAU3_Type * base,cau3_hash_ctx_internal_t * ctxInternal,const uint8_t * message,size_t messageSize)1890 static status_t cau3_hash_process_message_data(CAU3_Type *base,
1891                                                cau3_hash_ctx_internal_t *ctxInternal,
1892                                                const uint8_t *message,
1893                                                size_t messageSize)
1894 {
1895     status_t status;
1896     status_t (*funcUpdate)(CAU3_Type *cau3base, const uint8_t *msg, uint32_t numberOfBlocks, uint32_t *shaState,
1897                            cau3_task_done_t taskDone);
1898 
1899     /* first fill the internal buffer to full block */
1900     size_t toCopy = CAU3_HASH_BLOCK_SIZE - ctxInternal->blksz;
1901     (void)cau3_memcpy(&ctxInternal->blk.b[ctxInternal->blksz], message, toCopy);
1902     message += toCopy;
1903     messageSize -= toCopy;
1904 
1905     status     = kStatus_InvalidArgument;
1906     funcUpdate = NULL;
1907 
1908     switch (ctxInternal->algo)
1909     {
1910         case kCAU3_Sha256:
1911             funcUpdate = CAU3_Sha256Update;
1912             break;
1913 
1914         case kCAU3_Sha1:
1915             funcUpdate = CAU3_Sha1Update;
1916             break;
1917 
1918         default:
1919             /* All the cases have been listed above, the default clause should not be reached. */
1920             break;
1921     }
1922 
1923     if (NULL != funcUpdate)
1924     {
1925         /* process full internal block */
1926         status = funcUpdate(base, &ctxInternal->blk.b[0], CAU3_HASH_BLOCK_SIZE / 64u, ctxInternal->runningHash,
1927                             kCAU3_TaskDonePoll);
1928         if (kStatus_Success != status)
1929         {
1930             return status;
1931         }
1932 
1933         /* process all full blocks in message[] */
1934         while (messageSize >= CAU3_HASH_BLOCK_SIZE)
1935         {
1936             status =
1937                 funcUpdate(base, message, CAU3_HASH_BLOCK_SIZE / 64u, ctxInternal->runningHash, kCAU3_TaskDonePoll);
1938             if (kStatus_Success != status)
1939             {
1940                 return status;
1941             }
1942             message += CAU3_HASH_BLOCK_SIZE;
1943             messageSize -= CAU3_HASH_BLOCK_SIZE;
1944         }
1945 
1946         /* copy last incomplete message bytes into internal block */
1947         (void)cau3_memcpy(&ctxInternal->blk.b[0], message, messageSize);
1948         ctxInternal->blksz = messageSize;
1949     }
1950 
1951     return status;
1952 }
1953 
1954 /*!
1955  * @brief Finalize the running hash to make digest.
1956  *
1957  * This function empties the internal buffer, adds padding bits, and generates final digest.
1958  *
1959  * @param base SHA peripheral base address.
1960  * @param ctxInternal Internal context.
1961  * @return kStatus_Success.
1962  */
cau3_hash_finalize(CAU3_Type * base,cau3_hash_ctx_internal_t * ctxInternal)1963 static status_t cau3_hash_finalize(CAU3_Type *base, cau3_hash_ctx_internal_t *ctxInternal)
1964 {
1965     cau3_sha_block_t lastBlock;
1966     status_t status;
1967     status_t (*funcUpdate)(CAU3_Type *cau3base, const uint8_t *msg, uint32_t numberOfBlocks, uint32_t *shaState,
1968                            cau3_task_done_t taskDone);
1969 
1970     funcUpdate = NULL;
1971 
1972     switch (ctxInternal->algo)
1973     {
1974         case kCAU3_Sha256:
1975             funcUpdate = CAU3_Sha256Update;
1976             break;
1977 
1978         case kCAU3_Sha1:
1979             funcUpdate = CAU3_Sha1Update;
1980             break;
1981 
1982         default:
1983             /* All the cases have been listed above, the default clause should not be reached. */
1984             break;
1985     }
1986 
1987     if (NULL == funcUpdate)
1988     {
1989         return kStatus_InvalidArgument;
1990     }
1991 
1992     (void)memset(&lastBlock, 0, sizeof(cau3_sha_block_t));
1993 
1994     while (ctxInternal->blksz >= 64u)
1995     {
1996         status = funcUpdate(base, &ctxInternal->blk.b[0], 1, ctxInternal->runningHash, kCAU3_TaskDonePoll);
1997         if (kStatus_Success != status)
1998         {
1999             return status;
2000         }
2001         ctxInternal->blksz -= 64u;
2002         (void)memmove(&ctxInternal->blk.b[0], &ctxInternal->blk.b[64], ctxInternal->blksz);
2003     }
2004 
2005     /* this is last call, so need to flush buffered message bytes along with padding */
2006     if (ctxInternal->blksz <= 55u)
2007     {
2008         /* last data is 440 bits or less. */
2009         (void)cau3_memcpy(&lastBlock.b[0], &ctxInternal->blk.b[0], ctxInternal->blksz);
2010         lastBlock.b[ctxInternal->blksz] = (uint8_t)0x80U;
2011         lastBlock.w[15]                 = __REV(8u * ctxInternal->fullMessageSize);
2012         status = funcUpdate(base, &lastBlock.b[0], 1, ctxInternal->runningHash, kCAU3_TaskDonePoll);
2013         if (kStatus_Success != status)
2014         {
2015             return status;
2016         }
2017     }
2018     else
2019     {
2020         if (ctxInternal->blksz < 64u)
2021         {
2022             ctxInternal->blk.b[ctxInternal->blksz] = (uint8_t)0x80U;
2023             for (uint32_t i = ctxInternal->blksz + 1u; i < 64u; i++)
2024             {
2025                 ctxInternal->blk.b[i] = 0;
2026             }
2027         }
2028         else
2029         {
2030             lastBlock.b[0] = (uint8_t)0x80U;
2031         }
2032 
2033         status = funcUpdate(base, &ctxInternal->blk.b[0], 1, ctxInternal->runningHash, kCAU3_TaskDonePoll);
2034         if (kStatus_Success != status)
2035         {
2036             return status;
2037         }
2038         lastBlock.w[15] = __REV(8u * ctxInternal->fullMessageSize);
2039         status          = funcUpdate(base, &lastBlock.b[0], 1, ctxInternal->runningHash, kCAU3_TaskDonePoll);
2040         if (kStatus_Success != status)
2041         {
2042             return status;
2043         }
2044     }
2045     return status;
2046 }
2047 
2048 /*!
2049  * brief Initialize HASH context
2050  *
2051  * This function initializes the HASH.
2052  *
2053  * For blocking CAU3 HASH API, the HASH context contains all information required for context switch,
2054  * such as running hash.
2055  *
2056  * param base CAU3 peripheral base address
2057  * param[out] ctx Output hash context
2058  * param algo Underlaying algorithm to use for hash computation.
2059  * return Status of initialization
2060  */
CAU3_HASH_Init(CAU3_Type * base,cau3_hash_ctx_t * ctx,cau3_hash_algo_t algo)2061 status_t CAU3_HASH_Init(CAU3_Type *base, cau3_hash_ctx_t *ctx, cau3_hash_algo_t algo)
2062 {
2063     status_t status;
2064 
2065     cau3_hash_ctx_internal_t *ctxInternal;
2066     /* compile time check for the correct structure size */
2067     BUILD_ASSURE(sizeof(cau3_hash_ctx_t) >= sizeof(cau3_hash_ctx_internal_t), cau3_hash_ctx_t_size);
2068     uint32_t i, j;
2069 
2070     status = cau3_hash_check_input_args(base, ctx, algo);
2071     if (status != kStatus_Success)
2072     {
2073         return status;
2074     }
2075 
2076     /* set algorithm in context struct for later use */
2077     ctxInternal        = (cau3_hash_ctx_internal_t *)(uint32_t)ctx;
2078     ctxInternal->algo  = algo;
2079     ctxInternal->blksz = 0u;
2080     j                  = sizeof(ctxInternal->blk.w) / sizeof(ctxInternal->blk.w[0]);
2081     for (i = 0; i < j; i++)
2082     {
2083         ctxInternal->blk.w[0] = 0u;
2084     }
2085     ctxInternal->state           = kCAU3_StateHashInit;
2086     ctxInternal->fullMessageSize = 0;
2087 
2088     return status;
2089 }
2090 
2091 /*!
2092  * brief Add data to current HASH
2093  *
2094  * Add data to current HASH. This can be called repeatedly with an arbitrary amount of data to be
2095  * hashed. The functions blocks. If it returns kStatus_Success, the running hash or mac
2096  * has been updated (CAU3 has processed the input data), so the memory at ref input pointer
2097  * can be released back to system. The context is updated with the running hash or mac
2098  * and with all necessary information to support possible context switch.
2099  *
2100  * param base CAU3 peripheral base address
2101  * param[in,out] ctx HASH context
2102  * param input Input data
2103  * param inputSize Size of input data in bytes
2104  * return Status of the hash update operation
2105  */
CAU3_HASH_Update(CAU3_Type * base,cau3_hash_ctx_t * ctx,const uint8_t * input,size_t inputSize)2106 status_t CAU3_HASH_Update(CAU3_Type *base, cau3_hash_ctx_t *ctx, const uint8_t *input, size_t inputSize)
2107 {
2108     bool isUpdateState;
2109     status_t status;
2110     cau3_hash_ctx_internal_t *ctxInternal;
2111     size_t blockSize;
2112 
2113     if (inputSize == 0U)
2114     {
2115         return kStatus_Success;
2116     }
2117 
2118     ctxInternal = (cau3_hash_ctx_internal_t *)(uint32_t)ctx;
2119     status      = cau3_hash_check_context(ctxInternal, input);
2120     if (kStatus_Success != status)
2121     {
2122         return status;
2123     }
2124 
2125     ctxInternal->fullMessageSize += inputSize;
2126     blockSize = CAU3_HASH_BLOCK_SIZE;
2127     /* if we are still less than CAU3_HASH_BLOCK_SIZE bytes, keep only in context */
2128     if ((ctxInternal->blksz + inputSize) <= blockSize)
2129     {
2130         (void)cau3_memcpy((&ctxInternal->blk.b[0]) + ctxInternal->blksz, input, inputSize);
2131         ctxInternal->blksz += inputSize;
2132         return status;
2133     }
2134     else
2135     {
2136         isUpdateState = ctxInternal->state == kCAU3_StateHashUpdate;
2137         if (!isUpdateState)
2138         {
2139             /* start NEW hash */
2140             status = cau3_hash_engine_init(base, ctxInternal);
2141             if (status != kStatus_Success)
2142             {
2143                 return status;
2144             }
2145             ctxInternal->state = kCAU3_StateHashUpdate;
2146         }
2147     }
2148 
2149     /* process input data */
2150     status = cau3_hash_process_message_data(base, ctxInternal, input, inputSize);
2151     return status;
2152 }
2153 
2154 /*!
2155  * brief Finalize hashing
2156  *
2157  * Outputs the final hash (computed by CAU3_HASH_Update()) and erases the context.
2158  *
2159  * param[in,out] ctx Input hash context
2160  * param[out] output Output hash data
2161  * param[out] outputSize Output parameter storing the size of the output hash in bytes
2162  * return Status of the hash finish operation
2163  */
CAU3_HASH_Finish(CAU3_Type * base,cau3_hash_ctx_t * ctx,uint8_t * output,size_t * outputSize)2164 status_t CAU3_HASH_Finish(CAU3_Type *base, cau3_hash_ctx_t *ctx, uint8_t *output, size_t *outputSize)
2165 {
2166     size_t algOutSize = 0;
2167     status_t status;
2168     cau3_hash_ctx_internal_t *ctxInternal;
2169 
2170     ctxInternal = (cau3_hash_ctx_internal_t *)(uint32_t)ctx;
2171     status      = cau3_hash_check_context(ctxInternal, output);
2172     if (kStatus_Success != status)
2173     {
2174         return status;
2175     }
2176 
2177     if (ctxInternal->state == kCAU3_StateHashInit)
2178     {
2179         status = cau3_hash_engine_init(base, ctxInternal);
2180         if (status != kStatus_Success)
2181         {
2182             return status;
2183         }
2184     }
2185 
2186     size_t outSize = 0u;
2187 
2188     /* compute algorithm output length */
2189     switch (ctxInternal->algo)
2190     {
2191         case kCAU3_Sha256:
2192             outSize = (uint32_t)kCAU3_OutLenSha256;
2193             break;
2194         case kCAU3_Sha1:
2195             outSize = (uint32_t)kCAU3_OutLenSha1;
2196             break;
2197         default:
2198             /* All the cases have been listed above, the default clause should not be reached. */
2199             break;
2200     }
2201     algOutSize = outSize;
2202 
2203     /* flush message last incomplete block, if there is any, and add padding bits */
2204     status = cau3_hash_finalize(base, ctxInternal);
2205 
2206     if (outputSize != NULL)
2207     {
2208         if (algOutSize < *outputSize)
2209         {
2210             *outputSize = algOutSize;
2211         }
2212         else
2213         {
2214             algOutSize = *outputSize;
2215         }
2216     }
2217 
2218     (void)cau3_memcpy(&output[0], (const uint8_t *)ctxInternal->runningHash, algOutSize);
2219 
2220     (void)memset(ctx, 0, sizeof(cau3_hash_ctx_t));
2221     return status;
2222 }
2223 
2224 /*!
2225  * brief Create HASH on given data
2226  *
2227  * Perform the full SHA in one function call. The function is blocking.
2228  *
2229  * param base CAU3 peripheral base address
2230  * param algo Underlaying algorithm to use for hash computation.
2231  * param input Input data
2232  * param inputSize Size of input data in bytes
2233  * param[out] output Output hash data
2234  * param[out] outputSize Output parameter storing the size of the output hash in bytes
2235  * return Status of the one call hash operation.
2236  */
CAU3_HASH(CAU3_Type * base,cau3_hash_algo_t algo,const uint8_t * input,size_t inputSize,uint8_t * output,size_t * outputSize)2237 status_t CAU3_HASH(
2238     CAU3_Type *base, cau3_hash_algo_t algo, const uint8_t *input, size_t inputSize, uint8_t *output, size_t *outputSize)
2239 {
2240     cau3_hash_ctx_t hashCtx;
2241     status_t status;
2242 
2243     status = CAU3_HASH_Init(base, &hashCtx, algo);
2244     if (status != kStatus_Success)
2245     {
2246         return status;
2247     }
2248 
2249     status = CAU3_HASH_Update(base, &hashCtx, input, inputSize);
2250     if (status != kStatus_Success)
2251     {
2252         return status;
2253     }
2254 
2255     status = CAU3_HASH_Finish(base, &hashCtx, output, outputSize);
2256 
2257     return status;
2258 }
2259 
2260 /*! @brief CAU3 driver wait mechanism. */
cau3_wait(CAU3_Type * base)2261 static status_t cau3_wait(CAU3_Type *base)
2262 {
2263     status_t status;
2264 
2265     bool error = false;
2266     bool done  = false;
2267 
2268     /* Wait for 'done' or 'error' flag. */
2269     while ((!error) && (!done))
2270     {
2271         uint32_t temp32 = base->STA;
2272         error           = (bool)(temp32 & (uint32_t)kCAU3_StatusErrorIsr);
2273         done            = (bool)(temp32 & (uint32_t)kCAU3_StatusDoneIsr);
2274     }
2275 
2276     if (error)
2277     {
2278         base->COM = CAU3_COM_ALL_MASK; /* Reset all engine to clear the error flag */
2279         status    = kStatus_Fail;
2280     }
2281     else /* 'done' */
2282     {
2283         status = kStatus_Success;
2284 
2285         base->CW = (uint32_t)kCAU3_ClearDataSize;
2286         /* Clear 'done' interrupt status.  This also clears the mode register. */
2287         base->STA = (uint32_t)kCAU3_StatusDoneIsr;
2288     }
2289 
2290     return status;
2291 }
2292 
2293 /*!
2294  * @brief Clears the CAU3 module.
2295  * This function can be used to clear all sensitive data from theCAU3 module, such as private keys. It is called
2296  * internally by the CAU3 driver in case of an error or operation complete.
2297  * @param base CAU3 peripheral base address
2298  * @param pkha Include CAU3 PKHA register clear. If there is no PKHA, the argument is ignored.
2299  */
cau3_clear_all(CAU3_Type * base,bool addPKHA)2300 static void cau3_clear_all(CAU3_Type *base, bool addPKHA)
2301 {
2302     base->CW = (uint32_t)kCAU3_ClearAll;
2303     if (addPKHA)
2304     {
2305         (void)cau3_pkha_clear_regabne(base, true, true, true, true);
2306     }
2307 }
2308 
2309 /*!
2310  * @brief Reads an unaligned word.
2311  *
2312  * This function creates a 32-bit word from an input array of four bytes.
2313  *
2314  * @param src Input array of four bytes. The array can start at any address in memory.
2315  * @return 32-bit unsigned int created from the input byte array.
2316  */
cau3_get_word_from_unaligned(const uint8_t * srcAddr)2317 static inline uint32_t cau3_get_word_from_unaligned(const uint8_t *srcAddr)
2318 {
2319 #if (!(defined(__CORTEX_M)) || (defined(__CORTEX_M) && (__CORTEX_M == 0)))
2320     register const uint8_t *src = srcAddr;
2321     /* Cortex M0 does not support misaligned loads */
2322     if (0U != ((uint32_t)src & 0x3u))
2323     {
2324         union _align_bytes_t
2325         {
2326             uint32_t word;
2327             uint8_t byte[sizeof(uint32_t)];
2328         } my_bytes;
2329 
2330         my_bytes.byte[0] = *src;
2331         my_bytes.byte[1] = *(src + 1);
2332         my_bytes.byte[2] = *(src + 2);
2333         my_bytes.byte[3] = *(src + 3);
2334         return my_bytes.word;
2335     }
2336     else
2337     {
2338         /* addr aligned to 0-modulo-4 so it is safe to type cast */
2339         return *((const uint32_t *)(uintptr_t)src);
2340     }
2341 #elif defined(__CC_ARM) || defined(__ARMCC_VERSION)
2342     /* -O3 optimization in Keil Compiler 5 uses LDM instruction here (LDM r4!, {r0})
2343      *    which is wrong, because srcAddr might be unaligned.
2344      *    LDM on unaligned address causes hard-fault. so use memcpy() */
2345     uint32_t ret;
2346     memcpy(&ret, srcAddr, sizeof(uint32_t));
2347     return ret;
2348 #else
2349     return *((const uint32_t *)(uintptr_t)srcAddr);
2350 #endif
2351 }
2352 
2353 /*******************************************************************************
2354  * PKHA Code static
2355  ******************************************************************************/
2356 
cau3_pkha_clear_regabne(CAU3_Type * base,bool A,bool B,bool N,bool E)2357 static status_t cau3_pkha_clear_regabne(CAU3_Type *base, bool A, bool B, bool N, bool E)
2358 {
2359     cau3_mode_t mode;
2360 
2361     /* Set the PKHA algorithm and the appropriate function. */
2362     mode = (uint32_t)kCAU3_AlgorithmPKHA | 1U;
2363 
2364     /* Set ram area to clear. Clear all. */
2365     if (A)
2366     {
2367         mode |= ((uint32_t)1U << 19U);
2368     }
2369     if (B)
2370     {
2371         mode |= ((uint32_t)1U << 18U);
2372     }
2373     if (N)
2374     {
2375         mode |= ((uint32_t)1U << 16U);
2376     }
2377     if (E)
2378     {
2379         mode |= ((uint32_t)1U << 17U);
2380     }
2381 
2382     /* Write the mode register to the hardware.
2383      * NOTE: This will begin the operation. */
2384     base->MDPK = mode;
2385 
2386     /* Wait for 'done' */
2387     return cau3_wait(base);
2388 }
2389 
cau3_pkha_default_parms(cau3_pkha_mode_params_t * params)2390 static void cau3_pkha_default_parms(cau3_pkha_mode_params_t *params)
2391 {
2392     params->func        = (cau3_pkha_func_t)0;
2393     params->arithType   = kCAU3_PKHA_IntegerArith;
2394     params->montFormIn  = kCAU3_PKHA_NormalValue;
2395     params->montFormOut = kCAU3_PKHA_NormalValue;
2396     params->srcReg      = kCAU3_PKHA_RegAll;
2397     params->srcQuad     = kCAU3_PKHA_Quad0;
2398     params->dstReg      = kCAU3_PKHA_RegAll;
2399     params->dstQuad     = kCAU3_PKHA_Quad0;
2400     params->equalTime   = kCAU3_PKHA_NoTimingEqualized;
2401     params->r2modn      = kCAU3_PKHA_CalcR2;
2402 }
2403 
cau3_pkha_write_word(CAU3_Type * base,cau3_pkha_reg_area_t reg,uint8_t index,uint32_t data)2404 static void cau3_pkha_write_word(CAU3_Type *base, cau3_pkha_reg_area_t reg, uint8_t index, uint32_t data)
2405 {
2406     __IO uint32_t *pka = base->PKA0;
2407     __IO uint32_t *pkb = base->PKB0;
2408     __IO uint32_t *pkn = base->PKN0;
2409 
2410     switch (reg)
2411     {
2412         case kCAU3_PKHA_RegA:
2413             pka[index] = data;
2414             break;
2415 
2416         case kCAU3_PKHA_RegB:
2417             pkb[index] = data;
2418             break;
2419 
2420         case kCAU3_PKHA_RegN:
2421             pkn[index] = data;
2422             break;
2423 
2424         case kCAU3_PKHA_RegE:
2425             base->PKE[index] = data;
2426             break;
2427 
2428         default:
2429             /* All the cases have been listed above, the default clause should not be reached. */
2430             break;
2431     }
2432 }
2433 
cau3_pkha_read_word(CAU3_Type * base,cau3_pkha_reg_area_t reg,uint8_t index)2434 static uint32_t cau3_pkha_read_word(CAU3_Type *base, cau3_pkha_reg_area_t reg, uint8_t index)
2435 {
2436     uint32_t retval;
2437     __IO uint32_t *pka = base->PKA0;
2438     __IO uint32_t *pkb = base->PKB0;
2439     __IO uint32_t *pkn = base->PKN0;
2440 
2441     switch (reg)
2442     {
2443         case kCAU3_PKHA_RegA:
2444             retval = pka[index];
2445             break;
2446 
2447         case kCAU3_PKHA_RegB:
2448             retval = pkb[index];
2449             break;
2450 
2451         case kCAU3_PKHA_RegN:
2452             retval = pkn[index];
2453             break;
2454 
2455         default:
2456             retval = 0;
2457             break;
2458     }
2459     return retval;
2460 }
2461 
cau3_pkha_write_reg(CAU3_Type * base,cau3_pkha_reg_area_t reg,uint8_t quad,const uint8_t * data,size_t dataSize)2462 static status_t cau3_pkha_write_reg(
2463     CAU3_Type *base, cau3_pkha_reg_area_t reg, uint8_t quad, const uint8_t *data, size_t dataSize)
2464 {
2465     /* Select the word-based start index for each quadrant of 128 bytes. */
2466     uint8_t startIndex = (quad * 32u);
2467     uint32_t outWord;
2468 
2469     while (dataSize > 0U)
2470     {
2471         if (dataSize >= sizeof(uint32_t))
2472         {
2473             cau3_pkha_write_word(base, reg, startIndex++, cau3_get_word_from_unaligned(data));
2474             dataSize -= sizeof(uint32_t);
2475             data += sizeof(uint32_t);
2476         }
2477         else /* (dataSize > 0) && (dataSize < 4) */
2478         {
2479             outWord = 0;
2480             (void)cau3_memcpy(&outWord, (const uint32_t *)(uintptr_t)data, dataSize);
2481             cau3_pkha_write_word(base, reg, startIndex, outWord);
2482             dataSize = 0;
2483         }
2484     }
2485 
2486     return kStatus_Success;
2487 }
2488 
cau3_pkha_read_reg(CAU3_Type * base,cau3_pkha_reg_area_t reg,uint8_t quad,uint8_t * data,size_t dataSize)2489 static void cau3_pkha_read_reg(CAU3_Type *base, cau3_pkha_reg_area_t reg, uint8_t quad, uint8_t *data, size_t dataSize)
2490 {
2491     /* Select the word-based start index for each quadrant of 128 bytes. */
2492     uint8_t startIndex = (quad * 32u);
2493     size_t calcSize;
2494     uint32_t word;
2495 
2496     while (dataSize > 0U)
2497     {
2498         word = cau3_pkha_read_word(base, reg, startIndex++);
2499 
2500         calcSize = (dataSize >= sizeof(uint32_t)) ? sizeof(uint32_t) : dataSize;
2501         (void)cau3_memcpy(data, (const uint8_t *)&word, calcSize);
2502 
2503         data += calcSize;
2504         dataSize -= calcSize;
2505     }
2506 }
2507 
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)2508 static void cau3_pkha_init_data(CAU3_Type *base,
2509                                 const uint8_t *A,
2510                                 size_t sizeA,
2511                                 const uint8_t *B,
2512                                 size_t sizeB,
2513                                 const uint8_t *N,
2514                                 size_t sizeN,
2515                                 const uint8_t *E,
2516                                 size_t sizeE)
2517 {
2518     uint32_t clearMask = (uint32_t)kCAU3_ClearMode; /* clear Mode Register */
2519 
2520     /* Clear internal register states. */
2521     if (sizeA != 0U)
2522     {
2523         clearMask |= (uint32_t)kCAU3_ClearPkhaSizeA;
2524     }
2525     if (sizeB != 0U)
2526     {
2527         clearMask |= (uint32_t)kCAU3_ClearPkhaSizeB;
2528     }
2529     if (sizeN != 0U)
2530     {
2531         clearMask |= (uint32_t)kCAU3_ClearPkhaSizeN;
2532     }
2533     if (sizeE != 0U)
2534     {
2535         clearMask |= (uint32_t)kCAU3_ClearPkhaSizeE;
2536     }
2537 
2538     base->CW  = clearMask;
2539     base->STA = (uint32_t)kCAU3_StatusDoneIsr;
2540     (void)cau3_pkha_clear_regabne(base, (bool)(uintptr_t)A, (bool)(uintptr_t)B, (bool)(uintptr_t)N, (bool)(uintptr_t)E);
2541 
2542     /* Write register sizes. */
2543     /* Write modulus (N) and A and B register arguments. */
2544     if (sizeN != 0U)
2545     {
2546         base->PKNSZ = sizeN;
2547         if (N != NULL)
2548         {
2549             (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegN, 0, N, sizeN);
2550         }
2551     }
2552 
2553     if (sizeA != 0U)
2554     {
2555         base->PKASZ = sizeA;
2556         if (A != NULL)
2557         {
2558             (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegA, 0, A, sizeA);
2559         }
2560     }
2561 
2562     if (sizeB != 0U)
2563     {
2564         base->PKBSZ = sizeB;
2565         if (B != NULL)
2566         {
2567             (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegB, 0, B, sizeB);
2568         }
2569     }
2570 
2571     if (sizeE != 0U)
2572     {
2573         base->PKESZ = sizeE;
2574         if (E != NULL)
2575         {
2576             (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegE, 0, E, sizeE);
2577         }
2578     }
2579 }
2580 
cau3_pkha_mode_set_src_reg_copy(cau3_mode_t * outMode,cau3_pkha_reg_area_t reg)2581 static void cau3_pkha_mode_set_src_reg_copy(cau3_mode_t *outMode, cau3_pkha_reg_area_t reg)
2582 {
2583     int i = 0;
2584 
2585     do
2586     {
2587         reg = (cau3_pkha_reg_area_t)(uint32_t)((uint32_t)reg >> 1u);
2588         i++;
2589     } while ((uint32_t)reg != 0U);
2590 
2591     i = 4 - i;
2592     /* Source register must not be E. */
2593     if (i != 2)
2594     {
2595         *outMode |= ((uint32_t)i << 17u);
2596     }
2597 }
2598 
cau3_pkha_mode_set_dst_reg_copy(cau3_mode_t * outMode,cau3_pkha_reg_area_t reg)2599 static void cau3_pkha_mode_set_dst_reg_copy(cau3_mode_t *outMode, cau3_pkha_reg_area_t reg)
2600 {
2601     int i = 0;
2602 
2603     do
2604     {
2605         reg = (cau3_pkha_reg_area_t)(uint32_t)(((uint32_t)reg) >> 1u);
2606         i++;
2607     } while ((uint32_t)reg != 0U);
2608 
2609     i = 4 - i;
2610     *outMode |= ((uint32_t)i << 10u);
2611 }
2612 
cau3_pkha_mode_set_src_seg_copy(cau3_mode_t * outMode,const cau3_pkha_quad_area_t quad)2613 static void cau3_pkha_mode_set_src_seg_copy(cau3_mode_t *outMode, const cau3_pkha_quad_area_t quad)
2614 {
2615     *outMode |= ((uint32_t)quad << 8u);
2616 }
2617 
cau3_pkha_mode_set_dst_seg_copy(cau3_mode_t * outMode,const cau3_pkha_quad_area_t quad)2618 static void cau3_pkha_mode_set_dst_seg_copy(cau3_mode_t *outMode, const cau3_pkha_quad_area_t quad)
2619 {
2620     *outMode |= ((uint32_t)quad << 6u);
2621 }
2622 
2623 /*!
2624  * @brief Starts the PKHA operation.
2625  *
2626  * This function starts an operation configured by the params parameter.
2627  *
2628  * @param base CAU3 peripheral base address
2629  * @param params Configuration structure containing all settings required for PKHA operation.
2630  */
cau3_pkha_init_mode(CAU3_Type * base,const cau3_pkha_mode_params_t * params)2631 static status_t cau3_pkha_init_mode(CAU3_Type *base, const cau3_pkha_mode_params_t *params)
2632 {
2633     cau3_mode_t modeReg;
2634     status_t retval;
2635 
2636     /* Set the PKHA algorithm and the appropriate function. */
2637     modeReg = (uint32_t)kCAU3_AlgorithmPKHA;
2638     modeReg |= (uint32_t)params->func;
2639 
2640     if ((params->func == kCAU3_PKHA_CopyMemSizeN) || (params->func == kCAU3_PKHA_CopyMemSizeSrc))
2641     {
2642         /* Set source and destination registers and quads. */
2643         cau3_pkha_mode_set_src_reg_copy(&modeReg, params->srcReg);
2644         cau3_pkha_mode_set_dst_reg_copy(&modeReg, params->dstReg);
2645         cau3_pkha_mode_set_src_seg_copy(&modeReg, params->srcQuad);
2646         cau3_pkha_mode_set_dst_seg_copy(&modeReg, params->dstQuad);
2647     }
2648     else
2649     {
2650         /* Set the arithmetic type - integer or binary polynomial (F2m). */
2651         modeReg |= ((uint32_t)params->arithType << 17u);
2652 
2653         /* Set to use Montgomery form of inputs and/or outputs. */
2654         modeReg |= ((uint32_t)params->montFormIn << 19u);
2655         modeReg |= ((uint32_t)params->montFormOut << 18u);
2656 
2657         /* Set to use pre-computed R2modN */
2658         modeReg |= ((uint32_t)params->r2modn << 16u);
2659     }
2660 
2661     modeReg |= ((uint32_t)params->equalTime << 10u);
2662 
2663     /* Write the mode register to the hardware.
2664      * NOTE: This will begin the operation. */
2665     base->MDPK = modeReg;
2666 
2667     retval = cau3_wait(base);
2668     return (retval);
2669 }
2670 
cau3_pkha_modR2(CAU3_Type * base,const uint8_t * N,size_t sizeN,uint8_t * result,size_t * resultSize,cau3_pkha_f2m_t arithType)2671 static status_t cau3_pkha_modR2(
2672     CAU3_Type *base, const uint8_t *N, size_t sizeN, uint8_t *result, size_t *resultSize, cau3_pkha_f2m_t arithType)
2673 {
2674     status_t status;
2675     cau3_pkha_mode_params_t params;
2676 
2677     cau3_pkha_default_parms(&params);
2678     params.func      = kCAU3_PKHA_ArithModR2;
2679     params.arithType = arithType;
2680 
2681     cau3_pkha_init_data(base, NULL, 0, NULL, 0, N, sizeN, NULL, 0);
2682     status = cau3_pkha_init_mode(base, &params);
2683 
2684     if (status == kStatus_Success)
2685     {
2686         /* Read the result and size from register B0. */
2687         if ((resultSize != NULL) && (result != NULL))
2688         {
2689             *resultSize = base->PKBSZ;
2690             /* Read the data from the result register into place. */
2691             cau3_pkha_read_reg(base, kCAU3_PKHA_RegB, 0, result, *resultSize);
2692         }
2693     }
2694 
2695     return status;
2696 }
2697 
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)2698 static status_t cau3_pkha_modmul(CAU3_Type *base,
2699                                  const uint8_t *A,
2700                                  size_t sizeA,
2701                                  const uint8_t *B,
2702                                  size_t sizeB,
2703                                  const uint8_t *N,
2704                                  size_t sizeN,
2705                                  uint8_t *result,
2706                                  size_t *resultSize,
2707                                  cau3_pkha_f2m_t arithType,
2708                                  cau3_pkha_montgomery_form_t montIn,
2709                                  cau3_pkha_montgomery_form_t montOut,
2710                                  cau3_pkha_timing_t equalTime)
2711 {
2712     cau3_pkha_mode_params_t params;
2713     status_t status;
2714 
2715     if (arithType == kCAU3_PKHA_IntegerArith)
2716     {
2717         if (CAU3_PKHA_CompareBigNum(A, sizeA, N, sizeN) >= 0)
2718         {
2719             return (kStatus_InvalidArgument);
2720         }
2721 
2722         if (CAU3_PKHA_CompareBigNum(B, sizeB, N, sizeN) >= 0)
2723         {
2724             return (kStatus_InvalidArgument);
2725         }
2726     }
2727 
2728     cau3_pkha_default_parms(&params);
2729     params.func        = kCAU3_PKHA_ArithModMul;
2730     params.arithType   = arithType;
2731     params.montFormIn  = montIn;
2732     params.montFormOut = montOut;
2733     params.equalTime   = equalTime;
2734 
2735     cau3_pkha_init_data(base, A, sizeA, B, sizeB, N, sizeN, NULL, 0);
2736     status = cau3_pkha_init_mode(base, &params);
2737 
2738     if (status == kStatus_Success)
2739     {
2740         /* Read the result and size from register B0. */
2741         if ((resultSize != NULL) && (result != NULL))
2742         {
2743             *resultSize = base->PKBSZ;
2744             /* Read the data from the result register into place. */
2745             cau3_pkha_read_reg(base, kCAU3_PKHA_RegB, 0, result, *resultSize);
2746         }
2747     }
2748 
2749     return status;
2750 }
2751 
2752 /*******************************************************************************
2753  * PKHA Code public
2754  ******************************************************************************/
2755 /*!
2756  * addtogroup cau3_driver_pkha
2757  * {
2758  */
2759 
CAU3_PKHA_CompareBigNum(const uint8_t * a,size_t sizeA,const uint8_t * b,size_t sizeB)2760 int CAU3_PKHA_CompareBigNum(const uint8_t *a, size_t sizeA, const uint8_t *b, size_t sizeB)
2761 {
2762     int retval = 0;
2763 
2764     /* skip zero msbytes - integer a */
2765     while ((sizeA != 0U) && (0u == a[sizeA - 1U]))
2766     {
2767         sizeA--;
2768     }
2769 
2770     /* skip zero msbytes - integer b */
2771     while ((sizeB != 0U) && (0u == b[sizeB - 1U]))
2772     {
2773         sizeB--;
2774     }
2775 
2776     if (sizeA > sizeB)
2777     {
2778         retval = 1;
2779     } /* int a has more non-zero bytes, thus it is bigger than b */
2780     else if (sizeA < sizeB)
2781     {
2782         retval = -1;
2783     } /* int b has more non-zero bytes, thus it is bigger than a */
2784     else if (sizeA == 0U)
2785     {
2786         retval = 0;
2787     } /* sizeA = sizeB = 0 */
2788     else
2789     {
2790         int n;
2791         int i;
2792         int val;
2793         uint32_t equal;
2794 
2795         n     = (int32_t)((int32_t)sizeA - 1);
2796         i     = 0;
2797         equal = 0;
2798 
2799         while (n >= 0)
2800         {
2801             uint32_t chXor = ((uint32_t)a[i] ^ (uint32_t)b[i]);
2802 
2803             equal |= chXor;
2804             val = (int)chXor * ((int32_t)a[i] - (int32_t)b[i]);
2805 
2806             if (val < 0)
2807             {
2808                 retval = -1;
2809             }
2810 
2811             if (val > 0)
2812             {
2813                 retval = 1;
2814             }
2815 
2816             if (val == 0)
2817             {
2818                 val = 1;
2819             }
2820 
2821             if (0 != val)
2822             {
2823                 i++;
2824                 n--;
2825             }
2826         }
2827 
2828         if (0U == equal)
2829         {
2830             retval = 0;
2831         }
2832     }
2833     return (retval);
2834 }
2835 
2836 /*!
2837  * brief Converts from integer to Montgomery format.
2838  *
2839  * This function computes R2 mod N and optionally converts A or B into Montgomery format of A or B.
2840  *
2841  * param base CAU3 peripheral base address
2842  * param N modulus
2843  * param sizeN size of N in bytes
2844  * param[in,out] A The first input in non-Montgomery format. Output Montgomery format of the first input.
2845  * param[in,out] sizeA pointer to size variable. On input it holds size of input A in bytes. On output it holds size of
2846  *                Montgomery format of A in bytes.
2847  * param[in,out] B Second input in non-Montgomery format. Output Montgomery format of the second input.
2848  * param[in,out] sizeB pointer to size variable. On input it holds size of input B in bytes. On output it holds size of
2849  *                Montgomery format of B in bytes.
2850  * param[out] R2 Output Montgomery factor R2 mod N.
2851  * param[out] sizeR2 pointer to size variable. On output it holds size of Montgomery factor R2 mod N in bytes.
2852  * param equalTime Run the function time equalized or no timing equalization.
2853  * param arithType Type of arithmetic to perform (integer or F2m)
2854  * return Operation status.
2855  */
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)2856 status_t CAU3_PKHA_NormalToMontgomery(CAU3_Type *base,
2857                                       const uint8_t *N,
2858                                       size_t sizeN,
2859                                       uint8_t *A,
2860                                       size_t *sizeA,
2861                                       uint8_t *B,
2862                                       size_t *sizeB,
2863                                       uint8_t *R2,
2864                                       size_t *sizeR2,
2865                                       cau3_pkha_timing_t equalTime,
2866                                       cau3_pkha_f2m_t arithType)
2867 {
2868     status_t status;
2869 
2870 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
2871     status = cau3_lock_semaphore(base);
2872     if (kStatus_Success != status)
2873     {
2874         cau3_release_semaphore(base);
2875         return status;
2876     }
2877 #endif
2878 
2879     /* need to convert our Integer inputs into Montgomery format */
2880     if ((N != NULL) && (sizeN != 0U) && (R2 != NULL) && (sizeR2 != NULL))
2881     {
2882         /* 1. R2 = MOD_R2(N) */
2883         status = cau3_pkha_modR2(base, N, sizeN, R2, sizeR2, arithType);
2884         if (status != kStatus_Success)
2885         {
2886 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
2887             cau3_release_semaphore(base);
2888 #endif
2889             return status;
2890         }
2891 
2892         /* 2. A(Montgomery) = MOD_MUL_IM_OM(A, R2, N) */
2893         if ((A != NULL) && (sizeA != NULL))
2894         {
2895             status = cau3_pkha_modmul(base, A, *sizeA, R2, *sizeR2, N, sizeN, A, sizeA, arithType,
2896                                       kCAU3_PKHA_MontgomeryFormat, kCAU3_PKHA_MontgomeryFormat, equalTime);
2897             if (status != kStatus_Success)
2898             {
2899 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
2900                 cau3_release_semaphore(base);
2901 #endif
2902                 return status;
2903             }
2904         }
2905 
2906         /* 2. B(Montgomery) = MOD_MUL_IM_OM(B, R2, N) */
2907         if ((B != NULL) && (sizeB != NULL))
2908         {
2909             status = cau3_pkha_modmul(base, B, *sizeB, R2, *sizeR2, N, sizeN, B, sizeB, arithType,
2910                                       kCAU3_PKHA_MontgomeryFormat, kCAU3_PKHA_MontgomeryFormat, equalTime);
2911             if (status != kStatus_Success)
2912             {
2913 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
2914                 cau3_release_semaphore(base);
2915 #endif
2916                 return status;
2917             }
2918         }
2919 
2920         cau3_clear_all(base, true);
2921     }
2922     else
2923     {
2924         status = kStatus_InvalidArgument;
2925     }
2926 
2927 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
2928     cau3_release_semaphore(base);
2929 #endif
2930     return status;
2931 }
2932 
2933 /*!
2934  * brief Converts from Montgomery format to int.
2935  *
2936  * This function converts Montgomery format of A or B into int A or B.
2937  *
2938  * param base CAU3 peripheral base address
2939  * param N modulus.
2940  * param sizeN size of N modulus in bytes.
2941  * param[in,out] A Input first number in Montgomery format. Output is non-Montgomery format.
2942  * param[in,out] sizeA pointer to size variable. On input it holds size of the input A in bytes. On output it holds
2943  * size of non-Montgomery A in bytes.
2944  * param[in,out] B Input first number in Montgomery format. Output is non-Montgomery format.
2945  * param[in,out] sizeB pointer to size variable. On input it holds size of the input B in bytes. On output it holds
2946  * size of non-Montgomery B in bytes.
2947  * param equalTime Run the function time equalized or no timing equalization.
2948  * param arithType Type of arithmetic to perform (integer or F2m)
2949  * return Operation status.
2950  */
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)2951 status_t CAU3_PKHA_MontgomeryToNormal(CAU3_Type *base,
2952                                       const uint8_t *N,
2953                                       size_t sizeN,
2954                                       uint8_t *A,
2955                                       size_t *sizeA,
2956                                       uint8_t *B,
2957                                       size_t *sizeB,
2958                                       cau3_pkha_timing_t equalTime,
2959                                       cau3_pkha_f2m_t arithType)
2960 {
2961     uint8_t one     = 1;
2962     status_t status = kStatus_InvalidArgument;
2963 
2964 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
2965     status = cau3_lock_semaphore(base);
2966     if (kStatus_Success != status)
2967     {
2968         cau3_release_semaphore(base);
2969         return status;
2970     }
2971 #endif
2972 
2973     /* A = MOD_MUL_IM_OM(A(Montgomery), 1, N) */
2974     if ((A != NULL) && (sizeA != NULL))
2975     {
2976         status = cau3_pkha_modmul(base, A, *sizeA, &one, sizeof(one), N, sizeN, A, sizeA, arithType,
2977                                   kCAU3_PKHA_MontgomeryFormat, kCAU3_PKHA_MontgomeryFormat, equalTime);
2978         if (kStatus_Success != status)
2979         {
2980 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
2981             cau3_release_semaphore(base);
2982 #endif
2983             return status;
2984         }
2985     }
2986 
2987     /* B = MOD_MUL_IM_OM(B(Montgomery), 1, N) */
2988     if ((B != NULL) && (sizeB != NULL))
2989     {
2990         status = cau3_pkha_modmul(base, B, *sizeB, &one, sizeof(one), N, sizeN, B, sizeB, arithType,
2991                                   kCAU3_PKHA_MontgomeryFormat, kCAU3_PKHA_MontgomeryFormat, equalTime);
2992         if (kStatus_Success != status)
2993         {
2994 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
2995             cau3_release_semaphore(base);
2996 #endif
2997             return status;
2998         }
2999     }
3000 
3001     cau3_clear_all(base, true);
3002 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
3003     cau3_release_semaphore(base);
3004 #endif
3005     return status;
3006 }
3007 
3008 /*!
3009  * brief Performs modular addition - (A + B) mod N.
3010  *
3011  * This function performs modular addition of (A + B) mod N, with either
3012  * integer or binary polynomial (F2m) inputs.  In the F2m form, this function is
3013  * equivalent to a bitwise XOR and it is functionally the same as subtraction.
3014  *
3015  * param base CAU3 peripheral base address
3016  * param A first addend (integer or binary polynomial)
3017  * param sizeA Size of A in bytes
3018  * param B second addend (integer or binary polynomial)
3019  * param sizeB Size of B in bytes
3020  * param N modulus.
3021  * param sizeN Size of N in bytes.
3022  * param[out] result Output array to store result of operation
3023  * param[out] resultSize Output size of operation in bytes
3024  * param arithType Type of arithmetic to perform (integer or F2m)
3025  * return Operation status.
3026  */
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)3027 status_t CAU3_PKHA_ModAdd(CAU3_Type *base,
3028                           const uint8_t *A,
3029                           size_t sizeA,
3030                           const uint8_t *B,
3031                           size_t sizeB,
3032                           const uint8_t *N,
3033                           size_t sizeN,
3034                           uint8_t *result,
3035                           size_t *resultSize,
3036                           cau3_pkha_f2m_t arithType)
3037 {
3038     cau3_pkha_mode_params_t params;
3039     status_t status;
3040 
3041     if (arithType == kCAU3_PKHA_IntegerArith)
3042     {
3043         if (CAU3_PKHA_CompareBigNum(A, sizeA, N, sizeN) >= 0)
3044         {
3045             return (kStatus_InvalidArgument);
3046         }
3047 
3048         if (CAU3_PKHA_CompareBigNum(B, sizeB, N, sizeN) >= 0)
3049         {
3050             return (kStatus_InvalidArgument);
3051         }
3052     }
3053 
3054 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
3055     status = cau3_lock_semaphore(base);
3056     if (kStatus_Success != status)
3057     {
3058         cau3_release_semaphore(base);
3059         return status;
3060     }
3061 #endif
3062 
3063     cau3_pkha_default_parms(&params);
3064     params.func      = kCAU3_PKHA_ArithModAdd;
3065     params.arithType = arithType;
3066 
3067     cau3_pkha_init_data(base, A, sizeA, B, sizeB, N, sizeN, NULL, 0);
3068     status = cau3_pkha_init_mode(base, &params);
3069 
3070     if (status == kStatus_Success)
3071     {
3072         /* Read the result and size from register B0. */
3073         if ((resultSize != NULL) && (result != NULL))
3074         {
3075             *resultSize = base->PKBSZ;
3076             /* Read the data from the result register into place. */
3077             cau3_pkha_read_reg(base, kCAU3_PKHA_RegB, 0, result, *resultSize);
3078         }
3079     }
3080 
3081     cau3_clear_all(base, true);
3082 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
3083     cau3_release_semaphore(base);
3084 #endif
3085     return status;
3086 }
3087 
3088 /*!
3089  * brief Performs modular subtraction - (A - B) mod N.
3090  *
3091  * This function performs modular subtraction of (A - B) mod N with
3092  * integer inputs.
3093  *
3094  * param base CAU3 peripheral base address
3095  * param A first addend (integer or binary polynomial)
3096  * param sizeA Size of A in bytes
3097  * param B second addend (integer or binary polynomial)
3098  * param sizeB Size of B in bytes
3099  * param N modulus
3100  * param sizeN Size of N in bytes
3101  * param[out] result Output array to store result of operation
3102  * param[out] resultSize Output size of operation in bytes
3103  * return Operation status.
3104  */
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)3105 status_t CAU3_PKHA_ModSub1(CAU3_Type *base,
3106                            const uint8_t *A,
3107                            size_t sizeA,
3108                            const uint8_t *B,
3109                            size_t sizeB,
3110                            const uint8_t *N,
3111                            size_t sizeN,
3112                            uint8_t *result,
3113                            size_t *resultSize)
3114 {
3115     cau3_pkha_mode_params_t params;
3116     status_t status;
3117 
3118     if (CAU3_PKHA_CompareBigNum(A, sizeA, N, sizeN) >= 0)
3119     {
3120         return (kStatus_InvalidArgument);
3121     }
3122 
3123     if (CAU3_PKHA_CompareBigNum(B, sizeB, N, sizeN) >= 0)
3124     {
3125         return (kStatus_InvalidArgument);
3126     }
3127 
3128 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
3129     status = cau3_lock_semaphore(base);
3130     if (kStatus_Success != status)
3131     {
3132         cau3_release_semaphore(base);
3133         return status;
3134     }
3135 #endif
3136 
3137     cau3_pkha_default_parms(&params);
3138     params.func = kCAU3_PKHA_ArithModSub1;
3139     cau3_pkha_init_data(base, A, sizeA, B, sizeB, N, sizeN, NULL, 0);
3140 
3141     status = cau3_pkha_init_mode(base, &params);
3142 
3143     if (status == kStatus_Success)
3144     {
3145         /* Read the result and size from register B0. */
3146         if ((resultSize != NULL) && (result != NULL))
3147         {
3148             *resultSize = base->PKBSZ;
3149             /* Read the data from the result register into place. */
3150             cau3_pkha_read_reg(base, kCAU3_PKHA_RegB, 0, result, *resultSize);
3151         }
3152     }
3153 
3154     cau3_clear_all(base, true);
3155 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
3156     cau3_release_semaphore(base);
3157 #endif
3158     return status;
3159 }
3160 
3161 /*!
3162  * brief Performs modular subtraction - (B - A) mod N.
3163  *
3164  * This function performs modular subtraction of (B - A) mod N,
3165  * with integer inputs.
3166  *
3167  * param base CAU3 peripheral base address
3168  * param A first addend (integer or binary polynomial)
3169  * param sizeA Size of A in bytes
3170  * param B second addend (integer or binary polynomial)
3171  * param sizeB Size of B in bytes
3172  * param N modulus
3173  * param sizeN Size of N in bytes
3174  * param[out] result Output array to store result of operation
3175  * param[out] resultSize Output size of operation in bytes
3176  * return Operation status.
3177  */
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)3178 status_t CAU3_PKHA_ModSub2(CAU3_Type *base,
3179                            const uint8_t *A,
3180                            size_t sizeA,
3181                            const uint8_t *B,
3182                            size_t sizeB,
3183                            const uint8_t *N,
3184                            size_t sizeN,
3185                            uint8_t *result,
3186                            size_t *resultSize)
3187 {
3188     cau3_pkha_mode_params_t params;
3189     status_t status;
3190 
3191 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
3192     status = cau3_lock_semaphore(base);
3193     if (kStatus_Success != status)
3194     {
3195         cau3_release_semaphore(base);
3196         return status;
3197     }
3198 #endif
3199 
3200     cau3_pkha_default_parms(&params);
3201     params.func = kCAU3_PKHA_ArithModSub2;
3202 
3203     cau3_pkha_init_data(base, A, sizeA, B, sizeB, N, sizeN, NULL, 0);
3204     status = cau3_pkha_init_mode(base, &params);
3205 
3206     if (status == kStatus_Success)
3207     {
3208         /* Read the result and size from register B0. */
3209         if ((resultSize != NULL) && (result != NULL))
3210         {
3211             *resultSize = base->PKBSZ;
3212             /* Read the data from the result register into place. */
3213             cau3_pkha_read_reg(base, kCAU3_PKHA_RegB, 0, result, *resultSize);
3214         }
3215     }
3216 
3217     cau3_clear_all(base, true);
3218 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
3219     cau3_release_semaphore(base);
3220 #endif
3221     return status;
3222 }
3223 
3224 /*!
3225  * brief Performs modular multiplication - (A x B) mod N.
3226  *
3227  * This function performs modular multiplication with either integer or
3228  * binary polynomial (F2m) inputs.  It can optionally specify whether inputs
3229  * and/or outputs will be in Montgomery form or not.
3230  *
3231  * param base CAU3 peripheral base address
3232  * param A first addend (integer or binary polynomial)
3233  * param sizeA Size of A in bytes
3234  * param B second addend (integer or binary polynomial)
3235  * param sizeB Size of B in bytes
3236  * param N modulus.
3237  * param sizeN Size of N in bytes
3238  * param[out] result Output array to store result of operation
3239  * param[out] resultSize Output size of operation in bytes
3240  * param arithType Type of arithmetic to perform (integer or F2m)
3241  * param montIn Format of inputs
3242  * param montOut Format of output
3243  * param equalTime Run the function time equalized or no timing equalization. This argument is ignored for F2m modular
3244  * multiplication.
3245  * return Operation status.
3246  */
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)3247 status_t CAU3_PKHA_ModMul(CAU3_Type *base,
3248                           const uint8_t *A,
3249                           size_t sizeA,
3250                           const uint8_t *B,
3251                           size_t sizeB,
3252                           const uint8_t *N,
3253                           size_t sizeN,
3254                           uint8_t *result,
3255                           size_t *resultSize,
3256                           cau3_pkha_f2m_t arithType,
3257                           cau3_pkha_montgomery_form_t montIn,
3258                           cau3_pkha_montgomery_form_t montOut,
3259                           cau3_pkha_timing_t equalTime)
3260 {
3261     status_t status;
3262 
3263 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
3264     status = cau3_lock_semaphore(base);
3265     if (kStatus_Success != status)
3266     {
3267         cau3_release_semaphore(base);
3268         return status;
3269     }
3270 #endif
3271 
3272     status =
3273         cau3_pkha_modmul(base, A, sizeA, B, sizeB, N, sizeN, result, resultSize, arithType, montIn, montOut, equalTime);
3274 
3275     cau3_clear_all(base, true);
3276 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
3277     cau3_release_semaphore(base);
3278 #endif
3279     return status;
3280 }
3281 
3282 /*!
3283  * brief Performs modular exponentiation - (A^E) mod N.
3284  *
3285  * This function performs modular exponentiation with either integer or
3286  * binary polynomial (F2m) inputs.
3287  *
3288  * param base CAU3 peripheral base address
3289  * param A first addend (integer or binary polynomial)
3290  * param sizeA Size of A in bytes
3291  * param N modulus
3292  * param sizeN Size of N in bytes
3293  * param E exponent
3294  * param sizeE Size of E in bytes
3295  * param[out] result Output array to store result of operation
3296  * param[out] resultSize Output size of operation in bytes
3297  * param montIn Format of A input (normal or Montgomery)
3298  * param arithType Type of arithmetic to perform (integer or F2m)
3299  * param equalTime Run the function time equalized or no timing equalization.
3300  * return Operation status.
3301  */
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)3302 status_t CAU3_PKHA_ModExp(CAU3_Type *base,
3303                           const uint8_t *A,
3304                           size_t sizeA,
3305                           const uint8_t *N,
3306                           size_t sizeN,
3307                           const uint8_t *E,
3308                           size_t sizeE,
3309                           uint8_t *result,
3310                           size_t *resultSize,
3311                           cau3_pkha_f2m_t arithType,
3312                           cau3_pkha_montgomery_form_t montIn,
3313                           cau3_pkha_timing_t equalTime)
3314 {
3315     cau3_pkha_mode_params_t params;
3316     status_t status;
3317 
3318     if (arithType == kCAU3_PKHA_IntegerArith)
3319     {
3320         if (CAU3_PKHA_CompareBigNum(A, sizeA, N, sizeN) >= 0)
3321         {
3322             return (kStatus_InvalidArgument);
3323         }
3324     }
3325 
3326 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
3327     status = cau3_lock_semaphore(base);
3328     if (kStatus_Success != status)
3329     {
3330         cau3_release_semaphore(base);
3331         return status;
3332     }
3333 #endif
3334 
3335     cau3_pkha_default_parms(&params);
3336     params.func       = kCAU3_PKHA_ArithModExp;
3337     params.arithType  = arithType;
3338     params.montFormIn = montIn;
3339     params.equalTime  = equalTime;
3340 
3341     cau3_pkha_init_data(base, A, sizeA, NULL, 0, N, sizeN, E, sizeE);
3342     status = cau3_pkha_init_mode(base, &params);
3343 
3344     if (status == kStatus_Success)
3345     {
3346         /* Read the result and size from register B0. */
3347         if ((resultSize != NULL) && (result != NULL))
3348         {
3349             *resultSize = base->PKBSZ;
3350             /* Read the data from the result register into place. */
3351             cau3_pkha_read_reg(base, kCAU3_PKHA_RegB, 0, result, *resultSize);
3352         }
3353     }
3354 
3355     cau3_clear_all(base, true);
3356 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
3357     cau3_release_semaphore(base);
3358 #endif
3359     return status;
3360 }
3361 
3362 /*!
3363  * brief Performs Modular Square Root.
3364  *
3365  * This function performs modular square root with integer inputs.
3366  * The modular square root function computes output result B, such that ( B x B ) mod N = input A.
3367  * If no such B result exists, the result will be set to 0 and the PKHA "prime" flag
3368  * will be set. Input values A and B are limited to a maximum size of 128 bytes. Note that
3369  * two such square root values may exist. This algorithm will find either one of them, if any
3370  * exist. The second possible square root (B') can be found by calculating B' = N - B.
3371  *
3372  * param base CAU3 peripheral base address
3373  * param A input value, for which a square root is to be calculated
3374  * param sizeA Size of A in bytes
3375  * param N modulus
3376  * param sizeN Size of N in bytes
3377  * param[out] result Output array to store result of operation
3378  * param[out] resultSize Output size of operation in bytes
3379  * return Operation status.
3380  */
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)3381 status_t CAU3_PKHA_ModSqrt(CAU3_Type *base,
3382                            const uint8_t *A,
3383                            size_t sizeA,
3384                            const uint8_t *N,
3385                            size_t sizeN,
3386                            uint8_t *result,
3387                            size_t *resultSize)
3388 {
3389     cau3_pkha_mode_params_t params;
3390     status_t status;
3391 
3392     /* A < N */
3393     if (CAU3_PKHA_CompareBigNum(A, sizeA, N, sizeN) >= 0)
3394     {
3395         return (kStatus_InvalidArgument);
3396     }
3397 
3398 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
3399     status = cau3_lock_semaphore(base);
3400     if (kStatus_Success != status)
3401     {
3402         cau3_release_semaphore(base);
3403         return status;
3404     }
3405 #endif
3406 
3407     cau3_pkha_default_parms(&params);
3408     params.func = kCAU3_PKHA_ArithModSqrt;
3409 
3410     cau3_pkha_init_data(base, A, sizeA, NULL, 0, N, sizeN, NULL, 0);
3411     status = cau3_pkha_init_mode(base, &params);
3412 
3413     if (status == kStatus_Success)
3414     {
3415         /* Read the result and size from register B0. */
3416         if ((resultSize != NULL) && (result != NULL))
3417         {
3418             *resultSize = base->PKBSZ;
3419             /* Read the data from the result register into place. */
3420             cau3_pkha_read_reg(base, kCAU3_PKHA_RegB, 0, result, *resultSize);
3421         }
3422     }
3423 
3424     cau3_clear_all(base, true);
3425 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
3426     cau3_release_semaphore(base);
3427 #endif
3428     return status;
3429 }
3430 
3431 /*!
3432  * brief Performs modular reduction - (A) mod N.
3433  *
3434  * This function performs modular reduction with either integer or
3435  * binary polynomial (F2m) inputs.
3436  *
3437  * param base CAU3 peripheral base address
3438  * param A first addend (integer or binary polynomial)
3439  * param sizeA Size of A in bytes
3440  * param N modulus
3441  * param sizeN Size of N in bytes
3442  * param[out] result Output array to store result of operation
3443  * param[out] resultSize Output size of operation in bytes
3444  * param arithType Type of arithmetic to perform (integer or F2m)
3445  * return Operation status.
3446  */
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)3447 status_t CAU3_PKHA_ModRed(CAU3_Type *base,
3448                           const uint8_t *A,
3449                           size_t sizeA,
3450                           const uint8_t *N,
3451                           size_t sizeN,
3452                           uint8_t *result,
3453                           size_t *resultSize,
3454                           cau3_pkha_f2m_t arithType)
3455 {
3456     cau3_pkha_mode_params_t params;
3457     status_t status;
3458 
3459 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
3460     status = cau3_lock_semaphore(base);
3461     if (kStatus_Success != status)
3462     {
3463         cau3_release_semaphore(base);
3464         return status;
3465     }
3466 #endif
3467 
3468     cau3_pkha_default_parms(&params);
3469     params.func      = kCAU3_PKHA_ArithModRed;
3470     params.arithType = arithType;
3471 
3472     cau3_pkha_init_data(base, A, sizeA, NULL, 0, N, sizeN, NULL, 0);
3473     status = cau3_pkha_init_mode(base, &params);
3474 
3475     if (status == kStatus_Success)
3476     {
3477         /* Read the result and size from register B0. */
3478         if ((resultSize != NULL) && (result != NULL))
3479         {
3480             *resultSize = base->PKBSZ;
3481             /* Read the data from the result register into place. */
3482             cau3_pkha_read_reg(base, kCAU3_PKHA_RegB, 0, result, *resultSize);
3483         }
3484     }
3485 
3486     cau3_clear_all(base, true);
3487 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
3488     cau3_release_semaphore(base);
3489 #endif
3490     return status;
3491 }
3492 
3493 /*!
3494  * brief Performs modular inversion - (A^-1) mod N.
3495  *
3496  * This function performs modular inversion with either integer or
3497  * binary polynomial (F2m) inputs.
3498  *
3499  * param base CAU3 peripheral base address
3500  * param A first addend (integer or binary polynomial)
3501  * param sizeA Size of A in bytes
3502  * param N modulus
3503  * param sizeN Size of N in bytes
3504  * param[out] result Output array to store result of operation
3505  * param[out] resultSize Output size of operation in bytes
3506  * param arithType Type of arithmetic to perform (integer or F2m)
3507  * return Operation status.
3508  */
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)3509 status_t CAU3_PKHA_ModInv(CAU3_Type *base,
3510                           const uint8_t *A,
3511                           size_t sizeA,
3512                           const uint8_t *N,
3513                           size_t sizeN,
3514                           uint8_t *result,
3515                           size_t *resultSize,
3516                           cau3_pkha_f2m_t arithType)
3517 {
3518     cau3_pkha_mode_params_t params;
3519     status_t status;
3520 
3521     /* A must be less than N -> CAU3_PKHA_CompareBigNum() must return -1 */
3522     if (arithType == kCAU3_PKHA_IntegerArith)
3523     {
3524         if (CAU3_PKHA_CompareBigNum(A, sizeA, N, sizeN) >= 0)
3525         {
3526             return (kStatus_InvalidArgument);
3527         }
3528     }
3529 
3530 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
3531     status = cau3_lock_semaphore(base);
3532     if (kStatus_Success != status)
3533     {
3534         cau3_release_semaphore(base);
3535         return status;
3536     }
3537 #endif
3538 
3539     cau3_pkha_default_parms(&params);
3540     params.func      = kCAU3_PKHA_ArithModInv;
3541     params.arithType = arithType;
3542 
3543     cau3_pkha_init_data(base, A, sizeA, NULL, 0, N, sizeN, NULL, 0);
3544     status = cau3_pkha_init_mode(base, &params);
3545 
3546     if (status == kStatus_Success)
3547     {
3548         /* Read the result and size from register B0. */
3549         if ((resultSize != NULL) && (result != NULL))
3550         {
3551             *resultSize = base->PKBSZ;
3552             /* Read the data from the result register into place. */
3553             cau3_pkha_read_reg(base, kCAU3_PKHA_RegB, 0, result, *resultSize);
3554         }
3555     }
3556 
3557     cau3_clear_all(base, true);
3558 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
3559     cau3_release_semaphore(base);
3560 #endif
3561     return status;
3562 }
3563 
3564 /*!
3565  * brief Computes integer Montgomery factor R^2 mod N.
3566  *
3567  * This function computes a constant to assist in converting operands
3568  * into the Montgomery residue system representation.
3569  *
3570  * param base CAU3 peripheral base address
3571  * param N modulus
3572  * param sizeN Size of N in bytes
3573  * param[out] result Output array to store result of operation
3574  * param[out] resultSize Output size of operation in bytes
3575  * param arithType Type of arithmetic to perform (integer or F2m)
3576  * return Operation status.
3577  */
CAU3_PKHA_ModR2(CAU3_Type * base,const uint8_t * N,size_t sizeN,uint8_t * result,size_t * resultSize,cau3_pkha_f2m_t arithType)3578 status_t CAU3_PKHA_ModR2(
3579     CAU3_Type *base, const uint8_t *N, size_t sizeN, uint8_t *result, size_t *resultSize, cau3_pkha_f2m_t arithType)
3580 {
3581     status_t status;
3582 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
3583     status = cau3_lock_semaphore(base);
3584     if (kStatus_Success != status)
3585     {
3586         cau3_release_semaphore(base);
3587         return status;
3588     }
3589 #endif
3590     status = cau3_pkha_modR2(base, N, sizeN, result, resultSize, arithType);
3591     cau3_clear_all(base, true);
3592 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
3593     cau3_release_semaphore(base);
3594 #endif
3595     return status;
3596 }
3597 
3598 /*!
3599  * brief Performs Integer RERP mod P.
3600  *
3601  * This function is used to compute a constant to assist in converting operands into the
3602  * Montgomery residue system representation specifically for Chinese Remainder Theorem
3603  * while performing RSA with a CRT implementation where a modulus E=P x Q, and P and
3604  * Q are prime numbers. Although labeled RERP mod P, this routine (function) can also
3605  * compute RERQ mod Q.
3606  *
3607  * param base CAU3 peripheral base address
3608  * param P modulus P or Q of CRT, an odd integer
3609  * param sizeP Size of P in bytes
3610  * param sizeE Number of bytes of E = P x Q (this size must be given, though content of E itself is not used).
3611  * param[out] result Output array to store result of operation
3612  * param[out] resultSize Output size of operation in bytes
3613  * return Operation status.
3614  */
CAU3_PKHA_ModRR(CAU3_Type * base,const uint8_t * P,size_t sizeP,size_t sizeE,uint8_t * result,size_t * resultSize)3615 status_t CAU3_PKHA_ModRR(
3616     CAU3_Type *base, const uint8_t *P, size_t sizeP, size_t sizeE, uint8_t *result, size_t *resultSize)
3617 {
3618     status_t status;
3619     cau3_pkha_mode_params_t params;
3620 
3621 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
3622     status = cau3_lock_semaphore(base);
3623     if (kStatus_Success != status)
3624     {
3625         cau3_release_semaphore(base);
3626         return status;
3627     }
3628 #endif
3629 
3630     cau3_pkha_default_parms(&params);
3631     params.func = kCAU3_PKHA_ArithModRR;
3632 
3633     cau3_pkha_init_data(base, NULL, 0, NULL, 0, P, sizeP, NULL, sizeE);
3634     status = cau3_pkha_init_mode(base, &params);
3635 
3636     if (status == kStatus_Success)
3637     {
3638         /* Read the result and size from register B0. */
3639         if ((resultSize != NULL) && (result != NULL))
3640         {
3641             *resultSize = base->PKBSZ;
3642             /* Read the data from the result register into place. */
3643             cau3_pkha_read_reg(base, kCAU3_PKHA_RegB, 0, result, *resultSize);
3644         }
3645     }
3646 
3647 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
3648     cau3_release_semaphore(base);
3649 #endif
3650     return status;
3651 }
3652 
3653 /*!
3654  * brief Calculates the greatest common divisor - GCD (A, N).
3655  *
3656  * This function calculates the greatest common divisor of two inputs with
3657  * either integer or binary polynomial (F2m) inputs.
3658  *
3659  * param base CAU3 peripheral base address
3660  * param A first value (must be smaller than or equal to N)
3661  * param sizeA Size of A in bytes
3662  * param N second value (must be non-zero)
3663  * param sizeN Size of N in bytes
3664  * param[out] result Output array to store result of operation
3665  * param[out] resultSize Output size of operation in bytes
3666  * param arithType Type of arithmetic to perform (integer or F2m)
3667  * return Operation status.
3668  */
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)3669 status_t CAU3_PKHA_ModGcd(CAU3_Type *base,
3670                           const uint8_t *A,
3671                           size_t sizeA,
3672                           const uint8_t *N,
3673                           size_t sizeN,
3674                           uint8_t *result,
3675                           size_t *resultSize,
3676                           cau3_pkha_f2m_t arithType)
3677 {
3678     cau3_pkha_mode_params_t params;
3679     status_t status;
3680 
3681 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
3682     status = cau3_lock_semaphore(base);
3683     if (kStatus_Success != status)
3684     {
3685         cau3_release_semaphore(base);
3686         return status;
3687     }
3688 #endif
3689 
3690     cau3_pkha_default_parms(&params);
3691     params.func      = kCAU3_PKHA_ArithGcd;
3692     params.arithType = arithType;
3693 
3694     cau3_pkha_init_data(base, A, sizeA, NULL, 0, N, sizeN, NULL, 0);
3695     status = cau3_pkha_init_mode(base, &params);
3696 
3697     if (status == kStatus_Success)
3698     {
3699         /* Read the result and size from register B0. */
3700         if ((resultSize != NULL) && (result != NULL))
3701         {
3702             *resultSize = base->PKBSZ;
3703             /* Read the data from the result register into place. */
3704             cau3_pkha_read_reg(base, kCAU3_PKHA_RegB, 0, result, *resultSize);
3705         }
3706     }
3707 
3708     cau3_clear_all(base, true);
3709 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
3710     cau3_release_semaphore(base);
3711 #endif
3712     return status;
3713 }
3714 
3715 /*!
3716  * brief Executes Miller-Rabin primality test.
3717  *
3718  * This function calculates whether or not a candidate prime number is likely
3719  * to be a prime.
3720  *
3721  * param base CAU3 peripheral base address
3722  * param A initial random seed
3723  * param sizeA Size of A in bytes
3724  * param B number of trial runs
3725  * param sizeB Size of B in bytes
3726  * param N candidate prime integer
3727  * param sizeN Size of N in bytes
3728  * param[out] res True if the value is likely prime or false otherwise
3729  * return Operation status.
3730  */
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)3731 status_t CAU3_PKHA_PrimalityTest(CAU3_Type *base,
3732                                  const uint8_t *A,
3733                                  size_t sizeA,
3734                                  const uint8_t *B,
3735                                  size_t sizeB,
3736                                  const uint8_t *N,
3737                                  size_t sizeN,
3738                                  bool *res)
3739 {
3740     uint8_t result;
3741     cau3_pkha_mode_params_t params;
3742     status_t status;
3743 
3744 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
3745     status = cau3_lock_semaphore(base);
3746     if (kStatus_Success != status)
3747     {
3748         cau3_release_semaphore(base);
3749         return status;
3750     }
3751 #endif
3752 
3753     cau3_pkha_default_parms(&params);
3754     params.func = kCAU3_PKHA_ArithPrimalityTest;
3755     cau3_pkha_init_data(base, A, sizeA, B, sizeB, N, sizeN, NULL, 0);
3756     status = cau3_pkha_init_mode(base, &params);
3757 
3758     if (status == kStatus_Success)
3759     {
3760         /* Read the data from the result register into place. */
3761         cau3_pkha_read_reg(base, kCAU3_PKHA_RegB, 0, &result, 1);
3762 
3763         *res = (bool)result;
3764     }
3765 
3766     cau3_clear_all(base, true);
3767 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
3768     cau3_release_semaphore(base);
3769 #endif
3770     return status;
3771 }
3772 
3773 /*!
3774  * brief Adds elliptic curve points - A + B.
3775  *
3776  * This function performs ECC point addition over a prime field (Fp) or binary field (F2m) using
3777  * affine coordinates.
3778  *
3779  * param base CAU3 peripheral base address
3780  * param A Left-hand point
3781  * param B Right-hand point
3782  * param N Prime modulus of the field
3783  * param R2modN NULL (the function computes R2modN internally) or pointer to pre-computed R2modN (obtained from
3784  *               CAU3_PKHA_ModR2() function).
3785  * param aCurveParam A parameter from curve equation
3786  * param bCurveParam B parameter from curve equation (constant)
3787  * param size Size in bytes of curve points and parameters
3788  * param arithType Type of arithmetic to perform (integer or F2m)
3789  * param[out] result Result point
3790  * return Operation status.
3791  */
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)3792 status_t CAU3_PKHA_ECC_PointAdd(CAU3_Type *base,
3793                                 const cau3_pkha_ecc_point_t *A,
3794                                 const cau3_pkha_ecc_point_t *B,
3795                                 const uint8_t *N,
3796                                 const uint8_t *R2modN,
3797                                 const uint8_t *aCurveParam,
3798                                 const uint8_t *bCurveParam,
3799                                 size_t size,
3800                                 cau3_pkha_f2m_t arithType,
3801                                 cau3_pkha_ecc_point_t *result)
3802 {
3803     cau3_pkha_mode_params_t params;
3804     uint32_t clearMask;
3805     status_t status;
3806 
3807 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
3808     status = cau3_lock_semaphore(base);
3809     if (kStatus_Success != status)
3810     {
3811         cau3_release_semaphore(base);
3812         return status;
3813     }
3814 #endif
3815 
3816     cau3_pkha_default_parms(&params);
3817     params.func      = kCAU3_PKHA_ArithEccAdd;
3818     params.arithType = arithType;
3819     params.r2modn    = (R2modN != NULL) ? kCAU3_PKHA_InputR2 : kCAU3_PKHA_CalcR2;
3820 
3821     clearMask = (uint32_t)kCAU3_ClearMode;
3822 
3823     /* Clear internal register states. */
3824     clearMask |= (uint32_t)kCAU3_ClearPkhaSizeA;
3825     clearMask |= (uint32_t)kCAU3_ClearPkhaSizeB;
3826     clearMask |= (uint32_t)kCAU3_ClearPkhaSizeN;
3827     clearMask |= (uint32_t)kCAU3_ClearPkhaSizeE;
3828 
3829     base->CW  = clearMask;
3830     base->STA = (uint32_t)kCAU3_StatusDoneIsr;
3831     (void)cau3_pkha_clear_regabne(base, true, true, true, false);
3832 
3833     /* sizeN should be less than 64 bytes. */
3834     base->PKNSZ = size;
3835     (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegN, 0, N, size);
3836 
3837     base->PKASZ = size;
3838     (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegA, 0, A->X, size);
3839     (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegA, 1, A->Y, size);
3840     (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegA, 3, aCurveParam, size);
3841 
3842     base->PKBSZ = size;
3843     (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegB, 0, bCurveParam, size);
3844     (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegB, 1, B->X, size);
3845     (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegB, 2, B->Y, size);
3846     if (R2modN != NULL)
3847     {
3848         (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegB, 3, R2modN, size);
3849     }
3850 
3851     status = cau3_pkha_init_mode(base, &params);
3852 
3853     if (status == kStatus_Success)
3854     {
3855         /* Read the data from the result register into place. */
3856         cau3_pkha_read_reg(base, kCAU3_PKHA_RegB, 1, result->X, size);
3857         cau3_pkha_read_reg(base, kCAU3_PKHA_RegB, 2, result->Y, size);
3858     }
3859 
3860     cau3_clear_all(base, true);
3861 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
3862     cau3_release_semaphore(base);
3863 #endif
3864     return status;
3865 }
3866 
3867 /*!
3868  * brief Doubles elliptic curve points - B + B.
3869  *
3870  * This function performs ECC point doubling over a prime field (Fp) or binary field (F2m) using
3871  * affine coordinates.
3872  *
3873  * param base CAU3 peripheral base address
3874  * param B Point to double
3875  * param N Prime modulus of the field
3876  * param aCurveParam A parameter from curve equation
3877  * param bCurveParam B parameter from curve equation (constant)
3878  * param size Size in bytes of curve points and parameters
3879  * param arithType Type of arithmetic to perform (integer or F2m)
3880  * param[out] result Result point
3881  * return Operation status.
3882  */
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)3883 status_t CAU3_PKHA_ECC_PointDouble(CAU3_Type *base,
3884                                    const cau3_pkha_ecc_point_t *B,
3885                                    const uint8_t *N,
3886                                    const uint8_t *aCurveParam,
3887                                    const uint8_t *bCurveParam,
3888                                    size_t size,
3889                                    cau3_pkha_f2m_t arithType,
3890                                    cau3_pkha_ecc_point_t *result)
3891 {
3892     cau3_pkha_mode_params_t params;
3893     uint32_t clearMask;
3894     status_t status;
3895 
3896 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
3897     status = cau3_lock_semaphore(base);
3898     if (kStatus_Success != status)
3899     {
3900         cau3_release_semaphore(base);
3901         return status;
3902     }
3903 #endif
3904 
3905     cau3_pkha_default_parms(&params);
3906     params.func      = kCAU3_PKHA_ArithEccDouble;
3907     params.arithType = arithType;
3908 
3909     clearMask = (uint32_t)kCAU3_ClearMode;
3910 
3911     /* Clear internal register states. */
3912     clearMask |= (uint32_t)kCAU3_ClearPkhaSizeA;
3913     clearMask |= (uint32_t)kCAU3_ClearPkhaSizeB;
3914     clearMask |= (uint32_t)kCAU3_ClearPkhaSizeN;
3915     clearMask |= (uint32_t)kCAU3_ClearPkhaSizeE;
3916 
3917     base->CW  = clearMask;
3918     base->STA = (uint32_t)kCAU3_StatusDoneIsr;
3919     (void)cau3_pkha_clear_regabne(base, true, true, true, false);
3920 
3921     /* sizeN should be less than 64 bytes. */
3922     base->PKNSZ = size;
3923     (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegN, 0, N, size);
3924 
3925     base->PKASZ = size;
3926     (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegA, 3, aCurveParam, size);
3927 
3928     base->PKBSZ = size;
3929     (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegB, 0, bCurveParam, size);
3930     (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegB, 1, B->X, size);
3931     (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegB, 2, B->Y, size);
3932     status = cau3_pkha_init_mode(base, &params);
3933 
3934     if (status == kStatus_Success)
3935     {
3936         /* Read the data from the result register into place. */
3937         cau3_pkha_read_reg(base, kCAU3_PKHA_RegB, 1, result->X, size);
3938         cau3_pkha_read_reg(base, kCAU3_PKHA_RegB, 2, result->Y, size);
3939     }
3940 
3941     cau3_clear_all(base, true);
3942 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
3943     cau3_release_semaphore(base);
3944 #endif
3945     return status;
3946 }
3947 
3948 /*!
3949  * brief Multiplies an elliptic curve point by a scalar - E x (A0, A1).
3950  *
3951  * This function performs ECC point multiplication to multiply an ECC point by
3952  * a scalar integer multiplier over a prime field (Fp) or a binary field (F2m).
3953  *
3954  * param base CAU3 peripheral base address
3955  * param A Point as multiplicand
3956  * param E Scalar multiple
3957  * param sizeE The size of E, in bytes
3958  * param N Modulus, a prime number for the Fp field or Irreducible polynomial for F2m field.
3959  * param R2modN NULL (the function computes R2modN internally) or pointer to pre-computed R2modN (obtained from
3960  *        CAU3_PKHA_ModR2() function).
3961  * param aCurveParam A parameter from curve equation
3962  * param bCurveParam B parameter from curve equation (C parameter for operation over F2m).
3963  * param size Size in bytes of curve points and parameters
3964  * param equalTime Run the function time equalized or no timing equalization.
3965  * param arithType Type of arithmetic to perform (integer or F2m)
3966  * param[out] result Result point
3967  * return Operation status.
3968  */
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)3969 status_t CAU3_PKHA_ECC_PointMul(CAU3_Type *base,
3970                                 const cau3_pkha_ecc_point_t *A,
3971                                 const uint8_t *E,
3972                                 size_t sizeE,
3973                                 const uint8_t *N,
3974                                 const uint8_t *R2modN,
3975                                 const uint8_t *aCurveParam,
3976                                 const uint8_t *bCurveParam,
3977                                 size_t size,
3978                                 cau3_pkha_timing_t equalTime,
3979                                 cau3_pkha_f2m_t arithType,
3980                                 cau3_pkha_ecc_point_t *result)
3981 {
3982     cau3_pkha_mode_params_t params;
3983     uint32_t clearMask;
3984     status_t status;
3985 
3986 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
3987     status = cau3_lock_semaphore(base);
3988     if (kStatus_Success != status)
3989     {
3990         cau3_release_semaphore(base);
3991         return status;
3992     }
3993 #endif
3994 
3995     cau3_pkha_default_parms(&params);
3996     params.func      = kCAU3_PKHA_ArithEccMul;
3997     params.equalTime = equalTime;
3998     params.arithType = arithType;
3999     params.r2modn    = (R2modN != NULL) ? kCAU3_PKHA_InputR2 : kCAU3_PKHA_CalcR2;
4000 
4001     clearMask = (uint32_t)kCAU3_ClearMode;
4002 
4003     /* Clear internal register states. */
4004     clearMask |= (uint32_t)kCAU3_ClearPkhaSizeA;
4005     clearMask |= (uint32_t)kCAU3_ClearPkhaSizeB;
4006     clearMask |= (uint32_t)kCAU3_ClearPkhaSizeN;
4007     clearMask |= (uint32_t)kCAU3_ClearPkhaSizeE;
4008 
4009     base->CW  = clearMask;
4010     base->STA = (uint32_t)kCAU3_StatusDoneIsr;
4011     (void)cau3_pkha_clear_regabne(base, true, true, true, true);
4012 
4013     /* sizeN should be less than 64 bytes. */
4014     base->PKNSZ = size;
4015     (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegN, 0, N, size);
4016 
4017     base->PKESZ = sizeE;
4018     (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegE, 0, E, sizeE);
4019 
4020     base->PKASZ = size;
4021     (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegA, 0, A->X, size);
4022     (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegA, 1, A->Y, size);
4023     (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegA, 3, aCurveParam, size);
4024 
4025     base->PKBSZ = size;
4026     (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegB, 0, bCurveParam, size);
4027     if (R2modN != NULL)
4028     {
4029         (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegB, 1, R2modN, size);
4030     }
4031 
4032     status = cau3_pkha_init_mode(base, &params);
4033 
4034     if (status == kStatus_Success)
4035     {
4036         /* Read the data from the result register into place. */
4037         cau3_pkha_read_reg(base, kCAU3_PKHA_RegB, 1, result->X, size);
4038         cau3_pkha_read_reg(base, kCAU3_PKHA_RegB, 2, result->Y, size);
4039     }
4040 
4041     cau3_clear_all(base, true);
4042 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
4043     cau3_release_semaphore(base);
4044 #endif
4045     return status;
4046 }
4047 
4048 /*!
4049  * brief Computes scalar multiplication of a point on an elliptic curve in Montgomery form.
4050  *
4051  * This function computes the scalar multiplication of a point on an elliptic curve in
4052  * Montgomery form. The input and output are just the x coordinates of the points.
4053  * The points on a curve are defined by the equation E: B*y^2 = x^3 + A*x^2 + x mod p
4054  * This function computes a point multiplication on a Montgomery curve, using
4055  * Montgomery values, by means of a Montgomery ladder. At the end of the ladder, P2 = P3 + P1,
4056  * where P1 is the input and P3 is the result.
4057  *
4058  * param base CAU3 peripheral base address
4059  * param E Scalar multiplier, any integer
4060  * param sizeE The size of E, in bytes
4061  * param inputCoordinate Point as multiplicand, an input point's affine x coordinate
4062  * param A24 elliptic curve a24 parameter, that is, (A+2)/4
4063  * param N Modulus, a prime number.
4064  * param R2modN NULL (the function computes R2modN internally) or pointer to pre-computed R2modN (obtained from
4065  *        ref CAU3_PKHA_ModR2() function).
4066  * param size Size in bytes of curve points and parameters
4067  * param equalTime Run the function time equalized or no timing equalization.
4068  * param[out] outputCoordinate Resulting poin's x affine coordinate.
4069  * return Operation status.
4070  */
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)4071 status_t CAU3_PKHA_ECM_PointMul(CAU3_Type *base,
4072                                 const uint8_t *E,
4073                                 size_t sizeE,
4074                                 const uint8_t *inputCoordinate,
4075                                 const uint8_t *A24,
4076                                 const uint8_t *N,
4077                                 const uint8_t *R2modN,
4078                                 size_t size,
4079                                 cau3_pkha_timing_t equalTime,
4080                                 uint8_t *outputCoordinate)
4081 {
4082     cau3_pkha_mode_params_t params;
4083     uint32_t clearMask;
4084     status_t status;
4085 
4086 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
4087     status = cau3_lock_semaphore(base);
4088     if (kStatus_Success != status)
4089     {
4090         cau3_release_semaphore(base);
4091         return status;
4092     }
4093 #endif
4094 
4095     cau3_pkha_default_parms(&params);
4096     params.func      = kCAU3_PKHA_ArithEcmMul;
4097     params.equalTime = equalTime;
4098     params.r2modn    = (R2modN != NULL) ? kCAU3_PKHA_InputR2 : kCAU3_PKHA_CalcR2;
4099 
4100     clearMask = (uint32_t)kCAU3_ClearMode;
4101 
4102     /* Clear internal register states. */
4103     clearMask |= (uint32_t)kCAU3_ClearPkhaSizeA;
4104     clearMask |= (uint32_t)kCAU3_ClearPkhaSizeB;
4105     clearMask |= (uint32_t)kCAU3_ClearPkhaSizeN;
4106     clearMask |= (uint32_t)kCAU3_ClearPkhaSizeE;
4107 
4108     base->CW  = clearMask;
4109     base->STA = (uint32_t)kCAU3_StatusDoneIsr;
4110     (void)cau3_pkha_clear_regabne(base, true, true, true, true);
4111 
4112     base->PKNSZ = size;
4113     (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegN, 0, N, size);
4114 
4115     base->PKESZ = sizeE;
4116     (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegE, 0, E, sizeE);
4117 
4118     base->PKASZ = size;
4119     (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegA, 0, inputCoordinate, size);
4120     (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegA, 3, A24, size);
4121 
4122     if (R2modN != NULL)
4123     {
4124         base->PKBSZ = size;
4125         (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegB, 1, R2modN, size);
4126     }
4127 
4128     status = cau3_pkha_init_mode(base, &params);
4129 
4130     if (status == kStatus_Success)
4131     {
4132         /* Read the data from the result register into place. */
4133         (void)cau3_pkha_read_reg(base, kCAU3_PKHA_RegB, 1, outputCoordinate, size);
4134     }
4135 
4136     cau3_clear_all(base, true);
4137 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
4138     cau3_release_semaphore(base);
4139 #endif
4140     return status;
4141 }
4142 
4143 /*!
4144  * brief Multiplies an Edwards-form elliptic curve point by a scalar - E x (A0, A1).
4145  *
4146  * This function performs scalar multiplication of an Edwards-form elliptic curve point
4147  * in affine coordinates.
4148  * 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
4149  *
4150  * param base CAU3 peripheral base address
4151  * param A Point as multiplicand
4152  * param E Scalar multiple
4153  * param sizeE The size of E, in bytes
4154  * param N Modulus, a prime number for the Fp field.
4155  * param R2modN NULL (the function computes R2modN internally) or pointer to pre-computed R2modN (obtained from
4156  *        ref CAU3_PKHA_ModR2() function).
4157  * param aCurveParam A parameter from curve equation
4158  * param dCurveParam D parameter from curve equation.
4159  * param size Size in bytes of curve points and parameters
4160  * param equalTime Run the function time equalized or no timing equalization.
4161  * param[out] result Result point
4162  * return Operation status.
4163  */
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)4164 status_t CAU3_PKHA_ECT_PointMul(CAU3_Type *base,
4165                                 const cau3_pkha_ecc_point_t *A,
4166                                 const uint8_t *E,
4167                                 size_t sizeE,
4168                                 const uint8_t *N,
4169                                 const uint8_t *R2modN,
4170                                 const uint8_t *aCurveParam,
4171                                 const uint8_t *dCurveParam,
4172                                 size_t size,
4173                                 cau3_pkha_timing_t equalTime,
4174                                 cau3_pkha_ecc_point_t *result)
4175 {
4176     cau3_pkha_mode_params_t params;
4177     uint32_t clearMask;
4178     status_t status;
4179 
4180 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
4181     status = cau3_lock_semaphore(base);
4182     if (kStatus_Success != status)
4183     {
4184         cau3_release_semaphore(base);
4185         return status;
4186     }
4187 #endif
4188 
4189     cau3_pkha_default_parms(&params);
4190     params.func      = kCAU3_PKHA_ArithEctMul;
4191     params.equalTime = equalTime;
4192     params.r2modn    = (R2modN != NULL) ? kCAU3_PKHA_InputR2 : kCAU3_PKHA_CalcR2;
4193 
4194     clearMask = (uint32_t)kCAU3_ClearMode;
4195 
4196     /* Clear internal register states. */
4197     clearMask |= (uint32_t)kCAU3_ClearPkhaSizeA;
4198     clearMask |= (uint32_t)kCAU3_ClearPkhaSizeB;
4199     clearMask |= (uint32_t)kCAU3_ClearPkhaSizeN;
4200     clearMask |= (uint32_t)kCAU3_ClearPkhaSizeE;
4201 
4202     base->CW  = clearMask;
4203     base->STA = (uint32_t)kCAU3_StatusDoneIsr;
4204     (void)cau3_pkha_clear_regabne(base, true, true, true, true);
4205 
4206     base->PKNSZ = size;
4207     (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegN, 0, N, size);
4208 
4209     base->PKESZ = sizeE;
4210     (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegE, 0, E, sizeE);
4211 
4212     base->PKASZ = size;
4213     (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegA, 0, A->X, size);
4214     (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegA, 1, A->Y, size);
4215     (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegA, 3, aCurveParam, size);
4216 
4217     base->PKBSZ = size;
4218     (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegB, 0, dCurveParam, size);
4219     if (R2modN != NULL)
4220     {
4221         (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegB, 1, R2modN, size);
4222     }
4223 
4224     status = cau3_pkha_init_mode(base, &params);
4225 
4226     if (status == kStatus_Success)
4227     {
4228         /* Read the data from the result register into place. */
4229         cau3_pkha_read_reg(base, kCAU3_PKHA_RegB, 1, result->X, size);
4230         cau3_pkha_read_reg(base, kCAU3_PKHA_RegB, 2, result->Y, size);
4231     }
4232 
4233     cau3_clear_all(base, true);
4234 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
4235     cau3_release_semaphore(base);
4236 #endif
4237     return status;
4238 }
4239 
4240 /*!
4241  * brief Adds an Edwards-form elliptic curve points - A + B.
4242  *
4243  * This function performs Edwards-form elliptic curve point addition over a prime field (Fp) using affine coordinates.
4244  * 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
4245  *
4246  * param base CAU3 peripheral base address
4247  * param A Left-hand point
4248  * param B Right-hand point
4249  * param N Prime modulus of the field
4250  * param R2modN NULL (the function computes R2modN internally) or pointer to pre-computed R2modN (obtained from
4251  *               ref CAU3_PKHA_ModR2() function).
4252  * param aCurveParam A parameter from curve equation
4253  * param dCurveParam D parameter from curve equation
4254  * param size Size in bytes of curve points and parameters
4255  * param[out] result Result point
4256  * return Operation status.
4257  */
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)4258 status_t CAU3_PKHA_ECT_PointAdd(CAU3_Type *base,
4259                                 const cau3_pkha_ecc_point_t *A,
4260                                 const cau3_pkha_ecc_point_t *B,
4261                                 const uint8_t *N,
4262                                 const uint8_t *R2modN,
4263                                 const uint8_t *aCurveParam,
4264                                 const uint8_t *dCurveParam,
4265                                 size_t size,
4266                                 cau3_pkha_ecc_point_t *result)
4267 {
4268     cau3_pkha_mode_params_t params;
4269     uint32_t clearMask;
4270     status_t status;
4271 
4272 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
4273     status = cau3_lock_semaphore(base);
4274     if (kStatus_Success != status)
4275     {
4276         cau3_release_semaphore(base);
4277         return status;
4278     }
4279 #endif
4280 
4281     cau3_pkha_default_parms(&params);
4282     params.func   = kCAU3_PKHA_ArithEctAdd;
4283     params.r2modn = (R2modN != NULL) ? kCAU3_PKHA_InputR2 : kCAU3_PKHA_CalcR2;
4284 
4285     clearMask = (uint32_t)kCAU3_ClearMode;
4286 
4287     /* Clear internal register states. */
4288     clearMask |= (uint32_t)kCAU3_ClearPkhaSizeA;
4289     clearMask |= (uint32_t)kCAU3_ClearPkhaSizeB;
4290     clearMask |= (uint32_t)kCAU3_ClearPkhaSizeN;
4291     clearMask |= (uint32_t)kCAU3_ClearPkhaSizeE;
4292 
4293     base->CW  = clearMask;
4294     base->STA = (uint32_t)kCAU3_StatusDoneIsr;
4295     (void)cau3_pkha_clear_regabne(base, true, true, true, false);
4296 
4297     /* sizeN should be less than 64 bytes. */
4298     base->PKNSZ = size;
4299     (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegN, 0, N, size);
4300 
4301     base->PKASZ = size;
4302     (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegA, 0, A->X, size);
4303     (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegA, 1, A->Y, size);
4304     (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegA, 3, aCurveParam, size);
4305 
4306     base->PKBSZ = size;
4307     (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegB, 0, dCurveParam, size);
4308     (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegB, 1, B->X, size);
4309     (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegB, 2, B->Y, size);
4310     if (R2modN != NULL)
4311     {
4312         (void)cau3_pkha_write_reg(base, kCAU3_PKHA_RegB, 3, R2modN, size);
4313     }
4314 
4315     status = cau3_pkha_init_mode(base, &params);
4316 
4317     if (status == kStatus_Success)
4318     {
4319         /* Read the data from the result register into place. */
4320         cau3_pkha_read_reg(base, kCAU3_PKHA_RegB, 1, result->X, size);
4321         cau3_pkha_read_reg(base, kCAU3_PKHA_RegB, 2, result->Y, size);
4322     }
4323 
4324     cau3_clear_all(base, true);
4325 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
4326     cau3_release_semaphore(base);
4327 #endif
4328     return status;
4329 }
4330 
4331 /*!
4332  * brief   Perform a 3DES key parity check
4333  *
4334  * Performs a 3DES key parity check on three 8-byte keys.
4335  * The function is blocking.
4336  *
4337  * param base CAU3 peripheral base address
4338  * param   keySlot defines the key context to be used in the parity check
4339  *
4340  * return  status check from task completion
4341  */
CAU3_TDES_CheckParity(CAU3_Type * base,cau3_key_slot_t keySlot)4342 status_t CAU3_TDES_CheckParity(CAU3_Type *base, cau3_key_slot_t keySlot)
4343 {
4344     status_t completionStatus;
4345     cau3_task_done_t taskDone;
4346 
4347 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
4348     completionStatus = cau3_lock_semaphore(base);
4349     if (kStatus_Success != completionStatus)
4350     {
4351         cau3_release_semaphore(base);
4352         return completionStatus;
4353     }
4354 #endif
4355 
4356     taskDone = kCAU3_TaskDonePoll;
4357 
4358     /*  execute the cau3 "3des_check_parity" task  */
4359     base->CC_R[17] = (uint32_t)keySlot;           /*  keySlot  */
4360     base->CC_R30   = CAU3_DMEM_STK_BASE;          /*  initialize stack pointer (sp)  */
4361     base->CC_R31   = 0U;                          /*  set LR = 0 to signal a host task  */
4362     base->CC_PC    = CAU3_TASK_3DES_CHECK_PARITY; /*  call cau_3des_chk_parity()  */
4363     base->CC_CMD   = (uint32_t)taskDone;          /*  trigger cau3 execution  */
4364 
4365     /*  process the cau3 task completion signal specified by taskDone  */
4366     completionStatus = cau3_process_task_completion(base, taskDone);
4367 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
4368     cau3_release_semaphore(base);
4369 #endif
4370     return (completionStatus);
4371 }
4372 
4373 /*!
4374  * brief Load DES key into CAU3 key slot.
4375  *
4376  * Load the key context into the private DMEM.
4377  *
4378  * param   base CAU3 peripheral base address.
4379  * param   handle Handle used for the request.
4380  * param   key 0-mod-4 aligned pointer to 3DES key.
4381  * param   keySize 3DES key size in bytes. Shall equal 24.
4382  * return  status from set key operation
4383  */
CAU3_TDES_SetKey(CAU3_Type * base,cau3_handle_t * handle,const uint8_t * key,size_t keySize)4384 status_t CAU3_TDES_SetKey(CAU3_Type *base, cau3_handle_t *handle, const uint8_t *key, size_t keySize)
4385 {
4386     /* only work with aligned key[] */
4387     if (0U != (0x3U & (uintptr_t)key))
4388     {
4389         return kStatus_InvalidArgument;
4390     }
4391 
4392     /* keySize must be 24. */
4393     if (keySize != 24U)
4394     {
4395         return kStatus_InvalidArgument;
4396     }
4397 
4398     return cau3_load_key(base, key, keySize, (uint32_t)handle->keySlot, handle->taskDone);
4399 }
4400 
4401 /*!
4402  * brief   Perform a 3DES encryption
4403  *
4404  * Performs a 3DES "electronic code book" encryption on one 8-byte data block.
4405  * The source plaintext and destination ciphertext can overlap in system memory.
4406  * Supports both blocking and non-blocking task completion.
4407  *
4408  * param   base CAU3 peripheral base address.
4409  * param handle Handle used for this request.
4410  * param   plaintext is source uint8_t array of data bytes, any alignment
4411  * param   ciphertext is destination uint8_t array of data byte, any alignment
4412  *
4413  * return  status check from task completion
4414  */
CAU3_TDES_Encrypt(CAU3_Type * base,cau3_handle_t * handle,const uint8_t * plaintext,uint8_t * ciphertext)4415 status_t CAU3_TDES_Encrypt(CAU3_Type *base, cau3_handle_t *handle, const uint8_t *plaintext, uint8_t *ciphertext)
4416 {
4417     status_t completionStatus;
4418 
4419 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
4420     completionStatus = cau3_lock_semaphore(base);
4421     if (kStatus_Success != completionStatus)
4422     {
4423         cau3_release_semaphore(base);
4424         return completionStatus;
4425     }
4426 #endif
4427 
4428     /*  execute the cau3 "3des_encrypt_ecb" task  */
4429     base->CC_R[16] = (uintptr_t)plaintext;       /*  pPlainText  */
4430     base->CC_R[17] = (uint32_t)handle->keySlot;  /*  keySlot  */
4431     base->CC_R[19] = (uintptr_t)ciphertext;      /*  pCipherText  */
4432     base->CC_R30   = CAU3_DMEM_STK_BASE;         /*  initialize stack pointer (sp)  */
4433     base->CC_R31   = 0U;                         /*  set LR = 0 to signal a host task  */
4434     base->CC_PC    = CAU3_TASK_3DES_ENCRYPT;     /*  call cau_3des_encrypt()  */
4435     base->CC_CMD   = (uint32_t)handle->taskDone; /*  trigger cau3 execution  */
4436 
4437     /*  process the cau3 task completion signal specified by taskDone  */
4438     completionStatus = cau3_process_task_completion(base, handle->taskDone);
4439 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
4440     cau3_release_semaphore(base);
4441 #endif
4442     return (completionStatus);
4443 }
4444 
4445 /*!
4446  * brief   Perform a 3DES decryption
4447  *
4448  * Performs a 3DES "electronic code book" decryption on one 8-byte data block.
4449  * The source ciphertext and destination plaintext can overlap in sysMemory.
4450  * Supports both blocking and non-blocking task completion.
4451  *
4452  * param   base CAU3 peripheral base address.
4453  * param handle Handle used for this request.
4454  * param   ciphertext is destination uint8_t array of data byte, any alignment
4455  * param   plaintext is source uint8_t array of data bytes, any alignment
4456  * return  status check from task completion
4457  */
CAU3_TDES_Decrypt(CAU3_Type * base,cau3_handle_t * handle,const uint8_t * ciphertext,uint8_t * plaintext)4458 status_t CAU3_TDES_Decrypt(CAU3_Type *base, cau3_handle_t *handle, const uint8_t *ciphertext, uint8_t *plaintext)
4459 {
4460     status_t completionStatus;
4461 
4462 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
4463     completionStatus = cau3_lock_semaphore(base);
4464     if (kStatus_Success != completionStatus)
4465     {
4466         cau3_release_semaphore(base);
4467         return completionStatus;
4468     }
4469 #endif
4470 
4471     /*  execute the cau3 "3des_decrypt_ecb" task  */
4472     base->CC_R[16] = (uintptr_t)ciphertext;      /*  pCipherText  */
4473     base->CC_R[17] = (uint32_t)handle->keySlot;  /*  keySlot  */
4474     base->CC_R[19] = (uintptr_t)plaintext;       /*  pPlainText  */
4475     base->CC_R30   = CAU3_DMEM_STK_BASE;         /*  initialize stack pointer (sp)  */
4476     base->CC_R31   = 0U;                         /*  set LR = 0 to signal a host task  */
4477     base->CC_PC    = CAU3_TASK_3DES_DECRYPT;     /*  call cau_3des_decrypt()  */
4478     base->CC_CMD   = (uint32_t)handle->taskDone; /*  trigger cau3 execution  */
4479 
4480     /*  process the cau3 task completion signal specified by taskDone  */
4481     completionStatus = cau3_process_task_completion(base, handle->taskDone);
4482 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
4483     cau3_release_semaphore(base);
4484 #endif
4485     return (completionStatus);
4486 }
4487 
4488 /*!
4489  * brief Load 256-bit key into CAU3 key context (in key slot).
4490  *
4491  * Load the key context into the private DMEM for CHACHA20_POLY1305 AEAD.
4492  *
4493  * param   base CAU3 peripheral base address.
4494  * param   handle Handle used for the request.
4495  * param   key 0-mod-4 aligned pointer to CHACHA20_POLY1305 256-bit key.
4496  * param   keySize Size of the key in bytes. Shall be 32.
4497  * return  status from set key operation
4498  */
CAU3_CHACHA20_POLY1305_SetKey(CAU3_Type * base,cau3_handle_t * handle,const uint8_t * key,size_t keySize)4499 status_t CAU3_CHACHA20_POLY1305_SetKey(CAU3_Type *base, cau3_handle_t *handle, const uint8_t *key, size_t keySize)
4500 {
4501     /* only work with aligned key[] */
4502     if (0U != (0x3U & (uintptr_t)key))
4503     {
4504         return kStatus_InvalidArgument;
4505     }
4506 
4507     /* keySize must be 32. */
4508     if (keySize != 32U)
4509     {
4510         return kStatus_InvalidArgument;
4511     }
4512 
4513     union
4514     {
4515         uint8_t b[32];
4516         uint32_t w[8];
4517     } tempKey;
4518 
4519     for (uint32_t i = 0; i < ARRAY_SIZE(tempKey.w); i++)
4520     {
4521         tempKey.w[i] = __REV(((const uint32_t *)(uintptr_t)key)[i]);
4522     }
4523 
4524     return cau3_load_key(base, tempKey.b, keySize, (uint32_t)handle->keySlot, handle->taskDone);
4525 }
4526 
cau3_load_nonce(CAU3_Type * base,const uint8_t * nonce,cau3_key_slot_t keySlot)4527 static status_t cau3_load_nonce(CAU3_Type *base, const uint8_t *nonce, cau3_key_slot_t keySlot)
4528 {
4529     union
4530     {
4531         uint8_t b[16];
4532         uint32_t w[4];
4533     } tempIv;
4534 
4535     (void)memset(&tempIv, 0, sizeof(tempIv));
4536 
4537     /* set nonce to keySlot */
4538     (void)memcpy(tempIv.b, nonce, 12);
4539     /* swap bytes */
4540     tempIv.w[0] = __REV(tempIv.w[0]);
4541     tempIv.w[1] = __REV(tempIv.w[1]);
4542     tempIv.w[2] = __REV(tempIv.w[2]);
4543 
4544     return CAU3_LoadKeyInitVector(base, tempIv.b, keySlot, kCAU3_TaskDonePoll);
4545 }
4546 
4547 /*!
4548  * brief   Perform ChaCha-Poly encryption/authentication
4549  *
4550  * Perform ChaCha encryption over a message of "n" bytes, and authentication
4551  * over the encrypted data plus an additional authenticated data,
4552  * returning encrypted data + a message digest.
4553  *
4554  * param base CAU3 peripheral base address
4555  * param handle Handle used for this request. The keySlot member specifies key context with key and IV.
4556  * param plaintext The uint8_t source message to be encrypted, any alignment
4557  * param[out] ciphertext is a pointer to the output encrypted message, any aligment
4558  * param size The length of the plaintext and ciphertext in bytes
4559  * param aad A pointer to the additional authenticated data, any alignment
4560  * param aadLen Length of additional authenticated data in bytes
4561  * param nonce 0-mod-4 aligned pointer to CHACHA20_POLY1305 96-bit nonce.
4562  * param[out] tag A pointer to the 128-bit message digest output, any alignment
4563  *
4564  * return  status check from task completion
4565  */
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)4566 status_t CAU3_CHACHA20_POLY1305_Encrypt(CAU3_Type *base,
4567                                         cau3_handle_t *handle,
4568                                         const uint8_t *plaintext,
4569                                         uint8_t *ciphertext,
4570                                         size_t size,
4571                                         const uint8_t *aad,
4572                                         size_t aadLen,
4573                                         const uint8_t *nonce,
4574                                         uint8_t *tag)
4575 {
4576     status_t completionStatus;
4577 
4578     completionStatus = cau3_load_nonce(base, nonce, handle->keySlot);
4579     if (kStatus_Success != completionStatus)
4580     {
4581         return completionStatus;
4582     }
4583 
4584 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
4585     completionStatus = cau3_lock_semaphore(base);
4586     if (kStatus_Success != completionStatus)
4587     {
4588         cau3_release_semaphore(base);
4589         return completionStatus;
4590     }
4591 #endif
4592 
4593     base->CC_R[17] = (uint32_t)handle->keySlot;  /*  key/iv slot  */
4594     base->CC_R[18] = (uintptr_t)aad;             /*  AAD pointer  */
4595     base->CC_R[19] = aadLen;                     /*  AAD length (bytes)  */
4596     base->CC_R[20] = (uintptr_t)plaintext;       /*  Plaintext pointer  */
4597     base->CC_R[21] = size;                       /*  Plaintext length  */
4598     base->CC_R[22] = (uintptr_t)ciphertext;      /*  Ciphertext pointer  */
4599     base->CC_R[23] = (uintptr_t)tag;             /*  Tag pointer  */
4600     base->CC_R30   = CAU3_DMEM_STK_BASE;         /*  initialize stack pointer (sp)  */
4601     base->CC_R31   = 0U;                         /*  set LR = 0 to signal a host task  */
4602     base->CC_PC    = CAU3_TASK_CHA_POLY_ENCRYPT; /*  ChaChaPoly encrypt vector  */
4603     base->CC_CMD   = (uint32_t)handle->taskDone; /*  trigger cau3 execution  */
4604 
4605     /*  process the cau3 task completion signal specified by taskDone  */
4606     completionStatus = cau3_process_task_completion(base, handle->taskDone);
4607 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
4608     cau3_release_semaphore(base);
4609 #endif
4610     return (completionStatus);
4611 }
4612 
4613 /*!
4614  * brief   Perform ChaCha-Poly decryption/authentication check
4615  *
4616  * Perform ChaCha decryption over a message of "n" bytes, and checks
4617  * authentication over the encrypted data plus an additional authenticated data,
4618  * returning decrypted data. IF the tag authentication fails, the task terminates with error and
4619  * the output is forced to zero.
4620  *
4621  * param base CAU3 peripheral base address
4622  * param handle Handle used for this request. The keySlot member specifies key context with key and IV.
4623  * param ciphertext The uint8_t source msg to be decrypted, any alignment
4624  * param[out] plaintext A pointer to the output decrypted message, any alignment
4625  * param size Length of the plaintext and ciphertext in bytes
4626  * param aad A pointer to the additional authenticated data, any alignment
4627  * param aadLen Length of additional authenticated data in bytes
4628  * param nonce 0-mod-4 aligned pointer to CHACHA20_POLY1305 96-bit nonce.
4629  * param tag A pointer to the 128-bit msg digest input to be checked, any alignment
4630  *
4631  * return  status check from task completion
4632  *
4633  */
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)4634 status_t CAU3_CHACHA20_POLY1305_Decrypt(CAU3_Type *base,
4635                                         cau3_handle_t *handle,
4636                                         const uint8_t *ciphertext,
4637                                         uint8_t *plaintext,
4638                                         size_t size,
4639                                         const uint8_t *aad,
4640                                         size_t aadLen,
4641                                         const uint8_t *nonce,
4642                                         const uint8_t *tag)
4643 {
4644     status_t completionStatus;
4645 
4646     completionStatus = cau3_load_nonce(base, nonce, handle->keySlot);
4647     if (kStatus_Success != completionStatus)
4648     {
4649         return completionStatus;
4650     }
4651 
4652 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
4653     completionStatus = cau3_lock_semaphore(base);
4654     if (kStatus_Success != completionStatus)
4655     {
4656         cau3_release_semaphore(base);
4657         return completionStatus;
4658     }
4659 #endif
4660 
4661     base->CC_R[17] = (uint32_t)handle->keySlot;  /*  key/iv slot  */
4662     base->CC_R[18] = (uintptr_t)aad;             /*  AAD pointer  */
4663     base->CC_R[19] = aadLen;                     /*  AAD length (bytes)  */
4664     base->CC_R[20] = (uintptr_t)ciphertext;      /*  Ciphertext pointer  */
4665     base->CC_R[21] = size;                       /*  Cyphertext length  */
4666     base->CC_R[22] = (uintptr_t)plaintext;       /*  Plaintext pointer  */
4667     base->CC_R[23] = (uintptr_t)tag;             /*  Tag pointer  */
4668     base->CC_R30   = CAU3_DMEM_STK_BASE;         /*  initialize stack pointer (sp)  */
4669     base->CC_R31   = 0U;                         /*  set LR = 0 to signal a host task  */
4670     base->CC_PC    = CAU3_TASK_CHA_POLY_DECRYPT; /*  ChaChaPoly decrypt vector  */
4671     base->CC_CMD   = (uint32_t)handle->taskDone; /*  trigger cau3 execution  */
4672 
4673     /*  process the cau3 task completion signal specified by taskDone  */
4674     completionStatus = cau3_process_task_completion(base, handle->taskDone);
4675 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
4676     cau3_release_semaphore(base);
4677 #endif
4678     return (completionStatus);
4679 }
4680 
4681 /*!
4682  * brief   Perform an RFC3394 key blob unwrap
4683  *
4684  * Perform an RFC3394 unwrap of an AES encrypted key blob. The unwrapped
4685  * key blob is loaded into the specified key slot [1-3]. The initial
4686  * special hardware KEK contained in key slot 0 is typically used for the
4687  * unwrapping operation. The destination context number must be different than
4688  * the keySlot used for unwrapping.
4689  * Implements the algorithm at RFC 3394 to AES key unwrap. The
4690  * current implementation allows to unwrap up to 512 bits,
4691  * with the restriction of nblocks=2 or =4 or n=8(means it
4692  * unwraps only 128bits, 256bits or two 256 bits keys (512)). It
4693  * is allowed input key of 128 and 256bits only (passed using
4694  * the keyslot). The function also assumes the
4695  * ref CAU3_LoadSpecialKeyContext was called before.
4696  * It returns error and clear the destination context in case
4697  * parameters are not inside aceptable values.
4698  * In case n>4 && n!=8 it clears both destination contexts (the
4699  * dstContext and the adjacent/next context)
4700  * In case of n=8, the first unwraped key will be stored in the
4701  * dstContext slot, and the second key will be saved in the next
4702  * context (E.g: if dstContext=1, then first key goes to slot 1
4703  * and second key to slot 2. If dstContext=3 then first key goes
4704  * to slot 3 and second key goes to slot 1).
4705  * Examples of n usage.
4706  * E.g.: n = 2 means a unwraped key of 128 bits (2 * 64)
4707  * E.g.: n = 4 means a unwraped key of 256 bits (4 * 64)
4708  * E.g.: n = 8 means two unwraped keys of 256 bits (8 * 64)
4709  *
4710  * The function is blocking, it uses the polling task done signaling.
4711  *
4712  * param base CAU3 peripheral base address
4713  * param   keySlot is the key used to unwrap the key blob [0-3]
4714  * param   keyBlob 0-mod-4 aligned pointer is the RFC3394 wrapped key blob.
4715  * param   numberOfBlocks is the unwrapped keyBlob length as multiple of 64-bit blocks
4716  * param   dstContext is the destination key context for unwrapped blob [0-3]
4717  * retval  status check from task completion
4718  */
CAU3_KeyBlobUnwrap(CAU3_Type * base,cau3_key_slot_t keySlot,const uint8_t * keyBlob,uint32_t numberOfBlocks,cau3_key_slot_t dstContext)4719 status_t CAU3_KeyBlobUnwrap(CAU3_Type *base,
4720                             cau3_key_slot_t keySlot,
4721                             const uint8_t *keyBlob,
4722                             uint32_t numberOfBlocks,
4723                             cau3_key_slot_t dstContext)
4724 {
4725     status_t completionStatus;
4726     cau3_task_done_t taskDone;
4727 
4728     if (0U != (0x3U & (uintptr_t)keyBlob))
4729     {
4730         return kStatus_InvalidArgument;
4731     }
4732 
4733 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
4734     completionStatus = cau3_lock_semaphore(base);
4735     if (kStatus_Success != completionStatus)
4736     {
4737         cau3_release_semaphore(base);
4738         return completionStatus;
4739     }
4740 #endif
4741 
4742     taskDone = kCAU3_TaskDonePoll;
4743 
4744     /*  execute the cau3 "key blob unwrap" task  */
4745     base->CC_R[16] = (uintptr_t)keyBlob;        /*  pKeyBlob  */
4746     base->CC_R[17] = (uint32_t)keySlot;         /*  keySlot  */
4747     base->CC_R[18] = numberOfBlocks;            /*  numberOfBlocks  */
4748     base->CC_R[19] = (uint32_t)dstContext;      /*  destination key context  */
4749     base->CC_R30   = CAU3_DMEM_STK_BASE;        /*  initialize stack pointer (sp)  */
4750     base->CC_R31   = 0U;                        /*  set LR = 0 to signal a host task  */
4751     base->CC_PC    = CAU3_TASK_KEY_BLOB_UNWRAP; /*  call cau_key_blob_unwrap()  */
4752     base->CC_CMD   = (uint32_t)taskDone;        /*  trigger cau3 execution  */
4753 
4754     /*  process the cau3 task completion signal specified by taskDone  */
4755     completionStatus = cau3_process_task_completion(base, taskDone);
4756 #if defined(FSL_CAU3_USE_HW_SEMA) && (FSL_CAU3_USE_HW_SEMA > 0)
4757     cau3_release_semaphore(base);
4758 #endif
4759     return (completionStatus);
4760 }
4761