1 /*
2 * Copyright 2019-2021 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 decoded_from_explicit_params flag and API
188 */
decoded_flag_test(void)189 static int decoded_flag_test(void)
190 {
191 EC_GROUP *grp;
192 EC_GROUP *grp_copy = NULL;
193 ECPARAMETERS *ecparams = NULL;
194 ECPKPARAMETERS *ecpkparams = NULL;
195 EC_KEY *key = NULL;
196 unsigned char *encodedparams = NULL;
197 const unsigned char *encp;
198 int encodedlen;
199 int testresult = 0;
200
201 /* Test EC_GROUP_new not setting the flag */
202 grp = EC_GROUP_new(EC_GFp_simple_method());
203 if (!TEST_ptr(grp)
204 || !TEST_int_eq(grp->decoded_from_explicit_params, 0))
205 goto err;
206 EC_GROUP_free(grp);
207
208 /* Test EC_GROUP_new_by_curve_name not setting the flag */
209 grp = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1);
210 if (!TEST_ptr(grp)
211 || !TEST_int_eq(grp->decoded_from_explicit_params, 0))
212 goto err;
213
214 /* Test EC_GROUP_new_from_ecparameters not setting the flag */
215 if (!TEST_ptr(ecparams = EC_GROUP_get_ecparameters(grp, NULL))
216 || !TEST_ptr(grp_copy = EC_GROUP_new_from_ecparameters(ecparams))
217 || !TEST_int_eq(grp_copy->decoded_from_explicit_params, 0))
218 goto err;
219 EC_GROUP_free(grp_copy);
220 grp_copy = NULL;
221 ECPARAMETERS_free(ecparams);
222 ecparams = NULL;
223
224 /* Test EC_GROUP_new_from_ecpkparameters not setting the flag */
225 if (!TEST_int_eq(EC_GROUP_get_asn1_flag(grp), OPENSSL_EC_NAMED_CURVE)
226 || !TEST_ptr(ecpkparams = EC_GROUP_get_ecpkparameters(grp, NULL))
227 || !TEST_ptr(grp_copy = EC_GROUP_new_from_ecpkparameters(ecpkparams))
228 || !TEST_int_eq(grp_copy->decoded_from_explicit_params, 0)
229 || !TEST_ptr(key = EC_KEY_new())
230 /* Test EC_KEY_decoded_from_explicit_params on key without a group */
231 || !TEST_int_eq(EC_KEY_decoded_from_explicit_params(key), -1)
232 || !TEST_int_eq(EC_KEY_set_group(key, grp_copy), 1)
233 /* Test EC_KEY_decoded_from_explicit_params negative case */
234 || !TEST_int_eq(EC_KEY_decoded_from_explicit_params(key), 0))
235 goto err;
236 EC_GROUP_free(grp_copy);
237 grp_copy = NULL;
238 ECPKPARAMETERS_free(ecpkparams);
239 ecpkparams = NULL;
240
241 /* Test d2i_ECPKParameters with named params not setting the flag */
242 if (!TEST_int_gt(encodedlen = i2d_ECPKParameters(grp, &encodedparams), 0)
243 || !TEST_ptr(encp = encodedparams)
244 || !TEST_ptr(grp_copy = d2i_ECPKParameters(NULL, &encp, encodedlen))
245 || !TEST_int_eq(grp_copy->decoded_from_explicit_params, 0))
246 goto err;
247 EC_GROUP_free(grp_copy);
248 grp_copy = NULL;
249 OPENSSL_free(encodedparams);
250 encodedparams = NULL;
251
252 /* Asn1 flag stays set to explicit with EC_GROUP_new_from_ecpkparameters */
253 EC_GROUP_set_asn1_flag(grp, OPENSSL_EC_EXPLICIT_CURVE);
254 if (!TEST_ptr(ecpkparams = EC_GROUP_get_ecpkparameters(grp, NULL))
255 || !TEST_ptr(grp_copy = EC_GROUP_new_from_ecpkparameters(ecpkparams))
256 || !TEST_int_eq(EC_GROUP_get_asn1_flag(grp_copy), OPENSSL_EC_EXPLICIT_CURVE)
257 || !TEST_int_eq(grp_copy->decoded_from_explicit_params, 0))
258 goto err;
259 EC_GROUP_free(grp_copy);
260 grp_copy = NULL;
261
262 /* Test d2i_ECPKParameters with explicit params setting the flag */
263 if (!TEST_int_gt(encodedlen = i2d_ECPKParameters(grp, &encodedparams), 0)
264 || !TEST_ptr(encp = encodedparams)
265 || !TEST_ptr(grp_copy = d2i_ECPKParameters(NULL, &encp, encodedlen))
266 || !TEST_int_eq(EC_GROUP_get_asn1_flag(grp_copy), OPENSSL_EC_EXPLICIT_CURVE)
267 || !TEST_int_eq(grp_copy->decoded_from_explicit_params, 1)
268 || !TEST_int_eq(EC_KEY_set_group(key, grp_copy), 1)
269 /* Test EC_KEY_decoded_from_explicit_params positive case */
270 || !TEST_int_eq(EC_KEY_decoded_from_explicit_params(key), 1))
271 goto err;
272
273 testresult = 1;
274
275 err:
276 EC_KEY_free(key);
277 EC_GROUP_free(grp);
278 EC_GROUP_free(grp_copy);
279 ECPARAMETERS_free(ecparams);
280 ECPKPARAMETERS_free(ecpkparams);
281 OPENSSL_free(encodedparams);
282
283 return testresult;
284 }
285
286 static
ecpkparams_i2d2i_test(int n)287 int ecpkparams_i2d2i_test(int n)
288 {
289 EC_GROUP *g1 = NULL, *g2 = NULL;
290 FILE *fp = NULL;
291 int nid = curves[n].nid;
292 int testresult = 0;
293
294 /* create group */
295 if (!TEST_ptr(g1 = EC_GROUP_new_by_curve_name(nid)))
296 goto end;
297
298 /* encode params to file */
299 if (!TEST_ptr(fp = fopen("params.der", "wb"))
300 || !TEST_true(i2d_ECPKParameters_fp(fp, g1)))
301 goto end;
302
303 /* flush and close file */
304 if (!TEST_int_eq(fclose(fp), 0)) {
305 fp = NULL;
306 goto end;
307 }
308 fp = NULL;
309
310 /* decode params from file */
311 if (!TEST_ptr(fp = fopen("params.der", "rb"))
312 || !TEST_ptr(g2 = d2i_ECPKParameters_fp(fp, NULL)))
313 goto end;
314
315 testresult = 1; /* PASS */
316
317 end:
318 if (fp != NULL)
319 fclose(fp);
320
321 EC_GROUP_free(g1);
322 EC_GROUP_free(g2);
323
324 return testresult;
325 }
326
setup_tests(void)327 int setup_tests(void)
328 {
329 crv_len = EC_get_builtin_curves(NULL, 0);
330 if (!TEST_ptr(curves = OPENSSL_malloc(sizeof(*curves) * crv_len))
331 || !TEST_true(EC_get_builtin_curves(curves, crv_len)))
332 return 0;
333
334 ADD_TEST(field_tests_ecp_simple);
335 ADD_TEST(field_tests_ecp_mont);
336 #ifndef OPENSSL_NO_EC2M
337 ADD_TEST(field_tests_ec2_simple);
338 #endif
339 ADD_ALL_TESTS(field_tests_default, crv_len);
340 ADD_TEST(decoded_flag_test);
341 ADD_ALL_TESTS(ecpkparams_i2d2i_test, crv_len);
342
343 return 1;
344 }
345
cleanup_tests(void)346 void cleanup_tests(void)
347 {
348 OPENSSL_free(curves);
349 }
350