1e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley/* ==================================================================== 2e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. 3e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * 4e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * Redistribution and use in source and binary forms, with or without 5e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * modification, are permitted provided that the following conditions 6e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * are met: 7e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * 8e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * 1. Redistributions of source code must retain the above copyright 9e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * notice, this list of conditions and the following disclaimer. 10e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * 11e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * 2. Redistributions in binary form must reproduce the above copyright 12e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * notice, this list of conditions and the following disclaimer in 13e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * the documentation and/or other materials provided with the 14e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * distribution. 15e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * 16e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * 3. All advertising materials mentioning features or use of this 17e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * software must display the following acknowledgment: 18e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * "This product includes software developed by the OpenSSL Project 19e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 20e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * 21e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 22e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * endorse or promote products derived from this software without 23e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * prior written permission. For written permission, please contact 24e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * openssl-core@OpenSSL.org. 25e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * 26e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * 5. Products derived from this software may not be called "OpenSSL" 27e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * nor may "OpenSSL" appear in their names without prior written 28e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * permission of the OpenSSL Project. 29e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * 30e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * 6. Redistributions of any form whatsoever must retain the following 31e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * acknowledgment: 32e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * "This product includes software developed by the OpenSSL Project 33e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 34e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * 35e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 36e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 37e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 38e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 39e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 40e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 41e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 42e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 43e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 44e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 45e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 46e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * OF THE POSSIBILITY OF SUCH DAMAGE. 47e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * ==================================================================== 48e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * 49e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * This product includes cryptographic software written by Eric Young 50e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * (eay@cryptsoft.com). This product includes software written by Tim 51e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * Hudson (tjh@cryptsoft.com). */ 52e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 53e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#include <openssl/ecdsa.h> 54e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 55e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#include <vector> 56e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 57e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#include <openssl/bn.h> 58e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#include <openssl/crypto.h> 59e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#include <openssl/ec.h> 60e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#include <openssl/err.h> 61e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#include <openssl/mem.h> 624969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin#include <openssl/nid.h> 63e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#include <openssl/rand.h> 64e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 65e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleyenum Api { 66e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley kEncodedApi, 67e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley kRawApi, 68e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley}; 69e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 70e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// VerifyECDSASig returns true on success, false on failure. 71e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic bool VerifyECDSASig(Api api, const uint8_t *digest, 72e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley size_t digest_len, const ECDSA_SIG *ecdsa_sig, 73e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley EC_KEY *eckey, int expected_result) { 74e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley int actual_result; 75e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 76e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley switch (api) { 77e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley case kEncodedApi: { 78b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root uint8_t *der; 79b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root size_t der_len; 80b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root if (!ECDSA_SIG_to_bytes(&der, &der_len, ecdsa_sig)) { 81e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 82e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 83f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin bssl::UniquePtr<uint8_t> delete_der(der); 84b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root actual_result = ECDSA_verify(0, digest, digest_len, der, der_len, eckey); 85e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley break; 86e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 87e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 88e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley case kRawApi: 89e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley actual_result = ECDSA_do_verify(digest, digest_len, ecdsa_sig, eckey); 90e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley break; 91e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 92e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley default: 93e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 94e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 95e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return expected_result == actual_result; 96e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley} 97e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 98e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// TestTamperedSig verifies that signature verification fails when a valid 99e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// signature is tampered with. |ecdsa_sig| must be a valid signature, which will 100e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// be modified. TestTamperedSig returns true on success, false on failure. 101e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic bool TestTamperedSig(FILE *out, Api api, const uint8_t *digest, 102e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley size_t digest_len, ECDSA_SIG *ecdsa_sig, 103e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley EC_KEY *eckey, const BIGNUM *order) { 104e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Modify a single byte of the signature: to ensure we don't 105e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // garble the ASN1 structure, we read the raw signature and 106e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // modify a byte in one of the bignums directly. 107e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 108e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Store the two BIGNUMs in raw_buf. 109e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley size_t r_len = BN_num_bytes(ecdsa_sig->r); 110e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley size_t s_len = BN_num_bytes(ecdsa_sig->s); 111e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley size_t bn_len = BN_num_bytes(order); 112e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (r_len > bn_len || s_len > bn_len) { 113e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 114e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 115e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley size_t buf_len = 2 * bn_len; 116e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley std::vector<uint8_t> raw_buf(buf_len); 117e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Pad the bignums with leading zeroes. 1184139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley if (!BN_bn2bin_padded(raw_buf.data(), bn_len, ecdsa_sig->r) || 1194139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley !BN_bn2bin_padded(raw_buf.data() + bn_len, bn_len, ecdsa_sig->s)) { 120e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 121e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 122e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 123e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Modify a single byte in the buffer. 124e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley size_t offset = raw_buf[10] % buf_len; 125e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley uint8_t dirt = raw_buf[11] ? raw_buf[11] : 1; 126e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley raw_buf[offset] ^= dirt; 127e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Now read the BIGNUMs back in from raw_buf. 1284139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley if (BN_bin2bn(raw_buf.data(), bn_len, ecdsa_sig->r) == NULL || 1294139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley BN_bin2bn(raw_buf.data() + bn_len, bn_len, ecdsa_sig->s) == NULL || 130e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley !VerifyECDSASig(api, digest, digest_len, ecdsa_sig, eckey, 0)) { 131e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 132e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 133e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 134e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Sanity check: Undo the modification and verify signature. 135e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley raw_buf[offset] ^= dirt; 1364139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley if (BN_bin2bn(raw_buf.data(), bn_len, ecdsa_sig->r) == NULL || 1374139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley BN_bin2bn(raw_buf.data() + bn_len, bn_len, ecdsa_sig->s) == NULL || 138e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley !VerifyECDSASig(api, digest, digest_len, ecdsa_sig, eckey, 1)) { 139e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 140e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 141e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 142e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return true; 143e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley} 144e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 145e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic bool TestBuiltin(FILE *out) { 146e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Fill digest values with some random data. 147e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley uint8_t digest[20], wrong_digest[20]; 148e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (!RAND_bytes(digest, 20) || !RAND_bytes(wrong_digest, 20)) { 149e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fprintf(out, "ERROR: unable to get random data\n"); 150e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 151e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 152e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 153e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley static const struct { 154e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley int nid; 155e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley const char *name; 156e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } kCurves[] = { 157e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley { NID_secp224r1, "secp224r1" }, 158e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley { NID_X9_62_prime256v1, "secp256r1" }, 159e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley { NID_secp384r1, "secp384r1" }, 160e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley { NID_secp521r1, "secp521r1" }, 161e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley { NID_undef, NULL } 162e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley }; 163e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 164e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Create and verify ECDSA signatures with every available curve. 165e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fputs("\ntesting ECDSA_sign(), ECDSA_verify(), ECDSA_do_sign(), and " 166e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley "ECDSA_do_verify() with some internal curves:\n", out); 167e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 168e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley for (size_t n = 0; kCurves[n].nid != NID_undef; n++) { 169e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fprintf(out, "%s: ", kCurves[n].name); 170e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 171e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley int nid = kCurves[n].nid; 172f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(nid)); 173e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (!group) { 174e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fprintf(out, " failed\n"); 175e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 176e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 1774139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley const BIGNUM *order = EC_GROUP_get0_order(group.get()); 1784139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley if (BN_num_bits(order) < 160) { 179e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Too small to test. 180e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fprintf(out, " skipped\n"); 181e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley continue; 182e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 183e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 184e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Create a new ECDSA key. 185f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin bssl::UniquePtr<EC_KEY> eckey(EC_KEY_new()); 186e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (!eckey || !EC_KEY_set_group(eckey.get(), group.get()) || 187e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley !EC_KEY_generate_key(eckey.get())) { 188e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fprintf(out, " failed\n"); 189e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 190e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 191e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Create a second key. 192f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin bssl::UniquePtr<EC_KEY> wrong_eckey(EC_KEY_new()); 193e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (!wrong_eckey || !EC_KEY_set_group(wrong_eckey.get(), group.get()) || 194e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley !EC_KEY_generate_key(wrong_eckey.get())) { 195e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fprintf(out, " failed\n"); 196e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 197e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 198e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 199e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fprintf(out, "."); 200e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fflush(out); 201e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 202e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Check the key. 203e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (!EC_KEY_check_key(eckey.get())) { 204e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fprintf(out, " failed\n"); 205e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 206e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 207e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fprintf(out, "."); 208e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fflush(out); 209e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 210e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Test ASN.1-encoded signatures. 211e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Create a signature. 212e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley unsigned sig_len = ECDSA_size(eckey.get()); 213e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley std::vector<uint8_t> signature(sig_len); 2144139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley if (!ECDSA_sign(0, digest, 20, signature.data(), &sig_len, eckey.get())) { 215e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fprintf(out, " failed\n"); 216e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 217e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 218e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley signature.resize(sig_len); 219e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fprintf(out, "."); 220e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fflush(out); 221e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Verify the signature. 2224139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley if (!ECDSA_verify(0, digest, 20, signature.data(), signature.size(), 2234139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley eckey.get())) { 224e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fprintf(out, " failed\n"); 225e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 226e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 227e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fprintf(out, "."); 228e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fflush(out); 229e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Verify the signature with the wrong key. 2304139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley if (ECDSA_verify(0, digest, 20, signature.data(), signature.size(), 2314139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley wrong_eckey.get())) { 232e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fprintf(out, " failed\n"); 233e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 234e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 235e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fprintf(out, "."); 236e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fflush(out); 237e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Verify the signature using the wrong digest. 2384139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley if (ECDSA_verify(0, wrong_digest, 20, signature.data(), signature.size(), 2394139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley eckey.get())) { 240e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fprintf(out, " failed\n"); 241e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 242e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 243e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fprintf(out, "."); 244e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fflush(out); 245e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Verify a truncated signature. 2464139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley if (ECDSA_verify(0, digest, 20, signature.data(), signature.size() - 1, 2474139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley eckey.get())) { 248e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fprintf(out, " failed\n"); 249e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 250e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 251e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fprintf(out, "."); 252e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fflush(out); 253e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Verify a tampered signature. 254f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin bssl::UniquePtr<ECDSA_SIG> ecdsa_sig(ECDSA_SIG_from_bytes( 2554139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley signature.data(), signature.size())); 256e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (!ecdsa_sig || 257e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley !TestTamperedSig(out, kEncodedApi, digest, 20, ecdsa_sig.get(), 2584139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley eckey.get(), order)) { 259e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fprintf(out, " failed\n"); 260e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 261e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 262e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fprintf(out, "."); 263e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fflush(out); 264e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 265e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Test ECDSA_SIG signing and verification. 266e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Create a signature. 267e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley ecdsa_sig.reset(ECDSA_do_sign(digest, 20, eckey.get())); 268e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (!ecdsa_sig) { 269e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fprintf(out, " failed\n"); 270e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 271e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 272e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fprintf(out, "."); 273e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fflush(out); 274e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Verify the signature using the correct key. 275e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (!ECDSA_do_verify(digest, 20, ecdsa_sig.get(), eckey.get())) { 276e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fprintf(out, " failed\n"); 277e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 278e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 279e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fprintf(out, "."); 280e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fflush(out); 281e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Verify the signature with the wrong key. 282e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (ECDSA_do_verify(digest, 20, ecdsa_sig.get(), wrong_eckey.get())) { 283e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fprintf(out, " failed\n"); 284e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 285e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 286e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fprintf(out, "."); 287e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fflush(out); 288e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Verify the signature using the wrong digest. 289e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (ECDSA_do_verify(wrong_digest, 20, ecdsa_sig.get(), eckey.get())) { 290e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fprintf(out, " failed\n"); 291e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 292e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 293e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fprintf(out, "."); 294e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fflush(out); 295e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Verify a tampered signature. 296e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (!TestTamperedSig(out, kRawApi, digest, 20, ecdsa_sig.get(), eckey.get(), 2974139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley order)) { 298e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fprintf(out, " failed\n"); 299e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 300e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 301e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fprintf(out, "."); 302e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fflush(out); 303e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 304e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fprintf(out, " ok\n"); 305e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Clear bogus errors. 306e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley ERR_clear_error(); 307e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 308e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 309e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return true; 310e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley} 311e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 312b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Rootstatic bool TestECDSA_SIG_max_len(size_t order_len) { 313b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root /* Create the largest possible |ECDSA_SIG| of the given constraints. */ 314f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin bssl::UniquePtr<ECDSA_SIG> sig(ECDSA_SIG_new()); 315b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root if (!sig) { 316b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root return false; 317b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root } 318b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root std::vector<uint8_t> bytes(order_len, 0xff); 3194139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley if (!BN_bin2bn(bytes.data(), bytes.size(), sig->r) || 3204139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley !BN_bin2bn(bytes.data(), bytes.size(), sig->s)) { 321b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root return false; 322b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root } 323b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root /* Serialize it. */ 324b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root uint8_t *der; 325b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root size_t der_len; 326b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root if (!ECDSA_SIG_to_bytes(&der, &der_len, sig.get())) { 327b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root return false; 328b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root } 329f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin bssl::UniquePtr<uint8_t> delete_der(der); 330b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root 331b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root size_t max_len = ECDSA_SIG_max_len(order_len); 332b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root if (max_len != der_len) { 333b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root fprintf(stderr, "ECDSA_SIG_max_len(%u) returned %u, wanted %u\n", 334b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root static_cast<unsigned>(order_len), static_cast<unsigned>(max_len), 335b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root static_cast<unsigned>(der_len)); 336b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root return false; 337b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root } 338b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root return true; 339b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root} 340b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root 3414969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjaminstatic size_t BitsToBytes(size_t bits) { 3424969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin return (bits / 8) + (7 + (bits % 8)) / 8; 3434969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin} 3444969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin 345e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleyint main(void) { 346e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley CRYPTO_library_init(); 347e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 348b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root if (!TestBuiltin(stdout) || 3494969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin !TestECDSA_SIG_max_len(BitsToBytes(224)) || 3504969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin !TestECDSA_SIG_max_len(BitsToBytes(256)) || 3514969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin !TestECDSA_SIG_max_len(BitsToBytes(384)) || 3524969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin !TestECDSA_SIG_max_len(BitsToBytes(521)) || 3534969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin !TestECDSA_SIG_max_len(BitsToBytes(10000))) { 354e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley printf("\nECDSA test failed\n"); 355e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley ERR_print_errors_fp(stdout); 356e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return 1; 357e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 358e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 359e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley printf("\nPASS\n"); 360e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return 0; 361e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley} 362