1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2021, STMicroelectronics - All Rights Reserved 4 */ 5 6 #include <drvcrypt.h> 7 #include <drvcrypt_acipher.h> 8 #include <initcall.h> 9 #include <stdlib_ext.h> 10 #include <string.h> 11 #include <tee_api_types.h> 12 13 #include "common.h" 14 #include "stm32_pka.h" 15 16 static TEE_Result algo_to_pka_cid(uint32_t algo, 17 enum stm32_pka_curve_id *cid) 18 { 19 switch (algo) { 20 case TEE_ALG_ECDSA_P192: 21 *cid = PKA_NIST_P192; 22 break; 23 case TEE_ALG_ECDSA_P224: 24 *cid = PKA_NIST_P224; 25 break; 26 case TEE_ALG_ECDSA_P256: 27 *cid = PKA_NIST_P256; 28 break; 29 case TEE_ALG_ECDSA_P384: 30 *cid = PKA_NIST_P384; 31 break; 32 case TEE_ALG_ECDSA_P521: 33 *cid = PKA_NIST_P521; 34 break; 35 default: 36 EMSG("algorithm %#"PRIx32" not enabled", algo); 37 return TEE_ERROR_NOT_SUPPORTED; 38 } 39 40 return TEE_SUCCESS; 41 } 42 43 static TEE_Result curve_to_pka_cid(uint32_t curve, 44 enum stm32_pka_curve_id *cid) 45 { 46 switch (curve) { 47 case TEE_ECC_CURVE_NIST_P192: 48 *cid = PKA_NIST_P192; 49 break; 50 case TEE_ECC_CURVE_NIST_P224: 51 *cid = PKA_NIST_P224; 52 break; 53 case TEE_ECC_CURVE_NIST_P256: 54 *cid = PKA_NIST_P256; 55 break; 56 case TEE_ECC_CURVE_NIST_P384: 57 *cid = PKA_NIST_P384; 58 break; 59 case TEE_ECC_CURVE_NIST_P521: 60 *cid = PKA_NIST_P521; 61 break; 62 default: 63 EMSG("curve %#"PRIx32" not enabled", curve); 64 return TEE_ERROR_NOT_SUPPORTED; 65 } 66 67 return TEE_SUCCESS; 68 } 69 70 static TEE_Result stm32_gen_keypair(struct ecc_keypair *key, size_t size_bits) 71 { 72 TEE_Result res = TEE_ERROR_GENERIC; 73 struct stm32_pka_bn d = { }; 74 struct stm32_pka_point pk = { }; 75 enum stm32_pka_curve_id cid = PKA_LAST_CID; 76 size_t bytes = 0; 77 78 if (!key) 79 return TEE_ERROR_BAD_PARAMETERS; 80 81 FMSG("Using PKA"); 82 res = curve_to_pka_cid(key->curve, &cid); 83 if (res) 84 return res; 85 86 res = stm32_pka_get_max_size(&bytes, NULL, cid); 87 if (res) 88 return res; 89 90 if (size_bits > bytes * 8 || 91 crypto_bignum_num_bytes(key->d) > bytes || 92 crypto_bignum_num_bytes(key->x) > bytes || 93 crypto_bignum_num_bytes(key->y) > bytes) 94 return TEE_ERROR_BAD_PARAMETERS; 95 96 d.val = calloc(1, bytes); 97 d.size = bytes; 98 if (!d.val) 99 return TEE_ERROR_OUT_OF_MEMORY; 100 101 /* Private key is a random vector */ 102 res = crypto_rng_read(d.val, d.size); 103 if (res) { 104 free(d.val); 105 return res; 106 } 107 108 pk.x.val = calloc(1, bytes); 109 pk.x.size = bytes; 110 if (!pk.x.val) { 111 free(d.val); 112 return TEE_ERROR_OUT_OF_MEMORY; 113 } 114 115 pk.y.val = calloc(1, bytes); 116 pk.y.size = bytes; 117 if (!pk.y.val) { 118 free(pk.x.val); 119 free(d.val); 120 return TEE_ERROR_OUT_OF_MEMORY; 121 } 122 123 res = stm32_pka_edac_gen_pubkey(&d, &pk, cid); 124 if (res) 125 goto out; 126 127 res = crypto_bignum_bin2bn(d.val, d.size, key->d); 128 if (res) 129 goto out; 130 131 res = crypto_bignum_bin2bn(pk.x.val, pk.x.size, key->x); 132 if (res) 133 goto out; 134 135 res = crypto_bignum_bin2bn(pk.y.val, pk.y.size, key->y); 136 137 out: 138 free(pk.y.val); 139 free(pk.x.val); 140 free_wipe(d.val); 141 142 return res; 143 } 144 145 static TEE_Result sign(uint32_t algo, struct ecc_keypair *key, 146 const uint8_t *msg, size_t msg_size, 147 uint8_t *sig, size_t *sig_len) 148 { 149 TEE_Result res = TEE_ERROR_GENERIC; 150 enum stm32_pka_curve_id cid_from_algo = PKA_LAST_CID; 151 enum stm32_pka_curve_id cid = PKA_LAST_CID; 152 struct stm32_pka_bn d = { }; 153 struct stm32_pka_bn k = { }; 154 struct stm32_pka_bn sig_r = { }; 155 struct stm32_pka_bn sig_s = { }; 156 size_t bytes = 0; 157 158 if (!key || !msg || !sig || !sig_len) 159 return TEE_ERROR_BAD_PARAMETERS; 160 161 if (curve_to_pka_cid(key->curve, &cid) || 162 algo_to_pka_cid(algo, &cid_from_algo) || 163 cid_from_algo != cid) 164 return TEE_ERROR_BAD_PARAMETERS; 165 166 res = stm32_pka_get_max_size(&bytes, NULL, cid); 167 if (res) 168 return res; 169 170 if (crypto_bignum_num_bytes(key->d) > bytes || *sig_len < 2 * bytes) 171 return TEE_ERROR_BAD_PARAMETERS; 172 173 *sig_len = 2 * bytes; 174 175 d.size = crypto_bignum_num_bytes(key->d); 176 d.val = calloc(1, d.size); 177 if (!d.val) 178 return TEE_ERROR_OUT_OF_MEMORY; 179 180 crypto_bignum_bn2bin(key->d, d.val); 181 182 k.val = calloc(1, bytes); 183 k.size = bytes; 184 if (!k.val) { 185 free_wipe(d.val); 186 return TEE_ERROR_OUT_OF_MEMORY; 187 } 188 189 res = crypto_rng_read(k.val, k.size); 190 if (res) 191 goto out; 192 193 sig_r.val = (void *)sig; 194 sig_r.size = bytes; 195 sig_s.val = (void *)(sig + bytes); 196 sig_s.size = bytes; 197 198 res = stm32_pka_ecdsa_sign(msg, msg_size, &sig_r, &sig_s, &d, &k, cid); 199 200 out: 201 free_wipe(k.val); 202 free_wipe(d.val); 203 204 return res; 205 } 206 207 static TEE_Result stm32_sign(struct drvcrypt_sign_data *sdata) 208 { 209 if (!sdata) 210 return TEE_ERROR_BAD_PARAMETERS; 211 212 FMSG("Using PKA"); 213 return sign(sdata->algo, 214 sdata->key, 215 sdata->message.data, 216 sdata->message.length, 217 sdata->signature.data, 218 &sdata->signature.length); 219 } 220 221 static TEE_Result verify(uint32_t algo, struct ecc_public_key *key, 222 const uint8_t *msg, size_t msg_size, 223 const uint8_t *sig, size_t sig_size) 224 { 225 TEE_Result res = TEE_ERROR_GENERIC; 226 struct stm32_pka_bn sig_r = { }; 227 struct stm32_pka_bn sig_s = { }; 228 struct stm32_pka_point pk = { }; 229 enum stm32_pka_curve_id cid_from_algo = PKA_LAST_CID; 230 enum stm32_pka_curve_id cid = PKA_LAST_CID; 231 size_t bytes = 0; 232 233 if (!key || !msg || !sig) 234 return TEE_ERROR_BAD_PARAMETERS; 235 236 if (curve_to_pka_cid(key->curve, &cid) || 237 algo_to_pka_cid(algo, &cid_from_algo) || 238 cid_from_algo != cid) 239 return TEE_ERROR_BAD_PARAMETERS; 240 241 res = stm32_pka_get_max_size(&bytes, NULL, cid); 242 if (res) 243 return res; 244 245 if (sig_size % 2) 246 return TEE_ERROR_BAD_PARAMETERS; 247 248 sig_r.val = (void *)sig; 249 sig_r.size = sig_size / 2; 250 sig_s.val = (void *)(sig + sig_size / 2); 251 sig_s.size = sig_size / 2; 252 253 pk.x.size = crypto_bignum_num_bytes(key->x); 254 pk.x.val = calloc(1, pk.x.size); 255 if (!pk.x.val) 256 return TEE_ERROR_OUT_OF_MEMORY; 257 258 crypto_bignum_bn2bin(key->x, pk.x.val); 259 260 pk.y.size = crypto_bignum_num_bytes(key->y); 261 pk.y.val = calloc(1, pk.y.size); 262 if (!pk.y.val) { 263 free(pk.x.val); 264 return TEE_ERROR_OUT_OF_MEMORY; 265 } 266 267 crypto_bignum_bn2bin(key->y, pk.y.val); 268 269 res = stm32_pka_ecdsa_verif(msg, msg_size, &sig_r, &sig_s, &pk, cid); 270 271 free(pk.y.val); 272 free(pk.x.val); 273 274 return res; 275 } 276 277 static TEE_Result stm32_verify(struct drvcrypt_sign_data *sdata) 278 { 279 if (!sdata) 280 return TEE_ERROR_BAD_PARAMETERS; 281 282 FMSG("Using PKA"); 283 return verify(sdata->algo, 284 sdata->key, 285 sdata->message.data, 286 sdata->message.length, 287 sdata->signature.data, 288 sdata->signature.length); 289 } 290 291 static TEE_Result stm32_alloc_keypair(struct ecc_keypair *s, uint32_t type, 292 size_t size_bits __unused) 293 { 294 if (!s) 295 return TEE_ERROR_BAD_PARAMETERS; 296 297 /* This driver only supports ECDH/ECDSA */ 298 if (type != TEE_TYPE_ECDSA_KEYPAIR && 299 type != TEE_TYPE_ECDH_KEYPAIR) 300 return TEE_ERROR_NOT_IMPLEMENTED; 301 302 FMSG("Using PKA"); 303 memset(s, 0, sizeof(*s)); 304 305 s->d = crypto_bignum_allocate(PKA_MAX_ECC_LEN); 306 if (!s->d) 307 return TEE_ERROR_OUT_OF_MEMORY; 308 309 s->x = crypto_bignum_allocate(PKA_MAX_ECC_LEN); 310 if (!s->x) { 311 crypto_bignum_free(&s->d); 312 return TEE_ERROR_OUT_OF_MEMORY; 313 } 314 315 s->y = crypto_bignum_allocate(PKA_MAX_ECC_LEN); 316 if (!s->y) { 317 crypto_bignum_free(&s->d); 318 crypto_bignum_free(&s->x); 319 return TEE_ERROR_OUT_OF_MEMORY; 320 } 321 322 return TEE_SUCCESS; 323 } 324 325 static TEE_Result stm32_alloc_publickey(struct ecc_public_key *s, uint32_t type, 326 size_t size_bits __unused) 327 { 328 if (!s) 329 return TEE_ERROR_BAD_PARAMETERS; 330 331 /* This driver only supports ECDH/ECDSA */ 332 if (type != TEE_TYPE_ECDSA_PUBLIC_KEY && 333 type != TEE_TYPE_ECDH_PUBLIC_KEY) 334 return TEE_ERROR_NOT_IMPLEMENTED; 335 336 memset(s, 0, sizeof(*s)); 337 338 s->x = crypto_bignum_allocate(PKA_MAX_ECC_LEN); 339 if (!s->x) 340 return TEE_ERROR_OUT_OF_MEMORY; 341 342 s->y = crypto_bignum_allocate(PKA_MAX_ECC_LEN); 343 if (!s->y) { 344 crypto_bignum_free(&s->x); 345 return TEE_ERROR_OUT_OF_MEMORY; 346 } 347 348 return TEE_SUCCESS; 349 } 350 351 static void stm32_free_publickey(struct ecc_public_key *s) 352 { 353 if (!s) 354 return; 355 356 FMSG("Using PKA"); 357 crypto_bignum_free(&s->x); 358 crypto_bignum_free(&s->y); 359 } 360 361 static TEE_Result is_point_on_curve(struct stm32_pka_point *point, 362 enum stm32_pka_curve_id cid) 363 { 364 TEE_Result res = TEE_ERROR_GENERIC; 365 struct stm32_pka_bn r2modn = { }; 366 367 res = stm32_pka_get_max_size(&r2modn.size, NULL, cid); 368 if (res) 369 return res; 370 371 r2modn.val = calloc(1, r2modn.size); 372 if (!r2modn.val) 373 return TEE_ERROR_OUT_OF_MEMORY; 374 375 res = stm32_pka_ecc_compute_montgomery(&r2modn, cid); 376 if (res) 377 goto out; 378 379 res = stm32_pka_is_point_on_curve(point, &r2modn, cid); 380 out: 381 free(r2modn.val); 382 383 return res; 384 } 385 386 static TEE_Result shared_secret(struct ecc_keypair *private_key, 387 struct ecc_public_key *public_key, 388 void *secret, size_t *secret_len) 389 { 390 TEE_Result res = TEE_ERROR_GENERIC; 391 enum stm32_pka_curve_id cid = PKA_LAST_CID; 392 struct stm32_pka_bn d = { }; 393 struct stm32_pka_point pk = { }; 394 struct stm32_pka_point result = { }; 395 size_t bytes = 0; 396 397 if (!private_key || !public_key || !secret || !secret_len) 398 return TEE_ERROR_BAD_PARAMETERS; 399 400 if (private_key->curve != public_key->curve || 401 curve_to_pka_cid(public_key->curve, &cid)) 402 return TEE_ERROR_BAD_PARAMETERS; 403 404 res = stm32_pka_get_max_size(&bytes, NULL, cid); 405 if (res) 406 return res; 407 408 /* Convert provided value to PKA format */ 409 pk.x.size = crypto_bignum_num_bytes(public_key->x); 410 pk.x.val = calloc(1, pk.x.size); 411 if (!pk.x.val) 412 return TEE_ERROR_OUT_OF_MEMORY; 413 414 crypto_bignum_bn2bin(public_key->x, pk.x.val); 415 416 pk.y.size = crypto_bignum_num_bytes(public_key->y); 417 pk.y.val = calloc(1, pk.y.size); 418 if (!pk.y.val) { 419 res = TEE_ERROR_OUT_OF_MEMORY; 420 goto out; 421 } 422 423 crypto_bignum_bn2bin(public_key->y, pk.y.val); 424 425 d.size = crypto_bignum_num_bytes(private_key->d); 426 d.val = calloc(1, d.size); 427 if (!d.val) { 428 res = TEE_ERROR_OUT_OF_MEMORY; 429 goto out; 430 } 431 432 crypto_bignum_bn2bin(private_key->d, d.val); 433 434 /* Allocate intermediate point */ 435 result.x.size = bytes; 436 result.x.val = calloc(1, result.x.size); 437 if (!result.x.val) { 438 res = TEE_ERROR_OUT_OF_MEMORY; 439 goto out; 440 } 441 442 result.y.size = bytes; 443 result.y.val = calloc(1, result.y.size); 444 if (!result.y.val) { 445 res = TEE_ERROR_OUT_OF_MEMORY; 446 goto out; 447 } 448 449 /* 450 * We should check that provided public_key point is on the selected 451 * curve. 452 */ 453 res = is_point_on_curve(&pk, cid); 454 if (res) 455 goto out; 456 457 res = stm32_pka_ecc_scalar_mul(&d, &pk, &result, cid); 458 if (res) 459 goto out; 460 461 if (*secret_len < result.x.size) { 462 res = TEE_ERROR_BAD_PARAMETERS; 463 goto out; 464 } 465 466 memcpy(secret, result.x.val, result.x.size); 467 *secret_len = result.x.size; 468 out: 469 free_wipe(result.y.val); 470 free_wipe(result.x.val); 471 free_wipe(d.val); 472 free(pk.y.val); 473 free(pk.x.val); 474 475 return res; 476 } 477 478 static TEE_Result stm32_shared_secret(struct drvcrypt_secret_data *sdata) 479 { 480 if (!sdata) 481 return TEE_ERROR_BAD_PARAMETERS; 482 483 FMSG("Using PKA"); 484 return shared_secret(sdata->key_priv, 485 sdata->key_pub, 486 sdata->secret.data, 487 &sdata->secret.length); 488 } 489 490 /* 491 * Registration of the ECC Driver. 492 */ 493 static struct drvcrypt_ecc driver_ecc = { 494 .alloc_keypair = stm32_alloc_keypair, 495 .alloc_publickey = stm32_alloc_publickey, 496 .free_publickey = stm32_free_publickey, 497 .gen_keypair = stm32_gen_keypair, 498 .sign = stm32_sign, 499 .verify = stm32_verify, 500 .shared_secret = stm32_shared_secret, 501 }; 502 503 TEE_Result stm32_register_ecc(void) 504 { 505 return drvcrypt_register_ecc(&driver_ecc); 506 } 507