aboutsummaryrefslogtreecommitdiff
path: root/platform/ext/target/nxp/common/Native_Driver/drivers/fsl_casper.h
blob: 6191b585b11f66c7ff1f318a4e06a1cadc5dedb2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
/*
 * Copyright 2018-2019 NXP
 * All rights reserved.
 *
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#ifndef _FSL_CASPER_H_
#define _FSL_CASPER_H_

#include "fsl_common.h"

/*! @file */

/*******************************************************************************
 * Definitions
 *******************************************************************************/

/*!
 * @addtogroup casper_driver
 * @{
 */
/*! @name Driver version */
/*@{*/
/*! @brief CASPER driver version. Version 2.0.5.
 *
 * Current version: 2.0.5
 *
 * Change log:
 * - Version 2.0.0
 *   - Initial version
 * - Version 2.0.1
 *   - Bug fix KPSDK-24531 double_scalar_multiplication() result may be all zeroes for some specific input
 * - Version 2.0.2
 *   - Bug fix KPSDK-25015 CASPER_MEMCPY hard-fault on LPC55xx when both source and destination buffers are outside of
 * CASPER_RAM
 * - Version 2.0.3
 *   - Bug fix KPSDK-28107 RSUB, FILL and ZERO operations not implemented in enum _casper_operation.
 * - Version 2.0.4
 *   - For GCC compiler, enforce O1 optimize level, specifically to remove strict-aliasing option.
 *     This driver is very specific and requires -fno-strict-aliasing.
 * - Version 2.0.5
 *   - Fix sign-compare warning.
 */
#define FSL_CASPER_DRIVER_VERSION (MAKE_VERSION(2, 0, 5))
/*@}*/

/*! @brief CASPER operation
 *
 */
typedef enum _casper_operation
{
    kCASPER_OpMul6464NoSum = 0x01, /*! Walking 1 or more of J loop, doing r=a*b using 64x64=128*/
    kCASPER_OpMul6464Sum =
        0x02, /*! Walking 1 or more of J loop, doing c,r=r+a*b using 64x64=128, but assume inner j loop*/
    kCASPER_OpMul6464FullSum =
        0x03, /*! Walking 1 or more of J loop, doing c,r=r+a*b using 64x64=128, but sum all of w. */
    kCASPER_OpMul6464Reduce =
        0x04,               /*! Walking 1 or more of J loop, doing c,r[-1]=r+a*b using 64x64=128, but skip 1st write*/
    kCASPER_OpAdd64 = 0x08, /*! Walking add with off_AB, and in/out off_RES doing c,r=r+a+c using 64+64=65*/
    kCASPER_OpSub64 = 0x09, /*! Walking subtract with off_AB, and in/out off_RES doing r=r-a using 64-64=64, with last
                               borrow implicit if any*/
    kCASPER_OpDouble64 = 0x0A, /*! Walking add to self with off_RES doing c,r=r+r+c using 64+64=65*/
    kCASPER_OpXor64    = 0x0B, /*! Walking XOR with off_AB, and in/out off_RES doing r=r^a using 64^64=64*/
    kCASPER_OpRSub64   = 0x0C, /*! Walking subtract with off_AB, and in/out off_RES using r=a-r */
    kCASPER_OpShiftLeft32 =
        0x10, /*! Walking shift left doing r1,r=(b*D)|r1, where D is 2^amt and is loaded by app (off_CD not used)*/
    kCASPER_OpShiftRight32 = 0x11, /*! Walking shift right doing r,r1=(b*D)|r1, where D is 2^(32-amt) and is loaded by
                                      app (off_CD not used) and off_RES starts at MSW*/
    kCASPER_OpCopy        = 0x14,  /*! Copy from ABoff to resoff, 64b at a time*/
    kCASPER_OpRemask      = 0x15,  /*! Copy and mask from ABoff to resoff, 64b at a time*/
    kCASPER_OpFill        = 0x16,  /*! Fill RESOFF using 64 bits at a time with value in A and B */
    kCASPER_OpZero        = 0x17,  /*! Fill RESOFF using 64 bits at a time of 0s */
    kCASPER_OpCompare     = 0x18,  /*! Compare two arrays, running all the way to the end*/
    kCASPER_OpCompareFast = 0x19,  /*! Compare two arrays, stopping on 1st !=*/
} casper_operation_t;

