]> git.ipfire.org Git - thirdparty/openssl.git/blob - test/ec_internal_test.c
345ce199c5f85cd08b099552ba92ff8d742bfed5
[thirdparty/openssl.git] / test / ec_internal_test.c
1 /*
2 * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10 /*
11 * Low level APIs are deprecated for public use, but still ok for internal use.
12 */
13 #include "internal/deprecated.h"
14
15 #include "internal/nelem.h"
16 #include "testutil.h"
17 #include <openssl/ec.h>
18 #include "ec_local.h"
19 #include <openssl/objects.h>
20
21 static size_t crv_len = 0;
22 static EC_builtin_curve *curves = NULL;
23
24 /* sanity checks field_inv function pointer in EC_METHOD */
25 static int group_field_tests(const EC_GROUP *group, BN_CTX *ctx)
26 {
27 BIGNUM *a = NULL, *b = NULL, *c = NULL;
28 int ret = 0;
29
30 if (group->meth->field_inv == NULL || group->meth->field_mul == NULL)
31 return 1;
32
33 BN_CTX_start(ctx);
34 a = BN_CTX_get(ctx);
35 b = BN_CTX_get(ctx);
36 if (!TEST_ptr(c = BN_CTX_get(ctx))
37 /* 1/1 = 1 */
38 || !TEST_true(group->meth->field_inv(group, b, BN_value_one(), ctx))
39 || !TEST_true(BN_is_one(b))
40 /* (1/a)*a = 1 */
41 || !TEST_true(BN_rand(a, BN_num_bits(group->field) - 1,
42 BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY))
43 || !TEST_true(group->meth->field_inv(group, b, a, ctx))
44 || (group->meth->field_encode &&
45 !TEST_true(group->meth->field_encode(group, a, a, ctx)))
46 || (group->meth->field_encode &&
47 !TEST_true(group->meth->field_encode(group, b, b, ctx)))
48 || !TEST_true(group->meth->field_mul(group, c, a, b, ctx))
49 || (group->meth->field_decode &&
50 !TEST_true(group->meth->field_decode(group, c, c, ctx)))
51 || !TEST_true(BN_is_one(c)))
52 goto err;
53
54 /* 1/0 = error */
55 BN_zero(a);
56 if (!TEST_false(group->meth->field_inv(group, b, a, ctx))
57 || !TEST_true(ERR_GET_LIB(ERR_peek_last_error()) == ERR_LIB_EC)
58 || !TEST_true(ERR_GET_REASON(ERR_peek_last_error()) ==
59 EC_R_CANNOT_INVERT)
60 /* 1/p = error */
61 || !TEST_false(group->meth->field_inv(group, b, group->field, ctx))
62 || !TEST_true(ERR_GET_LIB(ERR_peek_last_error()) == ERR_LIB_EC)
63 || !TEST_true(ERR_GET_REASON(ERR_peek_last_error()) ==
64 EC_R_CANNOT_INVERT))
65 goto err;
66
67 ERR_clear_error();
68 ret = 1;
69 err:
70 BN_CTX_end(ctx);
71 return ret;
72 }
73
74 /* wrapper for group_field_tests for explicit curve params and EC_METHOD */
75 static int field_tests(const EC_METHOD *meth, const unsigned char *params,
76 int len)
77 {
78 BN_CTX *ctx = NULL;
79 BIGNUM *p = NULL, *a = NULL, *b = NULL;
80 EC_GROUP *group = NULL;
81 int ret = 0;
82
83 if (!TEST_ptr(ctx = BN_CTX_new()))
84 return 0;
85
86 BN_CTX_start(ctx);
87 p = BN_CTX_get(ctx);
88 a = BN_CTX_get(ctx);
89 if (!TEST_ptr(b = BN_CTX_get(ctx))
90 || !TEST_ptr(group = EC_GROUP_new(meth))
91 || !TEST_true(BN_bin2bn(params, len, p))
92 || !TEST_true(BN_bin2bn(params + len, len, a))
93 || !TEST_true(BN_bin2bn(params + 2 * len, len, b))
94 || !TEST_true(EC_GROUP_set_curve(group, p, a, b, ctx))
95 || !group_field_tests(group, ctx))
96 goto err;
97 ret = 1;
98
99 err:
100 BN_CTX_end(ctx);
101 BN_CTX_free(ctx);
102 if (group != NULL)
103 EC_GROUP_free(group);
104 return ret;
105 }
106
107 /* NIST prime curve P-256 */
108 static const unsigned char params_p256[] = {
109 /* p */
110 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
111 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
112 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
113 /* a */
114 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
115 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
116 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC,
117 /* b */
118 0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A, 0x93, 0xE7, 0xB3, 0xEB, 0xBD, 0x55,
119 0x76, 0x98, 0x86, 0xBC, 0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53, 0xB0, 0xF6,
120 0x3B, 0xCE, 0x3C, 0x3E, 0x27, 0xD2, 0x60, 0x4B
121 };
122
123 #ifndef OPENSSL_NO_EC2M
124 /* NIST binary curve B-283 */
125 static const unsigned char params_b283[] = {
126 /* p */
127 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
128 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
129 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA1,
130 /* a */
131 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
132 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
133 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
134 /* b */
135 0x02, 0x7B, 0x68, 0x0A, 0xC8, 0xB8, 0x59, 0x6D, 0xA5, 0xA4, 0xAF, 0x8A,
136 0x19, 0xA0, 0x30, 0x3F, 0xCA, 0x97, 0xFD, 0x76, 0x45, 0x30, 0x9F, 0xA2,
137 0xA5, 0x81, 0x48, 0x5A, 0xF6, 0x26, 0x3E, 0x31, 0x3B, 0x79, 0xA2, 0xF5
138 };
139 #endif
140
141 /* test EC_GFp_simple_method directly */
142 static int field_tests_ecp_simple(void)
143 {
144 TEST_info("Testing EC_GFp_simple_method()\n");
145 return field_tests(EC_GFp_simple_method(), params_p256,
146 sizeof(params_p256) / 3);
147 }
148
149 /* test EC_GFp_mont_method directly */
150 static int field_tests_ecp_mont(void)
151 {
152 TEST_info("Testing EC_GFp_mont_method()\n");
153 return field_tests(EC_GFp_mont_method(), params_p256,
154 sizeof(params_p256) / 3);
155 }
156
157 #ifndef OPENSSL_NO_EC2M
158 /* test EC_GF2m_simple_method directly */
159 static int field_tests_ec2_simple(void)
160 {
161 TEST_info("Testing EC_GF2m_simple_method()\n");
162 return field_tests(EC_GF2m_simple_method(), params_b283,
163 sizeof(params_b283) / 3);
164 }
165 #endif
166
167 /* test default method for a named curve */
168 static int field_tests_default(int n)
169 {
170 BN_CTX *ctx = NULL;
171 EC_GROUP *group = NULL;
172 int nid = curves[n].nid;
173 int ret = 0;
174
175 TEST_info("Testing curve %s\n", OBJ_nid2sn(nid));
176
177 if (!TEST_ptr(group = EC_GROUP_new_by_curve_name(nid))
178 || !TEST_ptr(ctx = BN_CTX_new())
179 || !group_field_tests(group, ctx))
180 goto err;
181
182 ret = 1;
183 err:
184 if (group != NULL)
185 EC_GROUP_free(group);
186 if (ctx != NULL)
187 BN_CTX_free(ctx);
188 return ret;
189 }
190
191 #ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
192 /*
193 * Tests a point known to cause an incorrect underflow in an old version of
194 * ecp_nist521.c
195 */
196 static int underflow_test(void)
197 {
198 BN_CTX *ctx = NULL;
199 EC_GROUP *grp = NULL;
200 EC_POINT *P = NULL, *Q = NULL, *R = NULL;
201 BIGNUM *x1 = NULL, *y1 = NULL, *z1 = NULL, *x2 = NULL, *y2 = NULL;
202 BIGNUM *k = NULL;
203 int testresult = 0;
204 const char *x1str =
205 "1534f0077fffffe87e9adcfe000000000000000000003e05a21d2400002e031b1f4"
206 "b80000c6fafa4f3c1288798d624a247b5e2ffffffffffffffefe099241900004";
207 const char *p521m1 =
208 "1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
209 "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe";
210
211 ctx = BN_CTX_new();
212 if (!TEST_ptr(ctx))
213 return 0;
214
215 BN_CTX_start(ctx);
216 x1 = BN_CTX_get(ctx);
217 y1 = BN_CTX_get(ctx);
218 z1 = BN_CTX_get(ctx);
219 x2 = BN_CTX_get(ctx);
220 y2 = BN_CTX_get(ctx);
221 k = BN_CTX_get(ctx);
222 if (!TEST_ptr(k))
223 goto err;
224
225 grp = EC_GROUP_new_by_curve_name(NID_secp521r1);
226 P = EC_POINT_new(grp);
227 Q = EC_POINT_new(grp);
228 R = EC_POINT_new(grp);
229 if (!TEST_ptr(grp) || !TEST_ptr(P) || !TEST_ptr(Q) || !TEST_ptr(R))
230 goto err;
231
232 if (!TEST_int_gt(BN_hex2bn(&x1, x1str), 0)
233 || !TEST_int_gt(BN_hex2bn(&y1, p521m1), 0)
234 || !TEST_int_gt(BN_hex2bn(&z1, p521m1), 0)
235 || !TEST_int_gt(BN_hex2bn(&k, "02"), 0)
236 || !TEST_true(ec_GFp_simple_set_Jprojective_coordinates_GFp(grp, P, x1,
237 y1, z1, ctx))
238 || !TEST_true(EC_POINT_mul(grp, Q, NULL, P, k, ctx))
239 || !TEST_true(EC_POINT_get_affine_coordinates(grp, Q, x1, y1, ctx))
240 || !TEST_true(EC_POINT_dbl(grp, R, P, ctx))
241 || !TEST_true(EC_POINT_get_affine_coordinates(grp, R, x2, y2, ctx)))
242 goto err;
243
244 if (!TEST_int_eq(BN_cmp(x1, x2), 0)
245 || !TEST_int_eq(BN_cmp(y1, y2), 0))
246 goto err;
247
248 testresult = 1;
249
250 err:
251 BN_CTX_end(ctx);
252 EC_POINT_free(P);
253 EC_POINT_free(Q);
254 EC_POINT_free(R);
255 EC_GROUP_free(grp);
256 BN_CTX_free(ctx);
257
258 return testresult;
259 }
260 #endif
261
262 /*
263 * Tests behavior of the decoded_from_explicit_params flag and API
264 */
265 static int decoded_flag_test(void)
266 {
267 EC_GROUP *grp;
268 EC_GROUP *grp_copy = NULL;
269 ECPARAMETERS *ecparams = NULL;
270 ECPKPARAMETERS *ecpkparams = NULL;
271 EC_KEY *key = NULL;
272 unsigned char *encodedparams = NULL;
273 const unsigned char *encp;
274 int encodedlen;
275 int testresult = 0;
276
277 /* Test EC_GROUP_new not setting the flag */
278 grp = EC_GROUP_new(EC_GFp_simple_method());
279 if (!TEST_ptr(grp)
280 || !TEST_int_eq(grp->decoded_from_explicit_params, 0))
281 goto err;
282 EC_GROUP_free(grp);
283
284 /* Test EC_GROUP_new_by_curve_name not setting the flag */
285 grp = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1);
286 if (!TEST_ptr(grp)
287 || !TEST_int_eq(grp->decoded_from_explicit_params, 0))
288 goto err;
289
290 /* Test EC_GROUP_new_from_ecparameters not setting the flag */
291 if (!TEST_ptr(ecparams = EC_GROUP_get_ecparameters(grp, NULL))
292 || !TEST_ptr(grp_copy = EC_GROUP_new_from_ecparameters(ecparams))
293 || !TEST_int_eq(grp_copy->decoded_from_explicit_params, 0))
294 goto err;
295 EC_GROUP_free(grp_copy);
296 grp_copy = NULL;
297 ECPARAMETERS_free(ecparams);
298 ecparams = NULL;
299
300 /* Test EC_GROUP_new_from_ecpkparameters not setting the flag */
301 if (!TEST_int_eq(EC_GROUP_get_asn1_flag(grp), OPENSSL_EC_NAMED_CURVE)
302 || !TEST_ptr(ecpkparams = EC_GROUP_get_ecpkparameters(grp, NULL))
303 || !TEST_ptr(grp_copy = EC_GROUP_new_from_ecpkparameters(ecpkparams))
304 || !TEST_int_eq(grp_copy->decoded_from_explicit_params, 0)
305 || !TEST_ptr(key = EC_KEY_new())
306 /* Test EC_KEY_decoded_from_explicit_params on key without a group */
307 || !TEST_int_eq(EC_KEY_decoded_from_explicit_params(key), -1)
308 || !TEST_int_eq(EC_KEY_set_group(key, grp_copy), 1)
309 /* Test EC_KEY_decoded_from_explicit_params negative case */
310 || !TEST_int_eq(EC_KEY_decoded_from_explicit_params(key), 0))
311 goto err;
312 EC_GROUP_free(grp_copy);
313 grp_copy = NULL;
314 ECPKPARAMETERS_free(ecpkparams);
315 ecpkparams = NULL;
316
317 /* Test d2i_ECPKParameters with named params not setting the flag */
318 if (!TEST_int_gt(encodedlen = i2d_ECPKParameters(grp, &encodedparams), 0)
319 || !TEST_ptr(encp = encodedparams)
320 || !TEST_ptr(grp_copy = d2i_ECPKParameters(NULL, &encp, encodedlen))
321 || !TEST_int_eq(grp_copy->decoded_from_explicit_params, 0))
322 goto err;
323 EC_GROUP_free(grp_copy);
324 grp_copy = NULL;
325 OPENSSL_free(encodedparams);
326 encodedparams = NULL;
327
328 /* Asn1 flag stays set to explicit with EC_GROUP_new_from_ecpkparameters */
329 EC_GROUP_set_asn1_flag(grp, OPENSSL_EC_EXPLICIT_CURVE);
330 if (!TEST_ptr(ecpkparams = EC_GROUP_get_ecpkparameters(grp, NULL))
331 || !TEST_ptr(grp_copy = EC_GROUP_new_from_ecpkparameters(ecpkparams))
332 || !TEST_int_eq(EC_GROUP_get_asn1_flag(grp_copy), OPENSSL_EC_EXPLICIT_CURVE)
333 || !TEST_int_eq(grp_copy->decoded_from_explicit_params, 0))
334 goto err;
335 EC_GROUP_free(grp_copy);
336 grp_copy = NULL;
337
338 /* Test d2i_ECPKParameters with explicit params setting the flag */
339 if (!TEST_int_gt(encodedlen = i2d_ECPKParameters(grp, &encodedparams), 0)
340 || !TEST_ptr(encp = encodedparams)
341 || !TEST_ptr(grp_copy = d2i_ECPKParameters(NULL, &encp, encodedlen))
342 || !TEST_int_eq(EC_GROUP_get_asn1_flag(grp_copy), OPENSSL_EC_EXPLICIT_CURVE)
343 || !TEST_int_eq(grp_copy->decoded_from_explicit_params, 1)
344 || !TEST_int_eq(EC_KEY_set_group(key, grp_copy), 1)
345 /* Test EC_KEY_decoded_from_explicit_params positive case */
346 || !TEST_int_eq(EC_KEY_decoded_from_explicit_params(key), 1))
347 goto err;
348
349 testresult = 1;
350
351 err:
352 EC_KEY_free(key);
353 EC_GROUP_free(grp);
354 EC_GROUP_free(grp_copy);
355 ECPARAMETERS_free(ecparams);
356 ECPKPARAMETERS_free(ecpkparams);
357 OPENSSL_free(encodedparams);
358
359 return testresult;
360 }
361
362 int setup_tests(void)
363 {
364 crv_len = EC_get_builtin_curves(NULL, 0);
365 if (!TEST_ptr(curves = OPENSSL_malloc(sizeof(*curves) * crv_len))
366 || !TEST_true(EC_get_builtin_curves(curves, crv_len)))
367 return 0;
368
369 ADD_TEST(field_tests_ecp_simple);
370 ADD_TEST(field_tests_ecp_mont);
371 #ifndef OPENSSL_NO_EC2M
372 ADD_TEST(field_tests_ec2_simple);
373 #endif
374 ADD_ALL_TESTS(field_tests_default, crv_len);
375 #ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
376 ADD_TEST(underflow_test);
377 #endif
378 ADD_TEST(decoded_flag_test);
379 return 1;
380 }
381
382 void cleanup_tests(void)
383 {
384 OPENSSL_free(curves);
385 }