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 20a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan#include <gtest/gtest.h> 21a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan 22f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin#include <openssl/bn.h> 23f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin#include <openssl/bytestring.h> 24e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#include <openssl/crypto.h> 25e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#include <openssl/ec_key.h> 26e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#include <openssl/err.h> 27e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#include <openssl/mem.h> 28f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin#include <openssl/nid.h> 29a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan#include <openssl/obj.h> 30a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan 318542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan#include "../bn/internal.h" 328ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan#include "../../test/test_util.h" 33e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 34e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 35e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// kECKeyWithoutPublic is an ECPrivateKey with the optional publicKey field 36e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// omitted. 37e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic const uint8_t kECKeyWithoutPublic[] = { 38e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 0x30, 0x31, 0x02, 0x01, 0x01, 0x04, 0x20, 0xc6, 0xc1, 0xaa, 0xda, 0x15, 0xb0, 39e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 0x76, 0x61, 0xf8, 0x14, 0x2c, 0x6c, 0xaf, 0x0f, 0xdb, 0x24, 0x1a, 0xff, 0x2e, 40e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 0xfe, 0x46, 0xc0, 0x93, 0x8b, 0x74, 0xf2, 0xbc, 0xc5, 0x30, 0x52, 0xb0, 0x77, 41e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 42e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley}; 43e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 444969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin// kECKeySpecifiedCurve is the above key with P-256's parameters explicitly 454969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin// spelled out rather than using a named curve. 464969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjaminstatic const uint8_t kECKeySpecifiedCurve[] = { 474969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 0x30, 0x82, 0x01, 0x22, 0x02, 0x01, 0x01, 0x04, 0x20, 0xc6, 0xc1, 0xaa, 484969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 0xda, 0x15, 0xb0, 0x76, 0x61, 0xf8, 0x14, 0x2c, 0x6c, 0xaf, 0x0f, 0xdb, 494969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 0x24, 0x1a, 0xff, 0x2e, 0xfe, 0x46, 0xc0, 0x93, 0x8b, 0x74, 0xf2, 0xbc, 504969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 0xc5, 0x30, 0x52, 0xb0, 0x77, 0xa0, 0x81, 0xfa, 0x30, 0x81, 0xf7, 0x02, 514969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 0x01, 0x01, 0x30, 0x2c, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01, 524969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 0x01, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 534969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 544969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 554969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 0x30, 0x5b, 0x04, 0x20, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 564969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 574969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 584969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 0x04, 0x20, 0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb, 594969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 0xbd, 0x55, 0x76, 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53, 604969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 0xb0, 0xf6, 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b, 0x03, 0x15, 614969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 0x00, 0xc4, 0x9d, 0x36, 0x08, 0x86, 0xe7, 0x04, 0x93, 0x6a, 0x66, 0x78, 624969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 0xe1, 0x13, 0x9d, 0x26, 0xb7, 0x81, 0x9f, 0x7e, 0x90, 0x04, 0x41, 0x04, 634969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, 0xe5, 644969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0, 654969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3, 0x42, 0xe2, 664969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16, 674969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 684969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 0x37, 0xbf, 0x51, 0xf5, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 694969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbc, 704969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 0xe6, 0xfa, 0xad, 0xa7, 0x17, 0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc, 714969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 0x63, 0x25, 0x51, 0x02, 0x01, 0x01, 724969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin}; 734969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 74e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// kECKeyMissingZeros is an ECPrivateKey containing a degenerate P-256 key where 75e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// the private key is one. The private key is incorrectly encoded without zero 76e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// padding. 77e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic const uint8_t kECKeyMissingZeros[] = { 78e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 0x30, 0x58, 0x02, 0x01, 0x01, 0x04, 0x01, 0x01, 0xa0, 0x0a, 0x06, 0x08, 0x2a, 79e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 80e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, 0xe5, 0x63, 81e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0, 0xf4, 0xa1, 82e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 83e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, 84e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5, 85e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley}; 86e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 87e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// kECKeyMissingZeros is an ECPrivateKey containing a degenerate P-256 key where 88e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// the private key is one. The private key is encoded with the required zero 89e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// padding. 90e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic const uint8_t kECKeyWithZeros[] = { 91e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 92e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 93e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 94e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0xa1, 95e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 0x44, 0x03, 0x42, 0x00, 0x04, 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 96e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 0xf8, 0xbc, 0xe6, 0xe5, 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 97e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 0xeb, 0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3, 98e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 99e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 100e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 0x37, 0xbf, 0x51, 0xf5, 101e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley}; 102e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 103e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// DecodeECPrivateKey decodes |in| as an ECPrivateKey structure and returns the 104e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// result or nullptr on error. 105f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjaminstatic bssl::UniquePtr<EC_KEY> DecodeECPrivateKey(const uint8_t *in, 106f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin size_t in_len) { 1074969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin CBS cbs; 1084969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin CBS_init(&cbs, in, in_len); 109f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin bssl::UniquePtr<EC_KEY> ret(EC_KEY_parse_private_key(&cbs, NULL)); 1104969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin if (!ret || CBS_len(&cbs) != 0) { 111e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return nullptr; 112e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 113e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return ret; 114e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley} 115e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 116e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// EncodeECPrivateKey encodes |key| as an ECPrivateKey structure into |*out|. It 117e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// returns true on success or false on error. 1184969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjaminstatic bool EncodeECPrivateKey(std::vector<uint8_t> *out, const EC_KEY *key) { 119909b19f027eb0af12513f4d5589efdd67e34bd91Steven Valdez bssl::ScopedCBB cbb; 1204969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin uint8_t *der; 1214969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin size_t der_len; 1224969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin if (!CBB_init(cbb.get(), 0) || 1234969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin !EC_KEY_marshal_private_key(cbb.get(), key, EC_KEY_get_enc_flags(key)) || 1244969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin !CBB_finish(cbb.get(), &der, &der_len)) { 1254969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin return false; 1264969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin } 1274969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin out->assign(der, der + der_len); 1284969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin OPENSSL_free(der); 1294969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin return true; 130e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley} 131e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 132a94fe0531b3c196ad078174259af2201b2e3a246Robert SloanTEST(ECTest, Encoding) { 133a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan bssl::UniquePtr<EC_KEY> key = 134a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan DecodeECPrivateKey(kECKeyWithoutPublic, sizeof(kECKeyWithoutPublic)); 135a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(key); 136e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 137a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan // Test that the encoding round-trips. 138e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley std::vector<uint8_t> out; 139a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(EncodeECPrivateKey(&out, key.get())); 140a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan EXPECT_EQ(Bytes(kECKeyWithoutPublic), Bytes(out.data(), out.size())); 141e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 142e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley const EC_POINT *pub_key = EC_KEY_get0_public_key(key.get()); 143a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(pub_key) << "Public key missing"; 144e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 145f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin bssl::UniquePtr<BIGNUM> x(BN_new()); 146f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin bssl::UniquePtr<BIGNUM> y(BN_new()); 147a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(x); 148a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(y); 149a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(EC_POINT_get_affine_coordinates_GFp( 150a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan EC_KEY_get0_group(key.get()), pub_key, x.get(), y.get(), NULL)); 151f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin bssl::UniquePtr<char> x_hex(BN_bn2hex(x.get())); 152f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin bssl::UniquePtr<char> y_hex(BN_bn2hex(y.get())); 153a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(x_hex); 154a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(y_hex); 155a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan 156a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan EXPECT_STREQ( 157a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan "c81561ecf2e54edefe6617db1c7a34a70744ddb261f269b83dacfcd2ade5a681", 158a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan x_hex.get()); 159a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan EXPECT_STREQ( 160a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan "e0e2afa3f9b6abe4c698ef6495f1be49a3196c5056acb3763fe4507eec596e88", 161a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan y_hex.get()); 162e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley} 163e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 164a94fe0531b3c196ad078174259af2201b2e3a246Robert SloanTEST(ECTest, ZeroPadding) { 165e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Check that the correct encoding round-trips. 166a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan bssl::UniquePtr<EC_KEY> key = 167a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan DecodeECPrivateKey(kECKeyWithZeros, sizeof(kECKeyWithZeros)); 168a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(key); 169e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley std::vector<uint8_t> out; 170a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan EXPECT_TRUE(EncodeECPrivateKey(&out, key.get())); 171a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan EXPECT_EQ(Bytes(kECKeyWithZeros), Bytes(out.data(), out.size())); 172e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 173e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Keys without leading zeros also parse, but they encode correctly. 174e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley key = DecodeECPrivateKey(kECKeyMissingZeros, sizeof(kECKeyMissingZeros)); 175a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(key); 176a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan EXPECT_TRUE(EncodeECPrivateKey(&out, key.get())); 177a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan EXPECT_EQ(Bytes(kECKeyWithZeros), Bytes(out.data(), out.size())); 178e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley} 179e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 180a94fe0531b3c196ad078174259af2201b2e3a246Robert SloanTEST(ECTest, SpecifiedCurve) { 1814969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin // Test keys with specified curves may be decoded. 182f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin bssl::UniquePtr<EC_KEY> key = 1834969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin DecodeECPrivateKey(kECKeySpecifiedCurve, sizeof(kECKeySpecifiedCurve)); 184a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(key); 1854969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 1864969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin // The group should have been interpreted as P-256. 187a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan EXPECT_EQ(NID_X9_62_prime256v1, 188a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan EC_GROUP_get_curve_name(EC_KEY_get0_group(key.get()))); 1894969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 1904969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin // Encoding the key should still use named form. 1914969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin std::vector<uint8_t> out; 192a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan EXPECT_TRUE(EncodeECPrivateKey(&out, key.get())); 193a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan EXPECT_EQ(Bytes(kECKeyWithoutPublic), Bytes(out.data(), out.size())); 194fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley} 195fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley 196a94fe0531b3c196ad078174259af2201b2e3a246Robert SloanTEST(ECTest, ArbitraryCurve) { 1974969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin // Make a P-256 key and extract the affine coordinates. 198f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); 199a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(key); 200a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(EC_KEY_generate_key(key.get())); 2014969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 2024969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin // Make an arbitrary curve which is identical to P-256. 2034969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin static const uint8_t kP[] = { 2044969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 2054969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 2064969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 2074969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin }; 2084969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin static const uint8_t kA[] = { 2094969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 2104969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 2114969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 2124969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin }; 2134969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin static const uint8_t kB[] = { 2144969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb, 0xbd, 2154969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 0x55, 0x76, 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53, 2164969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 0xb0, 0xf6, 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b, 2174969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin }; 2184969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin static const uint8_t kX[] = { 2194969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, 2204969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 0xe5, 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 2214969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, 2224969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin }; 2234969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin static const uint8_t kY[] = { 2244969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 2254969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 0x4a, 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 2264969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5, 2274969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin }; 2284969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin static const uint8_t kOrder[] = { 2294969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 2304969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 0xff, 0xff, 0xff, 0xff, 0xff, 0xbc, 0xe6, 0xfa, 0xad, 0xa7, 0x17, 2314969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc, 0x63, 0x25, 0x51, 2324969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin }; 233f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new()); 234a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(ctx); 235f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin bssl::UniquePtr<BIGNUM> p(BN_bin2bn(kP, sizeof(kP), nullptr)); 236a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(p); 237f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin bssl::UniquePtr<BIGNUM> a(BN_bin2bn(kA, sizeof(kA), nullptr)); 238a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(a); 239f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin bssl::UniquePtr<BIGNUM> b(BN_bin2bn(kB, sizeof(kB), nullptr)); 240a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(b); 241f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin bssl::UniquePtr<BIGNUM> gx(BN_bin2bn(kX, sizeof(kX), nullptr)); 242a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(gx); 243f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin bssl::UniquePtr<BIGNUM> gy(BN_bin2bn(kY, sizeof(kY), nullptr)); 244a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(gy); 245f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin bssl::UniquePtr<BIGNUM> order(BN_bin2bn(kOrder, sizeof(kOrder), nullptr)); 246a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(order); 2474969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 248f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin bssl::UniquePtr<EC_GROUP> group( 2494969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), ctx.get())); 250a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(group); 251f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin bssl::UniquePtr<EC_POINT> generator(EC_POINT_new(group.get())); 252a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(generator); 253a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp( 254a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan group.get(), generator.get(), gx.get(), gy.get(), ctx.get())); 255a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(EC_GROUP_set_generator(group.get(), generator.get(), order.get(), 256a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan BN_value_one())); 2574969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 2584969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin // |group| should not have a curve name. 259a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan EXPECT_EQ(NID_undef, EC_GROUP_get_curve_name(group.get())); 2604969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 2614969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin // Copy |key| to |key2| using |group|. 262f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin bssl::UniquePtr<EC_KEY> key2(EC_KEY_new()); 263a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(key2); 264f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group.get())); 265a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(point); 266f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin bssl::UniquePtr<BIGNUM> x(BN_new()), y(BN_new()); 267a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(x); 268a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(EC_KEY_set_group(key2.get(), group.get())); 269a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE( 270a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan EC_KEY_set_private_key(key2.get(), EC_KEY_get0_private_key(key.get()))); 271a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(EC_POINT_get_affine_coordinates_GFp( 272a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan EC_KEY_get0_group(key.get()), EC_KEY_get0_public_key(key.get()), x.get(), 273a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan y.get(), nullptr)); 274a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp(group.get(), point.get(), 275a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan x.get(), y.get(), nullptr)); 276a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(EC_KEY_set_public_key(key2.get(), point.get())); 2774969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 2784969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin // The key must be valid according to the new group too. 279a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan EXPECT_TRUE(EC_KEY_check_key(key2.get())); 28029c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan 28129c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan // Make a second instance of |group|. 28229c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan bssl::UniquePtr<EC_GROUP> group2( 28329c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), ctx.get())); 28429c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan ASSERT_TRUE(group2); 28529c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan bssl::UniquePtr<EC_POINT> generator2(EC_POINT_new(group2.get())); 28629c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan ASSERT_TRUE(generator2); 28729c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp( 28829c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan group2.get(), generator2.get(), gx.get(), gy.get(), ctx.get())); 28929c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan ASSERT_TRUE(EC_GROUP_set_generator(group2.get(), generator2.get(), 29029c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan order.get(), BN_value_one())); 29129c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan 29229c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan EXPECT_EQ(0, EC_GROUP_cmp(group.get(), group.get(), NULL)); 29329c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan EXPECT_EQ(0, EC_GROUP_cmp(group2.get(), group.get(), NULL)); 29429c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan 29529c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan // group3 uses the wrong generator. 29629c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan bssl::UniquePtr<EC_GROUP> group3( 29729c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), ctx.get())); 29829c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan ASSERT_TRUE(group3); 29929c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan bssl::UniquePtr<EC_POINT> generator3(EC_POINT_new(group3.get())); 30029c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan ASSERT_TRUE(generator3); 30129c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp( 30229c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan group3.get(), generator3.get(), x.get(), y.get(), ctx.get())); 30329c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan ASSERT_TRUE(EC_GROUP_set_generator(group3.get(), generator3.get(), 30429c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan order.get(), BN_value_one())); 30529c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan 30629c1d2cf8620ad14e06d8e7ff91db8f4de04d481Robert Sloan EXPECT_NE(0, EC_GROUP_cmp(group.get(), group3.get(), NULL)); 3074969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin} 3084969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 3090da4395e6883298b793bb05d45e57ed2e03167f9Robert SloanTEST(ECTest, SetKeyWithoutGroup) { 3100da4395e6883298b793bb05d45e57ed2e03167f9Robert Sloan bssl::UniquePtr<EC_KEY> key(EC_KEY_new()); 3110da4395e6883298b793bb05d45e57ed2e03167f9Robert Sloan ASSERT_TRUE(key); 3120da4395e6883298b793bb05d45e57ed2e03167f9Robert Sloan 3130da4395e6883298b793bb05d45e57ed2e03167f9Robert Sloan // Private keys may not be configured without a group. 3140da4395e6883298b793bb05d45e57ed2e03167f9Robert Sloan EXPECT_FALSE(EC_KEY_set_private_key(key.get(), BN_value_one())); 3150da4395e6883298b793bb05d45e57ed2e03167f9Robert Sloan 3160da4395e6883298b793bb05d45e57ed2e03167f9Robert Sloan // Public keys may not be configured without a group. 3170da4395e6883298b793bb05d45e57ed2e03167f9Robert Sloan bssl::UniquePtr<EC_GROUP> group( 3180da4395e6883298b793bb05d45e57ed2e03167f9Robert Sloan EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)); 3190da4395e6883298b793bb05d45e57ed2e03167f9Robert Sloan ASSERT_TRUE(group); 3200da4395e6883298b793bb05d45e57ed2e03167f9Robert Sloan EXPECT_FALSE( 3210da4395e6883298b793bb05d45e57ed2e03167f9Robert Sloan EC_KEY_set_public_key(key.get(), EC_GROUP_get0_generator(group.get()))); 3220da4395e6883298b793bb05d45e57ed2e03167f9Robert Sloan} 3230da4395e6883298b793bb05d45e57ed2e03167f9Robert Sloan 3240da4395e6883298b793bb05d45e57ed2e03167f9Robert SloanTEST(ECTest, GroupMismatch) { 3250da4395e6883298b793bb05d45e57ed2e03167f9Robert Sloan bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(NID_secp384r1)); 3260da4395e6883298b793bb05d45e57ed2e03167f9Robert Sloan ASSERT_TRUE(key); 3270da4395e6883298b793bb05d45e57ed2e03167f9Robert Sloan bssl::UniquePtr<EC_GROUP> p256( 3280da4395e6883298b793bb05d45e57ed2e03167f9Robert Sloan EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)); 3290da4395e6883298b793bb05d45e57ed2e03167f9Robert Sloan ASSERT_TRUE(p256); 3300da4395e6883298b793bb05d45e57ed2e03167f9Robert Sloan 3310da4395e6883298b793bb05d45e57ed2e03167f9Robert Sloan // Changing a key's group is invalid. 3320da4395e6883298b793bb05d45e57ed2e03167f9Robert Sloan EXPECT_FALSE(EC_KEY_set_group(key.get(), p256.get())); 3330da4395e6883298b793bb05d45e57ed2e03167f9Robert Sloan 3340da4395e6883298b793bb05d45e57ed2e03167f9Robert Sloan // Configuring a public key with the wrong group is invalid. 3350da4395e6883298b793bb05d45e57ed2e03167f9Robert Sloan EXPECT_FALSE( 3360da4395e6883298b793bb05d45e57ed2e03167f9Robert Sloan EC_KEY_set_public_key(key.get(), EC_GROUP_get0_generator(p256.get()))); 3370da4395e6883298b793bb05d45e57ed2e03167f9Robert Sloan} 3380da4395e6883298b793bb05d45e57ed2e03167f9Robert Sloan 339a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloanclass ECCurveTest : public testing::TestWithParam<EC_builtin_curve> {}; 340a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan 341a94fe0531b3c196ad078174259af2201b2e3a246Robert SloanTEST_P(ECCurveTest, SetAffine) { 342a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan // Generate an EC_KEY. 343a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid)); 344a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(key); 345a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(EC_KEY_generate_key(key.get())); 3464969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 3474969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin const EC_GROUP *const group = EC_KEY_get0_group(key.get()); 348a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan EXPECT_TRUE( 349a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan EC_POINT_is_on_curve(group, EC_KEY_get0_public_key(key.get()), nullptr)); 3504969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 351a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan // Get the public key's coordinates. 352a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan bssl::UniquePtr<BIGNUM> x(BN_new()); 353a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(x); 354a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan bssl::UniquePtr<BIGNUM> y(BN_new()); 355a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(y); 3560db7f543e9eb4209a3124ef956229ed0e942193dRobert Sloan bssl::UniquePtr<BIGNUM> p(BN_new()); 3570db7f543e9eb4209a3124ef956229ed0e942193dRobert Sloan ASSERT_TRUE(p); 358a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan EXPECT_TRUE(EC_POINT_get_affine_coordinates_GFp( 359a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan group, EC_KEY_get0_public_key(key.get()), x.get(), y.get(), nullptr)); 3600db7f543e9eb4209a3124ef956229ed0e942193dRobert Sloan EXPECT_TRUE( 3610db7f543e9eb4209a3124ef956229ed0e942193dRobert Sloan EC_GROUP_get_curve_GFp(group, p.get(), nullptr, nullptr, nullptr)); 362a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan 363a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan // Points on the curve should be accepted. 364a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan auto point = bssl::UniquePtr<EC_POINT>(EC_POINT_new(group)); 365a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(point); 366a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan EXPECT_TRUE(EC_POINT_set_affine_coordinates_GFp(group, point.get(), x.get(), 367a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan y.get(), nullptr)); 368a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan 369a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan // Subtract one from |y| to make the point no longer on the curve. 370a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan EXPECT_TRUE(BN_sub(y.get(), y.get(), BN_value_one())); 371a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan 372a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan // Points not on the curve should be rejected. 373a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan bssl::UniquePtr<EC_POINT> invalid_point(EC_POINT_new(group)); 374a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(invalid_point); 375a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan EXPECT_FALSE(EC_POINT_set_affine_coordinates_GFp(group, invalid_point.get(), 376a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan x.get(), y.get(), nullptr)); 3770db7f543e9eb4209a3124ef956229ed0e942193dRobert Sloan 3780db7f543e9eb4209a3124ef956229ed0e942193dRobert Sloan // Coordinates out of range should be rejected. 3790db7f543e9eb4209a3124ef956229ed0e942193dRobert Sloan EXPECT_TRUE(BN_add(y.get(), y.get(), BN_value_one())); 3800db7f543e9eb4209a3124ef956229ed0e942193dRobert Sloan EXPECT_TRUE(BN_add(y.get(), y.get(), p.get())); 3810db7f543e9eb4209a3124ef956229ed0e942193dRobert Sloan 3820db7f543e9eb4209a3124ef956229ed0e942193dRobert Sloan EXPECT_FALSE(EC_POINT_set_affine_coordinates_GFp(group, invalid_point.get(), 3830db7f543e9eb4209a3124ef956229ed0e942193dRobert Sloan x.get(), y.get(), nullptr)); 3840db7f543e9eb4209a3124ef956229ed0e942193dRobert Sloan EXPECT_FALSE( 3850db7f543e9eb4209a3124ef956229ed0e942193dRobert Sloan EC_KEY_set_public_key_affine_coordinates(key.get(), x.get(), y.get())); 386a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan} 387a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan 3888ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert SloanTEST_P(ECCurveTest, GenerateFIPS) { 389572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan // Generate an EC_KEY. 390572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid)); 391572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan ASSERT_TRUE(key); 3928ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan ASSERT_TRUE(EC_KEY_generate_key_fips(key.get())); 393572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan} 394572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan 395a94fe0531b3c196ad078174259af2201b2e3a246Robert SloanTEST_P(ECCurveTest, AddingEqualPoints) { 396a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid)); 397a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(key); 398a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(EC_KEY_generate_key(key.get())); 399a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan 400a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan const EC_GROUP *const group = EC_KEY_get0_group(key.get()); 4014969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 402f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin bssl::UniquePtr<EC_POINT> p1(EC_POINT_new(group)); 403a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(p1); 404a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(EC_POINT_copy(p1.get(), EC_KEY_get0_public_key(key.get()))); 4054969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 406a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan bssl::UniquePtr<EC_POINT> p2(EC_POINT_new(group)); 407a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(p2); 408a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(EC_POINT_copy(p2.get(), EC_KEY_get0_public_key(key.get()))); 4094969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 410a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan bssl::UniquePtr<EC_POINT> double_p1(EC_POINT_new(group)); 411a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(double_p1); 412f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new()); 413a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(ctx); 414a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(EC_POINT_dbl(group, double_p1.get(), p1.get(), ctx.get())); 4154969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 416a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan bssl::UniquePtr<EC_POINT> p1_plus_p2(EC_POINT_new(group)); 417a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(p1_plus_p2); 418a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE( 419a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan EC_POINT_add(group, p1_plus_p2.get(), p1.get(), p2.get(), ctx.get())); 4204969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 421a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan EXPECT_EQ(0, 422a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan EC_POINT_cmp(group, double_p1.get(), p1_plus_p2.get(), ctx.get())) 423a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan << "A+A != 2A"; 4244969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin} 4254969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 426a94fe0531b3c196ad078174259af2201b2e3a246Robert SloanTEST_P(ECCurveTest, MulZero) { 427a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(GetParam().nid)); 428a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(group); 429909b19f027eb0af12513f4d5589efdd67e34bd91Steven Valdez 430909b19f027eb0af12513f4d5589efdd67e34bd91Steven Valdez bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group.get())); 431a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(point); 432909b19f027eb0af12513f4d5589efdd67e34bd91Steven Valdez bssl::UniquePtr<BIGNUM> zero(BN_new()); 433a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(zero); 434909b19f027eb0af12513f4d5589efdd67e34bd91Steven Valdez BN_zero(zero.get()); 435a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(EC_POINT_mul(group.get(), point.get(), zero.get(), nullptr, 436a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan nullptr, nullptr)); 437909b19f027eb0af12513f4d5589efdd67e34bd91Steven Valdez 438a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan EXPECT_TRUE(EC_POINT_is_at_infinity(group.get(), point.get())) 439a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan << "g * 0 did not return point at infinity."; 440909b19f027eb0af12513f4d5589efdd67e34bd91Steven Valdez 441909b19f027eb0af12513f4d5589efdd67e34bd91Steven Valdez // Test that zero times an arbitrary point is also infinity. The generator is 442909b19f027eb0af12513f4d5589efdd67e34bd91Steven Valdez // used as the arbitrary point. 443909b19f027eb0af12513f4d5589efdd67e34bd91Steven Valdez bssl::UniquePtr<EC_POINT> generator(EC_POINT_new(group.get())); 444a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(generator); 445a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(EC_POINT_mul(group.get(), generator.get(), BN_value_one(), 446a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan nullptr, nullptr, nullptr)); 447a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan ASSERT_TRUE(EC_POINT_mul(group.get(), point.get(), nullptr, generator.get(), 448a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan zero.get(), nullptr)); 449a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan 450a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan EXPECT_TRUE(EC_POINT_is_at_infinity(group.get(), point.get())) 451a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan << "p * 0 did not return point at infinity."; 452909b19f027eb0af12513f4d5589efdd67e34bd91Steven Valdez} 453909b19f027eb0af12513f4d5589efdd67e34bd91Steven Valdez 45499319a18ffbf8991a8e752b4b8dacc9d39cdbd31Robert Sloan// Test that multiplying by the order produces ∞ and, moreover, that callers may 45599319a18ffbf8991a8e752b4b8dacc9d39cdbd31Robert Sloan// do so. |EC_POINT_mul| is almost exclusively used with reduced scalars, with 45699319a18ffbf8991a8e752b4b8dacc9d39cdbd31Robert Sloan// this exception. This comes from consumers following NIST SP 800-56A section 45799319a18ffbf8991a8e752b4b8dacc9d39cdbd31Robert Sloan// 5.6.2.3.2. (Though all our curves have cofactor one, so this check isn't 45899319a18ffbf8991a8e752b4b8dacc9d39cdbd31Robert Sloan// useful.) 45999319a18ffbf8991a8e752b4b8dacc9d39cdbd31Robert SloanTEST_P(ECCurveTest, MulOrder) { 46099319a18ffbf8991a8e752b4b8dacc9d39cdbd31Robert Sloan bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(GetParam().nid)); 46199319a18ffbf8991a8e752b4b8dacc9d39cdbd31Robert Sloan ASSERT_TRUE(group); 46299319a18ffbf8991a8e752b4b8dacc9d39cdbd31Robert Sloan 46399319a18ffbf8991a8e752b4b8dacc9d39cdbd31Robert Sloan // Test that g × order = ∞. 46499319a18ffbf8991a8e752b4b8dacc9d39cdbd31Robert Sloan bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group.get())); 46599319a18ffbf8991a8e752b4b8dacc9d39cdbd31Robert Sloan ASSERT_TRUE(point); 46699319a18ffbf8991a8e752b4b8dacc9d39cdbd31Robert Sloan ASSERT_TRUE(EC_POINT_mul(group.get(), point.get(), 46799319a18ffbf8991a8e752b4b8dacc9d39cdbd31Robert Sloan EC_GROUP_get0_order(group.get()), nullptr, nullptr, 46899319a18ffbf8991a8e752b4b8dacc9d39cdbd31Robert Sloan nullptr)); 46999319a18ffbf8991a8e752b4b8dacc9d39cdbd31Robert Sloan 47099319a18ffbf8991a8e752b4b8dacc9d39cdbd31Robert Sloan EXPECT_TRUE(EC_POINT_is_at_infinity(group.get(), point.get())) 47199319a18ffbf8991a8e752b4b8dacc9d39cdbd31Robert Sloan << "g * order did not return point at infinity."; 47299319a18ffbf8991a8e752b4b8dacc9d39cdbd31Robert Sloan 47399319a18ffbf8991a8e752b4b8dacc9d39cdbd31Robert Sloan // Test that p × order = ∞, for some arbitrary p. 47499319a18ffbf8991a8e752b4b8dacc9d39cdbd31Robert Sloan bssl::UniquePtr<BIGNUM> forty_two(BN_new()); 47599319a18ffbf8991a8e752b4b8dacc9d39cdbd31Robert Sloan ASSERT_TRUE(forty_two); 47699319a18ffbf8991a8e752b4b8dacc9d39cdbd31Robert Sloan ASSERT_TRUE(BN_set_word(forty_two.get(), 42)); 47799319a18ffbf8991a8e752b4b8dacc9d39cdbd31Robert Sloan ASSERT_TRUE(EC_POINT_mul(group.get(), point.get(), forty_two.get(), nullptr, 47899319a18ffbf8991a8e752b4b8dacc9d39cdbd31Robert Sloan nullptr, nullptr)); 47999319a18ffbf8991a8e752b4b8dacc9d39cdbd31Robert Sloan ASSERT_TRUE(EC_POINT_mul(group.get(), point.get(), nullptr, point.get(), 48099319a18ffbf8991a8e752b4b8dacc9d39cdbd31Robert Sloan EC_GROUP_get0_order(group.get()), nullptr)); 48199319a18ffbf8991a8e752b4b8dacc9d39cdbd31Robert Sloan 48299319a18ffbf8991a8e752b4b8dacc9d39cdbd31Robert Sloan EXPECT_TRUE(EC_POINT_is_at_infinity(group.get(), point.get())) 48399319a18ffbf8991a8e752b4b8dacc9d39cdbd31Robert Sloan << "p * order did not return point at infinity."; 48499319a18ffbf8991a8e752b4b8dacc9d39cdbd31Robert Sloan} 48599319a18ffbf8991a8e752b4b8dacc9d39cdbd31Robert Sloan 486a815d5abd1078d03df3278e5e3d512c7f6a11f9aRobert Sloan// Test that |EC_POINT_mul| works with out-of-range scalars. Even beyond the 487a815d5abd1078d03df3278e5e3d512c7f6a11f9aRobert Sloan// usual |bn_correct_top| disclaimer, we completely disclaim all hope here as a 488a815d5abd1078d03df3278e5e3d512c7f6a11f9aRobert Sloan// reduction is needed, but we'll compute the right answer. 489a815d5abd1078d03df3278e5e3d512c7f6a11f9aRobert SloanTEST_P(ECCurveTest, MulOutOfRange) { 490a815d5abd1078d03df3278e5e3d512c7f6a11f9aRobert Sloan bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(GetParam().nid)); 491a815d5abd1078d03df3278e5e3d512c7f6a11f9aRobert Sloan ASSERT_TRUE(group); 492a815d5abd1078d03df3278e5e3d512c7f6a11f9aRobert Sloan 493a815d5abd1078d03df3278e5e3d512c7f6a11f9aRobert Sloan bssl::UniquePtr<BIGNUM> n_minus_one(BN_dup(EC_GROUP_get0_order(group.get()))); 494a815d5abd1078d03df3278e5e3d512c7f6a11f9aRobert Sloan ASSERT_TRUE(n_minus_one); 495a815d5abd1078d03df3278e5e3d512c7f6a11f9aRobert Sloan ASSERT_TRUE(BN_sub_word(n_minus_one.get(), 1)); 496a815d5abd1078d03df3278e5e3d512c7f6a11f9aRobert Sloan 497a815d5abd1078d03df3278e5e3d512c7f6a11f9aRobert Sloan bssl::UniquePtr<BIGNUM> minus_one(BN_new()); 498a815d5abd1078d03df3278e5e3d512c7f6a11f9aRobert Sloan ASSERT_TRUE(minus_one); 499a815d5abd1078d03df3278e5e3d512c7f6a11f9aRobert Sloan ASSERT_TRUE(BN_one(minus_one.get())); 500a815d5abd1078d03df3278e5e3d512c7f6a11f9aRobert Sloan BN_set_negative(minus_one.get(), 1); 501a815d5abd1078d03df3278e5e3d512c7f6a11f9aRobert Sloan 502a815d5abd1078d03df3278e5e3d512c7f6a11f9aRobert Sloan bssl::UniquePtr<BIGNUM> seven(BN_new()); 503a815d5abd1078d03df3278e5e3d512c7f6a11f9aRobert Sloan ASSERT_TRUE(seven); 504a815d5abd1078d03df3278e5e3d512c7f6a11f9aRobert Sloan ASSERT_TRUE(BN_set_word(seven.get(), 7)); 505a815d5abd1078d03df3278e5e3d512c7f6a11f9aRobert Sloan 506a815d5abd1078d03df3278e5e3d512c7f6a11f9aRobert Sloan bssl::UniquePtr<BIGNUM> ten_n_plus_seven( 507a815d5abd1078d03df3278e5e3d512c7f6a11f9aRobert Sloan BN_dup(EC_GROUP_get0_order(group.get()))); 508a815d5abd1078d03df3278e5e3d512c7f6a11f9aRobert Sloan ASSERT_TRUE(ten_n_plus_seven); 509a815d5abd1078d03df3278e5e3d512c7f6a11f9aRobert Sloan ASSERT_TRUE(BN_mul_word(ten_n_plus_seven.get(), 10)); 510a815d5abd1078d03df3278e5e3d512c7f6a11f9aRobert Sloan ASSERT_TRUE(BN_add_word(ten_n_plus_seven.get(), 7)); 511a815d5abd1078d03df3278e5e3d512c7f6a11f9aRobert Sloan 512a815d5abd1078d03df3278e5e3d512c7f6a11f9aRobert Sloan bssl::UniquePtr<EC_POINT> point1(EC_POINT_new(group.get())), 513a815d5abd1078d03df3278e5e3d512c7f6a11f9aRobert Sloan point2(EC_POINT_new(group.get())); 514a815d5abd1078d03df3278e5e3d512c7f6a11f9aRobert Sloan ASSERT_TRUE(point1); 515a815d5abd1078d03df3278e5e3d512c7f6a11f9aRobert Sloan ASSERT_TRUE(point2); 516a815d5abd1078d03df3278e5e3d512c7f6a11f9aRobert Sloan 517a815d5abd1078d03df3278e5e3d512c7f6a11f9aRobert Sloan ASSERT_TRUE(EC_POINT_mul(group.get(), point1.get(), n_minus_one.get(), 518a815d5abd1078d03df3278e5e3d512c7f6a11f9aRobert Sloan nullptr, nullptr, nullptr)); 519a815d5abd1078d03df3278e5e3d512c7f6a11f9aRobert Sloan ASSERT_TRUE(EC_POINT_mul(group.get(), point2.get(), minus_one.get(), nullptr, 520a815d5abd1078d03df3278e5e3d512c7f6a11f9aRobert Sloan nullptr, nullptr)); 521a815d5abd1078d03df3278e5e3d512c7f6a11f9aRobert Sloan EXPECT_EQ(0, EC_POINT_cmp(group.get(), point1.get(), point2.get(), nullptr)) 522a815d5abd1078d03df3278e5e3d512c7f6a11f9aRobert Sloan << "-1 * G and (n-1) * G did not give the same result"; 523a815d5abd1078d03df3278e5e3d512c7f6a11f9aRobert Sloan 524a815d5abd1078d03df3278e5e3d512c7f6a11f9aRobert Sloan ASSERT_TRUE(EC_POINT_mul(group.get(), point1.get(), seven.get(), nullptr, 525a815d5abd1078d03df3278e5e3d512c7f6a11f9aRobert Sloan nullptr, nullptr)); 526a815d5abd1078d03df3278e5e3d512c7f6a11f9aRobert Sloan ASSERT_TRUE(EC_POINT_mul(group.get(), point2.get(), ten_n_plus_seven.get(), 527a815d5abd1078d03df3278e5e3d512c7f6a11f9aRobert Sloan nullptr, nullptr, nullptr)); 528a815d5abd1078d03df3278e5e3d512c7f6a11f9aRobert Sloan EXPECT_EQ(0, EC_POINT_cmp(group.get(), point1.get(), point2.get(), nullptr)) 529a815d5abd1078d03df3278e5e3d512c7f6a11f9aRobert Sloan << "7 * G and (10n + 7) * G did not give the same result"; 530a815d5abd1078d03df3278e5e3d512c7f6a11f9aRobert Sloan} 531a815d5abd1078d03df3278e5e3d512c7f6a11f9aRobert Sloan 532a12bf4695c4916207f946efafd9728eb941e3f0aRobert Sloan// Test that 10×∞ + G = G. 533a12bf4695c4916207f946efafd9728eb941e3f0aRobert SloanTEST_P(ECCurveTest, Mul) { 534a12bf4695c4916207f946efafd9728eb941e3f0aRobert Sloan bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(GetParam().nid)); 535a12bf4695c4916207f946efafd9728eb941e3f0aRobert Sloan ASSERT_TRUE(group); 536a12bf4695c4916207f946efafd9728eb941e3f0aRobert Sloan bssl::UniquePtr<EC_POINT> p(EC_POINT_new(group.get())); 537a12bf4695c4916207f946efafd9728eb941e3f0aRobert Sloan ASSERT_TRUE(p); 538a12bf4695c4916207f946efafd9728eb941e3f0aRobert Sloan bssl::UniquePtr<EC_POINT> result(EC_POINT_new(group.get())); 539a12bf4695c4916207f946efafd9728eb941e3f0aRobert Sloan ASSERT_TRUE(result); 540a12bf4695c4916207f946efafd9728eb941e3f0aRobert Sloan bssl::UniquePtr<BIGNUM> n(BN_new()); 541a12bf4695c4916207f946efafd9728eb941e3f0aRobert Sloan ASSERT_TRUE(n); 542a12bf4695c4916207f946efafd9728eb941e3f0aRobert Sloan ASSERT_TRUE(EC_POINT_set_to_infinity(group.get(), p.get())); 543a12bf4695c4916207f946efafd9728eb941e3f0aRobert Sloan ASSERT_TRUE(BN_set_word(n.get(), 10)); 544a12bf4695c4916207f946efafd9728eb941e3f0aRobert Sloan 545a12bf4695c4916207f946efafd9728eb941e3f0aRobert Sloan // First check that 10×∞ = ∞. 546a12bf4695c4916207f946efafd9728eb941e3f0aRobert Sloan ASSERT_TRUE(EC_POINT_mul(group.get(), result.get(), nullptr, p.get(), n.get(), 547a12bf4695c4916207f946efafd9728eb941e3f0aRobert Sloan nullptr)); 548a12bf4695c4916207f946efafd9728eb941e3f0aRobert Sloan EXPECT_TRUE(EC_POINT_is_at_infinity(group.get(), result.get())); 549a12bf4695c4916207f946efafd9728eb941e3f0aRobert Sloan 550a12bf4695c4916207f946efafd9728eb941e3f0aRobert Sloan // Now check that 10×∞ + G = G. 551a12bf4695c4916207f946efafd9728eb941e3f0aRobert Sloan const EC_POINT *generator = EC_GROUP_get0_generator(group.get()); 552a12bf4695c4916207f946efafd9728eb941e3f0aRobert Sloan ASSERT_TRUE(EC_POINT_mul(group.get(), result.get(), BN_value_one(), p.get(), 553a12bf4695c4916207f946efafd9728eb941e3f0aRobert Sloan n.get(), nullptr)); 554a12bf4695c4916207f946efafd9728eb941e3f0aRobert Sloan EXPECT_EQ(0, EC_POINT_cmp(group.get(), result.get(), generator, nullptr)); 555a12bf4695c4916207f946efafd9728eb941e3f0aRobert Sloan} 556a12bf4695c4916207f946efafd9728eb941e3f0aRobert Sloan 5578542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan#if !defined(BORINGSSL_SHARED_LIBRARY) 5588542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert SloanTEST_P(ECCurveTest, MulNonMinimal) { 5598542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(GetParam().nid)); 5608542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan ASSERT_TRUE(group); 5618542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan 5628542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan bssl::UniquePtr<BIGNUM> forty_two(BN_new()); 5638542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan ASSERT_TRUE(forty_two); 5648542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan ASSERT_TRUE(BN_set_word(forty_two.get(), 42)); 5658542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan 5668542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan // Compute g × 42. 5678542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group.get())); 5688542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan ASSERT_TRUE(point); 5698542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan ASSERT_TRUE(EC_POINT_mul(group.get(), point.get(), forty_two.get(), nullptr, 5708542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan nullptr, nullptr)); 5718542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan 5728542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan // Compute it again with a non-minimal 42, much larger than the scalar. 5738542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan ASSERT_TRUE(bn_resize_words(forty_two.get(), 64)); 5748542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan 5758542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan bssl::UniquePtr<EC_POINT> point2(EC_POINT_new(group.get())); 5768542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan ASSERT_TRUE(point2); 5778542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan ASSERT_TRUE(EC_POINT_mul(group.get(), point2.get(), forty_two.get(), nullptr, 5788542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan nullptr, nullptr)); 5798542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan EXPECT_EQ(0, EC_POINT_cmp(group.get(), point.get(), point2.get(), nullptr)); 5808542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan} 5818542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan#endif // BORINGSSL_SHARED_LIBRARY 5828542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan 583cd79cdebdcdadadb156e037973c927abf3dac79dRobert Sloan// Test that EC_KEY_set_private_key rejects invalid values. 584cd79cdebdcdadadb156e037973c927abf3dac79dRobert SloanTEST_P(ECCurveTest, SetInvalidPrivateKey) { 585cd79cdebdcdadadb156e037973c927abf3dac79dRobert Sloan bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid)); 586cd79cdebdcdadadb156e037973c927abf3dac79dRobert Sloan ASSERT_TRUE(key); 587cd79cdebdcdadadb156e037973c927abf3dac79dRobert Sloan 588cd79cdebdcdadadb156e037973c927abf3dac79dRobert Sloan bssl::UniquePtr<BIGNUM> bn(BN_new()); 589cd79cdebdcdadadb156e037973c927abf3dac79dRobert Sloan ASSERT_TRUE(BN_one(bn.get())); 590cd79cdebdcdadadb156e037973c927abf3dac79dRobert Sloan BN_set_negative(bn.get(), 1); 591cd79cdebdcdadadb156e037973c927abf3dac79dRobert Sloan EXPECT_FALSE(EC_KEY_set_private_key(key.get(), bn.get())) 592cd79cdebdcdadadb156e037973c927abf3dac79dRobert Sloan << "Unexpectedly set a key of -1"; 593cd79cdebdcdadadb156e037973c927abf3dac79dRobert Sloan ERR_clear_error(); 594cd79cdebdcdadadb156e037973c927abf3dac79dRobert Sloan 595cd79cdebdcdadadb156e037973c927abf3dac79dRobert Sloan ASSERT_TRUE( 596cd79cdebdcdadadb156e037973c927abf3dac79dRobert Sloan BN_copy(bn.get(), EC_GROUP_get0_order(EC_KEY_get0_group(key.get())))); 597cd79cdebdcdadadb156e037973c927abf3dac79dRobert Sloan EXPECT_FALSE(EC_KEY_set_private_key(key.get(), bn.get())) 598cd79cdebdcdadadb156e037973c927abf3dac79dRobert Sloan << "Unexpectedly set a key of the group order."; 599cd79cdebdcdadadb156e037973c927abf3dac79dRobert Sloan ERR_clear_error(); 600cd79cdebdcdadadb156e037973c927abf3dac79dRobert Sloan} 601cd79cdebdcdadadb156e037973c927abf3dac79dRobert Sloan 6028542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert SloanTEST_P(ECCurveTest, IgnoreOct2PointReturnValue) { 6038542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(GetParam().nid)); 6048542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan ASSERT_TRUE(group); 6058542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan 6068542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan bssl::UniquePtr<BIGNUM> forty_two(BN_new()); 6078542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan ASSERT_TRUE(forty_two); 6088542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan ASSERT_TRUE(BN_set_word(forty_two.get(), 42)); 6098542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan 6108542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan // Compute g × 42. 6118542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group.get())); 6128542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan ASSERT_TRUE(point); 6138542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan ASSERT_TRUE(EC_POINT_mul(group.get(), point.get(), forty_two.get(), nullptr, 6148542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan nullptr, nullptr)); 6158542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan 6168542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan // Serialize the point. 6178542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan size_t serialized_len = 6188542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan EC_POINT_point2oct(group.get(), point.get(), 6198542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan POINT_CONVERSION_UNCOMPRESSED, nullptr, 0, nullptr); 6208542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan ASSERT_NE(0u, serialized_len); 6218542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan 6228542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan std::vector<uint8_t> serialized(serialized_len); 6238542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan ASSERT_EQ(serialized_len, 6248542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan EC_POINT_point2oct(group.get(), point.get(), 6258542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan POINT_CONVERSION_UNCOMPRESSED, serialized.data(), 6268542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan serialized_len, nullptr)); 6278542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan 6288542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan // Create a serialized point that is not on the curve. 6298542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan serialized[serialized_len - 1]++; 6308542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan 6318542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan ASSERT_FALSE(EC_POINT_oct2point(group.get(), point.get(), serialized.data(), 6328542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan serialized.size(), nullptr)); 6338542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan // After a failure, |point| should have been set to the generator to defend 6348542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan // against code that doesn't check the return value. 6358542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan ASSERT_EQ(0, EC_POINT_cmp(group.get(), point.get(), 6368542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan EC_GROUP_get0_generator(group.get()), nullptr)); 6378542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan} 6388542c08a00c332af2ebca2a0c64b8d4d5fbd4cd2Robert Sloan 639a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloanstatic std::vector<EC_builtin_curve> AllCurves() { 6404969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin const size_t num_curves = EC_get_builtin_curves(nullptr, 0); 6414969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin std::vector<EC_builtin_curve> curves(num_curves); 6424969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin EC_get_builtin_curves(curves.data(), num_curves); 643a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan return curves; 6444969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin} 6454969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 646a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloanstatic std::string CurveToString( 647a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan const testing::TestParamInfo<EC_builtin_curve> ¶ms) { 648a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan // The comment field contains characters GTest rejects, so use the OBJ name. 649a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan return OBJ_nid2sn(params.param.nid); 650e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley} 651a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan 652a94fe0531b3c196ad078174259af2201b2e3a246Robert SloanINSTANTIATE_TEST_CASE_P(, ECCurveTest, testing::ValuesIn(AllCurves()), 653a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan CurveToString); 654