xref: /netbsd-src/crypto/external/bsd/openssl.old/dist/test/ec_internal_test.c (revision 4724848cf0da353df257f730694b7882798e5daf)
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