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