#define CASPER_CP 1
#define CASPER_CP_CTRL0 (0x0 >> 2)
#define CASPER_CP_CTRL1 (0x4 >> 2)
#define CASPER_CP_LOADER (0x8 >> 2)
#define CASPER_CP_STATUS (0xC >> 2)
#define CASPER_CP_INTENSET (0x10 >> 2)
#define CASPER_CP_INTENCLR (0x14 >> 2)
#define CASPER_CP_INTSTAT (0x18 >> 2)
#define CASPER_CP_AREG (0x20 >> 2)
#define CASPER_CP_BREG (0x24 >> 2)
#define CASPER_CP_CREG (0x28 >> 2)
#define CASPER_CP_DREG (0x2C >> 2)
#define CASPER_CP_RES0 (0x30 >> 2)
#define CASPER_CP_RES1 (0x34 >> 2)
#define CASPER_CP_RES2 (0x38 >> 2)
#define CASPER_CP_RES3 (0x3C >> 2)
#define CASPER_CP_MASK (0x60 >> 2)
#define CASPER_CP_REMASK (0x64 >> 2)
#define CASPER_CP_LOCK (0x80 >> 2)
#define CASPER_CP_ID (0xFFC >> 2)
/* mcr (cp,  opc1, value, CRn, CRm, opc2) */
#define CASPER_Wr32b(value, off) __arm_mcr(CASPER_CP, 0, value, ((off >> 4)), (off), 0)
/* mcrr(coproc, opc1, value, CRm) */
#define CASPER_Wr64b(value, off) __arm_mcrr(CASPER_CP, 0, value, off)
/* mrc(coproc, opc1, CRn, CRm, opc2) */
#define CASPER_Rd32b(off) __arm_mrc(CASPER_CP, 0, ((off >> 4)), (off), 0)

/*  The model for this algo is that it can be implemented for a fixed size RSA key */
/*  for max speed. If this is made into a variable (to allow varying size), then */
/*  it will be slower by a bit. */
/*  The file is compiled with N_bitlen passed in as number of bits of the RSA key */
/*  #define N_bitlen 2048 */
#define N_wordlen_max (4096 / 32)

#define CASPER_ECC_P256 1
#define CASPER_ECC_P384 0

#if CASPER_ECC_P256
#define N_bitlen 256
#endif /* CASPER_ECC_P256 */

#if CASPER_ECC_P384
#define N_bitlen 384
#endif /* CASPER_ECC_P256 */

#define NUM_LIMBS (N_bitlen / 32)

enum
{
    kCASPER_RamOffset_Result   = 0x0u,
    kCASPER_RamOffset_Base     = (N_wordlen_max + 8u),
    kCASPER_RamOffset_TempBase = (2u * N_wordlen_max + 16u),
    kCASPER_RamOffset_Modulus  = (kCASPER_RamOffset_TempBase + N_wordlen_max + 4u),
    kCASPER_RamOffset_M64      = 1022,
};

/*! @} */

/*******************************************************************************
 * API
 ******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif

/*!
 * @addtogroup casper_driver
 * @{
 */

/*!
 * @brief Enables clock and disables reset for CASPER peripheral.
 *
 * Enable clock and disable reset for CASPER.
 *
 * @param base CASPER base address
 */
void CASPER_Init(CASPER_Type *base);

/*!
 * @brief Disables clock for CASPER peripheral.
 *
 * Disable clock and enable reset.
 *
 * @param base CASPER base address
 */
void CASPER_Deinit(CASPER_Type *base);

/*!
 *@}
 */ /* end of casper_driver */

/*******************************************************************************
 * PKHA API
 ******************************************************************************/

/*!
 * @addtogroup casper_driver_pkha
 * @{
 */

/*!
 * @brief Performs modular exponentiation - (A^E) mod N.
 *
 * This function performs modular exponentiation.
 *
 * @param base CASPER base address
 * @param signature first addend (in little endian format)
 * @param pubN modulus (in little endian format)
 * @param wordLen Size of pubN in bytes
 * @param pubE exponent
 * @param[out] plaintext Output array to store result of operation (in little endian format)
 */
void CASPER_ModExp(CASPER_Type *base,
                   const uint8_t *signature,
                   const uint8_t *pubN,
                   size_t wordLen,
                   uint32_t pubE,
                   uint8_t *plaintext);

void CASPER_ecc_init(void);

/*!
 * @brief Performs ECC secp256r1 point single scalar multiplication
 *
 * This function performs ECC secp256r1 point single scalar multiplication
 * [resX; resY] = scalar * [X; Y]
 * Coordinates are affine in normal form, little endian.
 * Scalars are little endian.
 * All arrays are little endian byte arrays, uint32_t type is used
 * only to enforce the 32-bit alignment (0-mod-4 address).
 *
 * @param base CASPER base address
 * @param[out] resX Output X affine coordinate in normal form, little endian.
 * @param[out] resY Output Y affine coordinate in normal form, little endian.
 * @param X Input X affine coordinate in normal form, little endian.
 * @param Y Input Y affine coordinate in normal form, little endian.
 * @param scalar Input scalar integer, in normal form, little endian.
 */
