1 /*
2  * Copyright 2018-2021 NXP
3  * All rights reserved.
4  *
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #ifndef FSL_CASPER_H_
10 #define FSL_CASPER_H_
11 
12 #include "fsl_common.h"
13 
14 /*! @file */
15 
16 /*******************************************************************************
17  * Definitions
18  *******************************************************************************/
19 
20 /*!
21  * @addtogroup casper_driver
22  * @{
23  */
24 /*! @name Driver version */
25 /*! @{ */
26 /*! @brief CASPER driver version. Version 2.2.4.
27  *
28  * Current version: 2.2.4
29  *
30  * Change log:
31  * - Version 2.0.0
32  *   - Initial version
33  * - Version 2.0.1
34  *   - Bug fix KPSDK-24531 double_scalar_multiplication() result may be all zeroes for some specific input
35  * - Version 2.0.2
36  *   - Bug fix KPSDK-25015 CASPER_MEMCPY hard-fault on LPC55xx when both source and destination buffers are outside of
37  * CASPER_RAM
38  * - Version 2.0.3
39  *   - Bug fix KPSDK-28107 RSUB, FILL and ZERO operations not implemented in enum _casper_operation.
40  * - Version 2.0.4
41  *   - For GCC compiler, enforce O1 optimize level, specifically to remove strict-aliasing option.
42  *     This driver is very specific and requires -fno-strict-aliasing.
43  * - Version 2.0.5
44  *   - Fix sign-compare warning.
45  * - Version 2.0.6
46  *   - Fix IAR Pa082 warning.
47  * - Version 2.0.7
48  *   - Fix MISRA-C 2012 issue.
49  * - Version 2.0.8
50  *   - Add feature macro for CASPER_RAM_OFFSET.
51  * - Version 2.0.9
52  *   - Remove unused function Jac_oncurve().
53  *   - Fix ECC384 build.
54  * - Version 2.0.10
55  *   - Fix MISRA-C 2012 issue.
56  * - Version 2.1.0
57  *   - Add ECC NIST P-521 elliptic curve.
58  * - Version 2.2.0
59  *   - Rework driver to support multiple curves at once.
60  * - Version 2.2.1
61  *   - Fix MISRA-C 2012 issue.
62  * - Version 2.2.2
63  *   - Enable hardware interleaving to RAMX0 and RAMX1 for CASPER by feature macro FSL_FEATURE_CASPER_RAM_HW_INTERLEAVE
64  * - Version 2.2.3
65  *   - Added macro into CASPER_Init and CASPER_Deinit to support devices without clock and reset control.
66  * - Version 2.2.4
67  *   - Fix MISRA-C 2012 issue.
68  */
69 #define FSL_CASPER_DRIVER_VERSION (MAKE_VERSION(2, 2, 4))
70 /*! @} */
71 
72 /*! @brief CASPER operation
73  *
74  */
75 typedef enum _casper_operation
76 {
77     kCASPER_OpMul6464NoSum = 0x01, /*! Walking 1 or more of J loop, doing r=a*b using 64x64=128*/
78     kCASPER_OpMul6464Sum =
79         0x02, /*! Walking 1 or more of J loop, doing c,r=r+a*b using 64x64=128, but assume inner j loop*/
80     kCASPER_OpMul6464FullSum =
81         0x03, /*! Walking 1 or more of J loop, doing c,r=r+a*b using 64x64=128, but sum all of w. */
82     kCASPER_OpMul6464Reduce =
83         0x04,               /*! Walking 1 or more of J loop, doing c,r[-1]=r+a*b using 64x64=128, but skip 1st write*/
84     kCASPER_OpAdd64 = 0x08, /*! Walking add with off_AB, and in/out off_RES doing c,r=r+a+c using 64+64=65*/
85     kCASPER_OpSub64 = 0x09, /*! Walking subtract with off_AB, and in/out off_RES doing r=r-a using 64-64=64, with last
86                                borrow implicit if any*/
87     kCASPER_OpDouble64 = 0x0A, /*! Walking add to self with off_RES doing c,r=r+r+c using 64+64=65*/
88     kCASPER_OpXor64    = 0x0B, /*! Walking XOR with off_AB, and in/out off_RES doing r=r^a using 64^64=64*/
89     kCASPER_OpRSub64   = 0x0C, /*! Walking subtract with off_AB, and in/out off_RES using r=a-r */
90     kCASPER_OpShiftLeft32 =
91         0x10, /*! Walking shift left doing r1,r=(b*D)|r1, where D is 2^amt and is loaded by app (off_CD not used)*/
92     kCASPER_OpShiftRight32 = 0x11, /*! Walking shift right doing r,r1=(b*D)|r1, where D is 2^(32-amt) and is loaded by
93                                       app (off_CD not used) and off_RES starts at MSW*/
94     kCASPER_OpCopy        = 0x14,  /*! Copy from ABoff to resoff, 64b at a time*/
95     kCASPER_OpRemask      = 0x15,  /*! Copy and mask from ABoff to resoff, 64b at a time*/
96     kCASPER_OpFill        = 0x16,  /*! Fill RESOFF using 64 bits at a time with value in A and B */
97     kCASPER_OpZero        = 0x17,  /*! Fill RESOFF using 64 bits at a time of 0s */
98     kCASPER_OpCompare     = 0x18,  /*! Compare two arrays, running all the way to the end*/
99     kCASPER_OpCompareFast = 0x19,  /*! Compare two arrays, stopping on 1st !=*/
100 } casper_operation_t;
101 
102 /*! @brief Algorithm used for CASPER operation */
103 typedef enum _casper_algo_t
104 {
105     kCASPER_ECC_P256 = 0x01, /*!< ECC_P256*/
106     kCASPER_ECC_P384 = 0x02, /*!< ECC_P384 */
107     kCASPER_ECC_P521 = 0x03, /*!< ECC_P521 */
108 } casper_algo_t;
109 
110 #define CASPER_CP          1
111 #define CASPER_CP_CTRL0    (0x0 >> 2)
112 #define CASPER_CP_CTRL1    (0x4 >> 2)
113 #define CASPER_CP_LOADER   (0x8 >> 2)
114 #define CASPER_CP_STATUS   (0xC >> 2)
115 #define CASPER_CP_INTENSET (0x10 >> 2)
116 #define CASPER_CP_INTENCLR (0x14 >> 2)
117 #define CASPER_CP_INTSTAT  (0x18 >> 2)
118 #define CASPER_CP_AREG     (0x20 >> 2)
119 #define CASPER_CP_BREG     (0x24 >> 2)
120 #define CASPER_CP_CREG     (0x28 >> 2)
121 #define CASPER_CP_DREG     (0x2C >> 2)
122 #define CASPER_CP_RES0     (0x30 >> 2)
123 #define CASPER_CP_RES1     (0x34 >> 2)
124 #define CASPER_CP_RES2     (0x38 >> 2)
125 #define CASPER_CP_RES3     (0x3C >> 2)
126 #define CASPER_CP_MASK     (0x60 >> 2)
127 #define CASPER_CP_REMASK   (0x64 >> 2)
128 #define CASPER_CP_LOCK     (0x80 >> 2)
129 #define CASPER_CP_ID       (0xFFC >> 2)
130 /* mcr (cp,  opc1, value, CRn, CRm, opc2) */
131 #define CASPER_Wr32b(value, off) __arm_mcr(CASPER_CP, 0, value, ((off >> 4)), (off), 0)
132 /* mcrr(coproc, opc1, value, CRm) */
133 #define CASPER_Wr64b(value, off) __arm_mcrr(CASPER_CP, 0, value, off)
134 /* mrc(coproc, opc1, CRn, CRm, opc2) */
135 #define CASPER_Rd32b(off) __arm_mrc(CASPER_CP, 0, ((off >> 4)), (off), 0)
136 
137 /*  The model for this algo is that it can be implemented for a fixed size RSA key */
138 /*  for max speed. If this is made into a variable (to allow varying size), then */
139 /*  it will be slower by a bit. */
140 /*  The file is compiled with N_bitlen passed in as number of bits of the RSA key */
141 /*  #define N_bitlen 2048 */
142 #define N_wordlen_max (4096U / 32U)
143 
144 enum
145 {
146     kCASPER_RamOffset_Result   = 0x0u,
147     kCASPER_RamOffset_Base     = (N_wordlen_max + 8u),
148     kCASPER_RamOffset_TempBase = (2u * N_wordlen_max + 16u),
149     kCASPER_RamOffset_Modulus  = (kCASPER_RamOffset_TempBase + N_wordlen_max + 4u),
150     kCASPER_RamOffset_M64      = 1022U,
151 };
152 
153 /*! @} */
154 
155 /*******************************************************************************
156  * API
157  ******************************************************************************/
158 #if defined(__cplusplus)
159 extern "C" {
160 #endif
161 
162 /*!
163  * @addtogroup casper_driver
164  * @{
165  */
166 
167 /*!
168  * @brief Enables clock and disables reset for CASPER peripheral.
169  *
170  * Enable clock and disable reset for CASPER.
171  *
172  * @param base CASPER base address
173  */
174 void CASPER_Init(CASPER_Type *base);
175 
176 /*!
177  * @brief Disables clock for CASPER peripheral.
178  *
179  * Disable clock and enable reset.
180  *
181  * @param base CASPER base address
182  */
183 void CASPER_Deinit(CASPER_Type *base);
184 
185 /*!
186  *@}
187  */ /* end of casper_driver */
188 
189 /*******************************************************************************
190  * PKHA API
191  ******************************************************************************/
192 
193 /*!
194  * @addtogroup casper_driver_pkha
195  * @{
196  */
197 
198 /*!
199  * @brief Performs modular exponentiation - (A^E) mod N.
200  *
201  * This function performs modular exponentiation.
202  *
203  * @param base CASPER base address
204  * @param signature first addend (in little endian format)
205  * @param pubN modulus (in little endian format)
206  * @param wordLen Size of pubN in bytes
207  * @param pubE exponent
208  * @param[out] plaintext Output array to store result of operation (in little endian format)
209  */
210 void CASPER_ModExp(CASPER_Type *base,
211                    const uint8_t *signature,
212                    const uint8_t *pubN,
213                    size_t wordLen,
214                    uint32_t pubE,
215                    uint8_t *plaintext);
216 
217 /*!
218  * @brief Initialize prime modulus mod in Casper memory .
219  *
220  * Set the prime modulus mod in Casper memory and set N_wordlen
221  * according to selected algorithm.
222  *
223  * @param curve elliptic curve algoritm
224  */
225 void CASPER_ecc_init(casper_algo_t curve);
226 
227 /*!
228  * @brief Performs ECC secp256r1 point single scalar multiplication
229  *
230  * This function performs ECC secp256r1 point single scalar multiplication
231  * [resX; resY] = scalar * [X; Y]
232  * Coordinates are affine in normal form, little endian.
233  * Scalars are little endian.
234  * All arrays are little endian byte arrays, uint32_t type is used
235  * only to enforce the 32-bit alignment (0-mod-4 address).
236  *
237  * @param base CASPER base address
238  * @param[out] resX Output X affine coordinate in normal form, little endian.
239  * @param[out] resY Output Y affine coordinate in normal form, little endian.
240  * @param X Input X affine coordinate in normal form, little endian.
241  * @param Y Input Y affine coordinate in normal form, little endian.
242  * @param scalar Input scalar integer, in normal form, little endian.
243  */
244 void CASPER_ECC_SECP256R1_Mul(
245     CASPER_Type *base, uint32_t resX[8], uint32_t resY[8], uint32_t X[8], uint32_t Y[8], uint32_t scalar[8]);
246 
247 /*!
248  * @brief Performs ECC secp256r1 point double scalar multiplication
249  *
250  * This function performs ECC secp256r1 point double scalar multiplication
251  * [resX; resY] = scalar1 * [X1; Y1] + scalar2 * [X2; Y2]
252  * Coordinates are affine in normal form, little endian.
253  * Scalars are little endian.
254  * All arrays are little endian byte arrays, uint32_t type is used
255  * only to enforce the 32-bit alignment (0-mod-4 address).
256  *
257  * @param base CASPER base address
258  * @param[out] resX Output X affine coordinate.
259  * @param[out] resY Output Y affine coordinate.
260  * @param X1 Input X1 affine coordinate.
261  * @param Y1 Input Y1 affine coordinate.
262  * @param scalar1 Input scalar1 integer.
263  * @param X2 Input X2 affine coordinate.
264  * @param Y2 Input Y2 affine coordinate.
265  * @param scalar2 Input scalar2 integer.
266  */
267 void CASPER_ECC_SECP256R1_MulAdd(CASPER_Type *base,
268                                  uint32_t resX[8],
269                                  uint32_t resY[8],
270                                  uint32_t X1[8],
271                                  uint32_t Y1[8],
272                                  uint32_t scalar1[8],
273                                  uint32_t X2[8],
274                                  uint32_t Y2[8],
275                                  uint32_t scalar2[8]);
276 
277 /*!
278  * @brief Performs ECC secp384r1 point single scalar multiplication
279  *
280  * This function performs ECC secp384r1 point single scalar multiplication
281  * [resX; resY] = scalar * [X; Y]
282  * Coordinates are affine in normal form, little endian.
283  * Scalars are little endian.
284  * All arrays are little endian byte arrays, uint32_t type is used
285  * only to enforce the 32-bit alignment (0-mod-4 address).
286  *
287  * @param base CASPER base address
288  * @param[out] resX Output X affine coordinate in normal form, little endian.
289  * @param[out] resY Output Y affine coordinate in normal form, little endian.
290  * @param X Input X affine coordinate in normal form, little endian.
291  * @param Y Input Y affine coordinate in normal form, little endian.
292  * @param scalar Input scalar integer, in normal form, little endian.
293  */
294 void CASPER_ECC_SECP384R1_Mul(
295     CASPER_Type *base, uint32_t resX[12], uint32_t resY[12], uint32_t X[12], uint32_t Y[12], uint32_t scalar[12]);
296 
297 /*!
298  * @brief Performs ECC secp384r1 point double scalar multiplication
299  *
300  * This function performs ECC secp384r1 point double scalar multiplication
301  * [resX; resY] = scalar1 * [X1; Y1] + scalar2 * [X2; Y2]
302  * Coordinates are affine in normal form, little endian.
303  * Scalars are little endian.
304  * All arrays are little endian byte arrays, uint32_t type is used
305  * only to enforce the 32-bit alignment (0-mod-4 address).
306  *
307  * @param base CASPER base address
308  * @param[out] resX Output X affine coordinate.
309  * @param[out] resY Output Y affine coordinate.
310  * @param X1 Input X1 affine coordinate.
311  * @param Y1 Input Y1 affine coordinate.
312  * @param scalar1 Input scalar1 integer.
313  * @param X2 Input X2 affine coordinate.
314  * @param Y2 Input Y2 affine coordinate.
315  * @param scalar2 Input scalar2 integer.
316  */
317 void CASPER_ECC_SECP384R1_MulAdd(CASPER_Type *base,
318                                  uint32_t resX[12],
319                                  uint32_t resY[12],
320                                  uint32_t X1[12],
321                                  uint32_t Y1[12],
322                                  uint32_t scalar1[12],
323                                  uint32_t X2[12],
324                                  uint32_t Y2[12],
325                                  uint32_t scalar2[12]);
326 
327 /*!
328  * @brief Performs ECC secp521r1 point single scalar multiplication
329  *
330  * This function performs ECC secp521r1 point single scalar multiplication
331  * [resX; resY] = scalar * [X; Y]
332  * Coordinates are affine in normal form, little endian.
333  * Scalars are little endian.
334  * All arrays are little endian byte arrays, uint32_t type is used
335  * only to enforce the 32-bit alignment (0-mod-4 address).
336  *
337  * @param base CASPER base address
338  * @param[out] resX Output X affine coordinate in normal form, little endian.
339  * @param[out] resY Output Y affine coordinate in normal form, little endian.
340  * @param X Input X affine coordinate in normal form, little endian.
341  * @param Y Input Y affine coordinate in normal form, little endian.
342  * @param scalar Input scalar integer, in normal form, little endian.
343  */
344 void CASPER_ECC_SECP521R1_Mul(
345     CASPER_Type *base, uint32_t resX[18], uint32_t resY[18], uint32_t X[18], uint32_t Y[18], uint32_t scalar[18]);
346 
347 /*!
348  * @brief Performs ECC secp521r1 point double scalar multiplication
349  *
350  * This function performs ECC secp521r1 point double scalar multiplication
351  * [resX; resY] = scalar1 * [X1; Y1] + scalar2 * [X2; Y2]
352  * Coordinates are affine in normal form, little endian.
353  * Scalars are little endian.
354  * All arrays are little endian byte arrays, uint32_t type is used
355  * only to enforce the 32-bit alignment (0-mod-4 address).
356  *
357  * @param base CASPER base address
358  * @param[out] resX Output X affine coordinate.
359  * @param[out] resY Output Y affine coordinate.
360  * @param X1 Input X1 affine coordinate.
361  * @param Y1 Input Y1 affine coordinate.
362  * @param scalar1 Input scalar1 integer.
363  * @param X2 Input X2 affine coordinate.
364  * @param Y2 Input Y2 affine coordinate.
365  * @param scalar2 Input scalar2 integer.
366  */
367 void CASPER_ECC_SECP521R1_MulAdd(CASPER_Type *base,
368                                  uint32_t resX[18],
369                                  uint32_t resY[18],
370                                  uint32_t X1[18],
371                                  uint32_t Y1[18],
372                                  uint32_t scalar1[18],
373                                  uint32_t X2[18],
374                                  uint32_t Y2[18],
375                                  uint32_t scalar2[18]);
376 
377 void CASPER_ECC_equal(int *res, uint32_t *op1, uint32_t *op2);
378 void CASPER_ECC_equal_to_zero(int *res, uint32_t *op1);
379 
380 /*!
381  *@}
382  */ /* end of casper_driver_pkha */
383 
384 #if defined(__cplusplus)
385 }
386 #endif
387 
388 #endif /* FSL_CASPER_H_ */
389