Raise an error on syscall failure in tls_retry_write_records
[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 /*
263  * Tests behavior of the decoded_from_explicit_params flag and API
264  */
265 static int decoded_flag_test(void)
266 {
267     EC_GROUP *grp;
268     EC_GROUP *grp_copy = NULL;
269     ECPARAMETERS *ecparams = NULL;
270     ECPKPARAMETERS *ecpkparams = NULL;
271     EC_KEY *key = NULL;
272     unsigned char *encodedparams = NULL;
273     const unsigned char *encp;
274     int encodedlen;
275     int testresult = 0;
276
277     /* Test EC_GROUP_new not setting the flag */
278     grp = EC_GROUP_new(EC_GFp_simple_method());
279     if (!TEST_ptr(grp)
280         || !TEST_int_eq(grp->decoded_from_explicit_params, 0))
281         goto err;
282     EC_GROUP_free(grp);
283
284     /* Test EC_GROUP_new_by_curve_name not setting the flag */
285     grp = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1);
286     if (!TEST_ptr(grp)
287         || !TEST_int_eq(grp->decoded_from_explicit_params, 0))
288         goto err;
289
290     /* Test EC_GROUP_new_from_ecparameters not setting the flag */
291     if (!TEST_ptr(ecparams = EC_GROUP_get_ecparameters(grp, NULL))
292         || !TEST_ptr(grp_copy = EC_GROUP_new_from_ecparameters(ecparams))
293         || !TEST_int_eq(grp_copy->decoded_from_explicit_params, 0))
294         goto err;
295     EC_GROUP_free(grp_copy);
296     grp_copy = NULL;
297     ECPARAMETERS_free(ecparams);
298     ecparams = NULL;
299
300     /* Test EC_GROUP_new_from_ecpkparameters not setting the flag */
301     if (!TEST_int_eq(EC_GROUP_get_asn1_flag(grp), OPENSSL_EC_NAMED_CURVE)
302         || !TEST_ptr(ecpkparams = EC_GROUP_get_ecpkparameters(grp, NULL))
303         || !TEST_ptr(grp_copy = EC_GROUP_new_from_ecpkparameters(ecpkparams))
304         || !TEST_int_eq(grp_copy->decoded_from_explicit_params, 0)
305         || !TEST_ptr(key = EC_KEY_new())
306     /* Test EC_KEY_decoded_from_explicit_params on key without a group */
307         || !TEST_int_eq(EC_KEY_decoded_from_explicit_params(key), -1)
308         || !TEST_int_eq(EC_KEY_set_group(key, grp_copy), 1)
309     /* Test EC_KEY_decoded_from_explicit_params negative case */
310         || !TEST_int_eq(EC_KEY_decoded_from_explicit_params(key), 0))
311         goto err;
312     EC_GROUP_free(grp_copy);
313     grp_copy = NULL;
314     ECPKPARAMETERS_free(ecpkparams);
315     ecpkparams = NULL;
316
317     /* Test d2i_ECPKParameters with named params not setting the flag */
318     if (!TEST_int_gt(encodedlen = i2d_ECPKParameters(grp, &encodedparams), 0)
319         || !TEST_ptr(encp = encodedparams)
320         || !TEST_ptr(grp_copy = d2i_ECPKParameters(NULL, &encp, encodedlen))
321         || !TEST_int_eq(grp_copy->decoded_from_explicit_params, 0))
322         goto err;
323     EC_GROUP_free(grp_copy);
324     grp_copy = NULL;
325     OPENSSL_free(encodedparams);
326     encodedparams = NULL;
327
328     /* Asn1 flag stays set to explicit with EC_GROUP_new_from_ecpkparameters */
329     EC_GROUP_set_asn1_flag(grp, OPENSSL_EC_EXPLICIT_CURVE);
330     if (!TEST_ptr(ecpkparams = EC_GROUP_get_ecpkparameters(grp, NULL))
331         || !TEST_ptr(grp_copy = EC_GROUP_new_from_ecpkparameters(ecpkparams))
332         || !TEST_int_eq(EC_GROUP_get_asn1_flag(grp_copy), OPENSSL_EC_EXPLICIT_CURVE)
333         || !TEST_int_eq(grp_copy->decoded_from_explicit_params, 0))
334         goto err;
335     EC_GROUP_free(grp_copy);
336     grp_copy = NULL;
337
338     /* Test d2i_ECPKParameters with explicit params setting the flag */
339     if (!TEST_int_gt(encodedlen = i2d_ECPKParameters(grp, &encodedparams), 0)
340         || !TEST_ptr(encp = encodedparams)
341         || !TEST_ptr(grp_copy = d2i_ECPKParameters(NULL, &encp, encodedlen))
342         || !TEST_int_eq(EC_GROUP_get_asn1_flag(grp_copy), OPENSSL_EC_EXPLICIT_CURVE)
343         || !TEST_int_eq(grp_copy->decoded_from_explicit_params, 1)
344         || !TEST_int_eq(EC_KEY_set_group(key, grp_copy), 1)
345     /* Test EC_KEY_decoded_from_explicit_params positive case */
346         || !TEST_int_eq(EC_KEY_decoded_from_explicit_params(key), 1))
347         goto err;
348
349     testresult = 1;
350
351  err:
352     EC_KEY_free(key);
353     EC_GROUP_free(grp);
354     EC_GROUP_free(grp_copy);
355     ECPARAMETERS_free(ecparams);
356     ECPKPARAMETERS_free(ecpkparams);
357     OPENSSL_free(encodedparams);
358
359     return testresult;
360 }
361
362 int setup_tests(void)
363 {
364     crv_len = EC_get_builtin_curves(NULL, 0);
365     if (!TEST_ptr(curves = OPENSSL_malloc(sizeof(*curves) * crv_len))
366         || !TEST_true(EC_get_builtin_curves(curves, crv_len)))
367         return 0;
368
369     ADD_TEST(field_tests_ecp_simple);
370     ADD_TEST(field_tests_ecp_mont);
371 #ifndef OPENSSL_NO_EC2M
372     ADD_TEST(field_tests_ec2_simple);
373 #endif
374     ADD_ALL_TESTS(field_tests_default, crv_len);
375 #ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
376     ADD_TEST(underflow_test);
377 #endif
378     ADD_TEST(decoded_flag_test);
379     return 1;
380 }
381
382 void cleanup_tests(void)
383 {
384     OPENSSL_free(curves);
385 }