Update copyright year
[openssl.git] / test / ec_internal_test.c
1 /*
2  * Copyright 2019-2020 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 */
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_pseudo_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 */
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 */
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 */
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 */
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 */
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  */
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(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 int setup_tests(void)
263 {
264     crv_len = EC_get_builtin_curves(NULL, 0);
265     if (!TEST_ptr(curves = OPENSSL_malloc(sizeof(*curves) * crv_len))
266         || !TEST_true(EC_get_builtin_curves(curves, crv_len)))
267         return 0;
268
269     ADD_TEST(field_tests_ecp_simple);
270     ADD_TEST(field_tests_ecp_mont);
271 #ifndef OPENSSL_NO_EC2M
272     ADD_TEST(field_tests_ec2_simple);
273 #endif
274     ADD_ALL_TESTS(field_tests_default, crv_len);
275 #ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
276     ADD_TEST(underflow_test);
277 #endif
278     return 1;
279 }
280
281 void cleanup_tests(void)
282 {
283     OPENSSL_free(curves);
284 }