diff options
Diffstat (limited to 'src/lib/libcrypto/ec')
| -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 | { |
