1 /* 2 * Copyright (C) 2017 - This file is part of libecc project 3 * 4 * Authors: 5 * Ryad BENADJILA <ryadbenadjila@gmail.com> 6 * Arnaud EBALARD <arnaud.ebalard@ssi.gouv.fr> 7 * Jean-Pierre FLORI <jean-pierre.flori@ssi.gouv.fr> 8 * 9 * Contributors: 10 * Nicolas VIVET <nicolas.vivet@ssi.gouv.fr> 11 * Karim KHALFALLAH <karim.khalfallah@ssi.gouv.fr> 12 * 13 * This software is licensed under a dual BSD and GPL v2 license. 14 * See LICENSE file at the root folder of the project. 15 */ 16 #include <libecc/sig/ec_key.h> 17 #include <libecc/sig/sig_algs.h> 18 #include <libecc/curves/curves.h> 19 20 /* 21 * Check if given private key 'A' has been initialized. Returns 0 on success, 22 * -1 on error 23 */ 24 int priv_key_check_initialized(const ec_priv_key *A) 25 { 26 int ret = 0; 27 28 MUST_HAVE(((A != NULL) && (A->magic == PRIV_KEY_MAGIC) && (A->params != NULL)), ret, err); 29 30 err: 31 return ret; 32 } 33 34 /* 35 * Same as previous but also verifies that the signature algorithm type does 36 * match the one passed using 'alg_type'. Returns 0 on success, -1 on error. 37 */ 38 int priv_key_check_initialized_and_type(const ec_priv_key *A, 39 ec_alg_type alg_type) 40 { 41 int ret = 0; 42 43 MUST_HAVE(((A != NULL) && (A->magic == PRIV_KEY_MAGIC) && 44 (A->params != NULL) && (A->key_type == alg_type)), ret, err); 45 46 err: 47 return ret; 48 } 49 50 /* 51 * Import a private key from a buffer with known EC parameters and algorithm 52 * Note that no sanity check is performed by the function to verify key 53 * is valid for params. Also note that no deep copy of pointed params is 54 * performed. The function returns 0 on success, -1 on error. 55 */ 56 int ec_priv_key_import_from_buf(ec_priv_key *priv_key, 57 const ec_params *params, 58 const u8 *priv_key_buf, u8 priv_key_buf_len, 59 ec_alg_type ec_key_alg) 60 { 61 int ret; 62 63 MUST_HAVE((priv_key != NULL), ret, err); 64 65 ret = nn_init_from_buf(&(priv_key->x), priv_key_buf, priv_key_buf_len); EG(ret, err); 66 67 /* Set key type and pointer to EC params */ 68 priv_key->key_type = ec_key_alg; 69 priv_key->params = (const ec_params *)params; 70 priv_key->magic = PRIV_KEY_MAGIC; 71 72 err: 73 return ret; 74 } 75 76 /* 77 * Export a private key 'priv_key' to a buffer 'priv_key_buf' of length 78 * 'priv_key_buf_len'. The function returns 0 on sucess, -1 on error. 79 */ 80 int ec_priv_key_export_to_buf(const ec_priv_key *priv_key, u8 *priv_key_buf, 81 u8 priv_key_buf_len) 82 { 83 int ret; 84 bitcnt_t blen; 85 86 ret = priv_key_check_initialized(priv_key); EG(ret, err); 87 88 /* 89 * Check that there is enough room to export our private key without 90 * losing information. 91 */ 92 ret = nn_bitlen(&(priv_key->x), &blen); EG(ret, err); 93 MUST_HAVE(((8 * (u32)priv_key_buf_len) >= (u32)blen), ret, err); 94 95 /* Export our private key */ 96 ret = nn_export_to_buf(priv_key_buf, priv_key_buf_len, &(priv_key->x)); 97 98 err: 99 return ret; 100 } 101 102 /* 103 * Check if given public key 'A' has been initialized. Returns 0 on success, 104 * -1 on error 105 */ 106 int pub_key_check_initialized(const ec_pub_key *A) 107 { 108 int ret = 0; 109 110 MUST_HAVE(((A != NULL) && (A->magic == PUB_KEY_MAGIC) && (A->params != NULL)), ret, err); 111 112 err: 113 return ret; 114 } 115 116 /* 117 * Same as previous but also verifies that the signature algorithm type does 118 * match the one passed using 'alg_type'. Returns 0 on success, -1 on error. 119 */ 120 int pub_key_check_initialized_and_type(const ec_pub_key *A, 121 ec_alg_type alg_type) 122 { 123 int ret = 0; 124 125 MUST_HAVE(((A != NULL) && (A->magic == PUB_KEY_MAGIC) && 126 (A->params != NULL) && (A->key_type == alg_type)), ret, err); 127 128 err: 129 return ret; 130 } 131 132 /* 133 * Import a public key from a buffer with known EC parameters and algorithm 134 * Note that no sanity check is performed by the function to verify key 135 * is valid for params. Also note that no deep copy of pointed params is 136 * performed. The buffer contains projective point coordinates. The function 137 * returns 0 on success, -1 on error. 138 */ 139 int ec_pub_key_import_from_buf(ec_pub_key *pub_key, const ec_params *params, 140 const u8 *pub_key_buf, u8 pub_key_buf_len, 141 ec_alg_type ec_key_alg) 142 { 143 int ret, isone, check; 144 145 MUST_HAVE(((pub_key != NULL) && (pub_key_buf != NULL) && (params != NULL)), ret, err); 146 147 /* Import the projective point */ 148 ret = prj_pt_import_from_buf(&(pub_key->y), 149 pub_key_buf, pub_key_buf_len, 150 (ec_shortw_crv_src_t)&(params->ec_curve)); EG(ret, err); 151 152 /* If the cofactor of the curve is not 1, we check that 153 * our public key is indeed in the sub-group generated by 154 * our generator. 155 * NOTE: this is indeed a 'costly' operation, but it is necessary 156 * when we do not trust the public key that is provided, which can 157 * be the case in some protocols. 158 */ 159 ret = nn_isone(&(params->ec_gen_cofactor), &isone); EG(ret, err); 160 if (!isone) { 161 ret = check_prj_pt_order(&(pub_key->y), &(params->ec_gen_order), PUBLIC_PT, &check); EG(ret, err); 162 MUST_HAVE(check, ret, err); 163 } 164 165 /* Set key type and pointer to EC params */ 166 pub_key->key_type = ec_key_alg; 167 pub_key->params = (const ec_params *)params; 168 pub_key->magic = PUB_KEY_MAGIC; 169 170 err: 171 return ret; 172 } 173 174 /* 175 * Import a public key from a buffer with known EC parameters and algorithm 176 * Note that no sanity check is performed by the function to verify key 177 * is valid for params. Also note that no deep copy of pointed params is 178 * performed. The buffer contains affine point coordinates. The function 179 * returns 0 on success, -1 on error. 180 */ 181 int ec_pub_key_import_from_aff_buf(ec_pub_key *pub_key, const ec_params *params, 182 const u8 *pub_key_buf, u8 pub_key_buf_len, 183 ec_alg_type ec_key_alg) 184 { 185 int ret, isone, check; 186 187 MUST_HAVE(((pub_key != NULL) && (pub_key_buf != NULL) && (params != NULL)), ret, err); 188 189 /* Import the projective point */ 190 ret = prj_pt_import_from_aff_buf(&(pub_key->y), 191 pub_key_buf, pub_key_buf_len, 192 (ec_shortw_crv_src_t)&(params->ec_curve)); EG(ret, err); 193 194 /* If the cofactor of the curve is not 1, we check that 195 * our public key is indeed in the sub-group generated by 196 * our generator. 197 * NOTE: this is indeed a 'costly' operation, but it is necessary 198 * when we do not trust the public key that is provided, which can 199 * be the case in some protocols. 200 */ 201 ret = nn_isone(&(params->ec_gen_cofactor), &isone); EG(ret, err); 202 if (!isone){ 203 ret = check_prj_pt_order(&(pub_key->y), &(params->ec_gen_order), PUBLIC_PT, &check); EG(ret, err); 204 MUST_HAVE(check, ret, err); 205 } 206 207 /* Set key type and pointer to EC params */ 208 pub_key->key_type = ec_key_alg; 209 pub_key->params = (const ec_params *)params; 210 pub_key->magic = PUB_KEY_MAGIC; 211 212 err: 213 return ret; 214 } 215 216 /* 217 * Export a public key to a projective point buffer. The function returns 0 on 218 * success, -1 on error. 219 */ 220 int ec_pub_key_export_to_buf(const ec_pub_key *pub_key, u8 *pub_key_buf, 221 u8 pub_key_buf_len) 222 { 223 int ret; 224 225 ret = pub_key_check_initialized(pub_key); EG(ret, err); 226 ret = prj_pt_export_to_buf(&(pub_key->y), pub_key_buf, pub_key_buf_len); 227 228 err: 229 return ret; 230 } 231 232 /* 233 * Export a public key to an affine point buffer. The function returns 0 on 234 * success, -1 on error. 235 */ 236 int ec_pub_key_export_to_aff_buf(const ec_pub_key *pub_key, u8 *pub_key_buf, 237 u8 pub_key_buf_len) 238 { 239 int ret; 240 241 ret = pub_key_check_initialized(pub_key); EG(ret, err); 242 ret = prj_pt_export_to_aff_buf(&(pub_key->y), pub_key_buf, 243 pub_key_buf_len); 244 245 err: 246 return ret; 247 } 248 249 /* 250 * Check if given key pair 'A' has been initialized. Returns 0 on success, 251 * -1 on error 252 */ 253 int key_pair_check_initialized(const ec_key_pair *A) 254 { 255 int ret; 256 257 MUST_HAVE((A != NULL), ret, err); 258 259 ret = priv_key_check_initialized(&A->priv_key); EG(ret, err); 260 ret = pub_key_check_initialized(&A->pub_key); 261 262 err: 263 return ret; 264 } 265 266 /* 267 * Same as previous but also verifies that the signature algorithm type does 268 * match the one passed using 'alg_type'. Returns 0 on success, -1 on error. 269 */ 270 int key_pair_check_initialized_and_type(const ec_key_pair *A, 271 ec_alg_type alg_type) 272 { 273 int ret; 274 275 MUST_HAVE((A != NULL), ret, err); 276 277 ret = priv_key_check_initialized_and_type(&A->priv_key, alg_type); EG(ret, err); 278 ret = pub_key_check_initialized_and_type(&A->pub_key, alg_type); 279 280 err: 281 return ret; 282 } 283 284 /* 285 * Import a key pair from a buffer representing the private key. The associated 286 * public key is computed from the private key. The function returns 0 on 287 * success, -1 on error. 288 */ 289 int ec_key_pair_import_from_priv_key_buf(ec_key_pair *kp, 290 const ec_params *params, 291 const u8 *priv_key, u8 priv_key_len, 292 ec_alg_type ec_key_alg) 293 { 294 int ret; 295 296 MUST_HAVE((kp != NULL), ret, err); 297 298 /* Import private key */ 299 ret = ec_priv_key_import_from_buf(&(kp->priv_key), params, priv_key, 300 priv_key_len, ec_key_alg); EG(ret, err); 301 /* Generate associated public key. */ 302 ret = init_pubkey_from_privkey(&(kp->pub_key), &(kp->priv_key)); 303 304 err: 305 return ret; 306 } 307 308 /* 309 * Import a structured private key to buffer. The structure allows some sanity 310 * checks. The function returns 0 on success, -1 on error. 311 */ 312 int ec_structured_priv_key_import_from_buf(ec_priv_key *priv_key, 313 const ec_params *params, 314 const u8 *priv_key_buf, 315 u8 priv_key_buf_len, 316 ec_alg_type ec_key_alg) 317 { 318 u8 metadata_len = (3 * sizeof(u8)); 319 u8 crv_name_len; 320 u32 len; 321 int ret; 322 323 /* We first pull the metadata, consisting of: 324 * - One byte = the key type (public or private) 325 * - One byte = the algorithm type (ECDSA, ECKCDSA, ...) 326 * - One byte = the curve type (FRP256V1, ...) 327 */ 328 MUST_HAVE((priv_key != NULL) && (priv_key_buf != NULL) && (priv_key_buf_len > metadata_len), ret, err); 329 MUST_HAVE((params != NULL) && (params->curve_name != NULL), ret, err); 330 331 /* Pull and check the key type */ 332 MUST_HAVE((EC_PRIVKEY == priv_key_buf[0]), ret, err); 333 334 /* Pull and check the algorithm type */ 335 MUST_HAVE((ec_key_alg == priv_key_buf[1]), ret, err); 336 337 /* Pull and check the curve type */ 338 ret = local_strlen((const char *)params->curve_name, &len); EG(ret, err); 339 len += 1; 340 MUST_HAVE((len < 256), ret, err); 341 crv_name_len = (u8)len; 342 343 ret = ec_check_curve_type_and_name((ec_curve_type) (priv_key_buf[2]), 344 params->curve_name, crv_name_len); EG(ret, err); 345 ret = ec_priv_key_import_from_buf(priv_key, params, 346 priv_key_buf + metadata_len, 347 (u8)(priv_key_buf_len - metadata_len), 348 ec_key_alg); 349 350 err: 351 return ret; 352 } 353 354 /* 355 * Export a structured private key to buffer. The structure allows some sanity 356 * checks. The function returns 0 on success, -1 on error. 357 */ 358 int ec_structured_priv_key_export_to_buf(const ec_priv_key *priv_key, 359 u8 *priv_key_buf, u8 priv_key_buf_len) 360 { 361 362 u8 metadata_len = (3 * sizeof(u8)); 363 const u8 *curve_name; 364 u8 curve_name_len; 365 u32 len; 366 ec_curve_type curve_type; 367 int ret; 368 369 ret = priv_key_check_initialized(priv_key); EG(ret, err); 370 371 MUST_HAVE((priv_key_buf != NULL) && (priv_key_buf_len > metadata_len) && (priv_key->params->curve_name != NULL), ret, err); 372 373 /* 374 * We first put the metadata, consisting on: 375 * - One byte = the key type (public or private) 376 * - One byte = the algorithm type (ECDSA, ECKCDSA, ...) 377 * - One byte = the curve type (FRP256V1, ...) 378 */ 379 380 /* Push the key type */ 381 priv_key_buf[0] = (u8)EC_PRIVKEY; 382 383 /* Push the algorithm type */ 384 priv_key_buf[1] = (u8)priv_key->key_type; 385 386 /* Push the curve type */ 387 curve_name = priv_key->params->curve_name; 388 389 ret = local_strlen((const char *)curve_name, &len); EG(ret, err); 390 len += 1; 391 MUST_HAVE((len < 256), ret, err); 392 curve_name_len = (u8)len; 393 394 ret = ec_get_curve_type_by_name(curve_name, curve_name_len, &curve_type); EG(ret, err); 395 priv_key_buf[2] = (u8)curve_type; 396 397 /* Push the raw private key buffer */ 398 ret = ec_priv_key_export_to_buf(priv_key, priv_key_buf + metadata_len, 399 (u8)(priv_key_buf_len - metadata_len)); 400 401 err: 402 return ret; 403 } 404 405 /* 406 * Import a structured pub key from buffer. The structure allows some sanity 407 * checks. The function returns 0 on success, -1 on error. 408 */ 409 int ec_structured_pub_key_import_from_buf(ec_pub_key *pub_key, 410 const ec_params *params, 411 const u8 *pub_key_buf, 412 u8 pub_key_buf_len, 413 ec_alg_type ec_key_alg) 414 { 415 u8 metadata_len = (3 * sizeof(u8)); 416 u8 crv_name_len; 417 u32 len; 418 int ret; 419 420 MUST_HAVE((pub_key_buf != NULL) && (pub_key_buf_len > metadata_len), ret, err); 421 MUST_HAVE((params != NULL) && (params->curve_name != NULL), ret, err); 422 423 /* 424 * We first pull the metadata, consisting of: 425 * - One byte = the key type (public or private) 426 * - One byte = the algorithm type (ECDSA, ECKCDSA, ...) 427 * - One byte = the curve type (FRP256V1, ...) 428 */ 429 430 /* Pull and check the key type */ 431 MUST_HAVE((EC_PUBKEY == pub_key_buf[0]), ret, err); 432 433 /* Pull and check the algorithm type */ 434 MUST_HAVE((ec_key_alg == pub_key_buf[1]), ret, err); 435 436 /* Pull and check the curve type */ 437 ret = local_strlen((const char *)params->curve_name, &len); EG(ret, err); 438 len += 1; 439 MUST_HAVE((len < 256), ret, err); 440 crv_name_len = (u8)len; 441 442 ret = ec_check_curve_type_and_name((ec_curve_type) (pub_key_buf[2]), 443 params->curve_name, crv_name_len); EG(ret, err); 444 ret = ec_pub_key_import_from_buf(pub_key, params, 445 pub_key_buf + metadata_len, 446 (u8)(pub_key_buf_len - metadata_len), 447 ec_key_alg); 448 449 err: 450 return ret; 451 } 452 453 /* 454 * Export a structured pubate key to buffer. The structure allows some sanity 455 * checks. The function returns 0 on success, -1 on error. 456 */ 457 int ec_structured_pub_key_export_to_buf(const ec_pub_key *pub_key, 458 u8 *pub_key_buf, u8 pub_key_buf_len) 459 { 460 u8 metadata_len = (3 * sizeof(u8)); 461 const u8 *curve_name; 462 u8 curve_name_len; 463 u32 len; 464 ec_curve_type curve_type; 465 int ret; 466 467 ret = pub_key_check_initialized(pub_key); EG(ret, err); 468 469 MUST_HAVE((pub_key_buf != NULL) && (pub_key_buf_len > metadata_len), ret, err); 470 MUST_HAVE((pub_key->params->curve_name != NULL), ret, err); 471 472 /* 473 * We first put the metadata, consisting of: 474 * - One byte = the key type (public or private) 475 * - One byte = the algorithm type (ECDSA, ECKCDSA, ...) 476 * - One byte = the curve type (FRP256V1, ...) 477 */ 478 479 /* Push the key type */ 480 pub_key_buf[0] = (u8)EC_PUBKEY; 481 482 /* Push the algorithm type */ 483 pub_key_buf[1] = (u8)pub_key->key_type; 484 485 /* Push the curve type */ 486 curve_name = pub_key->params->curve_name; 487 488 ret = local_strlen((const char *)curve_name, &len); EG(ret, err); 489 len += 1; 490 MUST_HAVE((len < 256), ret, err); 491 curve_name_len = (u8)len; 492 493 ret = ec_get_curve_type_by_name(curve_name, curve_name_len, &curve_type); EG(ret, err); 494 pub_key_buf[2] = (u8)curve_type; 495 496 /* Push the raw pub key buffer */ 497 ret = ec_pub_key_export_to_buf(pub_key, pub_key_buf + metadata_len, 498 (u8)(pub_key_buf_len - metadata_len)); 499 500 err: 501 return ret; 502 } 503 504 /* 505 * Import a key pair from a structured private key buffer. The structure allows 506 * some sanity checks. The function returns 0 on success, -1 on error. 507 */ 508 int ec_structured_key_pair_import_from_priv_key_buf(ec_key_pair *kp, 509 const ec_params *params, 510 const u8 *priv_key_buf, 511 u8 priv_key_buf_len, 512 ec_alg_type ec_key_alg) 513 { 514 u8 metadata_len = (3 * sizeof(u8)); 515 u8 crv_name_len; 516 u32 len; 517 int ret; 518 519 MUST_HAVE((kp != NULL) && (priv_key_buf != NULL) && (priv_key_buf_len > metadata_len), ret, err); 520 MUST_HAVE((params != NULL) && (params->curve_name != NULL), ret, err); 521 522 /* We first pull the metadata, consisting on: 523 * - One byte = the key type (public or private) 524 * - One byte = the algorithm type (ECDSA, ECKCDSA, ...) 525 * - One byte = the curve type (FRP256V1, ...) 526 */ 527 528 /* Pull and check the key type */ 529 MUST_HAVE((EC_PRIVKEY == priv_key_buf[0]), ret, err); 530 531 /* Pull and check the algorithm type */ 532 MUST_HAVE((ec_key_alg == priv_key_buf[1]), ret, err); 533 534 /* Pull and check the curve type */ 535 ret = local_strlen((const char *)params->curve_name, &len); EG(ret, err); 536 len += 1; 537 MUST_HAVE((len < 256), ret, err); 538 crv_name_len = (u8)len; 539 540 ret = ec_check_curve_type_and_name((ec_curve_type) (priv_key_buf[2]), 541 params->curve_name, crv_name_len); EG(ret, err); 542 ret = ec_key_pair_import_from_priv_key_buf(kp, params, 543 priv_key_buf + metadata_len, 544 (u8)(priv_key_buf_len - metadata_len), 545 ec_key_alg); 546 547 err: 548 return ret; 549 } 550 551 /* 552 * Import a key pair from a two structured key buffer (private and public one) 553 * The function does not verify the coherency between private and public parts. 554 * The function returns 0 on success, -1 on error. 555 * 556 * NOTE: please use this API with care as it does not check the consistency 557 * between the private and public keys! On one side, this "saves" a costly 558 * scalar multiplication when there is confidence in the source of the buffers, 559 * but on the other side the user of the API MUST check the source (integrity) 560 * of the private/public key pair. If unsure, it is advised to use the 561 * ec_structured_key_pair_import_from_priv_key_buf API that safely derives the 562 * public key from the private key. 563 * 564 */ 565 int ec_structured_key_pair_import_from_buf(ec_key_pair *kp, 566 const ec_params *params, 567 const u8 *priv_key_buf, 568 u8 priv_key_buf_len, 569 const u8 *pub_key_buf, 570 u8 pub_key_buf_len, 571 ec_alg_type ec_key_alg) 572 { 573 int ret; 574 575 MUST_HAVE((kp != NULL), ret, err); 576 577 ret = ec_structured_pub_key_import_from_buf(&kp->pub_key, params, 578 pub_key_buf, 579 pub_key_buf_len, 580 ec_key_alg); EG(ret, err); 581 ret = ec_structured_priv_key_import_from_buf(&kp->priv_key, params, 582 priv_key_buf, 583 priv_key_buf_len, 584 ec_key_alg); 585 586 err: 587 return ret; 588 } 589 590 /* 591 * Generate a public/private key pair for given signature algorithm, using 592 * given EC params. The function returns 0 on success, -1 on error. 593 */ 594 int ec_key_pair_gen(ec_key_pair *kp, const ec_params *params, 595 ec_alg_type ec_key_alg) 596 { 597 int ret; 598 599 MUST_HAVE((kp != NULL) && (params != NULL), ret, err); 600 601 /* Get a random value in ]0,q[ */ 602 ret = nn_get_random_mod(&(kp->priv_key.x), &(params->ec_gen_order)); EG(ret, err); 603 604 /* Set key type and pointer to EC params for private key */ 605 kp->priv_key.key_type = ec_key_alg; 606 kp->priv_key.params = (const ec_params *)params; 607 kp->priv_key.magic = PRIV_KEY_MAGIC; 608 609 /* Call our private key generation function */ 610 ret = gen_priv_key(&(kp->priv_key)); EG(ret, err); 611 612 /* Generate associated public key. */ 613 ret = init_pubkey_from_privkey(&(kp->pub_key), &(kp->priv_key)); 614 615 err: 616 if (ret && (kp != NULL)) { 617 IGNORE_RET_VAL(local_memset(kp, 0, sizeof(ec_key_pair))); 618 } 619 return ret; 620 } 621