diff options
author | djm <> | 2012-10-13 21:25:14 +0000 |
---|---|---|
committer | djm <> | 2012-10-13 21:25:14 +0000 |
commit | 93723b50b639d8dc717bc1bf463fd46e1b321239 (patch) | |
tree | 281e0a29ae8f87a8c47fbd4deaa1f3d48b8cc5c1 /src/lib/libcrypto/ec/ec2_smpl.c | |
parent | 65e72ac55a6405783db7a12d7e35a7561d46005b (diff) | |
download | openbsd-93723b50b639d8dc717bc1bf463fd46e1b321239.tar.gz openbsd-93723b50b639d8dc717bc1bf463fd46e1b321239.tar.bz2 openbsd-93723b50b639d8dc717bc1bf463fd46e1b321239.zip |
resolve conflicts
Diffstat (limited to 'src/lib/libcrypto/ec/ec2_smpl.c')
-rw-r--r-- | src/lib/libcrypto/ec/ec2_smpl.c | 351 |
1 files changed, 14 insertions, 337 deletions
diff --git a/src/lib/libcrypto/ec/ec2_smpl.c b/src/lib/libcrypto/ec/ec2_smpl.c index 03deae6674..e0e59c7d82 100644 --- a/src/lib/libcrypto/ec/ec2_smpl.c +++ b/src/lib/libcrypto/ec/ec2_smpl.c | |||
@@ -71,10 +71,20 @@ | |||
71 | 71 | ||
72 | #include "ec_lcl.h" | 72 | #include "ec_lcl.h" |
73 | 73 | ||
74 | #ifndef OPENSSL_NO_EC2M | ||
75 | |||
76 | #ifdef OPENSSL_FIPS | ||
77 | #include <openssl/fips.h> | ||
78 | #endif | ||
79 | |||
74 | 80 | ||
75 | const EC_METHOD *EC_GF2m_simple_method(void) | 81 | const EC_METHOD *EC_GF2m_simple_method(void) |
76 | { | 82 | { |
83 | #ifdef OPENSSL_FIPS | ||
84 | return fips_ec_gf2m_simple_method(); | ||
85 | #else | ||
77 | static const EC_METHOD ret = { | 86 | static const EC_METHOD ret = { |
87 | EC_FLAGS_DEFAULT_OCT, | ||
78 | NID_X9_62_characteristic_two_field, | 88 | NID_X9_62_characteristic_two_field, |
79 | ec_GF2m_simple_group_init, | 89 | ec_GF2m_simple_group_init, |
80 | ec_GF2m_simple_group_finish, | 90 | ec_GF2m_simple_group_finish, |
@@ -93,9 +103,7 @@ const EC_METHOD *EC_GF2m_simple_method(void) | |||
93 | 0 /* get_Jprojective_coordinates_GFp */, | 103 | 0 /* get_Jprojective_coordinates_GFp */, |
94 | ec_GF2m_simple_point_set_affine_coordinates, | 104 | ec_GF2m_simple_point_set_affine_coordinates, |
95 | ec_GF2m_simple_point_get_affine_coordinates, | 105 | ec_GF2m_simple_point_get_affine_coordinates, |
96 | ec_GF2m_simple_set_compressed_coordinates, | 106 | 0,0,0, |
97 | ec_GF2m_simple_point2oct, | ||
98 | ec_GF2m_simple_oct2point, | ||
99 | ec_GF2m_simple_add, | 107 | ec_GF2m_simple_add, |
100 | ec_GF2m_simple_dbl, | 108 | ec_GF2m_simple_dbl, |
101 | ec_GF2m_simple_invert, | 109 | ec_GF2m_simple_invert, |
@@ -118,6 +126,7 @@ const EC_METHOD *EC_GF2m_simple_method(void) | |||
118 | 0 /* field_set_to_one */ }; | 126 | 0 /* field_set_to_one */ }; |
119 | 127 | ||
120 | return &ret; | 128 | return &ret; |
129 | #endif | ||
121 | } | 130 | } |
122 | 131 | ||
123 | 132 | ||
@@ -405,340 +414,6 @@ int ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *group, const EC_ | |||
405 | return ret; | 414 | return ret; |
406 | } | 415 | } |
407 | 416 | ||
408 | |||
409 | /* Calculates and sets the affine coordinates of an EC_POINT from the given | ||
410 | * compressed coordinates. Uses algorithm 2.3.4 of SEC 1. | ||
411 | * Note that the simple implementation only uses affine coordinates. | ||
412 | * | ||
413 | * The method is from the following publication: | ||
414 | * | ||
415 | * Harper, Menezes, Vanstone: | ||
416 | * "Public-Key Cryptosystems with Very Small Key Lengths", | ||
417 | * EUROCRYPT '92, Springer-Verlag LNCS 658, | ||
418 | * published February 1993 | ||
419 | * | ||
420 | * US Patents 6,141,420 and 6,618,483 (Vanstone, Mullin, Agnew) describe | ||
421 | * the same method, but claim no priority date earlier than July 29, 1994 | ||
422 | * (and additionally fail to cite the EUROCRYPT '92 publication as prior art). | ||
423 | */ | ||
424 | int ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *point, | ||
425 | const BIGNUM *x_, int y_bit, BN_CTX *ctx) | ||
426 | { | ||
427 | BN_CTX *new_ctx = NULL; | ||
428 | BIGNUM *tmp, *x, *y, *z; | ||
429 | int ret = 0, z0; | ||
430 | |||
431 | /* clear error queue */ | ||
432 | ERR_clear_error(); | ||
433 | |||
434 | if (ctx == NULL) | ||
435 | { | ||
436 | ctx = new_ctx = BN_CTX_new(); | ||
437 | if (ctx == NULL) | ||
438 | return 0; | ||
439 | } | ||
440 | |||
441 | y_bit = (y_bit != 0) ? 1 : 0; | ||
442 | |||
443 | BN_CTX_start(ctx); | ||
444 | tmp = BN_CTX_get(ctx); | ||
445 | x = BN_CTX_get(ctx); | ||
446 | y = BN_CTX_get(ctx); | ||
447 | z = BN_CTX_get(ctx); | ||
448 | if (z == NULL) goto err; | ||
449 | |||
450 | if (!BN_GF2m_mod_arr(x, x_, group->poly)) goto err; | ||
451 | if (BN_is_zero(x)) | ||
452 | { | ||
453 | if (!BN_GF2m_mod_sqrt_arr(y, &group->b, group->poly, ctx)) goto err; | ||
454 | } | ||
455 | else | ||
456 | { | ||
457 | if (!group->meth->field_sqr(group, tmp, x, ctx)) goto err; | ||
458 | if (!group->meth->field_div(group, tmp, &group->b, tmp, ctx)) goto err; | ||
459 | if (!BN_GF2m_add(tmp, &group->a, tmp)) goto err; | ||
460 | if (!BN_GF2m_add(tmp, x, tmp)) goto err; | ||
461 | if (!BN_GF2m_mod_solve_quad_arr(z, tmp, group->poly, ctx)) | ||
462 | { | ||
463 | unsigned long err = ERR_peek_last_error(); | ||
464 | |||
465 | if (ERR_GET_LIB(err) == ERR_LIB_BN && ERR_GET_REASON(err) == BN_R_NO_SOLUTION) | ||
466 | { | ||
467 | ERR_clear_error(); | ||
468 | ECerr(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSED_POINT); | ||
469 | } | ||
470 | else | ||
471 | ECerr(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_BN_LIB); | ||
472 | goto err; | ||
473 | } | ||
474 | z0 = (BN_is_odd(z)) ? 1 : 0; | ||
475 | if (!group->meth->field_mul(group, y, x, z, ctx)) goto err; | ||
476 | if (z0 != y_bit) | ||
477 | { | ||
478 | if (!BN_GF2m_add(y, y, x)) goto err; | ||
479 | } | ||
480 | } | ||
481 | |||
482 | if (!EC_POINT_set_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err; | ||
483 | |||
484 | ret = 1; | ||
485 | |||
486 | err: | ||
487 | BN_CTX_end(ctx); | ||
488 | if (new_ctx != NULL) | ||
489 | BN_CTX_free(new_ctx); | ||
490 | return ret; | ||
491 | } | ||
492 | |||
493 | |||
494 | /* Converts an EC_POINT to an octet string. | ||
495 | * If buf is NULL, the encoded length will be returned. | ||
496 | * If the length len of buf is smaller than required an error will be returned. | ||
497 | */ | ||
498 | size_t ec_GF2m_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form, | ||
499 | unsigned char *buf, size_t len, BN_CTX *ctx) | ||
500 | { | ||
501 | size_t ret; | ||
502 | BN_CTX *new_ctx = NULL; | ||
503 | int used_ctx = 0; | ||
504 | BIGNUM *x, *y, *yxi; | ||
505 | size_t field_len, i, skip; | ||
506 | |||
507 | if ((form != POINT_CONVERSION_COMPRESSED) | ||
508 | && (form != POINT_CONVERSION_UNCOMPRESSED) | ||
509 | && (form != POINT_CONVERSION_HYBRID)) | ||
510 | { | ||
511 | ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_INVALID_FORM); | ||
512 | goto err; | ||
513 | } | ||
514 | |||
515 | if (EC_POINT_is_at_infinity(group, point)) | ||
516 | { | ||
517 | /* encodes to a single 0 octet */ | ||
518 | if (buf != NULL) | ||
519 | { | ||
520 | if (len < 1) | ||
521 | { | ||
522 | ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL); | ||
523 | return 0; | ||
524 | } | ||
525 | buf[0] = 0; | ||
526 | } | ||
527 | return 1; | ||
528 | } | ||
529 | |||
530 | |||
531 | /* ret := required output buffer length */ | ||
532 | field_len = (EC_GROUP_get_degree(group) + 7) / 8; | ||
533 | ret = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len; | ||
534 | |||
535 | /* if 'buf' is NULL, just return required length */ | ||
536 | if (buf != NULL) | ||
537 | { | ||
538 | if (len < ret) | ||
539 | { | ||
540 | ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL); | ||
541 | goto err; | ||
542 | } | ||
543 | |||
544 | if (ctx == NULL) | ||
545 | { | ||
546 | ctx = new_ctx = BN_CTX_new(); | ||
547 | if (ctx == NULL) | ||
548 | return 0; | ||
549 | } | ||
550 | |||
551 | BN_CTX_start(ctx); | ||
552 | used_ctx = 1; | ||
553 | x = BN_CTX_get(ctx); | ||
554 | y = BN_CTX_get(ctx); | ||
555 | yxi = BN_CTX_get(ctx); | ||
556 | if (yxi == NULL) goto err; | ||
557 | |||
558 | if (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err; | ||
559 | |||
560 | buf[0] = form; | ||
561 | if ((form != POINT_CONVERSION_UNCOMPRESSED) && !BN_is_zero(x)) | ||
562 | { | ||
563 | if (!group->meth->field_div(group, yxi, y, x, ctx)) goto err; | ||
564 | if (BN_is_odd(yxi)) buf[0]++; | ||
565 | } | ||
566 | |||
567 | i = 1; | ||
568 | |||
569 | skip = field_len - BN_num_bytes(x); | ||
570 | if (skip > field_len) | ||
571 | { | ||
572 | ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR); | ||
573 | goto err; | ||
574 | } | ||
575 | while (skip > 0) | ||
576 | { | ||
577 | buf[i++] = 0; | ||
578 | skip--; | ||
579 | } | ||
580 | skip = BN_bn2bin(x, buf + i); | ||
581 | i += skip; | ||
582 | if (i != 1 + field_len) | ||
583 | { | ||
584 | ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR); | ||
585 | goto err; | ||
586 | } | ||
587 | |||
588 | if (form == POINT_CONVERSION_UNCOMPRESSED || form == POINT_CONVERSION_HYBRID) | ||
589 | { | ||
590 | skip = field_len - BN_num_bytes(y); | ||
591 | if (skip > field_len) | ||
592 | { | ||
593 | ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR); | ||
594 | goto err; | ||
595 | } | ||
596 | while (skip > 0) | ||
597 | { | ||
598 | buf[i++] = 0; | ||
599 | skip--; | ||
600 | } | ||
601 | skip = BN_bn2bin(y, buf + i); | ||
602 | i += skip; | ||
603 | } | ||
604 | |||
605 | if (i != ret) | ||
606 | { | ||
607 | ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR); | ||
608 | goto err; | ||
609 | } | ||
610 | } | ||
611 | |||
612 | if (used_ctx) | ||
613 | BN_CTX_end(ctx); | ||
614 | if (new_ctx != NULL) | ||
615 | BN_CTX_free(new_ctx); | ||
616 | return ret; | ||
617 | |||
618 | err: | ||
619 | if (used_ctx) | ||
620 | BN_CTX_end(ctx); | ||
621 | if (new_ctx != NULL) | ||
622 | BN_CTX_free(new_ctx); | ||
623 | return 0; | ||
624 | } | ||
625 | |||
626 | |||
627 | /* Converts an octet string representation to an EC_POINT. | ||
628 | * Note that the simple implementation only uses affine coordinates. | ||
629 | */ | ||
630 | int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point, | ||
631 | const unsigned char *buf, size_t len, BN_CTX *ctx) | ||
632 | { | ||
633 | point_conversion_form_t form; | ||
634 | int y_bit; | ||
635 | BN_CTX *new_ctx = NULL; | ||
636 | BIGNUM *x, *y, *yxi; | ||
637 | size_t field_len, enc_len; | ||
638 | int ret = 0; | ||
639 | |||
640 | if (len == 0) | ||
641 | { | ||
642 | ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL); | ||
643 | return 0; | ||
644 | } | ||
645 | form = buf[0]; | ||
646 | y_bit = form & 1; | ||
647 | form = form & ~1U; | ||
648 | if ((form != 0) && (form != POINT_CONVERSION_COMPRESSED) | ||
649 | && (form != POINT_CONVERSION_UNCOMPRESSED) | ||
650 | && (form != POINT_CONVERSION_HYBRID)) | ||
651 | { | ||
652 | ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); | ||
653 | return 0; | ||
654 | } | ||
655 | if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit) | ||
656 | { | ||
657 | ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); | ||
658 | return 0; | ||
659 | } | ||
660 | |||
661 | if (form == 0) | ||
662 | { | ||
663 | if (len != 1) | ||
664 | { | ||
665 | ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); | ||
666 | return 0; | ||
667 | } | ||
668 | |||
669 | return EC_POINT_set_to_infinity(group, point); | ||
670 | } | ||
671 | |||
672 | field_len = (EC_GROUP_get_degree(group) + 7) / 8; | ||
673 | enc_len = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len; | ||
674 | |||
675 | if (len != enc_len) | ||
676 | { | ||
677 | ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); | ||
678 | return 0; | ||
679 | } | ||
680 | |||
681 | if (ctx == NULL) | ||
682 | { | ||
683 | ctx = new_ctx = BN_CTX_new(); | ||
684 | if (ctx == NULL) | ||
685 | return 0; | ||
686 | } | ||
687 | |||
688 | BN_CTX_start(ctx); | ||
689 | x = BN_CTX_get(ctx); | ||
690 | y = BN_CTX_get(ctx); | ||
691 | yxi = BN_CTX_get(ctx); | ||
692 | if (yxi == NULL) goto err; | ||
693 | |||
694 | if (!BN_bin2bn(buf + 1, field_len, x)) goto err; | ||
695 | if (BN_ucmp(x, &group->field) >= 0) | ||
696 | { | ||
697 | ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); | ||
698 | goto err; | ||
699 | } | ||
700 | |||
701 | if (form == POINT_CONVERSION_COMPRESSED) | ||
702 | { | ||
703 | if (!EC_POINT_set_compressed_coordinates_GF2m(group, point, x, y_bit, ctx)) goto err; | ||
704 | } | ||
705 | else | ||
706 | { | ||
707 | if (!BN_bin2bn(buf + 1 + field_len, field_len, y)) goto err; | ||
708 | if (BN_ucmp(y, &group->field) >= 0) | ||
709 | { | ||
710 | ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); | ||
711 | goto err; | ||
712 | } | ||
713 | if (form == POINT_CONVERSION_HYBRID) | ||
714 | { | ||
715 | if (!group->meth->field_div(group, yxi, y, x, ctx)) goto err; | ||
716 | if (y_bit != BN_is_odd(yxi)) | ||
717 | { | ||
718 | ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); | ||
719 | goto err; | ||
720 | } | ||
721 | } | ||
722 | |||
723 | if (!EC_POINT_set_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err; | ||
724 | } | ||
725 | |||
726 | if (!EC_POINT_is_on_curve(group, point, ctx)) /* test required by X9.62 */ | ||
727 | { | ||
728 | ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_POINT_IS_NOT_ON_CURVE); | ||
729 | goto err; | ||
730 | } | ||
731 | |||
732 | ret = 1; | ||
733 | |||
734 | err: | ||
735 | BN_CTX_end(ctx); | ||
736 | if (new_ctx != NULL) | ||
737 | BN_CTX_free(new_ctx); | ||
738 | return ret; | ||
739 | } | ||
740 | |||
741 | |||
742 | /* Computes a + b and stores the result in r. r could be a or b, a could be b. | 417 | /* Computes a + b and stores the result in r. r could be a or b, a could be b. |
743 | * Uses algorithm A.10.2 of IEEE P1363. | 418 | * Uses algorithm A.10.2 of IEEE P1363. |
744 | */ | 419 | */ |
@@ -1040,3 +715,5 @@ int ec_GF2m_simple_field_div(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, | |||
1040 | { | 715 | { |
1041 | return BN_GF2m_mod_div(r, a, b, &group->field, ctx); | 716 | return BN_GF2m_mod_div(r, a, b, &group->field, ctx); |
1042 | } | 717 | } |
718 | |||
719 | #endif | ||