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