diff options
-rw-r--r-- | src/lib/libcrypto/ec/ec_asn1.c | 240 |
1 files changed, 144 insertions, 96 deletions
diff --git a/src/lib/libcrypto/ec/ec_asn1.c b/src/lib/libcrypto/ec/ec_asn1.c index 02609606ff..289bc3b271 100644 --- a/src/lib/libcrypto/ec/ec_asn1.c +++ b/src/lib/libcrypto/ec/ec_asn1.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ec_asn1.c,v 1.73 2024/10/15 06:35:59 tb Exp $ */ | 1 | /* $OpenBSD: ec_asn1.c,v 1.74 2024/10/17 14:34:06 tb Exp $ */ |
2 | /* | 2 | /* |
3 | * Written by Nils Larsch for the OpenSSL project. | 3 | * Written by Nils Larsch for the OpenSSL project. |
4 | */ | 4 | */ |
@@ -818,99 +818,98 @@ ec_asn1_group2pkparameters(const EC_GROUP *group) | |||
818 | return NULL; | 818 | return NULL; |
819 | } | 819 | } |
820 | 820 | ||
821 | static EC_GROUP * | 821 | static int |
822 | ec_asn1_parameters2group(const ECPARAMETERS *params) | 822 | ec_asn1_is_prime_field(const X9_62_FIELDID *fieldid) |
823 | { | 823 | { |
824 | int ok = 0, tmp; | 824 | int nid; |
825 | EC_GROUP *ret = NULL; | 825 | |
826 | BIGNUM *p = NULL, *a = NULL, *b = NULL, *order = NULL, *cofactor = NULL; | 826 | if (fieldid == NULL) { |
827 | EC_POINT *point = NULL; | ||
828 | int field_bits; | ||
829 | |||
830 | if (!params->fieldID || !params->fieldID->fieldType || | ||
831 | !params->fieldID->p.ptr) { | ||
832 | ECerror(EC_R_ASN1_ERROR); | 827 | ECerror(EC_R_ASN1_ERROR); |
833 | goto err; | 828 | return 0; |
834 | } | 829 | } |
835 | /* now extract the curve parameters a and b */ | 830 | if ((nid = OBJ_obj2nid(fieldid->fieldType)) == NID_undef) { |
836 | if (!params->curve || !params->curve->a || | 831 | ECerror(EC_R_INVALID_FIELD); |
837 | !params->curve->a->data || !params->curve->b || | 832 | return 0; |
838 | !params->curve->b->data) { | ||
839 | ECerror(EC_R_ASN1_ERROR); | ||
840 | goto err; | ||
841 | } | 833 | } |
842 | a = BN_bin2bn(params->curve->a->data, params->curve->a->length, NULL); | 834 | if (nid == NID_X9_62_characteristic_two_field) { |
843 | if (a == NULL) { | 835 | ECerror(EC_R_GF2M_NOT_SUPPORTED); |
844 | ECerror(ERR_R_BN_LIB); | 836 | return 0; |
845 | goto err; | ||
846 | } | 837 | } |
847 | b = BN_bin2bn(params->curve->b->data, params->curve->b->length, NULL); | 838 | if (nid != NID_X9_62_prime_field) { |
848 | if (b == NULL) { | 839 | ECerror(EC_R_UNSUPPORTED_FIELD); |
849 | ECerror(ERR_R_BN_LIB); | 840 | return 0; |
850 | goto err; | ||
851 | } | 841 | } |
852 | /* get the field parameters */ | 842 | |
853 | tmp = OBJ_obj2nid(params->fieldID->fieldType); | 843 | /* We can't check that this is actually a prime due to DoS risk. */ |
854 | if (tmp == NID_X9_62_characteristic_two_field) { | 844 | if (fieldid->p.prime == NULL) { |
855 | ECerror(EC_R_GF2M_NOT_SUPPORTED); | ||
856 | goto err; | ||
857 | } else if (tmp == NID_X9_62_prime_field) { | ||
858 | /* we have a curve over a prime field */ | ||
859 | /* extract the prime number */ | ||
860 | if (!params->fieldID->p.prime) { | ||
861 | ECerror(EC_R_ASN1_ERROR); | ||
862 | goto err; | ||
863 | } | ||
864 | p = ASN1_INTEGER_to_BN(params->fieldID->p.prime, NULL); | ||
865 | if (p == NULL) { | ||
866 | ECerror(ERR_R_ASN1_LIB); | ||
867 | goto err; | ||
868 | } | ||
869 | if (BN_is_negative(p) || BN_is_zero(p)) { | ||
870 | ECerror(EC_R_INVALID_FIELD); | ||
871 | goto err; | ||
872 | } | ||
873 | field_bits = BN_num_bits(p); | ||
874 | if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS) { | ||
875 | ECerror(EC_R_FIELD_TOO_LARGE); | ||
876 | goto err; | ||
877 | } | ||
878 | /* create the EC_GROUP structure */ | ||
879 | ret = EC_GROUP_new_curve_GFp(p, a, b, NULL); | ||
880 | } else { | ||
881 | ECerror(EC_R_INVALID_FIELD); | 845 | ECerror(EC_R_INVALID_FIELD); |
882 | goto err; | 846 | return 0; |
883 | } | 847 | } |
884 | 848 | ||
885 | if (ret == NULL) { | 849 | return 1; |
886 | ECerror(ERR_R_EC_LIB); | 850 | } |
851 | |||
852 | static int | ||
853 | ec_asn1_parameters_curve2group(const X9_62_CURVE *curve, | ||
854 | const ASN1_INTEGER *prime, EC_GROUP **out_group) | ||
855 | { | ||
856 | EC_GROUP *group = NULL; | ||
857 | BIGNUM *p = NULL, *a = NULL, *b = NULL; | ||
858 | int ret = 0; | ||
859 | |||
860 | if (*out_group != NULL) | ||
861 | goto err; | ||
862 | |||
863 | if ((p = ASN1_INTEGER_to_BN(prime, NULL)) == NULL) | ||
864 | goto err; | ||
865 | if ((a = BN_bin2bn(curve->a->data, curve->a->length, NULL)) == NULL) | ||
866 | goto err; | ||
867 | if ((b = BN_bin2bn(curve->b->data, curve->b->length, NULL)) == NULL) | ||
868 | goto err; | ||
869 | |||
870 | /* | ||
871 | * XXX - move these checks to ec_GFp_simple_group_set_curve()? | ||
872 | * What about checking 0 <= a, b < p? | ||
873 | */ | ||
874 | if (BN_is_zero(p) || BN_is_negative(p)) { | ||
875 | ECerror(EC_R_INVALID_FIELD); | ||
887 | goto err; | 876 | goto err; |
888 | } | 877 | } |
889 | /* extract seed (optional) */ | 878 | if (BN_num_bits(p) > OPENSSL_ECC_MAX_FIELD_BITS) { |
890 | if (params->curve->seed != NULL) { | 879 | ECerror(EC_R_FIELD_TOO_LARGE); |
891 | free(ret->seed); | ||
892 | if (!(ret->seed = malloc(params->curve->seed->length))) { | ||
893 | ECerror(ERR_R_MALLOC_FAILURE); | ||
894 | goto err; | ||
895 | } | ||
896 | memcpy(ret->seed, params->curve->seed->data, | ||
897 | params->curve->seed->length); | ||
898 | ret->seed_len = params->curve->seed->length; | ||
899 | } | ||
900 | if (!params->order || !params->base || !params->base->data) { | ||
901 | ECerror(EC_R_ASN1_ERROR); | ||
902 | goto err; | 880 | goto err; |
903 | } | 881 | } |
904 | if ((point = EC_POINT_new(ret)) == NULL) | 882 | |
883 | if ((group = EC_GROUP_new_curve_GFp(p, a, b, NULL)) == NULL) | ||
905 | goto err; | 884 | goto err; |
906 | 885 | ||
907 | /* set the point conversion form */ | 886 | *out_group = group; |
908 | EC_GROUP_set_point_conversion_form(ret, (point_conversion_form_t) | 887 | group = NULL; |
909 | (params->base->data[0] & ~0x01)); | 888 | |
889 | ret = 1; | ||
890 | |||
891 | err: | ||
892 | BN_free(p); | ||
893 | BN_free(a); | ||
894 | BN_free(b); | ||
895 | EC_GROUP_free(group); | ||
896 | |||
897 | return ret; | ||
898 | } | ||
910 | 899 | ||
911 | /* extract the ec point */ | 900 | static int |
912 | if (!EC_POINT_oct2point(ret, point, params->base->data, | 901 | ec_asn1_set_group_parameters(const ECPARAMETERS *params, EC_GROUP *group) |
913 | params->base->length, NULL)) { | 902 | { |
903 | EC_POINT *generator; | ||
904 | BIGNUM *order = NULL, *cofactor = NULL; | ||
905 | const ASN1_BIT_STRING *seed; | ||
906 | point_conversion_form_t form; | ||
907 | int ret = 0; | ||
908 | |||
909 | if ((generator = EC_POINT_new(group)) == NULL) | ||
910 | goto err; | ||
911 | if (!EC_POINT_oct2point(group, generator, | ||
912 | params->base->data, params->base->length, NULL)) { | ||
914 | ECerror(ERR_R_EC_LIB); | 913 | ECerror(ERR_R_EC_LIB); |
915 | goto err; | 914 | goto err; |
916 | } | 915 | } |
@@ -918,14 +917,6 @@ ec_asn1_parameters2group(const ECPARAMETERS *params) | |||
918 | ECerror(ERR_R_ASN1_LIB); | 917 | ECerror(ERR_R_ASN1_LIB); |
919 | goto err; | 918 | goto err; |
920 | } | 919 | } |
921 | if (BN_is_negative(order) || BN_is_zero(order)) { | ||
922 | ECerror(EC_R_INVALID_GROUP_ORDER); | ||
923 | goto err; | ||
924 | } | ||
925 | if (BN_num_bits(order) > field_bits + 1) { /* Hasse bound */ | ||
926 | ECerror(EC_R_INVALID_GROUP_ORDER); | ||
927 | goto err; | ||
928 | } | ||
929 | if (params->cofactor != NULL) { | 920 | if (params->cofactor != NULL) { |
930 | if ((cofactor = ASN1_INTEGER_to_BN(params->cofactor, | 921 | if ((cofactor = ASN1_INTEGER_to_BN(params->cofactor, |
931 | NULL)) == NULL) { | 922 | NULL)) == NULL) { |
@@ -933,27 +924,84 @@ ec_asn1_parameters2group(const ECPARAMETERS *params) | |||
933 | goto err; | 924 | goto err; |
934 | } | 925 | } |
935 | } | 926 | } |
936 | if (!EC_GROUP_set_generator(ret, point, order, cofactor)) { | 927 | |
928 | /* Checks the Hasse bound and sets the cofactor if possible or fails. */ | ||
929 | if (!EC_GROUP_set_generator(group, generator, order, cofactor)) { | ||
937 | ECerror(ERR_R_EC_LIB); | 930 | ECerror(ERR_R_EC_LIB); |
938 | goto err; | 931 | goto err; |
939 | } | 932 | } |
940 | ok = 1; | ||
941 | 933 | ||
942 | err: | 934 | if ((seed = params->curve->seed) != NULL) { |
943 | if (!ok) { | 935 | if (EC_GROUP_set_seed(group, seed->data, seed->length) == 0) { |
944 | EC_GROUP_free(ret); | 936 | ECerror(ERR_R_MALLOC_FAILURE); |
945 | ret = NULL; | 937 | goto err; |
938 | } | ||
946 | } | 939 | } |
947 | BN_free(p); | 940 | |
948 | BN_free(a); | 941 | /* oct2point has ensured that to be compressed, uncompressed, or hybrid. */ |
949 | BN_free(b); | 942 | form = params->base->data[0] & ~1U; |
943 | EC_GROUP_set_point_conversion_form(group, form); | ||
944 | |||
945 | ret = 1; | ||
946 | |||
947 | err: | ||
948 | EC_POINT_free(generator); | ||
950 | BN_free(order); | 949 | BN_free(order); |
951 | BN_free(cofactor); | 950 | BN_free(cofactor); |
952 | EC_POINT_free(point); | ||
953 | 951 | ||
954 | return ret; | 952 | return ret; |
955 | } | 953 | } |
956 | 954 | ||
955 | static int | ||
956 | ec_asn1_parameters_extract_prime_group(const ECPARAMETERS *params, | ||
957 | EC_GROUP **out_group) | ||
958 | { | ||
959 | EC_GROUP *group = NULL; | ||
960 | int ret = 0; | ||
961 | |||
962 | if (*out_group != NULL) | ||
963 | goto err; | ||
964 | |||
965 | if (!ec_asn1_is_prime_field(params->fieldID)) | ||
966 | goto err; | ||
967 | if (!ec_asn1_parameters_curve2group(params->curve, | ||
968 | params->fieldID->p.prime, &group)) | ||
969 | goto err; | ||
970 | if (!ec_asn1_set_group_parameters(params, group)) | ||
971 | goto err; | ||
972 | |||
973 | *out_group = group; | ||
974 | group = NULL; | ||
975 | |||
976 | ret = 1; | ||
977 | |||
978 | err: | ||
979 | EC_GROUP_free(group); | ||
980 | |||
981 | return ret; | ||
982 | } | ||
983 | |||
984 | static EC_GROUP * | ||
985 | ec_asn1_parameters2group(const ECPARAMETERS *params) | ||
986 | { | ||
987 | EC_GROUP *group = NULL; | ||
988 | |||
989 | if (params == NULL) { | ||
990 | ECerror(EC_R_ASN1_ERROR); | ||
991 | goto err; | ||
992 | } | ||
993 | |||
994 | if (!ec_asn1_parameters_extract_prime_group(params, &group)) | ||
995 | goto err; | ||
996 | |||
997 | return group; | ||
998 | |||
999 | err: | ||
1000 | EC_GROUP_free(group); | ||
1001 | |||
1002 | return NULL; | ||
1003 | } | ||
1004 | |||
957 | EC_GROUP * | 1005 | EC_GROUP * |
958 | ec_asn1_pkparameters2group(const ECPKPARAMETERS *params) | 1006 | ec_asn1_pkparameters2group(const ECPKPARAMETERS *params) |
959 | { | 1007 | { |