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 | |
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')
-rw-r--r-- | src/lib/libcrypto/Makefile | 3 | ||||
-rw-r--r-- | src/lib/libcrypto/bn/bn_internal.h | 4 | ||||
-rw-r--r-- | src/lib/libcrypto/bn/bn_mont.c | 71 | ||||
-rw-r--r-- | src/lib/libcrypto/ec/ec_field.c | 189 | ||||
-rw-r--r-- | src/lib/libcrypto/ec/ec_internal.h | 63 |
5 files changed, 299 insertions, 31 deletions
diff --git a/src/lib/libcrypto/Makefile b/src/lib/libcrypto/Makefile index dd64f07f48..7564001961 100644 --- a/src/lib/libcrypto/Makefile +++ b/src/lib/libcrypto/Makefile | |||
@@ -1,4 +1,4 @@ | |||
1 | # $OpenBSD: Makefile,v 1.233 2025/05/25 04:58:32 jsing Exp $ | 1 | # $OpenBSD: Makefile,v 1.234 2025/05/25 05:12:05 jsing Exp $ |
2 | 2 | ||
3 | LIB= crypto | 3 | LIB= crypto |
4 | LIBREBUILD=y | 4 | LIBREBUILD=y |
@@ -283,6 +283,7 @@ SRCS+= ec_asn1.c | |||
283 | SRCS+= ec_convert.c | 283 | SRCS+= ec_convert.c |
284 | SRCS+= ec_curve.c | 284 | SRCS+= ec_curve.c |
285 | SRCS+= ec_err.c | 285 | SRCS+= ec_err.c |
286 | SRCS+= ec_field.c | ||
286 | SRCS+= ec_key.c | 287 | SRCS+= ec_key.c |
287 | SRCS+= ec_lib.c | 288 | SRCS+= ec_lib.c |
288 | SRCS+= ec_mult.c | 289 | SRCS+= ec_mult.c |
diff --git a/src/lib/libcrypto/bn/bn_internal.h b/src/lib/libcrypto/bn/bn_internal.h index b6e903553f..a1f1515b57 100644 --- a/src/lib/libcrypto/bn/bn_internal.h +++ b/src/lib/libcrypto/bn/bn_internal.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: bn_internal.h,v 1.18 2025/05/25 04:58:32 jsing Exp $ */ | 1 | /* $OpenBSD: bn_internal.h,v 1.19 2025/05/25 05:12:05 jsing Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2023 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2023 Joel Sing <jsing@openbsd.org> |
4 | * | 4 | * |
@@ -45,6 +45,8 @@ void bn_mod_mul_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, | |||
45 | void bn_montgomery_multiply_words(BN_ULONG *rp, const BN_ULONG *ap, | 45 | void bn_montgomery_multiply_words(BN_ULONG *rp, const BN_ULONG *ap, |
46 | const BN_ULONG *bp, const BN_ULONG *np, BN_ULONG *tp, BN_ULONG n0, | 46 | const BN_ULONG *bp, const BN_ULONG *np, BN_ULONG *tp, BN_ULONG n0, |
47 | int n_len); | 47 | int n_len); |
48 | void bn_montgomery_reduce_words(BN_ULONG *r, BN_ULONG *a, const BN_ULONG *n, | ||
49 | BN_ULONG n0, int n_len); | ||
48 | 50 | ||
49 | #ifndef HAVE_BN_CT_NE_ZERO | 51 | #ifndef HAVE_BN_CT_NE_ZERO |
50 | static inline int | 52 | static inline int |
diff --git a/src/lib/libcrypto/bn/bn_mont.c b/src/lib/libcrypto/bn/bn_mont.c index ce88b23ca9..950846fa5b 100644 --- a/src/lib/libcrypto/bn/bn_mont.c +++ b/src/lib/libcrypto/bn/bn_mont.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: bn_mont.c,v 1.67 2025/05/25 04:58:32 jsing Exp $ */ | 1 | /* $OpenBSD: bn_mont.c,v 1.68 2025/05/25 05:12:05 jsing Exp $ */ |
2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
@@ -316,6 +316,44 @@ BN_MONT_CTX_set_locked(BN_MONT_CTX **pmctx, int lock, const BIGNUM *mod, | |||
316 | LCRYPTO_ALIAS(BN_MONT_CTX_set_locked); | 316 | LCRYPTO_ALIAS(BN_MONT_CTX_set_locked); |
317 | 317 | ||
318 | /* | 318 | /* |
319 | * bn_montgomery_reduce_words() performs Montgomery reduction, reducing the input | ||
320 | * from its Montgomery form aR to a, returning the result in r. a must be twice | ||
321 | * the length of the modulus. Note that the input is mutated in the process of | ||
322 | * performing the reduction. | ||
323 | */ | ||
324 | void | ||
325 | bn_montgomery_reduce_words(BN_ULONG *r, BN_ULONG *a, const BN_ULONG *n, | ||
326 | BN_ULONG n0, int n_len) | ||
327 | { | ||
328 | BN_ULONG v, mask; | ||
329 | BN_ULONG carry = 0; | ||
330 | int i; | ||
331 | |||
332 | /* Add multiples of the modulus, so that it becomes divisible by R. */ | ||
333 | for (i = 0; i < n_len; i++) { | ||
334 | v = bn_mul_add_words(&a[i], n, n_len, a[i] * n0); | ||
335 | bn_addw_addw(v, a[i + n_len], carry, &carry, &a[i + n_len]); | ||
336 | } | ||
337 | |||
338 | /* Divide by R (this is the equivalent of right shifting by n_len). */ | ||
339 | a = &a[n_len]; | ||
340 | |||
341 | /* | ||
342 | * The output is now in the range of [0, 2N). Attempt to reduce once by | ||
343 | * subtracting the modulus. If the reduction was necessary then the | ||
344 | * result is already in r, otherwise copy the value prior to reduction | ||
345 | * from the top half of a. | ||
346 | */ | ||
347 | mask = carry - bn_sub_words(r, a, n, n_len); | ||
348 | |||
349 | for (i = 0; i < n_len; i++) { | ||
350 | *r = (*r & ~mask) | (*a & mask); | ||
351 | r++; | ||
352 | a++; | ||
353 | } | ||
354 | } | ||
355 | |||
356 | /* | ||
319 | * bn_montgomery_reduce() performs Montgomery reduction, reducing the input | 357 | * bn_montgomery_reduce() performs Montgomery reduction, reducing the input |
320 | * from its Montgomery form aR to a, returning the result in r. Note that the | 358 | * from its Montgomery form aR to a, returning the result in r. Note that the |
321 | * input is mutated in the process of performing the reduction, destroying its | 359 | * input is mutated in the process of performing the reduction, destroying its |
@@ -325,7 +363,6 @@ static int | |||
325 | bn_montgomery_reduce(BIGNUM *r, BIGNUM *a, BN_MONT_CTX *mctx) | 363 | bn_montgomery_reduce(BIGNUM *r, BIGNUM *a, BN_MONT_CTX *mctx) |
326 | { | 364 | { |
327 | BIGNUM *n; | 365 | BIGNUM *n; |
328 | BN_ULONG *ap, *rp, n0, v, carry, mask; | ||
329 | int i, max, n_len; | 366 | int i, max, n_len; |
330 | 367 | ||
331 | n = &mctx->N; | 368 | n = &mctx->N; |
@@ -341,7 +378,8 @@ bn_montgomery_reduce(BIGNUM *r, BIGNUM *a, BN_MONT_CTX *mctx) | |||
341 | 378 | ||
342 | /* | 379 | /* |
343 | * Expand a to twice the length of the modulus, zero if necessary. | 380 | * Expand a to twice the length of the modulus, zero if necessary. |
344 | * XXX - make this a requirement of the caller. | 381 | * XXX - make this a requirement of the caller or use a temporary |
382 | * allocation. | ||
345 | */ | 383 | */ |
346 | if ((max = 2 * n_len) < n_len) | 384 | if ((max = 2 * n_len) < n_len) |
347 | return 0; | 385 | return 0; |
@@ -350,33 +388,8 @@ bn_montgomery_reduce(BIGNUM *r, BIGNUM *a, BN_MONT_CTX *mctx) | |||
350 | for (i = a->top; i < max; i++) | 388 | for (i = a->top; i < max; i++) |
351 | a->d[i] = 0; | 389 | a->d[i] = 0; |
352 | 390 | ||
353 | carry = 0; | 391 | bn_montgomery_reduce_words(r->d, a->d, n->d, mctx->n0[0], n_len); |
354 | n0 = mctx->n0[0]; | ||
355 | |||
356 | /* Add multiples of the modulus, so that it becomes divisible by R. */ | ||
357 | for (i = 0; i < n_len; i++) { | ||
358 | v = bn_mul_add_words(&a->d[i], n->d, n_len, a->d[i] * n0); | ||
359 | bn_addw_addw(v, a->d[i + n_len], carry, &carry, | ||
360 | &a->d[i + n_len]); | ||
361 | } | ||
362 | |||
363 | /* Divide by R (this is the equivalent of right shifting by n_len). */ | ||
364 | ap = &a->d[n_len]; | ||
365 | |||
366 | /* | ||
367 | * The output is now in the range of [0, 2N). Attempt to reduce once by | ||
368 | * subtracting the modulus. If the reduction was necessary then the | ||
369 | * result is already in r, otherwise copy the value prior to reduction | ||
370 | * from the top half of a. | ||
371 | */ | ||
372 | mask = carry - bn_sub_words(r->d, ap, n->d, n_len); | ||
373 | 392 | ||
374 | rp = r->d; | ||
375 | for (i = 0; i < n_len; i++) { | ||
376 | *rp = (*rp & ~mask) | (*ap & mask); | ||
377 | rp++; | ||
378 | ap++; | ||
379 | } | ||
380 | r->top = n_len; | 393 | r->top = n_len; |
381 | 394 | ||
382 | bn_correct_top(r); | 395 | bn_correct_top(r); |
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 | } | ||
diff --git a/src/lib/libcrypto/ec/ec_internal.h b/src/lib/libcrypto/ec/ec_internal.h new file mode 100644 index 0000000000..29b447e8c9 --- /dev/null +++ b/src/lib/libcrypto/ec/ec_internal.h | |||
@@ -0,0 +1,63 @@ | |||
1 | /* $OpenBSD: ec_internal.h,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 <openssl/bn.h> | ||
19 | |||
20 | #ifndef HEADER_EC_INTERNAL_H | ||
21 | #define HEADER_EC_INTERNAL_H | ||
22 | |||
23 | #define EC_FIELD_ELEMENT_MAX_BITS 521 | ||
24 | #define EC_FIELD_ELEMENT_MAX_BYTES \ | ||
25 | (EC_FIELD_ELEMENT_MAX_BITS + 7) / 8 | ||
26 | #define EC_FIELD_ELEMENT_MAX_WORDS \ | ||
27 | ((EC_FIELD_ELEMENT_MAX_BYTES + BN_BYTES - 1) / BN_BYTES) | ||
28 | |||
29 | typedef struct { | ||
30 | BN_ULONG w[EC_FIELD_ELEMENT_MAX_WORDS]; | ||
31 | } EC_FIELD_ELEMENT; | ||
32 | |||
33 | typedef struct { | ||
34 | size_t n; | ||
35 | EC_FIELD_ELEMENT m; | ||
36 | EC_FIELD_ELEMENT rr; | ||
37 | BN_ULONG minv0; | ||
38 | } EC_FIELD_MODULUS; | ||
39 | |||
40 | int ec_field_modulus_from_bn(EC_FIELD_MODULUS *fm, const BIGNUM *bn, | ||
41 | BN_CTX *ctx); | ||
42 | |||
43 | int ec_field_element_from_bn(const EC_FIELD_MODULUS *fm, const EC_GROUP *group, | ||
44 | EC_FIELD_ELEMENT *fe, const BIGNUM *bn, BN_CTX *ctx); | ||
45 | int ec_field_element_to_bn(const EC_FIELD_MODULUS *fm, const EC_FIELD_ELEMENT *fe, | ||
46 | BIGNUM *bn, BN_CTX *ctx); | ||
47 | |||
48 | void ec_field_element_copy(EC_FIELD_ELEMENT *dst, const EC_FIELD_ELEMENT *src); | ||
49 | |||
50 | int ec_field_element_equal(const EC_FIELD_MODULUS *fm, const EC_FIELD_ELEMENT *a, | ||
51 | const EC_FIELD_ELEMENT *b); | ||
52 | int ec_field_element_is_zero(const EC_FIELD_MODULUS *fm, const EC_FIELD_ELEMENT *fe); | ||
53 | |||
54 | void ec_field_element_add(const EC_FIELD_MODULUS *m, EC_FIELD_ELEMENT *r, | ||
55 | const EC_FIELD_ELEMENT *a, const EC_FIELD_ELEMENT *b); | ||
56 | void ec_field_element_sub(const EC_FIELD_MODULUS *m, EC_FIELD_ELEMENT *r, | ||
57 | const EC_FIELD_ELEMENT *a, const EC_FIELD_ELEMENT *b); | ||
58 | void ec_field_element_mul(const EC_FIELD_MODULUS *m, EC_FIELD_ELEMENT *r, | ||
59 | const EC_FIELD_ELEMENT *a, const EC_FIELD_ELEMENT *b); | ||
60 | void ec_field_element_sqr(const EC_FIELD_MODULUS *m, EC_FIELD_ELEMENT *r, | ||
61 | const EC_FIELD_ELEMENT *a); | ||
62 | |||
63 | #endif | ||