1d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* ====================================================================
2d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Copyright (c) 1998-2005 The OpenSSL Project.  All rights reserved.
3d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
4d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Redistribution and use in source and binary forms, with or without
5d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * modification, are permitted provided that the following conditions
6d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * are met:
7d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
8d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 1. Redistributions of source code must retain the above copyright
9d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    notice, this list of conditions and the following disclaimer.
10d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
11d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 2. Redistributions in binary form must reproduce the above copyright
12d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    notice, this list of conditions and the following disclaimer in
13d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    the documentation and/or other materials provided with the
14d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    distribution.
15d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
16d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 3. All advertising materials mentioning features or use of this
17d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    software must display the following acknowledgment:
18d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    "This product includes software developed by the OpenSSL Project
19d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
20d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
21d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
22d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    endorse or promote products derived from this software without
23d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    prior written permission. For written permission, please contact
24d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    openssl-core@OpenSSL.org.
25d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
26d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 5. Products derived from this software may not be called "OpenSSL"
27d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    nor may "OpenSSL" appear in their names without prior written
28d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    permission of the OpenSSL Project.
29d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
30d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 6. Redistributions of any form whatsoever must retain the following
31d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    acknowledgment:
32d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    "This product includes software developed by the OpenSSL Project
33d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
34d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
35d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
36d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
38d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
39d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
41d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
42d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
43d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
44d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
45d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
46d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * OF THE POSSIBILITY OF SUCH DAMAGE.
47d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ====================================================================
48d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
49d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * This product includes cryptographic software written by Eric Young
50d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * (eay@cryptsoft.com).  This product includes software written by Tim
51d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Hudson (tjh@cryptsoft.com). */
52d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
53d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/ecdsa.h>
54d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
55b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root#include <assert.h>
56d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <string.h>
57d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
58d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/bn.h>
59d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/err.h>
60d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/mem.h>
61d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
6269939df2891f62f7f00ff2ac275f1cd81a67454cRobert Sloan#include "../bn/internal.h"
63d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include "../ec/internal.h"
648ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan#include "../../internal.h"
65d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
66d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
67d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* digest_to_bn interprets |digest_len| bytes from |digest| as a big-endian
68d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * number and sets |out| to that value. It then truncates |out| so that it's,
69d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * at most, as long as |order|. It returns one on success and zero otherwise. */
70d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int digest_to_bn(BIGNUM *out, const uint8_t *digest, size_t digest_len,
71d9e397b599b13d642138480a28c14db7a136bf0Adam Langley                        const BIGNUM *order) {
72d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  size_t num_bits;
73d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
74d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  num_bits = BN_num_bits(order);
75d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  /* Need to truncate digest if it is too long: first truncate whole
76d9e397b599b13d642138480a28c14db7a136bf0Adam Langley   * bytes. */
77d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (8 * digest_len > num_bits) {
78d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    digest_len = (num_bits + 7) / 8;
79d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
80d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!BN_bin2bn(digest, digest_len, out)) {
81b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB);
82d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return 0;
83d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
84d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
85d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  /* If still too long truncate remaining bits with a shift */
86d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if ((8 * digest_len > num_bits) &&
87d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      !BN_rshift(out, out, 8 - (num_bits & 0x7))) {
88b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB);
89d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return 0;
90d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
91d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
92d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return 1;
93d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
94d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
958ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert SloanECDSA_SIG *ECDSA_SIG_new(void) {
968ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan  ECDSA_SIG *sig = OPENSSL_malloc(sizeof(ECDSA_SIG));
978ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan  if (sig == NULL) {
988ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan    return NULL;
998ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan  }
1008ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan  sig->r = BN_new();
1018ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan  sig->s = BN_new();
1028ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan  if (sig->r == NULL || sig->s == NULL) {
1038ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan    ECDSA_SIG_free(sig);
1048ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan    return NULL;
1058ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan  }
1068ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan  return sig;
1078ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan}
1088ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan
1098ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloanvoid ECDSA_SIG_free(ECDSA_SIG *sig) {
1108ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan  if (sig == NULL) {
1118ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan    return;
1128ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan  }
1138ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan
1148ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan  BN_free(sig->r);
1158ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan  BN_free(sig->s);
1168ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan  OPENSSL_free(sig);
1178ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan}
1188ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan
119d9e397b599b13d642138480a28c14db7a136bf0Adam LangleyECDSA_SIG *ECDSA_do_sign(const uint8_t *digest, size_t digest_len,
120a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan                         const EC_KEY *key) {
121d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return ECDSA_do_sign_ex(digest, digest_len, NULL, NULL, key);
122d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
123d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
124d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint ECDSA_do_verify(const uint8_t *digest, size_t digest_len,
125a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan                    const ECDSA_SIG *sig, const EC_KEY *eckey) {
126d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  int ret = 0;
127d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  BN_CTX *ctx;
1284139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  BIGNUM *u1, *u2, *m, *X;
129d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  EC_POINT *point = NULL;
130d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  const EC_GROUP *group;
131d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  const EC_POINT *pub_key;
132d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
133d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  /* check input values */
134d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if ((group = EC_KEY_get0_group(eckey)) == NULL ||
135d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      (pub_key = EC_KEY_get0_public_key(eckey)) == NULL ||
136d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      sig == NULL) {
137b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_MISSING_PARAMETERS);
138d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return 0;
139d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
140d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
141d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  ctx = BN_CTX_new();
142d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!ctx) {
143b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE);
144d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return 0;
145d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
146d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  BN_CTX_start(ctx);
147d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  u1 = BN_CTX_get(ctx);
148d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  u2 = BN_CTX_get(ctx);
149d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  m = BN_CTX_get(ctx);
150d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  X = BN_CTX_get(ctx);
1514139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  if (u1 == NULL || u2 == NULL || m == NULL || X == NULL) {
152b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB);
153d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
154d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
155d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
1564139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  const BIGNUM *order = EC_GROUP_get0_order(group);
157d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (BN_is_zero(sig->r) || BN_is_negative(sig->r) ||
158d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      BN_ucmp(sig->r, order) >= 0 || BN_is_zero(sig->s) ||
159d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      BN_is_negative(sig->s) || BN_ucmp(sig->s, order) >= 0) {
160b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_BAD_SIGNATURE);
161d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
162d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
163d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  /* calculate tmp1 = inv(S) mod order */
164c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  int no_inverse;
165c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  if (!BN_mod_inverse_odd(u2, &no_inverse, sig->s, order, ctx)) {
166b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB);
167d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
168d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
169d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!digest_to_bn(m, digest, digest_len, order)) {
170d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
171d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
172d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  /* u1 = m * tmp mod order */
173d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!BN_mod_mul(u1, m, u2, order, ctx)) {
174b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB);
175d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
176d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
177d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  /* u2 = r * w mod q */
178d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!BN_mod_mul(u2, sig->r, u2, order, ctx)) {
179b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB);
180d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
181d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
182d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
183d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  point = EC_POINT_new(group);
184d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (point == NULL) {
185b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE);
186d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
187d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
188d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!EC_POINT_mul(group, point, u1, pub_key, u2, ctx)) {
189b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB);
190d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
191d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
192d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!EC_POINT_get_affine_coordinates_GFp(group, point, X, NULL, ctx)) {
193b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB);
194d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
195d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
196d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!BN_nnmod(u1, X, order, ctx)) {
197b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB);
198d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
199d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
200d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  /* if the signature is correct u1 is equal to sig->r */
2012424d84dd6dbdc0d32a4c80e6810d168f722ce0bRobert Sloan  if (BN_ucmp(u1, sig->r) != 0) {
2022424d84dd6dbdc0d32a4c80e6810d168f722ce0bRobert Sloan    OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_BAD_SIGNATURE);
2032424d84dd6dbdc0d32a4c80e6810d168f722ce0bRobert Sloan    goto err;
2042424d84dd6dbdc0d32a4c80e6810d168f722ce0bRobert Sloan  }
2052424d84dd6dbdc0d32a4c80e6810d168f722ce0bRobert Sloan
2062424d84dd6dbdc0d32a4c80e6810d168f722ce0bRobert Sloan  ret = 1;
207d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
208d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyerr:
2094969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin  BN_CTX_end(ctx);
210d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  BN_CTX_free(ctx);
211e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  EC_POINT_free(point);
212d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return ret;
213d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
214d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
215a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloanstatic int ecdsa_sign_setup(const EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp,
216d9e397b599b13d642138480a28c14db7a136bf0Adam Langley                            BIGNUM **rp, const uint8_t *digest,
217d9e397b599b13d642138480a28c14db7a136bf0Adam Langley                            size_t digest_len) {
218d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  BN_CTX *ctx = NULL;
219572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan  BIGNUM *k = NULL, *kinv = NULL, *r = NULL, *tmp = NULL;
220d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  EC_POINT *tmp_point = NULL;
221d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  const EC_GROUP *group;
222d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  int ret = 0;
223d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
224d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL) {
225b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    OPENSSL_PUT_ERROR(ECDSA, ERR_R_PASSED_NULL_PARAMETER);
226d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return 0;
227d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
228d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
229d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (ctx_in == NULL) {
230d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if ((ctx = BN_CTX_new()) == NULL) {
231b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root      OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE);
232d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      return 0;
233d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
234d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  } else {
235d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    ctx = ctx_in;
236d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
237d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
238572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan  k = BN_new();
239572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan  kinv = BN_new(); /* this value is later returned in *kinvp */
240d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  r = BN_new(); /* this value is later returned in *rp    */
241c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  tmp = BN_new();
242572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan  if (k == NULL || kinv == NULL || r == NULL || tmp == NULL) {
243b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE);
244d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
245d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
246d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  tmp_point = EC_POINT_new(group);
247d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (tmp_point == NULL) {
248b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB);
249d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
250d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
2514139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley
2524139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  const BIGNUM *order = EC_GROUP_get0_order(group);
253d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
254572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan  /* Check that the size of the group order is FIPS compliant (FIPS 186-4
255572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan   * B.5.2). */
256572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan  if (BN_num_bits(order) < 160) {
257572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan    OPENSSL_PUT_ERROR(ECDSA, EC_R_INVALID_GROUP_ORDER);
258572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan    goto err;
259572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan  }
260572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan
261d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  do {
262d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    /* If possible, we'll include the private key and message digest in the k
263d9e397b599b13d642138480a28c14db7a136bf0Adam Langley     * generation. The |digest| argument is only empty if |ECDSA_sign_setup| is
264d9e397b599b13d642138480a28c14db7a136bf0Adam Langley     * being used. */
2658ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan    if (eckey->fixed_k != NULL) {
2668ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan      if (!BN_copy(k, eckey->fixed_k)) {
2678ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan        goto err;
2688ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan      }
2698ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan    } else if (digest_len > 0) {
270c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin      do {
271c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin        if (!BN_generate_dsa_nonce(k, order, EC_KEY_get0_private_key(eckey),
272c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin                                   digest, digest_len, ctx)) {
273c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin          OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED);
274c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin          goto err;
275c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin        }
276c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin      } while (BN_is_zero(k));
277c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin    } else if (!BN_rand_range_ex(k, 1, order)) {
278c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin      OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED);
279c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin      goto err;
280c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin    }
281d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
282572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan    /* Compute the inverse of k. The order is a prime, so use Fermat's Little
283572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan     * Theorem. Note |ec_group_get_mont_data| may return NULL but
284572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan     * |bn_mod_inverse_prime| allows this. */
285572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan    if (!bn_mod_inverse_prime(kinv, k, order, ctx,
286572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan                              ec_group_get_mont_data(group))) {
287572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan      OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB);
288572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan      goto err;
289572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan    }
290572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan
291d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    /* We do not want timing information to leak the length of k,
292d9e397b599b13d642138480a28c14db7a136bf0Adam Langley     * so we compute G*k using an equivalent scalar of fixed
293d9e397b599b13d642138480a28c14db7a136bf0Adam Langley     * bit-length. */
294d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
295d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (!BN_add(k, k, order)) {
296d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      goto err;
297d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
298d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (BN_num_bits(k) <= BN_num_bits(order)) {
299d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      if (!BN_add(k, k, order)) {
300d9e397b599b13d642138480a28c14db7a136bf0Adam Langley        goto err;
301d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      }
302d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
303d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
304d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    /* compute r the x-coordinate of generator * k */
305d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (!EC_POINT_mul(group, tmp_point, k, NULL, NULL, ctx)) {
306b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root      OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB);
307d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      goto err;
308d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
309c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin    if (!EC_POINT_get_affine_coordinates_GFp(group, tmp_point, tmp, NULL,
310c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin                                             ctx)) {
311b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root      OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB);
312d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      goto err;
313d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
314d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
315c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin    if (!BN_nnmod(r, tmp, order, ctx)) {
316b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root      OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB);
317d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      goto err;
318d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
319d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  } while (BN_is_zero(r));
320d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
321d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  /* clear old values if necessary */
322e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  BN_clear_free(*rp);
323e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  BN_clear_free(*kinvp);
324d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
325d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  /* save the pre-computed values  */
326d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  *rp = r;
327572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan  *kinvp = kinv;
328d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  ret = 1;
329d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
330d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyerr:
331572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan  BN_clear_free(k);
332d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!ret) {
333572a4e2e687520da9e518528d7371b794b1decc0Robert Sloan    BN_clear_free(kinv);
334e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    BN_clear_free(r);
335d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
336e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (ctx_in == NULL) {
337d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    BN_CTX_free(ctx);
338e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
339e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  EC_POINT_free(tmp_point);
340c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  BN_clear_free(tmp);
341d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return ret;
342d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
343d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
344a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloanint ECDSA_sign_setup(const EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinv,
345a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan                     BIGNUM **rp) {
346d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return ecdsa_sign_setup(eckey, ctx, kinv, rp, NULL, 0);
347d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
348d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
349d9e397b599b13d642138480a28c14db7a136bf0Adam LangleyECDSA_SIG *ECDSA_do_sign_ex(const uint8_t *digest, size_t digest_len,
350d9e397b599b13d642138480a28c14db7a136bf0Adam Langley                            const BIGNUM *in_kinv, const BIGNUM *in_r,
351a94fe0531b3c196ad078174259af2201b2e3a246Robert Sloan                            const EC_KEY *eckey) {
352d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  int ok = 0;
3534139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  BIGNUM *kinv = NULL, *s, *m = NULL, *tmp = NULL;
354d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  const BIGNUM *ckinv;
355d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  BN_CTX *ctx = NULL;
356d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  const EC_GROUP *group;
357d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  ECDSA_SIG *ret;
358d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  const BIGNUM *priv_key;
359d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
360d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (eckey->ecdsa_meth && eckey->ecdsa_meth->sign) {
361b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_NOT_IMPLEMENTED);
362d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return NULL;
363d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
364d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
365d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  group = EC_KEY_get0_group(eckey);
366d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  priv_key = EC_KEY_get0_private_key(eckey);
367d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
368d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (group == NULL || priv_key == NULL) {
369b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    OPENSSL_PUT_ERROR(ECDSA, ERR_R_PASSED_NULL_PARAMETER);
370d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return NULL;
371d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
372d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
373d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  ret = ECDSA_SIG_new();
374d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!ret) {
375b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE);
376d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return NULL;
377d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
378d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  s = ret->s;
379d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
3804139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  if ((ctx = BN_CTX_new()) == NULL ||
3814139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      (tmp = BN_new()) == NULL ||
3824139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley      (m = BN_new()) == NULL) {
383b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE);
384d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
385d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
386d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
3874139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  const BIGNUM *order = EC_GROUP_get0_order(group);
3884139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley
389d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!digest_to_bn(m, digest, digest_len, order)) {
390d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
391d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
392d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  for (;;) {
393d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (in_kinv == NULL || in_r == NULL) {
394d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      if (!ecdsa_sign_setup(eckey, ctx, &kinv, &ret->r, digest, digest_len)) {
395b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root        OPENSSL_PUT_ERROR(ECDSA, ERR_R_ECDSA_LIB);
396d9e397b599b13d642138480a28c14db7a136bf0Adam Langley        goto err;
397d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      }
398d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      ckinv = kinv;
399d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    } else {
400d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      ckinv = in_kinv;
401d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      if (BN_copy(ret->r, in_r) == NULL) {
402b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root        OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE);
403d9e397b599b13d642138480a28c14db7a136bf0Adam Langley        goto err;
404d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      }
405d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
406d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
407d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (!BN_mod_mul(tmp, priv_key, ret->r, order, ctx)) {
408b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root      OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB);
409d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      goto err;
410d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
411d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (!BN_mod_add_quick(s, tmp, m, order)) {
412b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root      OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB);
413d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      goto err;
414d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
415d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (!BN_mod_mul(s, s, ckinv, order, ctx)) {
416b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root      OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB);
417d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      goto err;
418d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
419d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (BN_is_zero(s)) {
420d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      /* if kinv and r have been supplied by the caller
421d9e397b599b13d642138480a28c14db7a136bf0Adam Langley       * don't to generate new kinv and r values */
422d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      if (in_kinv != NULL && in_r != NULL) {
423b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root        OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_NEED_NEW_SETUP_VALUES);
424d9e397b599b13d642138480a28c14db7a136bf0Adam Langley        goto err;
425d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      }
426d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    } else {
427d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      /* s != 0 => we have a valid signature */
428d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      break;
429d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
430d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
431d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
432d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  ok = 1;
433d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
434d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyerr:
435d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!ok) {
436d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    ECDSA_SIG_free(ret);
437d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    ret = NULL;
438d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
439e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  BN_CTX_free(ctx);
440e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  BN_clear_free(m);
441e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  BN_clear_free(tmp);
442e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  BN_clear_free(kinv);
443d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return ret;
444d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
445