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