summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authortb <>2024-10-17 14:34:06 +0000
committertb <>2024-10-17 14:34:06 +0000
commita2ef0e2df9a19f862265cd5c206555caba13070f (patch)
tree25130d18dbeb457738024eeceb2d57abb7cf62e9 /src
parent978d3a277baeb25c75e71e4d12342c47d1764205 (diff)
downloadopenbsd-a2ef0e2df9a19f862265cd5c206555caba13070f.tar.gz
openbsd-a2ef0e2df9a19f862265cd5c206555caba13070f.tar.bz2
openbsd-a2ef0e2df9a19f862265cd5c206555caba13070f.zip
Split ec_asn1_parameters2group() into digestible pieces
This becomes a simple wrapper function that currently does three checks: 1. ensure the fieldID is for a prime field 2. check that the purported prime is of reasonable size, extract and set curve coefficients and point conversion form 3. extract and set generator, order, cofactor and seed. Sanity checks such as the Hasse bound are dealt with in the EC_GROUP API, so need not be repeated here. They will become redundant once we enforce that the parameters represent a builtin curve anyway. ok jsing
Diffstat (limited to 'src')
-rw-r--r--src/lib/libcrypto/ec/ec_asn1.c240
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
821static EC_GROUP * 821static int
822ec_asn1_parameters2group(const ECPARAMETERS *params) 822ec_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
852static int
853ec_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 */ 900static int
912 if (!EC_POINT_oct2point(ret, point, params->base->data, 901ec_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
955static int
956ec_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
984static EC_GROUP *
985ec_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
957EC_GROUP * 1005EC_GROUP *
958ec_asn1_pkparameters2group(const ECPKPARAMETERS *params) 1006ec_asn1_pkparameters2group(const ECPKPARAMETERS *params)
959{ 1007{