diff options
Diffstat (limited to '')
-rw-r--r-- | src/lib/libcrypto/ec/ec_field.c | 17 | ||||
-rw-r--r-- | src/lib/libcrypto/ec/ec_internal.h | 4 | ||||
-rw-r--r-- | src/lib/libcrypto/ec/ec_lib.c | 10 | ||||
-rw-r--r-- | src/lib/libcrypto/ec/ec_local.h | 3 | ||||
-rw-r--r-- | src/lib/libcrypto/ec/ecp_hp_methods.c | 123 |
5 files changed, 132 insertions, 25 deletions
diff --git a/src/lib/libcrypto/ec/ec_field.c b/src/lib/libcrypto/ec/ec_field.c index ec1c7d11e0..6576526e77 100644 --- a/src/lib/libcrypto/ec/ec_field.c +++ b/src/lib/libcrypto/ec/ec_field.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ec_field.c,v 1.1 2025/05/25 05:12:05 jsing Exp $ */ | 1 | /* $OpenBSD: ec_field.c,v 1.3 2025/08/02 16:20:00 jsing Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2024 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2024 Joel Sing <jsing@openbsd.org> |
4 | * | 4 | * |
@@ -131,6 +131,19 @@ ec_field_element_copy(EC_FIELD_ELEMENT *dst, const EC_FIELD_ELEMENT *src) | |||
131 | memcpy(dst, src, sizeof(EC_FIELD_ELEMENT)); | 131 | memcpy(dst, src, sizeof(EC_FIELD_ELEMENT)); |
132 | } | 132 | } |
133 | 133 | ||
134 | void | ||
135 | ec_field_element_select(const EC_FIELD_MODULUS *fm, EC_FIELD_ELEMENT *r, | ||
136 | const EC_FIELD_ELEMENT *a, const EC_FIELD_ELEMENT *b, int conditional) | ||
137 | { | ||
138 | BN_ULONG mask; | ||
139 | int i; | ||
140 | |||
141 | mask = bn_ct_eq_zero_mask(conditional); | ||
142 | |||
143 | for (i = 0; i < fm->n; i++) | ||
144 | r->w[i] = (a->w[i] & mask) | (b->w[i] & ~mask); | ||
145 | } | ||
146 | |||
134 | int | 147 | int |
135 | ec_field_element_equal(const EC_FIELD_MODULUS *fm, const EC_FIELD_ELEMENT *a, | 148 | ec_field_element_equal(const EC_FIELD_MODULUS *fm, const EC_FIELD_ELEMENT *a, |
136 | const EC_FIELD_ELEMENT *b) | 149 | const EC_FIELD_ELEMENT *b) |
@@ -185,5 +198,5 @@ ec_field_element_sqr(const EC_FIELD_MODULUS *m, EC_FIELD_ELEMENT *r, | |||
185 | { | 198 | { |
186 | BN_ULONG t[EC_FIELD_ELEMENT_MAX_WORDS * 2 + 2]; | 199 | BN_ULONG t[EC_FIELD_ELEMENT_MAX_WORDS * 2 + 2]; |
187 | 200 | ||
188 | bn_mod_mul_words(r->w, a->w, a->w, m->m.w, t, m->minv0, m->n); | 201 | bn_mod_sqr_words(r->w, a->w, m->m.w, t, m->minv0, m->n); |
189 | } | 202 | } |
diff --git a/src/lib/libcrypto/ec/ec_internal.h b/src/lib/libcrypto/ec/ec_internal.h index 29b447e8c9..327d9ea94d 100644 --- a/src/lib/libcrypto/ec/ec_internal.h +++ b/src/lib/libcrypto/ec/ec_internal.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ec_internal.h,v 1.1 2025/05/25 05:12:05 jsing Exp $ */ | 1 | /* $OpenBSD: ec_internal.h,v 1.2 2025/08/02 15:44:09 jsing Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2024 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2024 Joel Sing <jsing@openbsd.org> |
4 | * | 4 | * |
@@ -46,6 +46,8 @@ int ec_field_element_to_bn(const EC_FIELD_MODULUS *fm, const EC_FIELD_ELEMENT *f | |||
46 | BIGNUM *bn, BN_CTX *ctx); | 46 | BIGNUM *bn, BN_CTX *ctx); |
47 | 47 | ||
48 | void ec_field_element_copy(EC_FIELD_ELEMENT *dst, const EC_FIELD_ELEMENT *src); | 48 | void ec_field_element_copy(EC_FIELD_ELEMENT *dst, const EC_FIELD_ELEMENT *src); |
49 | void ec_field_element_select(const EC_FIELD_MODULUS *fm, EC_FIELD_ELEMENT *r, | ||
50 | const EC_FIELD_ELEMENT *a, const EC_FIELD_ELEMENT *b, int conditional); | ||
49 | 51 | ||
50 | int ec_field_element_equal(const EC_FIELD_MODULUS *fm, const EC_FIELD_ELEMENT *a, | 52 | int ec_field_element_equal(const EC_FIELD_MODULUS *fm, const EC_FIELD_ELEMENT *a, |
51 | const EC_FIELD_ELEMENT *b); | 53 | const EC_FIELD_ELEMENT *b); |
diff --git a/src/lib/libcrypto/ec/ec_lib.c b/src/lib/libcrypto/ec/ec_lib.c index 7cc7efe73f..36f42ecc05 100644 --- a/src/lib/libcrypto/ec/ec_lib.c +++ b/src/lib/libcrypto/ec/ec_lib.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ec_lib.c,v 1.125 2025/05/24 08:25:58 jsing Exp $ */ | 1 | /* $OpenBSD: ec_lib.c,v 1.126 2025/08/02 15:47:27 jsing Exp $ */ |
2 | /* | 2 | /* |
3 | * Originally written by Bodo Moeller for the OpenSSL project. | 3 | * Originally written by Bodo Moeller for the OpenSSL project. |
4 | */ | 4 | */ |
@@ -165,6 +165,10 @@ EC_GROUP_copy(EC_GROUP *dst, const EC_GROUP *src) | |||
165 | 165 | ||
166 | dst->a_is_minus3 = src->a_is_minus3; | 166 | dst->a_is_minus3 = src->a_is_minus3; |
167 | 167 | ||
168 | memcpy(&dst->fm, &src->fm, sizeof(src->fm)); | ||
169 | memcpy(&dst->fe_a, &src->fe_a, sizeof(src->fe_a)); | ||
170 | memcpy(&dst->fe_b, &src->fe_b, sizeof(src->fe_b)); | ||
171 | |||
168 | BN_MONT_CTX_free(dst->mont_ctx); | 172 | BN_MONT_CTX_free(dst->mont_ctx); |
169 | dst->mont_ctx = NULL; | 173 | dst->mont_ctx = NULL; |
170 | if (src->mont_ctx != NULL) { | 174 | if (src->mont_ctx != NULL) { |
@@ -860,6 +864,10 @@ EC_POINT_copy(EC_POINT *dst, const EC_POINT *src) | |||
860 | return 0; | 864 | return 0; |
861 | dst->Z_is_one = src->Z_is_one; | 865 | dst->Z_is_one = src->Z_is_one; |
862 | 866 | ||
867 | memcpy(&dst->fe_x, &src->fe_x, sizeof(dst->fe_x)); | ||
868 | memcpy(&dst->fe_y, &src->fe_y, sizeof(dst->fe_y)); | ||
869 | memcpy(&dst->fe_z, &src->fe_z, sizeof(dst->fe_z)); | ||
870 | |||
863 | return 1; | 871 | return 1; |
864 | } | 872 | } |
865 | LCRYPTO_ALIAS(EC_POINT_copy); | 873 | LCRYPTO_ALIAS(EC_POINT_copy); |
diff --git a/src/lib/libcrypto/ec/ec_local.h b/src/lib/libcrypto/ec/ec_local.h index 75a3e25247..eac9e6d26c 100644 --- a/src/lib/libcrypto/ec/ec_local.h +++ b/src/lib/libcrypto/ec/ec_local.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ec_local.h,v 1.69 2025/05/25 05:19:26 jsing Exp $ */ | 1 | /* $OpenBSD: ec_local.h,v 1.70 2025/08/03 15:07:57 jsing Exp $ */ |
2 | /* | 2 | /* |
3 | * Originally written by Bodo Moeller for the OpenSSL project. | 3 | * Originally written by Bodo Moeller for the OpenSSL project. |
4 | */ | 4 | */ |
@@ -184,6 +184,7 @@ struct ec_point_st { | |||
184 | 184 | ||
185 | const EC_METHOD *EC_GFp_simple_method(void); | 185 | const EC_METHOD *EC_GFp_simple_method(void); |
186 | const EC_METHOD *EC_GFp_mont_method(void); | 186 | const EC_METHOD *EC_GFp_mont_method(void); |
187 | const EC_METHOD *EC_GFp_homogeneous_projective_method(void); | ||
187 | 188 | ||
188 | /* Compute r = scalar1 * point1 + scalar2 * point2 in non-constant time. */ | 189 | /* Compute r = scalar1 * point1 + scalar2 * point2 in non-constant time. */ |
189 | int ec_wnaf_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar1, | 190 | int ec_wnaf_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar1, |
diff --git a/src/lib/libcrypto/ec/ecp_hp_methods.c b/src/lib/libcrypto/ec/ecp_hp_methods.c index c62334e7c8..0b34a55b9d 100644 --- a/src/lib/libcrypto/ec/ecp_hp_methods.c +++ b/src/lib/libcrypto/ec/ecp_hp_methods.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ecp_hp_methods.c,v 1.3 2025/06/01 03:23:33 tb Exp $ */ | 1 | /* $OpenBSD: ecp_hp_methods.c,v 1.5 2025/08/03 15:44:00 jsing Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2024-2025 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2024-2025 Joel Sing <jsing@openbsd.org> |
4 | * | 4 | * |
@@ -22,15 +22,11 @@ | |||
22 | #include <openssl/err.h> | 22 | #include <openssl/err.h> |
23 | 23 | ||
24 | #include "bn_internal.h" | 24 | #include "bn_internal.h" |
25 | #include "crypto_internal.h" | ||
25 | #include "ec_local.h" | 26 | #include "ec_local.h" |
26 | #include "ec_internal.h" | 27 | #include "ec_internal.h" |
27 | #include "err_local.h" | 28 | #include "err_local.h" |
28 | 29 | ||
29 | /* | ||
30 | * TODO: | ||
31 | * - Constant time and blinding for scalar multiplication | ||
32 | */ | ||
33 | |||
34 | static int | 30 | static int |
35 | ec_group_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, | 31 | ec_group_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, |
36 | const BIGNUM *b, BN_CTX *ctx) | 32 | const BIGNUM *b, BN_CTX *ctx) |
@@ -439,10 +435,6 @@ ec_point_dbl_a1(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *c | |||
439 | ec_field_element_add(&group->fm, &b3, &gb, &gb); | 435 | ec_field_element_add(&group->fm, &b3, &gb, &gb); |
440 | ec_field_element_add(&group->fm, &b3, &b3, &gb); | 436 | ec_field_element_add(&group->fm, &b3, &b3, &gb); |
441 | 437 | ||
442 | /* b3 := 3 * b ; */ | ||
443 | ec_field_element_add(&group->fm, &b3, &gb, &gb); | ||
444 | ec_field_element_add(&group->fm, &b3, &b3, &gb); | ||
445 | |||
446 | /* t0 := X^2; t1 := Y^2; t2 := Z^2 ; */ | 438 | /* t0 := X^2; t1 := Y^2; t2 := Z^2 ; */ |
447 | ec_field_element_sqr(&group->fm, &t0, &X1); | 439 | ec_field_element_sqr(&group->fm, &t0, &X1); |
448 | ec_field_element_sqr(&group->fm, &t1, &Y1); | 440 | ec_field_element_sqr(&group->fm, &t1, &Y1); |
@@ -785,38 +777,129 @@ ec_points_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], | |||
785 | } | 777 | } |
786 | #endif | 778 | #endif |
787 | 779 | ||
780 | static void | ||
781 | ec_point_select(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, | ||
782 | const EC_POINT *b, int conditional) | ||
783 | { | ||
784 | ec_field_element_select(&group->fm, &r->fe_x, &a->fe_x, &b->fe_x, conditional); | ||
785 | ec_field_element_select(&group->fm, &r->fe_y, &a->fe_y, &b->fe_y, conditional); | ||
786 | ec_field_element_select(&group->fm, &r->fe_z, &a->fe_z, &b->fe_z, conditional); | ||
787 | } | ||
788 | |||
788 | static int | 789 | static int |
789 | ec_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, const EC_POINT *point, | 790 | ec_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, const EC_POINT *point, |
790 | BN_CTX *ctx) | 791 | BN_CTX *ctx) |
791 | { | 792 | { |
792 | EC_POINT *rr; | 793 | BIGNUM *cardinality; |
793 | int bits, i; | 794 | EC_POINT *multiples[15]; |
795 | EC_POINT *rr = NULL, *t = NULL; | ||
796 | uint8_t *scalar_bytes = NULL; | ||
797 | int scalar_len = 0; | ||
798 | uint8_t j, wv; | ||
799 | int conditional, i; | ||
794 | int ret = 0; | 800 | int ret = 0; |
795 | 801 | ||
796 | /* XXX - need constant time and blinding. */ | 802 | memset(multiples, 0, sizeof(multiples)); |
803 | |||
804 | BN_CTX_start(ctx); | ||
805 | |||
806 | /* XXX - consider blinding. */ | ||
807 | |||
808 | if ((cardinality = BN_CTX_get(ctx)) == NULL) | ||
809 | goto err; | ||
810 | if (!BN_mul(cardinality, group->order, group->cofactor, ctx)) | ||
811 | goto err; | ||
812 | |||
813 | /* XXX - handle scalar > cardinality and/or negative. */ | ||
814 | |||
815 | /* Convert scalar into big endian bytes. */ | ||
816 | scalar_len = BN_num_bytes(cardinality); | ||
817 | if ((scalar_bytes = calloc(1, scalar_len)) == NULL) | ||
818 | goto err; | ||
819 | if (!BN_bn2binpad(scalar, scalar_bytes, scalar_len)) | ||
820 | goto err; | ||
821 | |||
822 | /* Compute multiples of point. */ | ||
823 | if ((multiples[0] = EC_POINT_dup(point, group)) == NULL) | ||
824 | goto err; | ||
825 | for (i = 1; i < 15; i += 2) { | ||
826 | if ((multiples[i] = EC_POINT_new(group)) == NULL) | ||
827 | goto err; | ||
828 | if (!EC_POINT_dbl(group, multiples[i], multiples[i / 2], ctx)) | ||
829 | goto err; | ||
830 | if ((multiples[i + 1] = EC_POINT_new(group)) == NULL) | ||
831 | goto err; | ||
832 | if (!EC_POINT_add(group, multiples[i + 1], multiples[i], point, ctx)) | ||
833 | goto err; | ||
834 | } | ||
797 | 835 | ||
798 | if ((rr = EC_POINT_new(group)) == NULL) | 836 | if ((rr = EC_POINT_new(group)) == NULL) |
799 | goto err; | 837 | goto err; |
838 | if ((t = EC_POINT_new(group)) == NULL) | ||
839 | goto err; | ||
800 | 840 | ||
801 | bits = BN_num_bits(scalar); | 841 | if (!EC_POINT_set_to_infinity(group, rr)) |
842 | goto err; | ||
843 | |||
844 | for (i = 0; i < scalar_len; i++) { | ||
845 | if (i != 0) { | ||
846 | if (!EC_POINT_dbl(group, rr, rr, ctx)) | ||
847 | goto err; | ||
848 | if (!EC_POINT_dbl(group, rr, rr, ctx)) | ||
849 | goto err; | ||
850 | if (!EC_POINT_dbl(group, rr, rr, ctx)) | ||
851 | goto err; | ||
852 | if (!EC_POINT_dbl(group, rr, rr, ctx)) | ||
853 | goto err; | ||
854 | } | ||
802 | 855 | ||
803 | EC_POINT_copy(rr, point); | 856 | if (!EC_POINT_set_to_infinity(group, t)) |
857 | goto err; | ||
858 | |||
859 | wv = scalar_bytes[i] >> 4; | ||
860 | for (j = 1; j < 16; j++) { | ||
861 | conditional = crypto_ct_eq_u8(j, wv); | ||
862 | ec_point_select(group, t, t, multiples[j - 1], conditional); | ||
863 | } | ||
864 | if (!EC_POINT_add(group, rr, rr, t, ctx)) | ||
865 | goto err; | ||
804 | 866 | ||
805 | for (i = bits - 2; i >= 0; i--) { | ||
806 | if (!EC_POINT_dbl(group, rr, rr, ctx)) | 867 | if (!EC_POINT_dbl(group, rr, rr, ctx)) |
807 | goto err; | 868 | goto err; |
808 | if (BN_is_bit_set(scalar, i)) { | 869 | if (!EC_POINT_dbl(group, rr, rr, ctx)) |
809 | if (!EC_POINT_add(group, rr, rr, point, ctx)) | 870 | goto err; |
810 | goto err; | 871 | if (!EC_POINT_dbl(group, rr, rr, ctx)) |
872 | goto err; | ||
873 | if (!EC_POINT_dbl(group, rr, rr, ctx)) | ||
874 | goto err; | ||
875 | |||
876 | if (!EC_POINT_set_to_infinity(group, t)) | ||
877 | goto err; | ||
878 | |||
879 | wv = scalar_bytes[i] & 0xf; | ||
880 | for (j = 1; j < 16; j++) { | ||
881 | conditional = crypto_ct_eq_u8(j, wv); | ||
882 | ec_point_select(group, t, t, multiples[j - 1], conditional); | ||
811 | } | 883 | } |
884 | if (!EC_POINT_add(group, rr, rr, t, ctx)) | ||
885 | goto err; | ||
812 | } | 886 | } |
813 | 887 | ||
814 | EC_POINT_copy(r, rr); | 888 | if (!EC_POINT_copy(r, rr)) |
889 | goto err; | ||
815 | 890 | ||
816 | ret = 1; | 891 | ret = 1; |
817 | 892 | ||
818 | err: | 893 | err: |
894 | for (i = 0; i < 15; i++) | ||
895 | EC_POINT_free(multiples[i]); | ||
896 | |||
819 | EC_POINT_free(rr); | 897 | EC_POINT_free(rr); |
898 | EC_POINT_free(t); | ||
899 | |||
900 | freezero(scalar_bytes, scalar_len); | ||
901 | |||
902 | BN_CTX_end(ctx); | ||
820 | 903 | ||
821 | return ret; | 904 | return ret; |
822 | } | 905 | } |