xref: /openssl/test/ec_internal_test.c (revision d93f154d)
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 /*
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 */
group_field_tests(const EC_GROUP * group,BN_CTX * ctx)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 */
field_tests(const EC_METHOD * meth,const unsigned char * params,int len)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 */
field_tests_ecp_simple(void)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 */
field_tests_ecp_mont(void)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 */
field_tests_ec2_simple(void)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 */
field_tests_default(int n)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  */
underflow_test(void)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(ossl_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 EC_KEY_set_private_key
264  */
set_private_key(void)265 static int set_private_key(void)
266 {
267     EC_KEY *key = NULL, *aux_key = NULL;
268     int testresult = 0;
269 
270     key = EC_KEY_new_by_curve_name(NID_secp224r1);
271     aux_key = EC_KEY_new_by_curve_name(NID_secp224r1);
272     if (!TEST_ptr(key)
273         || !TEST_ptr(aux_key)
274         || !TEST_int_eq(EC_KEY_generate_key(key), 1)
275         || !TEST_int_eq(EC_KEY_generate_key(aux_key), 1))
276         goto err;
277 
278     /* Test setting a valid private key */
279     if (!TEST_int_eq(EC_KEY_set_private_key(key, aux_key->priv_key), 1))
280         goto err;
281 
282     /* Test compliance with legacy behavior for NULL private keys */
283     if (!TEST_int_eq(EC_KEY_set_private_key(key, NULL), 0)
284         || !TEST_ptr_null(key->priv_key))
285         goto err;
286 
287     testresult = 1;
288 
289  err:
290     EC_KEY_free(key);
291     EC_KEY_free(aux_key);
292     return testresult;
293 }
294 
295 /*
296  * Tests behavior of the decoded_from_explicit_params flag and API
297  */
decoded_flag_test(void)298 static int decoded_flag_test(void)
299 {
300     EC_GROUP *grp;
301     EC_GROUP *grp_copy = NULL;
302     ECPARAMETERS *ecparams = NULL;
303     ECPKPARAMETERS *ecpkparams = NULL;
304     EC_KEY *key = NULL;
305     unsigned char *encodedparams = NULL;
306     const unsigned char *encp;
307     int encodedlen;
308     int testresult = 0;
309 
310     /* Test EC_GROUP_new not setting the flag */
311     grp = EC_GROUP_new(EC_GFp_simple_method());
312     if (!TEST_ptr(grp)
313         || !TEST_int_eq(grp->decoded_from_explicit_params, 0))
314         goto err;
315     EC_GROUP_free(grp);
316 
317     /* Test EC_GROUP_new_by_curve_name not setting the flag */
318     grp = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1);
319     if (!TEST_ptr(grp)
320         || !TEST_int_eq(grp->decoded_from_explicit_params, 0))
321         goto err;
322 
323     /* Test EC_GROUP_new_from_ecparameters not setting the flag */
324     if (!TEST_ptr(ecparams = EC_GROUP_get_ecparameters(grp, NULL))
325         || !TEST_ptr(grp_copy = EC_GROUP_new_from_ecparameters(ecparams))
326         || !TEST_int_eq(grp_copy->decoded_from_explicit_params, 0))
327         goto err;
328     EC_GROUP_free(grp_copy);
329     grp_copy = NULL;
330     ECPARAMETERS_free(ecparams);
331     ecparams = NULL;
332 
333     /* Test EC_GROUP_new_from_ecpkparameters not setting the flag */
334     if (!TEST_int_eq(EC_GROUP_get_asn1_flag(grp), OPENSSL_EC_NAMED_CURVE)
335         || !TEST_ptr(ecpkparams = EC_GROUP_get_ecpkparameters(grp, NULL))
336         || !TEST_ptr(grp_copy = EC_GROUP_new_from_ecpkparameters(ecpkparams))
337         || !TEST_int_eq(grp_copy->decoded_from_explicit_params, 0)
338         || !TEST_ptr(key = EC_KEY_new())
339     /* Test EC_KEY_decoded_from_explicit_params on key without a group */
340         || !TEST_int_eq(EC_KEY_decoded_from_explicit_params(key), -1)
341         || !TEST_int_eq(EC_KEY_set_group(key, grp_copy), 1)
342     /* Test EC_KEY_decoded_from_explicit_params negative case */
343         || !TEST_int_eq(EC_KEY_decoded_from_explicit_params(key), 0))
344         goto err;
345     EC_GROUP_free(grp_copy);
346     grp_copy = NULL;
347     ECPKPARAMETERS_free(ecpkparams);
348     ecpkparams = NULL;
349 
350     /* Test d2i_ECPKParameters with named params not setting the flag */
351     if (!TEST_int_gt(encodedlen = i2d_ECPKParameters(grp, &encodedparams), 0)
352         || !TEST_ptr(encp = encodedparams)
353         || !TEST_ptr(grp_copy = d2i_ECPKParameters(NULL, &encp, encodedlen))
354         || !TEST_int_eq(grp_copy->decoded_from_explicit_params, 0))
355         goto err;
356     EC_GROUP_free(grp_copy);
357     grp_copy = NULL;
358     OPENSSL_free(encodedparams);
359     encodedparams = NULL;
360 
361     /* Asn1 flag stays set to explicit with EC_GROUP_new_from_ecpkparameters */
362     EC_GROUP_set_asn1_flag(grp, OPENSSL_EC_EXPLICIT_CURVE);
363     if (!TEST_ptr(ecpkparams = EC_GROUP_get_ecpkparameters(grp, NULL))
364         || !TEST_ptr(grp_copy = EC_GROUP_new_from_ecpkparameters(ecpkparams))
365         || !TEST_int_eq(EC_GROUP_get_asn1_flag(grp_copy), OPENSSL_EC_EXPLICIT_CURVE)
366         || !TEST_int_eq(grp_copy->decoded_from_explicit_params, 0))
367         goto err;
368     EC_GROUP_free(grp_copy);
369     grp_copy = NULL;
370 
371     /* Test d2i_ECPKParameters with explicit params setting the flag */
372     if (!TEST_int_gt(encodedlen = i2d_ECPKParameters(grp, &encodedparams), 0)
373         || !TEST_ptr(encp = encodedparams)
374         || !TEST_ptr(grp_copy = d2i_ECPKParameters(NULL, &encp, encodedlen))
375         || !TEST_int_eq(EC_GROUP_get_asn1_flag(grp_copy), OPENSSL_EC_EXPLICIT_CURVE)
376         || !TEST_int_eq(grp_copy->decoded_from_explicit_params, 1)
377         || !TEST_int_eq(EC_KEY_set_group(key, grp_copy), 1)
378     /* Test EC_KEY_decoded_from_explicit_params positive case */
379         || !TEST_int_eq(EC_KEY_decoded_from_explicit_params(key), 1))
380         goto err;
381 
382     testresult = 1;
383 
384  err:
385     EC_KEY_free(key);
386     EC_GROUP_free(grp);
387     EC_GROUP_free(grp_copy);
388     ECPARAMETERS_free(ecparams);
389     ECPKPARAMETERS_free(ecpkparams);
390     OPENSSL_free(encodedparams);
391 
392     return testresult;
393 }
394 
395 static
ecpkparams_i2d2i_test(int n)396 int ecpkparams_i2d2i_test(int n)
397 {
398     EC_GROUP *g1 = NULL, *g2 = NULL;
399     FILE *fp = NULL;
400     int nid = curves[n].nid;
401     int testresult = 0;
402 
403     /* create group */
404     if (!TEST_ptr(g1 = EC_GROUP_new_by_curve_name(nid)))
405         goto end;
406 
407     /* encode params to file */
408     if (!TEST_ptr(fp = fopen("params.der", "wb"))
409             || !TEST_true(i2d_ECPKParameters_fp(fp, g1)))
410         goto end;
411 
412     /* flush and close file */
413     if (!TEST_int_eq(fclose(fp), 0)) {
414         fp = NULL;
415         goto end;
416     }
417     fp = NULL;
418 
419     /* decode params from file */
420     if (!TEST_ptr(fp = fopen("params.der", "rb"))
421             || !TEST_ptr(g2 = d2i_ECPKParameters_fp(fp, NULL)))
422         goto end;
423 
424     testresult = 1; /* PASS */
425 
426 end:
427     if (fp != NULL)
428         fclose(fp);
429 
430     EC_GROUP_free(g1);
431     EC_GROUP_free(g2);
432 
433     return testresult;
434 }
435 
setup_tests(void)436 int setup_tests(void)
437 {
438     crv_len = EC_get_builtin_curves(NULL, 0);
439     if (!TEST_ptr(curves = OPENSSL_malloc(sizeof(*curves) * crv_len))
440         || !TEST_true(EC_get_builtin_curves(curves, crv_len)))
441         return 0;
442 
443     ADD_TEST(field_tests_ecp_simple);
444     ADD_TEST(field_tests_ecp_mont);
445 #ifndef OPENSSL_NO_EC2M
446     ADD_TEST(field_tests_ec2_simple);
447 #endif
448     ADD_ALL_TESTS(field_tests_default, crv_len);
449 #ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
450     ADD_TEST(underflow_test);
451 #endif
452     ADD_TEST(set_private_key);
453     ADD_TEST(decoded_flag_test);
454     ADD_ALL_TESTS(ecpkparams_i2d2i_test, crv_len);
455 
456     return 1;
457 }
458 
cleanup_tests(void)459 void cleanup_tests(void)
460 {
461     OPENSSL_free(curves);
462 }
463