1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2024 Rockchip Electronics Co., Ltd 4 */ 5 6 #include <common.h> 7 #include <crypto.h> 8 #include <dm.h> 9 #include <linux/errno.h> 10 #include <rockchip/crypto_mpa.h> 11 #include <rockchip/crypto_v2.h> 12 #include <rockchip/crypto_ecc.h> 13 14 #define WORDS2BYTES(words) ((words) * 4) 15 16 #define RK_ECP_IS_BIGNUM_INVALID(b) (!b || !b->d || b->size > RK_ECP_MAX_WORDS) 17 #define RK_ECP_IS_POINT_INVALID(p) (RK_ECP_IS_BIGNUM_INVALID(p->x) && \ 18 RK_ECP_IS_BIGNUM_INVALID(p->y)) 19 20 /*************************************************************/ 21 /* Macros for waiting EC machine ready states */ 22 /*************************************************************/ 23 #define RK_ECP_WRITE_REG(offset, val) crypto_write((val), (offset)) 24 #define RK_ECP_READ_REG(offset) crypto_read((offset)) 25 26 #define RK_ECP_RAM_FOR_ECC() \ 27 RK_ECP_WRITE_REG(RK_ECC_RAM_CTL, RK_ECC_RAM_CTL_SEL_MASK | RK_ECC_RAM_CTL_ECC) 28 29 #define RK_ECP_RAM_FOR_CPU() \ 30 RK_ECP_WRITE_REG(RK_ECC_RAM_CTL, RK_ECC_RAM_CTL_SEL_MASK | RK_ECC_RAM_CTL_CPU) 31 32 /* big endian to little endian */ 33 #define RK_ECP_LOAD_DATA(dst, big_src) rk_ecp_load_data(dst, big_src) 34 35 /* little endian to littel endian */ 36 #define RK_ECP_LOAD_DATA_EXT(dst, src, n_bytes) \ 37 do { \ 38 util_word_memset((void *)(dst), 0, RK_ECP_MAX_WORDS);\ 39 util_word_memcpy((void *)(dst), (void *)(src), (n_bytes) / 4); \ 40 } while (0) 41 42 #define RK_GET_GRPOUP_NBYTES(grp) ((grp)->p_len) 43 44 #define RK_LOAD_GROUP_A(G) do { \ 45 grp->curve_name = #G; \ 46 grp->wide = G ## _wide;\ 47 grp->p = G ## _p; \ 48 grp->p_len = sizeof(G ## _p); \ 49 grp->a = G ## _a; \ 50 grp->a_len = sizeof(G ## _a); \ 51 grp->n = G ## _n; \ 52 grp->n_len = sizeof(G ## _n); \ 53 grp->gx = G ## _gx; \ 54 grp->gx_len = sizeof(G ## _gx); \ 55 grp->gy = G ## _gy; \ 56 grp->gy_len = sizeof(G ## _gy); \ 57 } while (0) 58 59 /* transform to big endian */ 60 /* 61 * Domain parameters for secp192r1 62 */ 63 static const uint32_t secp192r1_wide = RK_ECC_CURVE_WIDE_192; 64 65 static const uint8_t secp192r1_p[] = { 66 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 67 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 68 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 69 }; 70 71 static const uint8_t secp192r1_a[] = { 72 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 73 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 74 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 75 }; 76 77 static const uint8_t secp192r1_gx[] = { 78 0x12, 0x10, 0xFF, 0x82, 0xFD, 0x0A, 0xFF, 0xF4, 79 0x00, 0x88, 0xA1, 0x43, 0xEB, 0x20, 0xBF, 0x7C, 80 0xF6, 0x90, 0x30, 0xB0, 0x0E, 0xA8, 0x8D, 0x18, 81 }; 82 83 static const uint8_t secp192r1_gy[] = { 84 0x11, 0x48, 0x79, 0x1E, 0xA1, 0x77, 0xF9, 0x73, 85 0xD5, 0xCD, 0x24, 0x6B, 0xED, 0x11, 0x10, 0x63, 86 0x78, 0xDA, 0xC8, 0xFF, 0x95, 0x2B, 0x19, 0x07, 87 }; 88 89 static const uint8_t secp192r1_n[] = { 90 0x31, 0x28, 0xD2, 0xB4, 0xB1, 0xC9, 0x6B, 0x14, 91 0x36, 0xF8, 0xDE, 0x99, 0xFF, 0xFF, 0xFF, 0xFF, 92 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 93 }; 94 95 /* 96 * Domain parameters for secp224r1 97 */ 98 static const uint32_t secp224r1_wide = RK_ECC_CURVE_WIDE_224; 99 100 static const uint8_t secp224r1_p[] = { 101 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 102 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 103 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 104 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 105 }; 106 107 static const uint8_t secp224r1_a[] = { 108 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 109 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 110 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 111 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 112 }; 113 114 static const uint8_t secp224r1_gx[] = { 115 0x21, 0x1D, 0x5C, 0x11, 0xD6, 0x80, 0x32, 0x34, 116 0x22, 0x11, 0xC2, 0x56, 0xD3, 0xC1, 0x03, 0x4A, 117 0xB9, 0x90, 0x13, 0x32, 0x7F, 0xBF, 0xB4, 0x6B, 118 0xBD, 0x0C, 0x0E, 0xB7, 119 }; 120 121 static const uint8_t secp224r1_gy[] = { 122 0x34, 0x7E, 0x00, 0x85, 0x99, 0x81, 0xD5, 0x44, 123 0x64, 0x47, 0x07, 0x5A, 0xA0, 0x75, 0x43, 0xCD, 124 0xE6, 0xDF, 0x22, 0x4C, 0xFB, 0x23, 0xF7, 0xB5, 125 0x88, 0x63, 0x37, 0xBD, 126 }; 127 128 static const uint8_t secp224r1_n[] = { 129 0x3D, 0x2A, 0x5C, 0x5C, 0x45, 0x29, 0xDD, 0x13, 130 0x3E, 0xF0, 0xB8, 0xE0, 0xA2, 0x16, 0xFF, 0xFF, 131 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 132 0xFF, 0xFF, 0xFF, 0xFF, 133 }; 134 135 /* 136 * Domain parameters for secp256r1 137 */ 138 static const uint32_t secp256r1_wide = RK_ECC_CURVE_WIDE_256; 139 140 static const uint8_t secp256r1_p[] = { 141 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 142 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 143 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 144 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 145 }; 146 147 static const uint8_t secp256r1_a[] = { 148 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 149 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 150 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 151 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 152 }; 153 154 static const uint8_t secp256r1_gx[] = { 155 0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4, 156 0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, 0x77, 157 0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8, 158 0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, 0x17, 0x6B, 159 }; 160 161 static const uint8_t secp256r1_gy[] = { 162 0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB, 163 0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, 0x2B, 164 0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E, 165 0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, 0xE3, 0x4F, 166 }; 167 168 static const uint8_t secp256r1_n[] = { 169 0x51, 0x25, 0x63, 0xFC, 0xC2, 0xCA, 0xB9, 0xF3, 170 0x84, 0x9E, 0x17, 0xA7, 0xAD, 0xFA, 0xE6, 0xBC, 171 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 172 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 173 }; 174 175 /* 176 * Domain parameters for sm2p256v1_p 177 */ 178 static const uint32_t sm2p256v1_wide = RK_ECC_CURVE_WIDE_256; 179 180 static const uint8_t sm2p256v1_p[] = { 181 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 182 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 183 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 184 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 185 }; 186 187 static const uint8_t sm2p256v1_a[] = { 188 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 189 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 190 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 191 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 192 }; 193 194 static const uint8_t sm2p256v1_gx[] = { 195 0xC7, 0x74, 0x4C, 0x33, 0x89, 0x45, 0x5A, 0x71, 196 0xE1, 0x0B, 0x66, 0xF2, 0xBF, 0x0B, 0xE3, 0x8F, 197 0x94, 0xC9, 0x39, 0x6A, 0x46, 0x04, 0x99, 0x5F, 198 0x19, 0x81, 0x19, 0x1F, 0x2C, 0xAE, 0xC4, 0x32, 199 }; 200 201 static const uint8_t sm2p256v1_gy[] = { 202 0xA0, 0xF0, 0x39, 0x21, 0xE5, 0x32, 0xDF, 0x02, 203 0x40, 0x47, 0x2A, 0xC6, 0x7C, 0x87, 0xA9, 0xD0, 204 0x53, 0x21, 0x69, 0x6B, 0xE3, 0xCE, 0xBD, 0x59, 205 0x9C, 0x77, 0xF6, 0xF4, 0xA2, 0x36, 0x37, 0xBC, 206 }; 207 208 static const uint8_t sm2p256v1_n[] = { 209 0x23, 0x41, 0xD5, 0x39, 0x09, 0xF4, 0xBB, 0x53, 210 0x2B, 0x05, 0xC6, 0x21, 0x6B, 0xDF, 0x03, 0x72, 211 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 212 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 213 }; 214 215 static inline u32 word_reverse(u32 word) 216 { 217 u32 i; 218 u32 new_word = 0; 219 220 for (i = 0; i < sizeof(u32); i++) { 221 new_word |= (word & 0xff) << (8 * (sizeof(u32) - i - 1)); 222 word >>= 8; 223 } 224 225 return new_word; 226 } 227 228 static inline bool is_ec_supported(void) 229 { 230 return !!RK_ECP_READ_REG(RK_ECC_MAX_CURVE_WIDE); 231 } 232 233 /* reverse endian word copy */ 234 static int rk_ecp_load_data(u32 *dst, struct mpa_num *src) 235 { 236 u32 i; 237 u32 dst_pos, src_pos; 238 239 util_word_memset(dst, 0, RK_ECP_MAX_WORDS); 240 241 dst_pos = src->size - 1; 242 src_pos = 0; 243 244 for (i = 0; i < src->size; i++) 245 dst[dst_pos--] = word_reverse(src->d[src_pos++]); 246 247 return 0; 248 } 249 250 static int rk_word_cmp_zero(uint32_t *buf1, uint32_t n_words) 251 { 252 int ret = 0; 253 uint32_t i; 254 255 for (i = 0 ; i < n_words; i++) { 256 if (buf1[i] != 0) 257 ret = -EINVAL; 258 } 259 260 return ret; 261 } 262 263 /* 264 * Set a group using well-known domain parameters 265 */ 266 static int rk_ecp_group_load(struct rk_ecp_group *grp, enum rk_ecp_group_id id) 267 { 268 memset(grp, 0x00, sizeof(*grp)); 269 270 grp->id = id; 271 272 switch (id) { 273 case RK_ECP_DP_SECP192R1: 274 RK_LOAD_GROUP_A(secp192r1); 275 return 0; 276 277 case RK_ECP_DP_SECP224R1: 278 RK_LOAD_GROUP_A(secp224r1); 279 return 0; 280 281 case RK_ECP_DP_SECP256R1: 282 RK_LOAD_GROUP_A(secp256r1); 283 return 0; 284 285 case RK_ECP_DP_SM2P256V1: 286 RK_LOAD_GROUP_A(sm2p256v1); 287 return 0; 288 289 default: 290 return -EINVAL; 291 } 292 } 293 294 static int rockchip_ecc_request_set(uint32_t ecc_ctl, uint32_t wide) 295 { 296 RK_ECP_WRITE_REG(RK_ECC_CURVE_WIDE, wide); 297 298 RK_ECP_WRITE_REG(RK_ECC_INT_EN, 0); 299 RK_ECP_WRITE_REG(RK_ECC_INT_ST, RK_ECP_READ_REG(RK_ECC_INT_ST)); 300 RK_ECP_WRITE_REG(RK_ECC_CTL, ecc_ctl); 301 302 return 0; 303 } 304 305 static int rockchip_ecc_request_wait_done(void) 306 { 307 int ret = 0; 308 u32 reg_val = 0; 309 310 do { 311 reg_val = crypto_read(RK_ECC_INT_ST); 312 } while ((reg_val & 0x01) != RK_ECC_INT_ST_DONE); 313 314 if (RK_ECP_READ_REG(RK_ECC_ABN_ST)) { 315 ret = -EFAULT; 316 goto exit; 317 } 318 319 exit: 320 if (ret) { 321 printf("RK_ECC_CTL = %08x\n", RK_ECP_READ_REG(RK_ECC_CTL)); 322 printf("RK_ECC_INT_EN = %08x\n", RK_ECP_READ_REG(RK_ECC_INT_EN)); 323 printf("RK_ECC_CURVE_WIDE = %08x\n", RK_ECP_READ_REG(RK_ECC_CURVE_WIDE)); 324 printf("RK_ECC_RAM_CTL = %08x\n", RK_ECP_READ_REG(RK_ECC_RAM_CTL)); 325 printf("RK_ECC_INT_ST = %08x\n", RK_ECP_READ_REG(RK_ECC_INT_ST)); 326 printf("RK_ECC_ABN_ST = %08x\n", RK_ECP_READ_REG(RK_ECC_ABN_ST)); 327 } 328 329 RK_ECP_WRITE_REG(RK_ECC_CTL, 0); 330 RK_ECP_RAM_FOR_CPU(); 331 332 return ret; 333 } 334 335 static int rockchip_ecc_request_trigger(void) 336 { 337 uint32_t ecc_ctl = RK_ECP_READ_REG(RK_ECC_CTL); 338 339 RK_ECP_RAM_FOR_ECC(); 340 341 RK_ECP_WRITE_REG(RK_ECC_CTL, ecc_ctl | RK_ECC_CTL_REQ_ECC); 342 343 return rockchip_ecc_request_wait_done(); 344 } 345 346 static uint32_t rockchip_ecc_get_group_id(uint32_t crypto_algo) 347 { 348 switch (crypto_algo) { 349 case CRYPTO_ECC_192R1: 350 return RK_ECP_DP_SECP192R1; 351 case CRYPTO_ECC_224R1: 352 return RK_ECP_DP_SECP224R1; 353 case CRYPTO_ECC_256R1: 354 return RK_ECP_DP_SECP256R1; 355 case CRYPTO_SM2: 356 return RK_ECP_DP_SM2P256V1; 357 default: 358 return RK_ECP_DP_NONE; 359 } 360 } 361 362 int rockchip_ecc_verify(uint32_t crypto_algo, uint8_t *hash, uint32_t hash_len, 363 struct rk_ecp_point *point_P, struct rk_ecp_point *point_sign) 364 { 365 int ret; 366 uint32_t curve_sel = 0; 367 struct mpa_num *bn_hash = NULL; 368 uint32_t group_id = rockchip_ecc_get_group_id(crypto_algo); 369 struct rk_ecp_group grp; 370 struct rk_ecc_verify *ecc_st = (struct rk_ecc_verify *)SM2_RAM_BASE; 371 372 if (!is_ec_supported()) 373 return -ENOSYS; 374 375 if (!hash || 376 hash_len == 0 || 377 hash_len > RK_ECP_MAX_BYTES || 378 RK_ECP_IS_POINT_INVALID(point_P) || 379 RK_ECP_IS_POINT_INVALID(point_sign)) { 380 ret = -EINVAL; 381 goto exit; 382 } 383 384 ret = rk_ecp_group_load(&grp, group_id); 385 if (ret) 386 goto exit; 387 388 rk_mpa_alloc(&bn_hash, hash, BYTE2WORD(hash_len)); 389 if (!bn_hash) { 390 ret = -ENOMEM; 391 goto exit; 392 } 393 394 RK_ECP_RAM_FOR_CPU(); 395 396 curve_sel = group_id == RK_ECP_DP_SM2P256V1 ? 397 RK_ECC_CTL_FUNC_SM2_CURVER : RK_ECC_CTL_FUNC_ECC_CURVER; 398 399 RK_ECP_LOAD_DATA(ecc_st->e, bn_hash); 400 RK_ECP_LOAD_DATA(ecc_st->r_, point_sign->x); 401 RK_ECP_LOAD_DATA(ecc_st->s_, point_sign->y); 402 RK_ECP_LOAD_DATA(ecc_st->p_x, point_P->x); 403 RK_ECP_LOAD_DATA(ecc_st->p_y, point_P->y); 404 405 RK_ECP_LOAD_DATA_EXT(ecc_st->A, grp.a, grp.a_len); 406 RK_ECP_LOAD_DATA_EXT(ecc_st->P, grp.p, grp.p_len); 407 RK_ECP_LOAD_DATA_EXT(ecc_st->N, grp.n, grp.n_len); 408 409 RK_ECP_LOAD_DATA_EXT(ecc_st->G_x, grp.gx, grp.gx_len); 410 RK_ECP_LOAD_DATA_EXT(ecc_st->G_y, grp.gy, grp.gy_len); 411 412 rockchip_ecc_request_set(curve_sel | RK_ECC_CTL_FUNC_SEL_VERIFY, grp.wide); 413 414 ret = rockchip_ecc_request_trigger(); 415 if (ret || 416 rk_word_cmp_zero(ecc_st->v, RK_ECP_MAX_WORDS) || 417 rk_word_cmp_zero(ecc_st->r_, RK_ECP_MAX_WORDS) == 0) { 418 ret = -EKEYREJECTED; 419 } 420 exit: 421 rk_mpa_free(&bn_hash); 422 423 return ret; 424 } 425