Ensure bn_cmp_words can handle the case where n == 0
[openssl.git] / test / ec_internal_test.c
1 /*
2  * Copyright 2019 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_lcl.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 */
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 */
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 */
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 */
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 */
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 */
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 int setup_tests(void)
187 {
188     crv_len = EC_get_builtin_curves(NULL, 0);
189     if (!TEST_ptr(curves = OPENSSL_malloc(sizeof(*curves) * crv_len))
190         || !TEST_true(EC_get_builtin_curves(curves, crv_len)))
191         return 0;
192
193     ADD_TEST(field_tests_ecp_simple);
194     ADD_TEST(field_tests_ecp_mont);
195 #ifndef OPENSSL_NO_EC2M
196     ADD_TEST(field_tests_ec2_simple);
197 #endif
198     ADD_ALL_TESTS(field_tests_default, crv_len);
199     return 1;
200 }
201
202 void cleanup_tests(void)
203 {
204     OPENSSL_free(curves);
205 }