diff options
Diffstat (limited to 'src/lib/libcrypto/ec/ecp_smpl.c')
-rw-r--r-- | src/lib/libcrypto/ec/ecp_smpl.c | 379 |
1 files changed, 10 insertions, 369 deletions
diff --git a/src/lib/libcrypto/ec/ecp_smpl.c b/src/lib/libcrypto/ec/ecp_smpl.c index 66a92e2a90..7cbb321f9a 100644 --- a/src/lib/libcrypto/ec/ecp_smpl.c +++ b/src/lib/libcrypto/ec/ecp_smpl.c | |||
@@ -65,11 +65,19 @@ | |||
65 | #include <openssl/err.h> | 65 | #include <openssl/err.h> |
66 | #include <openssl/symhacks.h> | 66 | #include <openssl/symhacks.h> |
67 | 67 | ||
68 | #ifdef OPENSSL_FIPS | ||
69 | #include <openssl/fips.h> | ||
70 | #endif | ||
71 | |||
68 | #include "ec_lcl.h" | 72 | #include "ec_lcl.h" |
69 | 73 | ||
70 | const EC_METHOD *EC_GFp_simple_method(void) | 74 | const EC_METHOD *EC_GFp_simple_method(void) |
71 | { | 75 | { |
76 | #ifdef OPENSSL_FIPS | ||
77 | return fips_ec_gfp_simple_method(); | ||
78 | #else | ||
72 | static const EC_METHOD ret = { | 79 | static const EC_METHOD ret = { |
80 | EC_FLAGS_DEFAULT_OCT, | ||
73 | NID_X9_62_prime_field, | 81 | NID_X9_62_prime_field, |
74 | ec_GFp_simple_group_init, | 82 | ec_GFp_simple_group_init, |
75 | ec_GFp_simple_group_finish, | 83 | ec_GFp_simple_group_finish, |
@@ -88,9 +96,7 @@ const EC_METHOD *EC_GFp_simple_method(void) | |||
88 | ec_GFp_simple_get_Jprojective_coordinates_GFp, | 96 | ec_GFp_simple_get_Jprojective_coordinates_GFp, |
89 | ec_GFp_simple_point_set_affine_coordinates, | 97 | ec_GFp_simple_point_set_affine_coordinates, |
90 | ec_GFp_simple_point_get_affine_coordinates, | 98 | ec_GFp_simple_point_get_affine_coordinates, |
91 | ec_GFp_simple_set_compressed_coordinates, | 99 | 0,0,0, |
92 | ec_GFp_simple_point2oct, | ||
93 | ec_GFp_simple_oct2point, | ||
94 | ec_GFp_simple_add, | 100 | ec_GFp_simple_add, |
95 | ec_GFp_simple_dbl, | 101 | ec_GFp_simple_dbl, |
96 | ec_GFp_simple_invert, | 102 | ec_GFp_simple_invert, |
@@ -110,6 +116,7 @@ const EC_METHOD *EC_GFp_simple_method(void) | |||
110 | 0 /* field_set_to_one */ }; | 116 | 0 /* field_set_to_one */ }; |
111 | 117 | ||
112 | return &ret; | 118 | return &ret; |
119 | #endif | ||
113 | } | 120 | } |
114 | 121 | ||
115 | 122 | ||
@@ -633,372 +640,6 @@ int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group, const EC_P | |||
633 | return ret; | 640 | return ret; |
634 | } | 641 | } |
635 | 642 | ||
636 | |||
637 | int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *point, | ||
638 | const BIGNUM *x_, int y_bit, BN_CTX *ctx) | ||
639 | { | ||
640 | BN_CTX *new_ctx = NULL; | ||
641 | BIGNUM *tmp1, *tmp2, *x, *y; | ||
642 | int ret = 0; | ||
643 | |||
644 | /* clear error queue*/ | ||
645 | ERR_clear_error(); | ||
646 | |||
647 | if (ctx == NULL) | ||
648 | { | ||
649 | ctx = new_ctx = BN_CTX_new(); | ||
650 | if (ctx == NULL) | ||
651 | return 0; | ||
652 | } | ||
653 | |||
654 | y_bit = (y_bit != 0); | ||
655 | |||
656 | BN_CTX_start(ctx); | ||
657 | tmp1 = BN_CTX_get(ctx); | ||
658 | tmp2 = BN_CTX_get(ctx); | ||
659 | x = BN_CTX_get(ctx); | ||
660 | y = BN_CTX_get(ctx); | ||
661 | if (y == NULL) goto err; | ||
662 | |||
663 | /* Recover y. We have a Weierstrass equation | ||
664 | * y^2 = x^3 + a*x + b, | ||
665 | * so y is one of the square roots of x^3 + a*x + b. | ||
666 | */ | ||
667 | |||
668 | /* tmp1 := x^3 */ | ||
669 | if (!BN_nnmod(x, x_, &group->field,ctx)) goto err; | ||
670 | if (group->meth->field_decode == 0) | ||
671 | { | ||
672 | /* field_{sqr,mul} work on standard representation */ | ||
673 | if (!group->meth->field_sqr(group, tmp2, x_, ctx)) goto err; | ||
674 | if (!group->meth->field_mul(group, tmp1, tmp2, x_, ctx)) goto err; | ||
675 | } | ||
676 | else | ||
677 | { | ||
678 | if (!BN_mod_sqr(tmp2, x_, &group->field, ctx)) goto err; | ||
679 | if (!BN_mod_mul(tmp1, tmp2, x_, &group->field, ctx)) goto err; | ||
680 | } | ||
681 | |||
682 | /* tmp1 := tmp1 + a*x */ | ||
683 | if (group->a_is_minus3) | ||
684 | { | ||
685 | if (!BN_mod_lshift1_quick(tmp2, x, &group->field)) goto err; | ||
686 | if (!BN_mod_add_quick(tmp2, tmp2, x, &group->field)) goto err; | ||
687 | if (!BN_mod_sub_quick(tmp1, tmp1, tmp2, &group->field)) goto err; | ||
688 | } | ||
689 | else | ||
690 | { | ||
691 | if (group->meth->field_decode) | ||
692 | { | ||
693 | if (!group->meth->field_decode(group, tmp2, &group->a, ctx)) goto err; | ||
694 | if (!BN_mod_mul(tmp2, tmp2, x, &group->field, ctx)) goto err; | ||
695 | } | ||
696 | else | ||
697 | { | ||
698 | /* field_mul works on standard representation */ | ||
699 | if (!group->meth->field_mul(group, tmp2, &group->a, x, ctx)) goto err; | ||
700 | } | ||
701 | |||
702 | if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) goto err; | ||
703 | } | ||
704 | |||
705 | /* tmp1 := tmp1 + b */ | ||
706 | if (group->meth->field_decode) | ||
707 | { | ||
708 | if (!group->meth->field_decode(group, tmp2, &group->b, ctx)) goto err; | ||
709 | if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) goto err; | ||
710 | } | ||
711 | else | ||
712 | { | ||
713 | if (!BN_mod_add_quick(tmp1, tmp1, &group->b, &group->field)) goto err; | ||
714 | } | ||
715 | |||
716 | if (!BN_mod_sqrt(y, tmp1, &group->field, ctx)) | ||
717 | { | ||
718 | unsigned long err = ERR_peek_last_error(); | ||
719 | |||
720 | if (ERR_GET_LIB(err) == ERR_LIB_BN && ERR_GET_REASON(err) == BN_R_NOT_A_SQUARE) | ||
721 | { | ||
722 | ERR_clear_error(); | ||
723 | ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSED_POINT); | ||
724 | } | ||
725 | else | ||
726 | ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_BN_LIB); | ||
727 | goto err; | ||
728 | } | ||
729 | |||
730 | if (y_bit != BN_is_odd(y)) | ||
731 | { | ||
732 | if (BN_is_zero(y)) | ||
733 | { | ||
734 | int kron; | ||
735 | |||
736 | kron = BN_kronecker(x, &group->field, ctx); | ||
737 | if (kron == -2) goto err; | ||
738 | |||
739 | if (kron == 1) | ||
740 | ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSION_BIT); | ||
741 | else | ||
742 | /* BN_mod_sqrt() should have cought this error (not a square) */ | ||
743 | ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSED_POINT); | ||
744 | goto err; | ||
745 | } | ||
746 | if (!BN_usub(y, &group->field, y)) goto err; | ||
747 | } | ||
748 | if (y_bit != BN_is_odd(y)) | ||
749 | { | ||
750 | ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_INTERNAL_ERROR); | ||
751 | goto err; | ||
752 | } | ||
753 | |||
754 | if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) goto err; | ||
755 | |||
756 | ret = 1; | ||
757 | |||
758 | err: | ||
759 | BN_CTX_end(ctx); | ||
760 | if (new_ctx != NULL) | ||
761 | BN_CTX_free(new_ctx); | ||
762 | return ret; | ||
763 | } | ||
764 | |||
765 | |||
766 | size_t ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form, | ||
767 | unsigned char *buf, size_t len, BN_CTX *ctx) | ||
768 | { | ||
769 | size_t ret; | ||
770 | BN_CTX *new_ctx = NULL; | ||
771 | int used_ctx = 0; | ||
772 | BIGNUM *x, *y; | ||
773 | size_t field_len, i, skip; | ||
774 | |||
775 | if ((form != POINT_CONVERSION_COMPRESSED) | ||
776 | && (form != POINT_CONVERSION_UNCOMPRESSED) | ||
777 | && (form != POINT_CONVERSION_HYBRID)) | ||
778 | { | ||
779 | ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_INVALID_FORM); | ||
780 | goto err; | ||
781 | } | ||
782 | |||
783 | if (EC_POINT_is_at_infinity(group, point)) | ||
784 | { | ||
785 | /* encodes to a single 0 octet */ | ||
786 | if (buf != NULL) | ||
787 | { | ||
788 | if (len < 1) | ||
789 | { | ||
790 | ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL); | ||
791 | return 0; | ||
792 | } | ||
793 | buf[0] = 0; | ||
794 | } | ||
795 | return 1; | ||
796 | } | ||
797 | |||
798 | |||
799 | /* ret := required output buffer length */ | ||
800 | field_len = BN_num_bytes(&group->field); | ||
801 | ret = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len; | ||
802 | |||
803 | /* if 'buf' is NULL, just return required length */ | ||
804 | if (buf != NULL) | ||
805 | { | ||
806 | if (len < ret) | ||
807 | { | ||
808 | ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL); | ||
809 | goto err; | ||
810 | } | ||
811 | |||
812 | if (ctx == NULL) | ||
813 | { | ||
814 | ctx = new_ctx = BN_CTX_new(); | ||
815 | if (ctx == NULL) | ||
816 | return 0; | ||
817 | } | ||
818 | |||
819 | BN_CTX_start(ctx); | ||
820 | used_ctx = 1; | ||
821 | x = BN_CTX_get(ctx); | ||
822 | y = BN_CTX_get(ctx); | ||
823 | if (y == NULL) goto err; | ||
824 | |||
825 | if (!EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx)) goto err; | ||
826 | |||
827 | if ((form == POINT_CONVERSION_COMPRESSED || form == POINT_CONVERSION_HYBRID) && BN_is_odd(y)) | ||
828 | buf[0] = form + 1; | ||
829 | else | ||
830 | buf[0] = form; | ||
831 | |||
832 | i = 1; | ||
833 | |||
834 | skip = field_len - BN_num_bytes(x); | ||
835 | if (skip > field_len) | ||
836 | { | ||
837 | ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR); | ||
838 | goto err; | ||
839 | } | ||
840 | while (skip > 0) | ||
841 | { | ||
842 | buf[i++] = 0; | ||
843 | skip--; | ||
844 | } | ||
845 | skip = BN_bn2bin(x, buf + i); | ||
846 | i += skip; | ||
847 | if (i != 1 + field_len) | ||
848 | { | ||
849 | ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR); | ||
850 | goto err; | ||
851 | } | ||
852 | |||
853 | if (form == POINT_CONVERSION_UNCOMPRESSED || form == POINT_CONVERSION_HYBRID) | ||
854 | { | ||
855 | skip = field_len - BN_num_bytes(y); | ||
856 | if (skip > field_len) | ||
857 | { | ||
858 | ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR); | ||
859 | goto err; | ||
860 | } | ||
861 | while (skip > 0) | ||
862 | { | ||
863 | buf[i++] = 0; | ||
864 | skip--; | ||
865 | } | ||
866 | skip = BN_bn2bin(y, buf + i); | ||
867 | i += skip; | ||
868 | } | ||
869 | |||
870 | if (i != ret) | ||
871 | { | ||
872 | ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR); | ||
873 | goto err; | ||
874 | } | ||
875 | } | ||
876 | |||
877 | if (used_ctx) | ||
878 | BN_CTX_end(ctx); | ||
879 | if (new_ctx != NULL) | ||
880 | BN_CTX_free(new_ctx); | ||
881 | return ret; | ||
882 | |||
883 | err: | ||
884 | if (used_ctx) | ||
885 | BN_CTX_end(ctx); | ||
886 | if (new_ctx != NULL) | ||
887 | BN_CTX_free(new_ctx); | ||
888 | return 0; | ||
889 | } | ||
890 | |||
891 | |||
892 | int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point, | ||
893 | const unsigned char *buf, size_t len, BN_CTX *ctx) | ||
894 | { | ||
895 | point_conversion_form_t form; | ||
896 | int y_bit; | ||
897 | BN_CTX *new_ctx = NULL; | ||
898 | BIGNUM *x, *y; | ||
899 | size_t field_len, enc_len; | ||
900 | int ret = 0; | ||
901 | |||
902 | if (len == 0) | ||
903 | { | ||
904 | ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL); | ||
905 | return 0; | ||
906 | } | ||
907 | form = buf[0]; | ||
908 | y_bit = form & 1; | ||
909 | form = form & ~1U; | ||
910 | if ((form != 0) && (form != POINT_CONVERSION_COMPRESSED) | ||
911 | && (form != POINT_CONVERSION_UNCOMPRESSED) | ||
912 | && (form != POINT_CONVERSION_HYBRID)) | ||
913 | { | ||
914 | ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); | ||
915 | return 0; | ||
916 | } | ||
917 | if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit) | ||
918 | { | ||
919 | ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); | ||
920 | return 0; | ||
921 | } | ||
922 | |||
923 | if (form == 0) | ||
924 | { | ||
925 | if (len != 1) | ||
926 | { | ||
927 | ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); | ||
928 | return 0; | ||
929 | } | ||
930 | |||
931 | return EC_POINT_set_to_infinity(group, point); | ||
932 | } | ||
933 | |||
934 | field_len = BN_num_bytes(&group->field); | ||
935 | enc_len = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len; | ||
936 | |||
937 | if (len != enc_len) | ||
938 | { | ||
939 | ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); | ||
940 | return 0; | ||
941 | } | ||
942 | |||
943 | if (ctx == NULL) | ||
944 | { | ||
945 | ctx = new_ctx = BN_CTX_new(); | ||
946 | if (ctx == NULL) | ||
947 | return 0; | ||
948 | } | ||
949 | |||
950 | BN_CTX_start(ctx); | ||
951 | x = BN_CTX_get(ctx); | ||
952 | y = BN_CTX_get(ctx); | ||
953 | if (y == NULL) goto err; | ||
954 | |||
955 | if (!BN_bin2bn(buf + 1, field_len, x)) goto err; | ||
956 | if (BN_ucmp(x, &group->field) >= 0) | ||
957 | { | ||
958 | ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); | ||
959 | goto err; | ||
960 | } | ||
961 | |||
962 | if (form == POINT_CONVERSION_COMPRESSED) | ||
963 | { | ||
964 | if (!EC_POINT_set_compressed_coordinates_GFp(group, point, x, y_bit, ctx)) goto err; | ||
965 | } | ||
966 | else | ||
967 | { | ||
968 | if (!BN_bin2bn(buf + 1 + field_len, field_len, y)) goto err; | ||
969 | if (BN_ucmp(y, &group->field) >= 0) | ||
970 | { | ||
971 | ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); | ||
972 | goto err; | ||
973 | } | ||
974 | if (form == POINT_CONVERSION_HYBRID) | ||
975 | { | ||
976 | if (y_bit != BN_is_odd(y)) | ||
977 | { | ||
978 | ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); | ||
979 | goto err; | ||
980 | } | ||
981 | } | ||
982 | |||
983 | if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) goto err; | ||
984 | } | ||
985 | |||
986 | if (!EC_POINT_is_on_curve(group, point, ctx)) /* test required by X9.62 */ | ||
987 | { | ||
988 | ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_POINT_IS_NOT_ON_CURVE); | ||
989 | goto err; | ||
990 | } | ||
991 | |||
992 | ret = 1; | ||
993 | |||
994 | err: | ||
995 | BN_CTX_end(ctx); | ||
996 | if (new_ctx != NULL) | ||
997 | BN_CTX_free(new_ctx); | ||
998 | return ret; | ||
999 | } | ||
1000 | |||
1001 | |||
1002 | int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx) | 643 | int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx) |
1003 | { | 644 | { |
1004 | int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *); | 645 | int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *); |