void CASPER_ECC_SECP256R1_Mul(
    CASPER_Type *base, uint32_t resX[8], uint32_t resY[8], uint32_t X[8], uint32_t Y[8], uint32_t scalar[8]);

/*!
 * @brief Performs ECC secp256r1 point double scalar multiplication
 *
 * This function performs ECC secp256r1 point double scalar multiplication
 * [resX; resY] = scalar1 * [X1; Y1] + scalar2 * [X2; Y2]
 * Coordinates are affine in normal form, little endian.
 * Scalars are little endian.
 * All arrays are little endian byte arrays, uint32_t type is used
 * only to enforce the 32-bit alignment (0-mod-4 address).
 *
 * @param base CASPER base address
 * @param[out] resX Output X affine coordinate.
 * @param[out] resY Output Y affine coordinate.
 * @param X1 Input X1 affine coordinate.
 * @param Y1 Input Y1 affine coordinate.
 * @param scalar1 Input scalar1 integer.
 * @param X2 Input X2 affine coordinate.
 * @param Y2 Input Y2 affine coordinate.
 * @param scalar2 Input scalar2 integer.
 */
void CASPER_ECC_SECP256R1_MulAdd(CASPER_Type *base,
                                 uint32_t resX[8],
                                 uint32_t resY[8],
                                 uint32_t X1[8],
                                 uint32_t Y1[8],
                                 uint32_t scalar1[8],
                                 uint32_t X2[8],
                                 uint32_t Y2[8],
                                 uint32_t scalar2[8]);

/*!
 * @brief Performs ECC secp384r1 point single scalar multiplication
 *
 * This function performs ECC secp384r1 point single scalar multiplication
 * [resX; resY] = scalar * [X; Y]
 * Coordinates are affine in normal form, little endian.
 * Scalars are little endian.
 * All arrays are little endian byte arrays, uint32_t type is used
 * only to enforce the 32-bit alignment (0-mod-4 address).
 *
 * @param base CASPER base address
 * @param[out] resX Output X affine coordinate in normal form, little endian.
 * @param[out] resY Output Y affine coordinate in normal form, little endian.
 * @param X Input X affine coordinate in normal form, little endian.
 * @param Y Input Y affine coordinate in normal form, little endian.
 * @param scalar Input scalar integer, in normal form, little endian.
 */
void CASPER_ECC_SECP384R1_Mul(
    CASPER_Type *base, uint32_t resX[12], uint32_t resY[12], uint32_t X[12], uint32_t Y[12], uint32_t scalar[12]);

/*!
 * @brief Performs ECC secp384r1 point double scalar multiplication
 *
 * This function performs ECC secp384r1 point double scalar multiplication
 * [resX; resY] = scalar1 * [X1; Y1] + scalar2 * [X2; Y2]
 * Coordinates are affine in normal form, little endian.
 * Scalars are little endian.
 * All arrays are little endian byte arrays, uint32_t type is used
 * only to enforce the 32-bit alignment (0-mod-4 address).
 *
 * @param base CASPER base address
 * @param[out] resX Output X affine coordinate.
 * @param[out] resY Output Y affine coordinate.
 * @param X1 Input X1 affine coordinate.
 * @param Y1 Input Y1 affine coordinate.
 * @param scalar1 Input scalar1 integer.
 * @param X2 Input X2 affine coordinate.
 * @param Y2 Input Y2 affine coordinate.
 * @param scalar2 Input scalar2 integer.
 */
void CASPER_ECC_SECP384R1_MulAdd(CASPER_Type *base,
                                 uint32_t resX[12],
                                 uint32_t resY[12],
                                 uint32_t X1[12],
                                 uint32_t Y1[12],
                                 uint32_t scalar1[12],
                                 uint32_t X2[12],
                                 uint32_t Y2[12],
                                 uint32_t scalar2[12]);

void CASPER_ECC_equal(int *res, uint32_t *op1, uint32_t *op2);
void CASPER_ECC_equal_to_zero(int *res, uint32_t *op1);

/*!
 *@}
 */ /* end of casper_driver_pkha */

#if defined(__cplusplus)
}
#endif

#endif /* _FSL_CASPER_H_ */