diff options
author | jsing <> | 2025-05-25 05:12:05 +0000 |
---|---|---|
committer | jsing <> | 2025-05-25 05:12:05 +0000 |
commit | 06551b0f228f49af60110396bb1a7f0fe0202321 (patch) | |
tree | d2a89424948ea33ced8fe1bb82297f1988893a57 /src/lib/libcrypto/ec/ec_field.c | |
parent | d1e92fb0ec242ccd5715534e3cfab9187b27c62b (diff) | |
download | openbsd-06551b0f228f49af60110396bb1a7f0fe0202321.tar.gz openbsd-06551b0f228f49af60110396bb1a7f0fe0202321.tar.bz2 openbsd-06551b0f228f49af60110396bb1a7f0fe0202321.zip |
Implement EC field element operations.
Provide EC_FIELD_ELEMENT and EC_FIELD_MODULUS, which allow for operations
on fixed width fields in constant time. These can in turn be used to
implement Elliptic Curve cryptography for prime fields, without needing
to use BN. This will improve the code, reduces timing leaks and enable
further optimisation.
ok beck@ tb@
Diffstat (limited to 'src/lib/libcrypto/ec/ec_field.c')
-rw-r--r-- | src/lib/libcrypto/ec/ec_field.c | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/src/lib/libcrypto/ec/ec_field.c b/src/lib/libcrypto/ec/ec_field.c new file mode 100644 index 0000000000..ec1c7d11e0 --- /dev/null +++ b/src/lib/libcrypto/ec/ec_field.c | |||
@@ -0,0 +1,189 @@ | |||
1 | /* $OpenBSD: ec_field.c,v 1.1 2025/05/25 05:12:05 jsing Exp $ */ | ||
2 | /* | ||
3 | * Copyright (c) 2024 Joel Sing <jsing@openbsd.org> | ||
4 | * | ||
5 | * Permission to use, copy, modify, and distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | |||
18 | #include <string.h> | ||
19 | |||
20 | #include <openssl/ec.h> | ||
21 | |||
22 | #include "bn_local.h" | ||
23 | #include "bn_internal.h" | ||
24 | #include "ec_local.h" | ||
25 | #include "ec_internal.h" | ||
26 | |||
27 | int | ||
28 | ec_field_modulus_from_bn(EC_FIELD_MODULUS *fm, const BIGNUM *bn, BN_CTX *ctx) | ||
29 | { | ||
30 | BN_MONT_CTX *mctx = NULL; | ||
31 | size_t i; | ||
32 | int ret = 0; | ||
33 | |||
34 | if (BN_is_negative(bn)) | ||
35 | goto err; | ||
36 | if (BN_num_bits(bn) > EC_FIELD_ELEMENT_MAX_BITS) | ||
37 | goto err; | ||
38 | |||
39 | memset(fm, 0, sizeof(*fm)); | ||
40 | |||
41 | fm->n = (BN_num_bits(bn) + BN_BITS2 - 1) / BN_BITS2; | ||
42 | |||
43 | for (i = 0; i < bn->top; i++) | ||
44 | fm->m.w[i] = bn->d[i]; | ||
45 | |||
46 | /* XXX - implement this without BN_MONT_CTX. */ | ||
47 | if ((mctx = BN_MONT_CTX_new()) == NULL) | ||
48 | goto err; | ||
49 | if (!BN_MONT_CTX_set(mctx, bn, ctx)) | ||
50 | goto err; | ||
51 | |||
52 | for (i = 0; i < mctx->RR.top; i++) | ||
53 | fm->rr.w[i] = mctx->RR.d[i]; | ||
54 | |||
55 | fm->minv0 = mctx->n0[0]; | ||
56 | |||
57 | ret = 1; | ||
58 | |||
59 | err: | ||
60 | BN_MONT_CTX_free(mctx); | ||
61 | |||
62 | return ret; | ||
63 | } | ||
64 | |||
65 | int | ||
66 | ec_field_element_from_bn(const EC_FIELD_MODULUS *fm, const EC_GROUP *group, | ||
67 | EC_FIELD_ELEMENT *fe, const BIGNUM *bn, BN_CTX *ctx) | ||
68 | { | ||
69 | BN_ULONG t[EC_FIELD_ELEMENT_MAX_WORDS * 2 + 2]; | ||
70 | BIGNUM *tmp; | ||
71 | size_t i; | ||
72 | int ret = 0; | ||
73 | |||
74 | BN_CTX_start(ctx); | ||
75 | |||
76 | if ((tmp = BN_CTX_get(ctx)) == NULL) | ||
77 | goto err; | ||
78 | |||
79 | /* XXX - enforce 0 <= n < p. */ | ||
80 | |||
81 | if (BN_num_bits(bn) > EC_FIELD_ELEMENT_MAX_BITS) | ||
82 | goto err; | ||
83 | |||
84 | /* XXX - do this without BN. */ | ||
85 | if (!BN_nnmod(tmp, bn, group->p, ctx)) | ||
86 | goto err; | ||
87 | |||
88 | if (BN_num_bits(tmp) > EC_FIELD_ELEMENT_MAX_BITS) | ||
89 | abort(); | ||
90 | |||
91 | memset(fe->w, 0, sizeof(fe->w)); | ||
92 | |||
93 | for (i = 0; i < tmp->top; i++) | ||
94 | fe->w[i] = tmp->d[i]; | ||
95 | |||
96 | bn_mod_mul_words(fe->w, fe->w, fm->rr.w, fm->m.w, t, fm->minv0, fm->n); | ||
97 | |||
98 | ret = 1; | ||
99 | |||
100 | err: | ||
101 | BN_CTX_end(ctx); | ||
102 | |||
103 | return ret; | ||
104 | } | ||
105 | |||
106 | int | ||
107 | ec_field_element_to_bn(const EC_FIELD_MODULUS *fm, const EC_FIELD_ELEMENT *fe, | ||
108 | BIGNUM *bn, BN_CTX *ctx) | ||
109 | { | ||
110 | BN_ULONG t[EC_FIELD_ELEMENT_MAX_WORDS * 2 + 2]; | ||
111 | size_t i; | ||
112 | |||
113 | if (!bn_wexpand(bn, fm->n)) | ||
114 | return 0; | ||
115 | |||
116 | memset(t, 0, sizeof(t)); | ||
117 | for (i = 0; i < fm->n; i++) | ||
118 | t[i] = fe->w[i]; | ||
119 | |||
120 | bn_montgomery_reduce_words(bn->d, t, fm->m.w, fm->minv0, fm->n); | ||
121 | |||
122 | bn->top = fm->n; | ||
123 | bn_correct_top(bn); | ||
124 | |||
125 | return 1; | ||
126 | } | ||
127 | |||
128 | void | ||
129 | ec_field_element_copy(EC_FIELD_ELEMENT *dst, const EC_FIELD_ELEMENT *src) | ||
130 | { | ||
131 | memcpy(dst, src, sizeof(EC_FIELD_ELEMENT)); | ||
132 | } | ||
133 | |||
134 | int | ||
135 | ec_field_element_equal(const EC_FIELD_MODULUS *fm, const EC_FIELD_ELEMENT *a, | ||
136 | const EC_FIELD_ELEMENT *b) | ||
137 | { | ||
138 | BN_ULONG v = 0; | ||
139 | int i; | ||
140 | |||
141 | for (i = 0; i < fm->n; i++) | ||
142 | v |= a->w[i] ^ b->w[i]; | ||
143 | |||
144 | return bn_ct_eq_zero(v); | ||
145 | } | ||
146 | |||
147 | int | ||
148 | ec_field_element_is_zero(const EC_FIELD_MODULUS *fm, const EC_FIELD_ELEMENT *fe) | ||
149 | { | ||
150 | BN_ULONG v = 0; | ||
151 | int i; | ||
152 | |||
153 | for (i = 0; i < fm->n; i++) | ||
154 | v |= fe->w[i]; | ||
155 | |||
156 | return bn_ct_eq_zero(v); | ||
157 | } | ||
158 | |||
159 | void | ||
160 | ec_field_element_add(const EC_FIELD_MODULUS *m, EC_FIELD_ELEMENT *r, | ||
161 | const EC_FIELD_ELEMENT *a, const EC_FIELD_ELEMENT *b) | ||
162 | { | ||
163 | bn_mod_add_words(r->w, a->w, b->w, m->m.w, m->n); | ||
164 | } | ||
165 | |||
166 | void | ||
167 | ec_field_element_sub(const EC_FIELD_MODULUS *m, EC_FIELD_ELEMENT *r, | ||
168 | const EC_FIELD_ELEMENT *a, const EC_FIELD_ELEMENT *b) | ||
169 | { | ||
170 | bn_mod_sub_words(r->w, a->w, b->w, m->m.w, m->n); | ||
171 | } | ||
172 | |||
173 | void | ||
174 | ec_field_element_mul(const EC_FIELD_MODULUS *m, EC_FIELD_ELEMENT *r, | ||
175 | const EC_FIELD_ELEMENT *a, const EC_FIELD_ELEMENT *b) | ||
176 | { | ||
177 | BN_ULONG t[EC_FIELD_ELEMENT_MAX_WORDS * 2 + 2]; | ||
178 | |||
179 | bn_mod_mul_words(r->w, a->w, b->w, m->m.w, t, m->minv0, m->n); | ||
180 | } | ||
181 | |||
182 | void | ||
183 | ec_field_element_sqr(const EC_FIELD_MODULUS *m, EC_FIELD_ELEMENT *r, | ||
184 | const EC_FIELD_ELEMENT *a) | ||
185 | { | ||
186 | BN_ULONG t[EC_FIELD_ELEMENT_MAX_WORDS * 2 + 2]; | ||
187 | |||
188 | bn_mod_mul_words(r->w, a->w, a->w, m->m.w, t, m->minv0, m->n); | ||
189 | } | ||