• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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