1e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley/* Copyright (c) 2014, Google Inc.
2e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley *
3e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * Permission to use, copy, modify, and/or distribute this software for any
4e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * purpose with or without fee is hereby granted, provided that the above
5e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * copyright notice and this permission notice appear in all copies.
6e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley *
7e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
15e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#include <stdio.h>
16e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#include <string.h>
17e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
18e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#include <vector>
19e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
20e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#include <openssl/crypto.h>
21e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#include <openssl/ec_key.h>
22e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#include <openssl/err.h>
23e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#include <openssl/mem.h>
24e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
25e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#include "../test/scoped_types.h"
26e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
27e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
28e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// kECKeyWithoutPublic is an ECPrivateKey with the optional publicKey field
29e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// omitted.
30e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic const uint8_t kECKeyWithoutPublic[] = {
31e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  0x30, 0x31, 0x02, 0x01, 0x01, 0x04, 0x20, 0xc6, 0xc1, 0xaa, 0xda, 0x15, 0xb0,
32e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  0x76, 0x61, 0xf8, 0x14, 0x2c, 0x6c, 0xaf, 0x0f, 0xdb, 0x24, 0x1a, 0xff, 0x2e,
33e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  0xfe, 0x46, 0xc0, 0x93, 0x8b, 0x74, 0xf2, 0xbc, 0xc5, 0x30, 0x52, 0xb0, 0x77,
34e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07,
35e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley};
36e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
37e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// kECKeyMissingZeros is an ECPrivateKey containing a degenerate P-256 key where
38e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// the private key is one. The private key is incorrectly encoded without zero
39e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// padding.
40e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic const uint8_t kECKeyMissingZeros[] = {
41e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  0x30, 0x58, 0x02, 0x01, 0x01, 0x04, 0x01, 0x01, 0xa0, 0x0a, 0x06, 0x08, 0x2a,
42e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04,
43e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, 0xe5, 0x63,
44e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0, 0xf4, 0xa1,
45e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f,
46e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57,
47e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5,
48e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley};
49e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
50e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// kECKeyMissingZeros is an ECPrivateKey containing a degenerate P-256 key where
51e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// the private key is one. The private key is encoded with the required zero
52e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// padding.
53e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic const uint8_t kECKeyWithZeros[] = {
54e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
55e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
56e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
57e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0xa1,
58e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  0x44, 0x03, 0x42, 0x00, 0x04, 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47,
59e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  0xf8, 0xbc, 0xe6, 0xe5, 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d,
60e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  0xeb, 0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3,
61e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e,
62e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68,
63e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  0x37, 0xbf, 0x51, 0xf5,
64e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley};
65e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
66e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// DecodeECPrivateKey decodes |in| as an ECPrivateKey structure and returns the
67e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// result or nullptr on error.
68e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic ScopedEC_KEY DecodeECPrivateKey(const uint8_t *in, size_t in_len) {
69e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  const uint8_t *inp = in;
70e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  ScopedEC_KEY ret(d2i_ECPrivateKey(NULL, &inp, in_len));
71e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (!ret || inp != in + in_len) {
72e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return nullptr;
73e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
74e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  return ret;
75e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley}
76e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
77e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// EncodeECPrivateKey encodes |key| as an ECPrivateKey structure into |*out|. It
78e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// returns true on success or false on error.
79e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic bool EncodeECPrivateKey(std::vector<uint8_t> *out, EC_KEY *key) {
80e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  int len = i2d_ECPrivateKey(key, NULL);
81e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  out->resize(len);
824139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  uint8_t *outp = out->data();
83e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  return i2d_ECPrivateKey(key, &outp) == len;
84e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley}
85e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
86e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleybool Testd2i_ECPrivateKey() {
87e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  ScopedEC_KEY key = DecodeECPrivateKey(kECKeyWithoutPublic,
88e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley                                        sizeof(kECKeyWithoutPublic));
89e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (!key) {
90e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    fprintf(stderr, "Failed to parse private key.\n");
91e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    ERR_print_errors_fp(stderr);
92e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
93e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
94e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
95e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  std::vector<uint8_t> out;
96e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (!EncodeECPrivateKey(&out, key.get())) {
97e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    fprintf(stderr, "Failed to serialize private key.\n");
98e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    ERR_print_errors_fp(stderr);
99e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
100e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
101e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
102e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (std::vector<uint8_t>(kECKeyWithoutPublic,
103e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley                           kECKeyWithoutPublic + sizeof(kECKeyWithoutPublic)) !=
104e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      out) {
105e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    fprintf(stderr, "Serialisation of key doesn't match original.\n");
106e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
107e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
108e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
109e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  const EC_POINT *pub_key = EC_KEY_get0_public_key(key.get());
110e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (pub_key == NULL) {
111e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    fprintf(stderr, "Public key missing.\n");
112e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
113e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
114e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
115e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  ScopedBIGNUM x(BN_new());
116e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  ScopedBIGNUM y(BN_new());
117e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (!x || !y) {
118e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
119e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
120e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (!EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(key.get()),
121e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley                                           pub_key, x.get(), y.get(), NULL)) {
122e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    fprintf(stderr, "Failed to get public key in affine coordinates.\n");
123e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
124e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
125e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  ScopedOpenSSLString x_hex(BN_bn2hex(x.get()));
126e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  ScopedOpenSSLString y_hex(BN_bn2hex(y.get()));
12753b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley  if (!x_hex || !y_hex) {
12853b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley    return false;
12953b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley  }
130e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (0 != strcmp(
131e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley          x_hex.get(),
132e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley          "c81561ecf2e54edefe6617db1c7a34a70744ddb261f269b83dacfcd2ade5a681") ||
133e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      0 != strcmp(
134e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley          y_hex.get(),
135e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley          "e0e2afa3f9b6abe4c698ef6495f1be49a3196c5056acb3763fe4507eec596e88")) {
136e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    fprintf(stderr, "Incorrect public key: %s %s\n", x_hex.get(), y_hex.get());
137e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
138e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
139e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
140e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  return true;
141e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley}
142e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
143e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic bool TestZeroPadding() {
144e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  // Check that the correct encoding round-trips.
145e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  ScopedEC_KEY key = DecodeECPrivateKey(kECKeyWithZeros,
146e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley                                        sizeof(kECKeyWithZeros));
147e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  std::vector<uint8_t> out;
148e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (!key || !EncodeECPrivateKey(&out, key.get())) {
149e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    ERR_print_errors_fp(stderr);
150e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
151e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
152e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
153e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (std::vector<uint8_t>(kECKeyWithZeros,
154e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley                           kECKeyWithZeros + sizeof(kECKeyWithZeros)) != out) {
155e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    fprintf(stderr, "Serialisation of key was incorrect.\n");
156e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
157e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
158e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
159e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  // Keys without leading zeros also parse, but they encode correctly.
160e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  key = DecodeECPrivateKey(kECKeyMissingZeros, sizeof(kECKeyMissingZeros));
161e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (!key || !EncodeECPrivateKey(&out, key.get())) {
162e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    ERR_print_errors_fp(stderr);
163e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
164e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
165e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
166e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (std::vector<uint8_t>(kECKeyWithZeros,
167e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley                           kECKeyWithZeros + sizeof(kECKeyWithZeros)) != out) {
168e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    fprintf(stderr, "Serialisation of key was incorrect.\n");
169e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
170e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
171e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
172e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  return true;
173e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley}
174e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
175fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langleybool TestSetAffine(const int nid) {
176fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  ScopedEC_KEY key(EC_KEY_new_by_curve_name(nid));
177fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (!key) {
178fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    return false;
179fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
180fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
181fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  const EC_GROUP *const group = EC_KEY_get0_group(key.get());
182fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
183fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (!EC_KEY_generate_key(key.get())) {
184fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    fprintf(stderr, "EC_KEY_generate_key failed with nid %d\n", nid);
185fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    ERR_print_errors_fp(stderr);
186fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    return false;
187fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
188fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
189fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (!EC_POINT_is_on_curve(group, EC_KEY_get0_public_key(key.get()),
190fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley                            nullptr)) {
191fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    fprintf(stderr, "generated point is not on curve with nid %d", nid);
192fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    ERR_print_errors_fp(stderr);
193fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    return false;
194fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
195fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
196fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  ScopedBIGNUM x(BN_new());
197fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  ScopedBIGNUM y(BN_new());
198fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (!EC_POINT_get_affine_coordinates_GFp(group,
199fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley                                           EC_KEY_get0_public_key(key.get()),
200fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley                                           x.get(), y.get(), nullptr)) {
201fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    fprintf(stderr, "EC_POINT_get_affine_coordinates_GFp failed with nid %d\n",
202fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley            nid);
203fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    ERR_print_errors_fp(stderr);
204fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    return false;
205fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
206fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
207fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  ScopedEC_POINT point(EC_POINT_new(group));
208fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (!point) {
209fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    return false;
210fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
211fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
212fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (!EC_POINT_set_affine_coordinates_GFp(group, point.get(), x.get(), y.get(),
213fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley                                           nullptr)) {
214fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    fprintf(stderr, "EC_POINT_set_affine_coordinates_GFp failed with nid %d\n",
215fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley            nid);
216fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    ERR_print_errors_fp(stderr);
217fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    return false;
218fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
219fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
220fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  // Subtract one from |y| to make the point no longer on the curve.
221fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (!BN_sub(y.get(), y.get(), BN_value_one())) {
222fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    return false;
223fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
224fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
225fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  ScopedEC_POINT invalid_point(EC_POINT_new(group));
226fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (!invalid_point) {
227fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    return false;
228fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
229fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
230fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (EC_POINT_set_affine_coordinates_GFp(group, invalid_point.get(), x.get(),
231fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley                                          y.get(), nullptr)) {
232fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    fprintf(stderr,
233fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley            "EC_POINT_set_affine_coordinates_GFp succeeded with invalid "
234fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley            "coordinates with nid %d\n",
235fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley            nid);
236fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    ERR_print_errors_fp(stderr);
237fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    return false;
238fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
239fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
240fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  return true;
241fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley}
242fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
243e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleyint main(void) {
244e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  CRYPTO_library_init();
245e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  ERR_load_crypto_strings();
246e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
247e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (!Testd2i_ECPrivateKey() ||
248fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley      !TestZeroPadding() ||
249fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley      !TestSetAffine(NID_secp224r1) ||
250fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley      !TestSetAffine(NID_X9_62_prime256v1) ||
251fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley      !TestSetAffine(NID_secp384r1) ||
252fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley      !TestSetAffine(NID_secp521r1)) {
253e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    fprintf(stderr, "failed\n");
254e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return 1;
255e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
256e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
257e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  printf("PASS\n");
258e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  return 0;
259e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley}
260