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