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