Built motion from commit 6a09e18b.|2.6.11
[motion2.git] / legacy-libs / grpc-cloned / deps / grpc / third_party / boringssl / crypto / fipsmodule / ec / ec_test.cc
1 /* Copyright (c) 2014, Google Inc.
2  *
3  * Permission to use, copy, modify, and/or distribute this software for any
4  * purpose with or without fee is hereby granted, provided that the above
5  * copyright notice and this permission notice appear in all copies.
6  *
7  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18
19 #include <vector>
20
21 #include <gtest/gtest.h>
22
23 #include <openssl/bn.h>
24 #include <openssl/bytestring.h>
25 #include <openssl/crypto.h>
26 #include <openssl/ec_key.h>
27 #include <openssl/err.h>
28 #include <openssl/mem.h>
29 #include <openssl/nid.h>
30 #include <openssl/obj.h>
31
32 #include "../../test/file_test.h"
33 #include "../../test/test_util.h"
34 #include "../bn/internal.h"
35 #include "internal.h"
36
37
38 // kECKeyWithoutPublic is an ECPrivateKey with the optional publicKey field
39 // omitted.
40 static const uint8_t kECKeyWithoutPublic[] = {
41   0x30, 0x31, 0x02, 0x01, 0x01, 0x04, 0x20, 0xc6, 0xc1, 0xaa, 0xda, 0x15, 0xb0,
42   0x76, 0x61, 0xf8, 0x14, 0x2c, 0x6c, 0xaf, 0x0f, 0xdb, 0x24, 0x1a, 0xff, 0x2e,
43   0xfe, 0x46, 0xc0, 0x93, 0x8b, 0x74, 0xf2, 0xbc, 0xc5, 0x30, 0x52, 0xb0, 0x77,
44   0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07,
45 };
46
47 // kECKeySpecifiedCurve is the above key with P-256's parameters explicitly
48 // spelled out rather than using a named curve.
49 static const uint8_t kECKeySpecifiedCurve[] = {
50     0x30, 0x82, 0x01, 0x22, 0x02, 0x01, 0x01, 0x04, 0x20, 0xc6, 0xc1, 0xaa,
51     0xda, 0x15, 0xb0, 0x76, 0x61, 0xf8, 0x14, 0x2c, 0x6c, 0xaf, 0x0f, 0xdb,
52     0x24, 0x1a, 0xff, 0x2e, 0xfe, 0x46, 0xc0, 0x93, 0x8b, 0x74, 0xf2, 0xbc,
53     0xc5, 0x30, 0x52, 0xb0, 0x77, 0xa0, 0x81, 0xfa, 0x30, 0x81, 0xf7, 0x02,
54     0x01, 0x01, 0x30, 0x2c, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01,
55     0x01, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01,
56     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
57     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
58     0x30, 0x5b, 0x04, 0x20, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01,
59     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
60     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc,
61     0x04, 0x20, 0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb,
62     0xbd, 0x55, 0x76, 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53,
63     0xb0, 0xf6, 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b, 0x03, 0x15,
64     0x00, 0xc4, 0x9d, 0x36, 0x08, 0x86, 0xe7, 0x04, 0x93, 0x6a, 0x66, 0x78,
65     0xe1, 0x13, 0x9d, 0x26, 0xb7, 0x81, 0x9f, 0x7e, 0x90, 0x04, 0x41, 0x04,
66     0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, 0xe5,
67     0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0,
68     0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3, 0x42, 0xe2,
69     0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16,
70     0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68,
71     0x37, 0xbf, 0x51, 0xf5, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
72     0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbc,
73     0xe6, 0xfa, 0xad, 0xa7, 0x17, 0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc,
74     0x63, 0x25, 0x51, 0x02, 0x01, 0x01,
75 };
76
77 // kECKeyMissingZeros is an ECPrivateKey containing a degenerate P-256 key where
78 // the private key is one. The private key is incorrectly encoded without zero
79 // padding.
80 static const uint8_t kECKeyMissingZeros[] = {
81   0x30, 0x58, 0x02, 0x01, 0x01, 0x04, 0x01, 0x01, 0xa0, 0x0a, 0x06, 0x08, 0x2a,
82   0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04,
83   0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, 0xe5, 0x63,
84   0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0, 0xf4, 0xa1,
85   0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f,
86   0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57,
87   0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5,
88 };
89
90 // kECKeyMissingZeros is an ECPrivateKey containing a degenerate P-256 key where
91 // the private key is one. The private key is encoded with the required zero
92 // padding.
93 static const uint8_t kECKeyWithZeros[] = {
94   0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
95   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
96   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
97   0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0xa1,
98   0x44, 0x03, 0x42, 0x00, 0x04, 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47,
99   0xf8, 0xbc, 0xe6, 0xe5, 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d,
100   0xeb, 0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3,
101   0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e,
102   0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68,
103   0x37, 0xbf, 0x51, 0xf5,
104 };
105
106 // DecodeECPrivateKey decodes |in| as an ECPrivateKey structure and returns the
107 // result or nullptr on error.
108 static bssl::UniquePtr<EC_KEY> DecodeECPrivateKey(const uint8_t *in,
109                                                   size_t in_len) {
110   CBS cbs;
111   CBS_init(&cbs, in, in_len);
112   bssl::UniquePtr<EC_KEY> ret(EC_KEY_parse_private_key(&cbs, NULL));
113   if (!ret || CBS_len(&cbs) != 0) {
114     return nullptr;
115   }
116   return ret;
117 }
118
119 // EncodeECPrivateKey encodes |key| as an ECPrivateKey structure into |*out|. It
120 // returns true on success or false on error.
121 static bool EncodeECPrivateKey(std::vector<uint8_t> *out, const EC_KEY *key) {
122   bssl::ScopedCBB cbb;
123   uint8_t *der;
124   size_t der_len;
125   if (!CBB_init(cbb.get(), 0) ||
126       !EC_KEY_marshal_private_key(cbb.get(), key, EC_KEY_get_enc_flags(key)) ||
127       !CBB_finish(cbb.get(), &der, &der_len)) {
128     return false;
129   }
130   out->assign(der, der + der_len);
131   OPENSSL_free(der);
132   return true;
133 }
134
135 TEST(ECTest, Encoding) {
136   bssl::UniquePtr<EC_KEY> key =
137       DecodeECPrivateKey(kECKeyWithoutPublic, sizeof(kECKeyWithoutPublic));
138   ASSERT_TRUE(key);
139
140   // Test that the encoding round-trips.
141   std::vector<uint8_t> out;
142   ASSERT_TRUE(EncodeECPrivateKey(&out, key.get()));
143   EXPECT_EQ(Bytes(kECKeyWithoutPublic), Bytes(out.data(), out.size()));
144
145   const EC_POINT *pub_key = EC_KEY_get0_public_key(key.get());
146   ASSERT_TRUE(pub_key) << "Public key missing";
147
148   bssl::UniquePtr<BIGNUM> x(BN_new());
149   bssl::UniquePtr<BIGNUM> y(BN_new());
150   ASSERT_TRUE(x);
151   ASSERT_TRUE(y);
152   ASSERT_TRUE(EC_POINT_get_affine_coordinates_GFp(
153       EC_KEY_get0_group(key.get()), pub_key, x.get(), y.get(), NULL));
154   bssl::UniquePtr<char> x_hex(BN_bn2hex(x.get()));
155   bssl::UniquePtr<char> y_hex(BN_bn2hex(y.get()));
156   ASSERT_TRUE(x_hex);
157   ASSERT_TRUE(y_hex);
158
159   EXPECT_STREQ(
160       "c81561ecf2e54edefe6617db1c7a34a70744ddb261f269b83dacfcd2ade5a681",
161       x_hex.get());
162   EXPECT_STREQ(
163       "e0e2afa3f9b6abe4c698ef6495f1be49a3196c5056acb3763fe4507eec596e88",
164       y_hex.get());
165 }
166
167 TEST(ECTest, ZeroPadding) {
168   // Check that the correct encoding round-trips.
169   bssl::UniquePtr<EC_KEY> key =
170       DecodeECPrivateKey(kECKeyWithZeros, sizeof(kECKeyWithZeros));
171   ASSERT_TRUE(key);
172   std::vector<uint8_t> out;
173   EXPECT_TRUE(EncodeECPrivateKey(&out, key.get()));
174   EXPECT_EQ(Bytes(kECKeyWithZeros), Bytes(out.data(), out.size()));
175
176   // Keys without leading zeros also parse, but they encode correctly.
177   key = DecodeECPrivateKey(kECKeyMissingZeros, sizeof(kECKeyMissingZeros));
178   ASSERT_TRUE(key);
179   EXPECT_TRUE(EncodeECPrivateKey(&out, key.get()));
180   EXPECT_EQ(Bytes(kECKeyWithZeros), Bytes(out.data(), out.size()));
181 }
182
183 TEST(ECTest, SpecifiedCurve) {
184   // Test keys with specified curves may be decoded.
185   bssl::UniquePtr<EC_KEY> key =
186       DecodeECPrivateKey(kECKeySpecifiedCurve, sizeof(kECKeySpecifiedCurve));
187   ASSERT_TRUE(key);
188
189   // The group should have been interpreted as P-256.
190   EXPECT_EQ(NID_X9_62_prime256v1,
191             EC_GROUP_get_curve_name(EC_KEY_get0_group(key.get())));
192
193   // Encoding the key should still use named form.
194   std::vector<uint8_t> out;
195   EXPECT_TRUE(EncodeECPrivateKey(&out, key.get()));
196   EXPECT_EQ(Bytes(kECKeyWithoutPublic), Bytes(out.data(), out.size()));
197 }
198
199 TEST(ECTest, ArbitraryCurve) {
200   // Make a P-256 key and extract the affine coordinates.
201   bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
202   ASSERT_TRUE(key);
203   ASSERT_TRUE(EC_KEY_generate_key(key.get()));
204
205   // Make an arbitrary curve which is identical to P-256.
206   static const uint8_t kP[] = {
207       0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
208       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
209       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
210   };
211   static const uint8_t kA[] = {
212       0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
213       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
214       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc,
215   };
216   static const uint8_t kB[] = {
217       0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb, 0xbd,
218       0x55, 0x76, 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53,
219       0xb0, 0xf6, 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b,
220   };
221   static const uint8_t kX[] = {
222       0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6,
223       0xe5, 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb,
224       0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96,
225   };
226   static const uint8_t kY[] = {
227       0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb,
228       0x4a, 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31,
229       0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5,
230   };
231   static const uint8_t kOrder[] = {
232       0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
233       0xff, 0xff, 0xff, 0xff, 0xff, 0xbc, 0xe6, 0xfa, 0xad, 0xa7, 0x17,
234       0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc, 0x63, 0x25, 0x51,
235   };
236   bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
237   ASSERT_TRUE(ctx);
238   bssl::UniquePtr<BIGNUM> p(BN_bin2bn(kP, sizeof(kP), nullptr));
239   ASSERT_TRUE(p);
240   bssl::UniquePtr<BIGNUM> a(BN_bin2bn(kA, sizeof(kA), nullptr));
241   ASSERT_TRUE(a);
242   bssl::UniquePtr<BIGNUM> b(BN_bin2bn(kB, sizeof(kB), nullptr));
243   ASSERT_TRUE(b);
244   bssl::UniquePtr<BIGNUM> gx(BN_bin2bn(kX, sizeof(kX), nullptr));
245   ASSERT_TRUE(gx);
246   bssl::UniquePtr<BIGNUM> gy(BN_bin2bn(kY, sizeof(kY), nullptr));
247   ASSERT_TRUE(gy);
248   bssl::UniquePtr<BIGNUM> order(BN_bin2bn(kOrder, sizeof(kOrder), nullptr));
249   ASSERT_TRUE(order);
250
251   bssl::UniquePtr<EC_GROUP> group(
252       EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), ctx.get()));
253   ASSERT_TRUE(group);
254   bssl::UniquePtr<EC_POINT> generator(EC_POINT_new(group.get()));
255   ASSERT_TRUE(generator);
256   ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp(
257       group.get(), generator.get(), gx.get(), gy.get(), ctx.get()));
258   ASSERT_TRUE(EC_GROUP_set_generator(group.get(), generator.get(), order.get(),
259                                      BN_value_one()));
260
261   // |group| should not have a curve name.
262   EXPECT_EQ(NID_undef, EC_GROUP_get_curve_name(group.get()));
263
264   // Copy |key| to |key2| using |group|.
265   bssl::UniquePtr<EC_KEY> key2(EC_KEY_new());
266   ASSERT_TRUE(key2);
267   bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group.get()));
268   ASSERT_TRUE(point);
269   bssl::UniquePtr<BIGNUM> x(BN_new()), y(BN_new());
270   ASSERT_TRUE(x);
271   ASSERT_TRUE(EC_KEY_set_group(key2.get(), group.get()));
272   ASSERT_TRUE(
273       EC_KEY_set_private_key(key2.get(), EC_KEY_get0_private_key(key.get())));
274   ASSERT_TRUE(EC_POINT_get_affine_coordinates_GFp(
275       EC_KEY_get0_group(key.get()), EC_KEY_get0_public_key(key.get()), x.get(),
276       y.get(), nullptr));
277   ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp(group.get(), point.get(),
278                                                   x.get(), y.get(), nullptr));
279   ASSERT_TRUE(EC_KEY_set_public_key(key2.get(), point.get()));
280
281   // The key must be valid according to the new group too.
282   EXPECT_TRUE(EC_KEY_check_key(key2.get()));
283
284   // Make a second instance of |group|.
285   bssl::UniquePtr<EC_GROUP> group2(
286       EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), ctx.get()));
287   ASSERT_TRUE(group2);
288   bssl::UniquePtr<EC_POINT> generator2(EC_POINT_new(group2.get()));
289   ASSERT_TRUE(generator2);
290   ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp(
291       group2.get(), generator2.get(), gx.get(), gy.get(), ctx.get()));
292   ASSERT_TRUE(EC_GROUP_set_generator(group2.get(), generator2.get(),
293                                      order.get(), BN_value_one()));
294
295   EXPECT_EQ(0, EC_GROUP_cmp(group.get(), group.get(), NULL));
296   EXPECT_EQ(0, EC_GROUP_cmp(group2.get(), group.get(), NULL));
297
298   // group3 uses the wrong generator.
299   bssl::UniquePtr<EC_GROUP> group3(
300       EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), ctx.get()));
301   ASSERT_TRUE(group3);
302   bssl::UniquePtr<EC_POINT> generator3(EC_POINT_new(group3.get()));
303   ASSERT_TRUE(generator3);
304   ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp(
305       group3.get(), generator3.get(), x.get(), y.get(), ctx.get()));
306   ASSERT_TRUE(EC_GROUP_set_generator(group3.get(), generator3.get(),
307                                      order.get(), BN_value_one()));
308
309   EXPECT_NE(0, EC_GROUP_cmp(group.get(), group3.get(), NULL));
310
311 #if !defined(BORINGSSL_SHARED_LIBRARY)
312   // group4 has non-minimal components that do not fit in |EC_SCALAR| and the
313   // future |EC_FELEM|.
314   ASSERT_TRUE(bn_resize_words(p.get(), 32));
315   ASSERT_TRUE(bn_resize_words(a.get(), 32));
316   ASSERT_TRUE(bn_resize_words(b.get(), 32));
317   ASSERT_TRUE(bn_resize_words(gx.get(), 32));
318   ASSERT_TRUE(bn_resize_words(gy.get(), 32));
319   ASSERT_TRUE(bn_resize_words(order.get(), 32));
320
321   bssl::UniquePtr<EC_GROUP> group4(
322       EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), ctx.get()));
323   ASSERT_TRUE(group4);
324   bssl::UniquePtr<EC_POINT> generator4(EC_POINT_new(group4.get()));
325   ASSERT_TRUE(generator4);
326   ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp(
327       group4.get(), generator4.get(), gx.get(), gy.get(), ctx.get()));
328   ASSERT_TRUE(EC_GROUP_set_generator(group4.get(), generator4.get(),
329                                      order.get(), BN_value_one()));
330
331   EXPECT_EQ(0, EC_GROUP_cmp(group.get(), group4.get(), NULL));
332 #endif
333 }
334
335 TEST(ECTest, SetKeyWithoutGroup) {
336   bssl::UniquePtr<EC_KEY> key(EC_KEY_new());
337   ASSERT_TRUE(key);
338
339   // Private keys may not be configured without a group.
340   EXPECT_FALSE(EC_KEY_set_private_key(key.get(), BN_value_one()));
341
342   // Public keys may not be configured without a group.
343   bssl::UniquePtr<EC_GROUP> group(
344       EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
345   ASSERT_TRUE(group);
346   EXPECT_FALSE(
347       EC_KEY_set_public_key(key.get(), EC_GROUP_get0_generator(group.get())));
348 }
349
350 TEST(ECTest, GroupMismatch) {
351   bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(NID_secp384r1));
352   ASSERT_TRUE(key);
353   bssl::UniquePtr<EC_GROUP> p256(
354       EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
355   ASSERT_TRUE(p256);
356
357   // Changing a key's group is invalid.
358   EXPECT_FALSE(EC_KEY_set_group(key.get(), p256.get()));
359
360   // Configuring a public key with the wrong group is invalid.
361   EXPECT_FALSE(
362       EC_KEY_set_public_key(key.get(), EC_GROUP_get0_generator(p256.get())));
363 }
364
365 TEST(ECTest, EmptyKey) {
366   bssl::UniquePtr<EC_KEY> key(EC_KEY_new());
367   ASSERT_TRUE(key);
368   EXPECT_FALSE(EC_KEY_get0_group(key.get()));
369   EXPECT_FALSE(EC_KEY_get0_public_key(key.get()));
370   EXPECT_FALSE(EC_KEY_get0_private_key(key.get()));
371 }
372
373 class ECCurveTest : public testing::TestWithParam<EC_builtin_curve> {
374  public:
375   const EC_GROUP *group() const { return group_.get(); }
376
377   void SetUp() override {
378     group_.reset(EC_GROUP_new_by_curve_name(GetParam().nid));
379     ASSERT_TRUE(group_);
380   }
381
382  private:
383   bssl::UniquePtr<EC_GROUP> group_;
384 };
385
386 TEST_P(ECCurveTest, SetAffine) {
387   // Generate an EC_KEY.
388   bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid));
389   ASSERT_TRUE(key);
390   ASSERT_TRUE(EC_KEY_generate_key(key.get()));
391
392   EXPECT_TRUE(EC_POINT_is_on_curve(group(), EC_KEY_get0_public_key(key.get()),
393                                    nullptr));
394
395   // Get the public key's coordinates.
396   bssl::UniquePtr<BIGNUM> x(BN_new());
397   ASSERT_TRUE(x);
398   bssl::UniquePtr<BIGNUM> y(BN_new());
399   ASSERT_TRUE(y);
400   bssl::UniquePtr<BIGNUM> p(BN_new());
401   ASSERT_TRUE(p);
402   EXPECT_TRUE(EC_POINT_get_affine_coordinates_GFp(
403       group(), EC_KEY_get0_public_key(key.get()), x.get(), y.get(), nullptr));
404   EXPECT_TRUE(
405       EC_GROUP_get_curve_GFp(group(), p.get(), nullptr, nullptr, nullptr));
406
407   // Points on the curve should be accepted.
408   auto point = bssl::UniquePtr<EC_POINT>(EC_POINT_new(group()));
409   ASSERT_TRUE(point);
410   EXPECT_TRUE(EC_POINT_set_affine_coordinates_GFp(group(), point.get(), x.get(),
411                                                   y.get(), nullptr));
412
413   // Subtract one from |y| to make the point no longer on the curve.
414   EXPECT_TRUE(BN_sub(y.get(), y.get(), BN_value_one()));
415
416   // Points not on the curve should be rejected.
417   bssl::UniquePtr<EC_POINT> invalid_point(EC_POINT_new(group()));
418   ASSERT_TRUE(invalid_point);
419   EXPECT_FALSE(EC_POINT_set_affine_coordinates_GFp(group(), invalid_point.get(),
420                                                    x.get(), y.get(), nullptr));
421
422   // Coordinates out of range should be rejected.
423   EXPECT_TRUE(BN_add(y.get(), y.get(), BN_value_one()));
424   EXPECT_TRUE(BN_add(y.get(), y.get(), p.get()));
425
426   EXPECT_FALSE(EC_POINT_set_affine_coordinates_GFp(group(), invalid_point.get(),
427                                                    x.get(), y.get(), nullptr));
428   EXPECT_FALSE(
429       EC_KEY_set_public_key_affine_coordinates(key.get(), x.get(), y.get()));
430 }
431
432 TEST_P(ECCurveTest, GenerateFIPS) {
433   // Generate an EC_KEY.
434   bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid));
435   ASSERT_TRUE(key);
436   ASSERT_TRUE(EC_KEY_generate_key_fips(key.get()));
437 }
438
439 TEST_P(ECCurveTest, AddingEqualPoints) {
440   bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid));
441   ASSERT_TRUE(key);
442   ASSERT_TRUE(EC_KEY_generate_key(key.get()));
443
444   bssl::UniquePtr<EC_POINT> p1(EC_POINT_new(group()));
445   ASSERT_TRUE(p1);
446   ASSERT_TRUE(EC_POINT_copy(p1.get(), EC_KEY_get0_public_key(key.get())));
447
448   bssl::UniquePtr<EC_POINT> p2(EC_POINT_new(group()));
449   ASSERT_TRUE(p2);
450   ASSERT_TRUE(EC_POINT_copy(p2.get(), EC_KEY_get0_public_key(key.get())));
451
452   bssl::UniquePtr<EC_POINT> double_p1(EC_POINT_new(group()));
453   ASSERT_TRUE(double_p1);
454   bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
455   ASSERT_TRUE(ctx);
456   ASSERT_TRUE(EC_POINT_dbl(group(), double_p1.get(), p1.get(), ctx.get()));
457
458   bssl::UniquePtr<EC_POINT> p1_plus_p2(EC_POINT_new(group()));
459   ASSERT_TRUE(p1_plus_p2);
460   ASSERT_TRUE(
461       EC_POINT_add(group(), p1_plus_p2.get(), p1.get(), p2.get(), ctx.get()));
462
463   EXPECT_EQ(0,
464             EC_POINT_cmp(group(), double_p1.get(), p1_plus_p2.get(), ctx.get()))
465       << "A+A != 2A";
466 }
467
468 TEST_P(ECCurveTest, MulZero) {
469   bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group()));
470   ASSERT_TRUE(point);
471   bssl::UniquePtr<BIGNUM> zero(BN_new());
472   ASSERT_TRUE(zero);
473   BN_zero(zero.get());
474   ASSERT_TRUE(EC_POINT_mul(group(), point.get(), zero.get(), nullptr, nullptr,
475                            nullptr));
476
477   EXPECT_TRUE(EC_POINT_is_at_infinity(group(), point.get()))
478       << "g * 0 did not return point at infinity.";
479
480   // Test that zero times an arbitrary point is also infinity. The generator is
481   // used as the arbitrary point.
482   bssl::UniquePtr<EC_POINT> generator(EC_POINT_new(group()));
483   ASSERT_TRUE(generator);
484   ASSERT_TRUE(EC_POINT_mul(group(), generator.get(), BN_value_one(), nullptr,
485                            nullptr, nullptr));
486   ASSERT_TRUE(EC_POINT_mul(group(), point.get(), nullptr, generator.get(),
487                            zero.get(), nullptr));
488
489   EXPECT_TRUE(EC_POINT_is_at_infinity(group(), point.get()))
490       << "p * 0 did not return point at infinity.";
491 }
492
493 // Test that multiplying by the order produces âˆž and, moreover, that callers may
494 // do so. |EC_POINT_mul| is almost exclusively used with reduced scalars, with
495 // this exception. This comes from consumers following NIST SP 800-56A section
496 // 5.6.2.3.2. (Though all our curves have cofactor one, so this check isn't
497 // useful.)
498 TEST_P(ECCurveTest, MulOrder) {
499   // Test that g Ã— order = âˆž.
500   bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group()));
501   ASSERT_TRUE(point);
502   ASSERT_TRUE(EC_POINT_mul(group(), point.get(), EC_GROUP_get0_order(group()),
503                            nullptr, nullptr, nullptr));
504
505   EXPECT_TRUE(EC_POINT_is_at_infinity(group(), point.get()))
506       << "g * order did not return point at infinity.";
507
508   // Test that p Ã— order = âˆž, for some arbitrary p.
509   bssl::UniquePtr<BIGNUM> forty_two(BN_new());
510   ASSERT_TRUE(forty_two);
511   ASSERT_TRUE(BN_set_word(forty_two.get(), 42));
512   ASSERT_TRUE(EC_POINT_mul(group(), point.get(), forty_two.get(), nullptr,
513                            nullptr, nullptr));
514   ASSERT_TRUE(EC_POINT_mul(group(), point.get(), nullptr, point.get(),
515                            EC_GROUP_get0_order(group()), nullptr));
516
517   EXPECT_TRUE(EC_POINT_is_at_infinity(group(), point.get()))
518       << "p * order did not return point at infinity.";
519 }
520
521 // Test that |EC_POINT_mul| works with out-of-range scalars. The operation will
522 // not be constant-time, but we'll compute the right answer.
523 TEST_P(ECCurveTest, MulOutOfRange) {
524   bssl::UniquePtr<BIGNUM> n_minus_one(BN_dup(EC_GROUP_get0_order(group())));
525   ASSERT_TRUE(n_minus_one);
526   ASSERT_TRUE(BN_sub_word(n_minus_one.get(), 1));
527
528   bssl::UniquePtr<BIGNUM> minus_one(BN_new());
529   ASSERT_TRUE(minus_one);
530   ASSERT_TRUE(BN_one(minus_one.get()));
531   BN_set_negative(minus_one.get(), 1);
532
533   bssl::UniquePtr<BIGNUM> seven(BN_new());
534   ASSERT_TRUE(seven);
535   ASSERT_TRUE(BN_set_word(seven.get(), 7));
536
537   bssl::UniquePtr<BIGNUM> ten_n_plus_seven(
538       BN_dup(EC_GROUP_get0_order(group())));
539   ASSERT_TRUE(ten_n_plus_seven);
540   ASSERT_TRUE(BN_mul_word(ten_n_plus_seven.get(), 10));
541   ASSERT_TRUE(BN_add_word(ten_n_plus_seven.get(), 7));
542
543   bssl::UniquePtr<EC_POINT> point1(EC_POINT_new(group())),
544       point2(EC_POINT_new(group()));
545   ASSERT_TRUE(point1);
546   ASSERT_TRUE(point2);
547
548   ASSERT_TRUE(EC_POINT_mul(group(), point1.get(), n_minus_one.get(), nullptr,
549                            nullptr, nullptr));
550   ASSERT_TRUE(EC_POINT_mul(group(), point2.get(), minus_one.get(), nullptr,
551                            nullptr, nullptr));
552   EXPECT_EQ(0, EC_POINT_cmp(group(), point1.get(), point2.get(), nullptr))
553       << "-1 * G and (n-1) * G did not give the same result";
554
555   ASSERT_TRUE(EC_POINT_mul(group(), point1.get(), seven.get(), nullptr, nullptr,
556                            nullptr));
557   ASSERT_TRUE(EC_POINT_mul(group(), point2.get(), ten_n_plus_seven.get(),
558                            nullptr, nullptr, nullptr));
559   EXPECT_EQ(0, EC_POINT_cmp(group(), point1.get(), point2.get(), nullptr))
560       << "7 * G and (10n + 7) * G did not give the same result";
561 }
562
563 // Test that 10×∞ + G = G.
564 TEST_P(ECCurveTest, Mul) {
565   bssl::UniquePtr<EC_POINT> p(EC_POINT_new(group()));
566   ASSERT_TRUE(p);
567   bssl::UniquePtr<EC_POINT> result(EC_POINT_new(group()));
568   ASSERT_TRUE(result);
569   bssl::UniquePtr<BIGNUM> n(BN_new());
570   ASSERT_TRUE(n);
571   ASSERT_TRUE(EC_POINT_set_to_infinity(group(), p.get()));
572   ASSERT_TRUE(BN_set_word(n.get(), 10));
573
574   // First check that 10×∞ = âˆž.
575   ASSERT_TRUE(
576       EC_POINT_mul(group(), result.get(), nullptr, p.get(), n.get(), nullptr));
577   EXPECT_TRUE(EC_POINT_is_at_infinity(group(), result.get()));
578
579   // Now check that 10×∞ + G = G.
580   const EC_POINT *generator = EC_GROUP_get0_generator(group());
581   ASSERT_TRUE(EC_POINT_mul(group(), result.get(), BN_value_one(), p.get(),
582                            n.get(), nullptr));
583   EXPECT_EQ(0, EC_POINT_cmp(group(), result.get(), generator, nullptr));
584 }
585
586 TEST_P(ECCurveTest, MulNonMinimal) {
587   bssl::UniquePtr<BIGNUM> forty_two(BN_new());
588   ASSERT_TRUE(forty_two);
589   ASSERT_TRUE(BN_set_word(forty_two.get(), 42));
590
591   // Compute g Ã— 42.
592   bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group()));
593   ASSERT_TRUE(point);
594   ASSERT_TRUE(EC_POINT_mul(group(), point.get(), forty_two.get(), nullptr,
595                            nullptr, nullptr));
596
597   // Compute it again with a non-minimal 42, much larger than the scalar.
598   ASSERT_TRUE(bn_resize_words(forty_two.get(), 64));
599
600   bssl::UniquePtr<EC_POINT> point2(EC_POINT_new(group()));
601   ASSERT_TRUE(point2);
602   ASSERT_TRUE(EC_POINT_mul(group(), point2.get(), forty_two.get(), nullptr,
603                            nullptr, nullptr));
604   EXPECT_EQ(0, EC_POINT_cmp(group(), point.get(), point2.get(), nullptr));
605 }
606
607 // Test that EC_KEY_set_private_key rejects invalid values.
608 TEST_P(ECCurveTest, SetInvalidPrivateKey) {
609   bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid));
610   ASSERT_TRUE(key);
611
612   bssl::UniquePtr<BIGNUM> bn(BN_new());
613   ASSERT_TRUE(BN_one(bn.get()));
614   BN_set_negative(bn.get(), 1);
615   EXPECT_FALSE(EC_KEY_set_private_key(key.get(), bn.get()))
616       << "Unexpectedly set a key of -1";
617   ERR_clear_error();
618
619   ASSERT_TRUE(
620       BN_copy(bn.get(), EC_GROUP_get0_order(EC_KEY_get0_group(key.get()))));
621   EXPECT_FALSE(EC_KEY_set_private_key(key.get(), bn.get()))
622       << "Unexpectedly set a key of the group order.";
623   ERR_clear_error();
624 }
625
626 TEST_P(ECCurveTest, IgnoreOct2PointReturnValue) {
627   bssl::UniquePtr<BIGNUM> forty_two(BN_new());
628   ASSERT_TRUE(forty_two);
629   ASSERT_TRUE(BN_set_word(forty_two.get(), 42));
630
631   // Compute g Ã— 42.
632   bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group()));
633   ASSERT_TRUE(point);
634   ASSERT_TRUE(EC_POINT_mul(group(), point.get(), forty_two.get(), nullptr,
635                            nullptr, nullptr));
636
637   // Serialize the point.
638   size_t serialized_len = EC_POINT_point2oct(
639       group(), point.get(), POINT_CONVERSION_UNCOMPRESSED, nullptr, 0, nullptr);
640   ASSERT_NE(0u, serialized_len);
641
642   std::vector<uint8_t> serialized(serialized_len);
643   ASSERT_EQ(
644       serialized_len,
645       EC_POINT_point2oct(group(), point.get(), POINT_CONVERSION_UNCOMPRESSED,
646                          serialized.data(), serialized_len, nullptr));
647
648   // Create a serialized point that is not on the curve.
649   serialized[serialized_len - 1]++;
650
651   ASSERT_FALSE(EC_POINT_oct2point(group(), point.get(), serialized.data(),
652                                   serialized.size(), nullptr));
653   // After a failure, |point| should have been set to the generator to defend
654   // against code that doesn't check the return value.
655   ASSERT_EQ(0, EC_POINT_cmp(group(), point.get(),
656                             EC_GROUP_get0_generator(group()), nullptr));
657 }
658
659 TEST_P(ECCurveTest, DoubleSpecialCase) {
660   const EC_POINT *g = EC_GROUP_get0_generator(group());
661
662   bssl::UniquePtr<EC_POINT> two_g(EC_POINT_new(group()));
663   ASSERT_TRUE(two_g);
664   ASSERT_TRUE(EC_POINT_dbl(group(), two_g.get(), g, nullptr));
665
666   bssl::UniquePtr<EC_POINT> p(EC_POINT_new(group()));
667   ASSERT_TRUE(p);
668   ASSERT_TRUE(EC_POINT_mul(group(), p.get(), BN_value_one(), g, BN_value_one(),
669                            nullptr));
670   EXPECT_EQ(0, EC_POINT_cmp(group(), p.get(), two_g.get(), nullptr));
671
672   EC_SCALAR one;
673   ASSERT_TRUE(ec_bignum_to_scalar(group(), &one, BN_value_one()));
674   ASSERT_TRUE(
675       ec_point_mul_scalar_public(group(), p.get(), &one, g, &one, nullptr));
676   EXPECT_EQ(0, EC_POINT_cmp(group(), p.get(), two_g.get(), nullptr));
677 }
678
679 // This a regression test for a P-224 bug, but we may as well run it for all
680 // curves.
681 TEST_P(ECCurveTest, P224Bug) {
682   // P = -G
683   const EC_POINT *g = EC_GROUP_get0_generator(group());
684   bssl::UniquePtr<EC_POINT> p(EC_POINT_dup(g, group()));
685   ASSERT_TRUE(p);
686   ASSERT_TRUE(EC_POINT_invert(group(), p.get(), nullptr));
687
688   // Compute 31 * P + 32 * G = G
689   bssl::UniquePtr<EC_POINT> ret(EC_POINT_new(group()));
690   ASSERT_TRUE(ret);
691   bssl::UniquePtr<BIGNUM> bn31(BN_new()), bn32(BN_new());
692   ASSERT_TRUE(bn31);
693   ASSERT_TRUE(bn32);
694   ASSERT_TRUE(BN_set_word(bn31.get(), 31));
695   ASSERT_TRUE(BN_set_word(bn32.get(), 32));
696   ASSERT_TRUE(EC_POINT_mul(group(), ret.get(), bn32.get(), p.get(), bn31.get(),
697                            nullptr));
698
699   EXPECT_EQ(0, EC_POINT_cmp(group(), ret.get(), g, nullptr));
700 }
701
702 static std::vector<EC_builtin_curve> AllCurves() {
703   const size_t num_curves = EC_get_builtin_curves(nullptr, 0);
704   std::vector<EC_builtin_curve> curves(num_curves);
705   EC_get_builtin_curves(curves.data(), num_curves);
706   return curves;
707 }
708
709 static std::string CurveToString(
710     const testing::TestParamInfo<EC_builtin_curve> &params) {
711   // The comment field contains characters GTest rejects, so use the OBJ name.
712   return OBJ_nid2sn(params.param.nid);
713 }
714
715 INSTANTIATE_TEST_CASE_P(, ECCurveTest, testing::ValuesIn(AllCurves()),
716                         CurveToString);
717
718 static bssl::UniquePtr<EC_GROUP> GetCurve(FileTest *t, const char *key) {
719   std::string curve_name;
720   if (!t->GetAttribute(&curve_name, key)) {
721     return nullptr;
722   }
723
724   if (curve_name == "P-224") {
725     return bssl::UniquePtr<EC_GROUP>(EC_GROUP_new_by_curve_name(NID_secp224r1));
726   }
727   if (curve_name == "P-256") {
728     return bssl::UniquePtr<EC_GROUP>(EC_GROUP_new_by_curve_name(
729         NID_X9_62_prime256v1));
730   }
731   if (curve_name == "P-384") {
732     return bssl::UniquePtr<EC_GROUP>(EC_GROUP_new_by_curve_name(NID_secp384r1));
733   }
734   if (curve_name == "P-521") {
735     return bssl::UniquePtr<EC_GROUP>(EC_GROUP_new_by_curve_name(NID_secp521r1));
736   }
737
738   t->PrintLine("Unknown curve '%s'", curve_name.c_str());
739   return nullptr;
740 }
741
742 static bssl::UniquePtr<BIGNUM> GetBIGNUM(FileTest *t, const char *key) {
743   std::vector<uint8_t> bytes;
744   if (!t->GetBytes(&bytes, key)) {
745     return nullptr;
746   }
747
748   return bssl::UniquePtr<BIGNUM>(
749       BN_bin2bn(bytes.data(), bytes.size(), nullptr));
750 }
751
752 TEST(ECTest, ScalarBaseMultVectors) {
753   bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
754   ASSERT_TRUE(ctx);
755
756   FileTestGTest("crypto/fipsmodule/ec/ec_scalar_base_mult_tests.txt",
757                 [&](FileTest *t) {
758     bssl::UniquePtr<EC_GROUP> group = GetCurve(t, "Curve");
759     ASSERT_TRUE(group);
760     bssl::UniquePtr<BIGNUM> n = GetBIGNUM(t, "N");
761     ASSERT_TRUE(n);
762     bssl::UniquePtr<BIGNUM> x = GetBIGNUM(t, "X");
763     ASSERT_TRUE(x);
764     bssl::UniquePtr<BIGNUM> y = GetBIGNUM(t, "Y");
765     ASSERT_TRUE(y);
766     bool is_infinity = BN_is_zero(x.get()) && BN_is_zero(y.get());
767
768     bssl::UniquePtr<BIGNUM> px(BN_new());
769     ASSERT_TRUE(px);
770     bssl::UniquePtr<BIGNUM> py(BN_new());
771     ASSERT_TRUE(py);
772     auto check_point = [&](const EC_POINT *p) {
773       if (is_infinity) {
774         EXPECT_TRUE(EC_POINT_is_at_infinity(group.get(), p));
775       } else {
776         ASSERT_TRUE(EC_POINT_get_affine_coordinates_GFp(
777             group.get(), p, px.get(), py.get(), ctx.get()));
778         EXPECT_EQ(0, BN_cmp(x.get(), px.get()));
779         EXPECT_EQ(0, BN_cmp(y.get(), py.get()));
780       }
781     };
782
783     const EC_POINT *g = EC_GROUP_get0_generator(group.get());
784     bssl::UniquePtr<EC_POINT> p(EC_POINT_new(group.get()));
785     ASSERT_TRUE(p);
786     // Test single-point multiplication.
787     ASSERT_TRUE(EC_POINT_mul(group.get(), p.get(), n.get(), nullptr, nullptr,
788                              ctx.get()));
789     check_point(p.get());
790
791     ASSERT_TRUE(
792         EC_POINT_mul(group.get(), p.get(), nullptr, g, n.get(), ctx.get()));
793     check_point(p.get());
794
795     // These tests take a very long time, but are worth running when we make
796     // non-trivial changes to the EC code.
797 #if 0
798     // Test two-point multiplication.
799     bssl::UniquePtr<BIGNUM> a(BN_new()), b(BN_new());
800     for (int i = -64; i < 64; i++) {
801       SCOPED_TRACE(i);
802       ASSERT_TRUE(BN_set_word(a.get(), abs(i)));
803       if (i < 0) {
804         ASSERT_TRUE(BN_sub(a.get(), EC_GROUP_get0_order(group.get()), a.get()));
805       }
806
807       ASSERT_TRUE(BN_copy(b.get(), n.get()));
808       ASSERT_TRUE(BN_sub(b.get(), b.get(), a.get()));
809       if (BN_is_negative(b.get())) {
810         ASSERT_TRUE(BN_add(b.get(), b.get(), EC_GROUP_get0_order(group.get())));
811       }
812
813       ASSERT_TRUE(
814           EC_POINT_mul(group.get(), p.get(), a.get(), g, b.get(), ctx.get()));
815       check_point(p.get());
816
817       EC_SCALAR a_scalar, b_scalar;
818       ASSERT_TRUE(ec_bignum_to_scalar(group.get(), &a_scalar, a.get()));
819       ASSERT_TRUE(ec_bignum_to_scalar(group.get(), &b_scalar, b.get()));
820       ASSERT_TRUE(ec_point_mul_scalar_public(group.get(), p.get(), &a_scalar, g,
821                                              &b_scalar, ctx.get()));
822       check_point(p.get());
823     }
824 #endif
825   });
826 }