summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/regress/lib/libcrypto/ec/Makefile25
-rw-r--r--src/regress/lib/libcrypto/ec/ec_point_conversion.c249
2 files changed, 268 insertions, 6 deletions
diff --git a/src/regress/lib/libcrypto/ec/Makefile b/src/regress/lib/libcrypto/ec/Makefile
index 76b552fa23..394ac51226 100644
--- a/src/regress/lib/libcrypto/ec/Makefile
+++ b/src/regress/lib/libcrypto/ec/Makefile
@@ -1,9 +1,22 @@
1# $OpenBSD: Makefile,v 1.4 2021/04/20 17:09:45 tb Exp $ 1# $OpenBSD: Makefile,v 1.5 2021/04/21 20:15:08 tb Exp $
2 2
3PROG= ectest 3PROGS += ectest
4LDADD= ${CRYPTO_INT} 4PROGS += ec_point_conversion
5DPADD= ${LIBCRYPTO} 5
6WARNINGS= Yes 6.for t in ${PROGS}
7CFLAGS+= -DLIBRESSL_INTERNAL -Werror 7REGRESS_TARGETS += run-$t
8.endfor
9
10LDADD = ${CRYPTO_INT}
11DPADD = ${LIBCRYPTO}
12WARNINGS = Yes
13CFLAGS += -DLIBRESSL_INTERNAL -Wall -Wundef -Werror
14
15CLEANFILES += ${PROGS}
16
17.for t in ${PROGS}
18run-$t: $t
19 ./$t
20.endfor
8 21
9.include <bsd.regress.mk> 22.include <bsd.regress.mk>
diff --git a/src/regress/lib/libcrypto/ec/ec_point_conversion.c b/src/regress/lib/libcrypto/ec/ec_point_conversion.c
new file mode 100644
index 0000000000..97ba70034d
--- /dev/null
+++ b/src/regress/lib/libcrypto/ec/ec_point_conversion.c
@@ -0,0 +1,249 @@
1/* $OpenBSD: ec_point_conversion.c,v 1.1 2021/04/21 20:15:08 tb Exp $ */
2/*
3 * Copyright (c) 2021 Theo Buehler <tb@openbsd.org>
4 * Copyright (c) 2021 Joel Sing <jsing@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <err.h>
20#include <stdio.h>
21#include <stdlib.h>
22
23#include <openssl/ec.h>
24#include <openssl/objects.h>
25
26int bn_rand_interval(BIGNUM *, const BIGNUM *, const BIGNUM *);
27
28int forms[] = {
29 POINT_CONVERSION_COMPRESSED,
30 POINT_CONVERSION_UNCOMPRESSED,
31 POINT_CONVERSION_HYBRID,
32};
33
34static const size_t N_FORMS = sizeof(forms) / sizeof(forms[0]);
35#define N_RANDOM_POINTS 10
36
37static const char *
38form2str(int form)
39{
40 switch (form) {
41 case POINT_CONVERSION_COMPRESSED:
42 return "compressed form";
43 case POINT_CONVERSION_UNCOMPRESSED:
44 return "uncompressed form";
45 case POINT_CONVERSION_HYBRID:
46 return "hybrid form";
47 default:
48 return "unknown form";
49 }
50}
51
52static void
53hexdump(const unsigned char *buf, size_t len)
54{
55 size_t i;
56
57 for (i = 1; i <= len; i++)
58 fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n");
59
60 if (len % 8)
61 fprintf(stderr, "\n");
62}
63
64static int
65roundtrip(EC_GROUP *group, EC_POINT *point, int form, BIGNUM *x, BIGNUM *y)
66{
67 BIGNUM *x_out = NULL, *y_out = NULL;
68 size_t len;
69 uint8_t *buf = NULL;
70 int failed = 1;
71
72 if ((len = EC_POINT_point2oct(group, point, form, NULL, 0, NULL)) == 0)
73 errx(1, "point2oct");
74 if ((buf = malloc(len)) == NULL)
75 errx(1, "malloc");
76 if (EC_POINT_point2oct(group, point, form, buf, len, NULL) != len)
77 errx(1, "point2oct");
78
79 if (!EC_POINT_oct2point(group, point, buf, len, NULL))
80 errx(1, "%s oct2point", form2str(form));
81
82 if ((x_out = BN_new()) == NULL)
83 errx(1, "new x_out");
84 if ((y_out = BN_new()) == NULL)
85 errx(1, "new y_out");
86
87 if (!EC_POINT_get_affine_coordinates(group, point, x_out, y_out, NULL))
88 errx(1, "get affine");
89
90 if (BN_cmp(x, x_out) != 0) {
91 warnx("%s: x", form2str(form));
92 goto err;
93 }
94 if (BN_cmp(y, y_out) != 0) {
95 warnx("%s: y", form2str(form));
96 goto err;
97 }
98
99 failed = 0;
100
101 err:
102 if (failed)
103 hexdump(buf, len);
104
105 free(buf);
106 BN_free(x_out);
107 BN_free(y_out);
108
109 return failed;
110}
111
112static int
113hybrid_corner_case(void)
114{
115 BIGNUM *x = NULL, *y = NULL;
116 EC_GROUP *group;
117 EC_POINT *point;
118 size_t i;
119 int failed = 0;
120
121 if (!BN_hex2bn(&x, "0"))
122 errx(1, "BN_hex2bn x");
123 if (!BN_hex2bn(&y, "01"))
124 errx(1, "BN_hex2bn y");
125
126 if ((group = EC_GROUP_new_by_curve_name(NID_sect571k1)) == NULL)
127 errx(1, "group");
128 if ((point = EC_POINT_new(group)) == NULL)
129 errx(1, "point");
130
131 if (!EC_POINT_set_affine_coordinates(group, point, x, y, NULL))
132 errx(1, "set affine");
133
134 for (i = 0; i < N_FORMS; i++)
135 failed |= roundtrip(group, point, forms[i], x, y);
136
137 fprintf(stderr, "%s: %s\n", __func__, failed ? "FAILED" : "SUCCESS");
138
139 EC_GROUP_free(group);
140 EC_POINT_free(point);
141 BN_free(x);
142 BN_free(y);
143
144 return failed;
145}
146
147/* XXX This only tests multiples of the generator for now... */
148static int
149test_random_points_on_curve(EC_builtin_curve *curve)
150{
151 EC_GROUP *group;
152 BIGNUM *order = NULL;
153 BIGNUM *random;
154 BIGNUM *x, *y;
155 size_t i, j;
156 int failed = 0;
157
158 fprintf(stderr, "%s\n", OBJ_nid2sn(curve->nid));
159 if ((group = EC_GROUP_new_by_curve_name(curve->nid)) == NULL)
160 errx(1, "EC_GROUP_new_by_curve_name");
161
162 if ((order = BN_new()) == NULL)
163 errx(1, "BN_new order");
164 if ((random = BN_new()) == NULL)
165 errx(1, "BN_new random");
166 if ((x = BN_new()) == NULL)
167 errx(1, "BN_new x");
168 if ((y = BN_new()) == NULL)
169 errx(1, "BN_new y");
170
171 if (!EC_GROUP_get_order(group, order, NULL))
172 errx(1, "EC_group_get_order");
173
174 for (i = 0; i < N_RANDOM_POINTS; i++) {
175 EC_POINT *random_point;
176
177 if (!bn_rand_interval(random, BN_value_one(), order))
178 errx(1, "bn_rand_interval");
179
180 if ((random_point = EC_POINT_new(group)) == NULL)
181 errx(1, "EC_POINT_new");
182
183 if (!EC_POINT_mul(group, random_point, random, NULL, NULL, NULL))
184 errx(1, "EC_POINT_mul");
185
186 if (EC_POINT_is_at_infinity(group, random_point)) {
187 EC_POINT_free(random_point);
188
189 warnx("info: got infinity");
190 fprintf(stderr, "random = ");
191 BN_print_fp(stderr, random);
192 fprintf(stderr, "\n");
193
194 continue;
195 }
196
197 if (!EC_POINT_get_affine_coordinates(group, random_point,
198 x, y, NULL))
199 errx(1, "EC_POINT_get_affine_coordinates");
200
201 for (j = 0; j < N_FORMS; j++)
202 failed |= roundtrip(group, random_point, forms[j], x, y);
203
204 EC_POINT_free(random_point);
205 }
206
207 BN_free(order);
208 BN_free(random);
209 BN_free(x);
210 BN_free(y);
211 EC_GROUP_free(group);
212
213 return failed;
214}
215
216static int
217test_random_points(void)
218{
219 EC_builtin_curve *all_curves = NULL;
220 size_t ncurves = 0;
221 size_t curve_id;
222 int failed = 0;
223
224 ncurves = EC_get_builtin_curves(NULL, 0);
225 if ((all_curves = calloc(ncurves, sizeof(EC_builtin_curve))) == NULL)
226 err(1, "calloc builtin curves");
227 EC_get_builtin_curves(all_curves, ncurves);
228
229 for (curve_id = 0; curve_id < ncurves; curve_id++)
230 test_random_points_on_curve(&all_curves[curve_id]);
231
232 fprintf(stderr, "%s: %s\n", __func__, failed ? "FAILED" : "SUCCESS");
233
234 free(all_curves);
235 return failed;
236}
237
238int
239main(int argc, char **argv)
240{
241 int failed = 0;
242
243 failed |= test_random_points();
244 failed |= hybrid_corner_case();
245
246 fprintf(stderr, "%s\n", failed ? "FAILED" : "SUCCESS");
247
248 return failed;
249}