1d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* Originally written by Bodo Moeller for the OpenSSL project.
2d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ====================================================================
3d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Copyright (c) 1998-2005 The OpenSSL Project.  All rights reserved.
4d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
5d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Redistribution and use in source and binary forms, with or without
6d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * modification, are permitted provided that the following conditions
7d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * are met:
8d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
9d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 1. Redistributions of source code must retain the above copyright
10d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    notice, this list of conditions and the following disclaimer.
11d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
12d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 2. Redistributions in binary form must reproduce the above copyright
13d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    notice, this list of conditions and the following disclaimer in
14d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    the documentation and/or other materials provided with the
15d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    distribution.
16d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
17d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 3. All advertising materials mentioning features or use of this
18d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    software must display the following acknowledgment:
19d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    "This product includes software developed by the OpenSSL Project
20d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
21d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
22d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
23d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    endorse or promote products derived from this software without
24d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    prior written permission. For written permission, please contact
25d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    openssl-core@openssl.org.
26d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
27d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 5. Products derived from this software may not be called "OpenSSL"
28d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    nor may "OpenSSL" appear in their names without prior written
29d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    permission of the OpenSSL Project.
30d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
31d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 6. Redistributions of any form whatsoever must retain the following
32d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    acknowledgment:
33d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    "This product includes software developed by the OpenSSL Project
34d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
35d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
36d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
37d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
39d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
40d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
42d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
45d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
47d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * OF THE POSSIBILITY OF SUCH DAMAGE.
48d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ====================================================================
49d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
50d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * This product includes cryptographic software written by Eric Young
51d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * (eay@cryptsoft.com).  This product includes software written by Tim
52d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Hudson (tjh@cryptsoft.com).
53d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
54d9e397b599b13d642138480a28c14db7a136bf0Adam Langley */
55d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* ====================================================================
56d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
57d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
58d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Portions of the attached software ("Contribution") are developed by
59d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
60d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
61d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * The Contribution is licensed pursuant to the OpenSSL open source
62d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * license provided above.
63d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
64d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * The elliptic curve binary polynomial software is originally written by
65d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems
66d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Laboratories. */
67d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
68d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/ec_key.h>
69d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
70d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <string.h>
71d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
72d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/ec.h>
73d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/engine.h>
74d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/err.h>
75d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/ex_data.h>
76d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/mem.h>
77e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#include <openssl/thread.h>
78d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
79d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include "internal.h"
80e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#include "../internal.h"
81d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
82d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
83e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT;
84e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
85d9e397b599b13d642138480a28c14db7a136bf0Adam LangleyEC_KEY *EC_KEY_new(void) { return EC_KEY_new_method(NULL); }
86d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
87d9e397b599b13d642138480a28c14db7a136bf0Adam LangleyEC_KEY *EC_KEY_new_method(const ENGINE *engine) {
88d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  EC_KEY *ret = (EC_KEY *)OPENSSL_malloc(sizeof(EC_KEY));
89d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (ret == NULL) {
90d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    OPENSSL_PUT_ERROR(EC, EC_KEY_new_method, ERR_R_MALLOC_FAILURE);
91d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return NULL;
92d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
93d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
94d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  memset(ret, 0, sizeof(EC_KEY));
95d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
96d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (engine) {
97d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    ret->ecdsa_meth = ENGINE_get_ECDSA_method(engine);
98d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
99d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (ret->ecdsa_meth) {
100d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    METHOD_ref(ret->ecdsa_meth);
101d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
102d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
103d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  ret->version = 1;
104d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  ret->conv_form = POINT_CONVERSION_UNCOMPRESSED;
105d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  ret->references = 1;
106d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
107e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (!CRYPTO_new_ex_data(&g_ex_data_class, ret, &ret->ex_data)) {
108d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err1;
109d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
110d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
111d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (ret->ecdsa_meth && ret->ecdsa_meth->init && !ret->ecdsa_meth->init(ret)) {
112d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err2;
113d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
114d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
115d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return ret;
116d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
117d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyerr2:
118e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  CRYPTO_free_ex_data(&g_ex_data_class, ret, &ret->ex_data);
119d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyerr1:
120d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (ret->ecdsa_meth) {
121d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    METHOD_unref(ret->ecdsa_meth);
122d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
123d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  OPENSSL_free(ret);
124d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return NULL;
125d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
126d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
127d9e397b599b13d642138480a28c14db7a136bf0Adam LangleyEC_KEY *EC_KEY_new_by_curve_name(int nid) {
128d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  EC_KEY *ret = EC_KEY_new();
129d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (ret == NULL) {
130e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    OPENSSL_PUT_ERROR(EC, EC_KEY_new_by_curve_name, ERR_R_MALLOC_FAILURE);
131d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return NULL;
132d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
133d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  ret->group = EC_GROUP_new_by_curve_name(nid);
134d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (ret->group == NULL) {
135d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    EC_KEY_free(ret);
136d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return NULL;
137d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
138d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return ret;
139d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
140d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
141d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyvoid EC_KEY_free(EC_KEY *r) {
142d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (r == NULL) {
143d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return;
144d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
145d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
14653b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley  if (!CRYPTO_refcount_dec_and_test_zero(&r->references)) {
147d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return;
148d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
149d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
150d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (r->ecdsa_meth) {
151d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (r->ecdsa_meth->finish) {
152d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      r->ecdsa_meth->finish(r);
153d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
154d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    METHOD_unref(r->ecdsa_meth);
155d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
156d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
157e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  EC_GROUP_free(r->group);
158e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  EC_POINT_free(r->pub_key);
159e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  BN_clear_free(r->priv_key);
160d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
161e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  CRYPTO_free_ex_data(&g_ex_data_class, r, &r->ex_data);
162d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
163d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  OPENSSL_cleanse((void *)r, sizeof(EC_KEY));
164d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  OPENSSL_free(r);
165d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
166d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
167d9e397b599b13d642138480a28c14db7a136bf0Adam LangleyEC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src) {
168d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (dest == NULL || src == NULL) {
169d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    OPENSSL_PUT_ERROR(EC, EC_KEY_copy, ERR_R_PASSED_NULL_PARAMETER);
170d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return NULL;
171d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
172e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  /* Copy the parameters. */
173d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (src->group) {
174d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    /* TODO(fork): duplicating the group seems wasteful. */
175e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    EC_GROUP_free(dest->group);
176e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    dest->group = EC_GROUP_dup(src->group);
177d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (dest->group == NULL) {
178d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      return NULL;
179d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
180d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
181d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
182e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  /* Copy the public key. */
183d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (src->pub_key && src->group) {
184e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    EC_POINT_free(dest->pub_key);
185e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    dest->pub_key = EC_POINT_dup(src->pub_key, src->group);
186d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (dest->pub_key == NULL) {
187d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      return NULL;
188d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
189d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
190d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
191d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  /* copy the private key */
192d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (src->priv_key) {
193d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (dest->priv_key == NULL) {
194d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      dest->priv_key = BN_new();
195d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      if (dest->priv_key == NULL) {
196d9e397b599b13d642138480a28c14db7a136bf0Adam Langley        return NULL;
197d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      }
198d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
199d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (!BN_copy(dest->priv_key, src->priv_key)) {
200d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      return NULL;
201d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
202d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
203d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  /* copy method/extra data */
20421c70997ab3c62b97960fd66f02b619850e5d978Adam Langley  if (src->ecdsa_meth) {
20521c70997ab3c62b97960fd66f02b619850e5d978Adam Langley      METHOD_unref(dest->ecdsa_meth);
20621c70997ab3c62b97960fd66f02b619850e5d978Adam Langley      dest->ecdsa_meth = src->ecdsa_meth;
20721c70997ab3c62b97960fd66f02b619850e5d978Adam Langley      METHOD_ref(dest->ecdsa_meth);
20821c70997ab3c62b97960fd66f02b619850e5d978Adam Langley  }
209e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  CRYPTO_free_ex_data(&g_ex_data_class, dest, &dest->ex_data);
210e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (!CRYPTO_dup_ex_data(&g_ex_data_class, &dest->ex_data,
211d9e397b599b13d642138480a28c14db7a136bf0Adam Langley                          &src->ex_data)) {
212d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return NULL;
213d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
214d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
215d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  /* copy the rest */
216d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  dest->enc_flag = src->enc_flag;
217d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  dest->conv_form = src->conv_form;
218d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  dest->version = src->version;
219d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  dest->flags = src->flags;
220d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
221d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return dest;
222d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
223d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
224d9e397b599b13d642138480a28c14db7a136bf0Adam LangleyEC_KEY *EC_KEY_dup(const EC_KEY *ec_key) {
225d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  EC_KEY *ret = EC_KEY_new();
226d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (ret == NULL) {
227d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return NULL;
228d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
229d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (EC_KEY_copy(ret, ec_key) == NULL) {
230d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    EC_KEY_free(ret);
231d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return NULL;
232d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
233d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return ret;
234d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
235d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
236d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint EC_KEY_up_ref(EC_KEY *r) {
23753b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley  CRYPTO_refcount_inc(&r->references);
23853b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley  return 1;
239d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
240d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
241d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint EC_KEY_is_opaque(const EC_KEY *key) {
242d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return key->ecdsa_meth && (key->ecdsa_meth->flags & ECDSA_FLAG_OPAQUE);
243d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
244d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
245d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyconst EC_GROUP *EC_KEY_get0_group(const EC_KEY *key) { return key->group; }
246d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
247d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group) {
248e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  EC_GROUP_free(key->group);
249d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  /* TODO(fork): duplicating the group seems wasteful but see
250d9e397b599b13d642138480a28c14db7a136bf0Adam Langley   * |EC_KEY_set_conv_form|. */
251d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  key->group = EC_GROUP_dup(group);
252d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return (key->group == NULL) ? 0 : 1;
253d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
254d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
255d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyconst BIGNUM *EC_KEY_get0_private_key(const EC_KEY *key) {
256d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return key->priv_key;
257d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
258d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
259d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *priv_key) {
260e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  BN_clear_free(key->priv_key);
261d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  key->priv_key = BN_dup(priv_key);
262d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return (key->priv_key == NULL) ? 0 : 1;
263d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
264d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
265d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyconst EC_POINT *EC_KEY_get0_public_key(const EC_KEY *key) {
266d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return key->pub_key;
267d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
268d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
269d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub_key) {
270e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  EC_POINT_free(key->pub_key);
271d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  key->pub_key = EC_POINT_dup(pub_key, key->group);
272d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return (key->pub_key == NULL) ? 0 : 1;
273d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
274d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
275d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyunsigned int EC_KEY_get_enc_flags(const EC_KEY *key) { return key->enc_flag; }
276d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
277d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyvoid EC_KEY_set_enc_flags(EC_KEY *key, unsigned int flags) {
278d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  key->enc_flag = flags;
279d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
280d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
281d9e397b599b13d642138480a28c14db7a136bf0Adam Langleypoint_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *key) {
282d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return key->conv_form;
283d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
284d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
285d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyvoid EC_KEY_set_conv_form(EC_KEY *key, point_conversion_form_t cform) {
286d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  key->conv_form = cform;
287d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
288d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
289d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint EC_KEY_precompute_mult(EC_KEY *key, BN_CTX *ctx) {
290d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (key->group == NULL) {
291d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return 0;
292d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
293d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return EC_GROUP_precompute_mult(key->group, ctx);
294d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
295d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
296d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint EC_KEY_check_key(const EC_KEY *eckey) {
297d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  int ok = 0;
298d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  BN_CTX *ctx = NULL;
299d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  const BIGNUM *order = NULL;
300d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  EC_POINT *point = NULL;
301d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
302d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!eckey || !eckey->group || !eckey->pub_key) {
303d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    OPENSSL_PUT_ERROR(EC, EC_KEY_check_key, ERR_R_PASSED_NULL_PARAMETER);
304d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return 0;
305d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
306d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
307d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (EC_POINT_is_at_infinity(eckey->group, eckey->pub_key)) {
308d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    OPENSSL_PUT_ERROR(EC, EC_KEY_check_key, EC_R_POINT_AT_INFINITY);
309d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
310d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
311d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
312d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  ctx = BN_CTX_new();
313d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  point = EC_POINT_new(eckey->group);
314d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
315d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (ctx == NULL ||
316d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      point == NULL) {
317d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
318d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
319d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
320d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  /* testing whether the pub_key is on the elliptic curve */
321d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!EC_POINT_is_on_curve(eckey->group, eckey->pub_key, ctx)) {
322d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    OPENSSL_PUT_ERROR(EC, EC_KEY_check_key, EC_R_POINT_IS_NOT_ON_CURVE);
323d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
324d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
325d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  /* testing whether pub_key * order is the point at infinity */
326d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  /* TODO(fork): can this be skipped if the cofactor is one or if we're about
327d9e397b599b13d642138480a28c14db7a136bf0Adam Langley   * to check the private key, below? */
328d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  order = &eckey->group->order;
329d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (BN_is_zero(order)) {
330d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    OPENSSL_PUT_ERROR(EC, EC_KEY_check_key, EC_R_INVALID_GROUP_ORDER);
331d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
332d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
333d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!EC_POINT_mul(eckey->group, point, NULL, eckey->pub_key, order, ctx)) {
334d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    OPENSSL_PUT_ERROR(EC, EC_KEY_check_key, ERR_R_EC_LIB);
335d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
336d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
337d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!EC_POINT_is_at_infinity(eckey->group, point)) {
338d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    OPENSSL_PUT_ERROR(EC, EC_KEY_check_key, EC_R_WRONG_ORDER);
339d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
340d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
341d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  /* in case the priv_key is present :
342d9e397b599b13d642138480a28c14db7a136bf0Adam Langley   * check if generator * priv_key == pub_key
343d9e397b599b13d642138480a28c14db7a136bf0Adam Langley   */
344d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (eckey->priv_key) {
345d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (BN_cmp(eckey->priv_key, order) >= 0) {
346d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      OPENSSL_PUT_ERROR(EC, EC_KEY_check_key, EC_R_WRONG_ORDER);
347d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      goto err;
348d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
349d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (!EC_POINT_mul(eckey->group, point, eckey->priv_key, NULL, NULL, ctx)) {
350d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      OPENSSL_PUT_ERROR(EC, EC_KEY_check_key, ERR_R_EC_LIB);
351d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      goto err;
352d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
353d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (EC_POINT_cmp(eckey->group, point, eckey->pub_key, ctx) != 0) {
354d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      OPENSSL_PUT_ERROR(EC, EC_KEY_check_key, EC_R_INVALID_PRIVATE_KEY);
355d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      goto err;
356d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
357d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
358d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  ok = 1;
359d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
360d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyerr:
361e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  BN_CTX_free(ctx);
362e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  EC_POINT_free(point);
363d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return ok;
364d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
365d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
366d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x,
367d9e397b599b13d642138480a28c14db7a136bf0Adam Langley                                             BIGNUM *y) {
368d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  BN_CTX *ctx = NULL;
369d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  BIGNUM *tx, *ty;
370d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  EC_POINT *point = NULL;
371d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  int ok = 0;
372d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
373d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!key || !key->group || !x || !y) {
374d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    OPENSSL_PUT_ERROR(EC, EC_KEY_set_public_key_affine_coordinates,
375d9e397b599b13d642138480a28c14db7a136bf0Adam Langley                      ERR_R_PASSED_NULL_PARAMETER);
376d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return 0;
377d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
378d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  ctx = BN_CTX_new();
379d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  point = EC_POINT_new(key->group);
380d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
381d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (ctx == NULL ||
382d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      point == NULL) {
383d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
384d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
385d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
386d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  tx = BN_CTX_get(ctx);
387d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  ty = BN_CTX_get(ctx);
388d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
389d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!EC_POINT_set_affine_coordinates_GFp(key->group, point, x, y, ctx) ||
390d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      !EC_POINT_get_affine_coordinates_GFp(key->group, point, tx, ty, ctx)) {
391d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
392d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
393d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
394d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  /* Check if retrieved coordinates match originals: if not values
395d9e397b599b13d642138480a28c14db7a136bf0Adam Langley   * are out of range. */
396d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (BN_cmp(x, tx) || BN_cmp(y, ty)) {
397d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    OPENSSL_PUT_ERROR(EC, EC_KEY_set_public_key_affine_coordinates,
398d9e397b599b13d642138480a28c14db7a136bf0Adam Langley                      EC_R_COORDINATES_OUT_OF_RANGE);
399d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
400d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
401d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
402d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!EC_KEY_set_public_key(key, point)) {
403d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
404d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
405d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
406d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (EC_KEY_check_key(key) == 0) {
407d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
408d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
409d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
410d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  ok = 1;
411d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
412d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyerr:
413e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  BN_CTX_free(ctx);
414e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  EC_POINT_free(point);
415d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return ok;
416d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
417d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
418d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint EC_KEY_generate_key(EC_KEY *eckey) {
419d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  int ok = 0;
420d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  BN_CTX *ctx = NULL;
421d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  BIGNUM *priv_key = NULL, *order = NULL;
422d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  EC_POINT *pub_key = NULL;
423d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
424d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!eckey || !eckey->group) {
425d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    OPENSSL_PUT_ERROR(EC, EC_KEY_generate_key, ERR_R_PASSED_NULL_PARAMETER);
426d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return 0;
427d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
428d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
429d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  order = BN_new();
430d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  ctx = BN_CTX_new();
431d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
432d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (order == NULL ||
433d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      ctx == NULL) {
434d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
435d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
436d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
437d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (eckey->priv_key == NULL) {
438d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    priv_key = BN_new();
439d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (priv_key == NULL) {
440d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      goto err;
441d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
442d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  } else {
443d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    priv_key = eckey->priv_key;
444d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
445d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
446d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!EC_GROUP_get_order(eckey->group, order, ctx)) {
447d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
448d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
449d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
450d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  do {
451d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (!BN_rand_range(priv_key, order)) {
452d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      goto err;
453d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
454d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  } while (BN_is_zero(priv_key));
455d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
456d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (eckey->pub_key == NULL) {
457d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    pub_key = EC_POINT_new(eckey->group);
458d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (pub_key == NULL) {
459d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      goto err;
460d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
461d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  } else {
462d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    pub_key = eckey->pub_key;
463d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
464d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
465d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!EC_POINT_mul(eckey->group, pub_key, priv_key, NULL, NULL, ctx)) {
466d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    goto err;
467d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
468d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
469d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  eckey->priv_key = priv_key;
470d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  eckey->pub_key = pub_key;
471d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
472d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  ok = 1;
473d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
474d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyerr:
475e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  BN_free(order);
476e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (eckey->pub_key == NULL) {
477d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    EC_POINT_free(pub_key);
478e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
479e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (eckey->priv_key == NULL) {
480d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    BN_free(priv_key);
481e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
482e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  BN_CTX_free(ctx);
483d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return ok;
484d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
485d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
486d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint EC_KEY_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
487d9e397b599b13d642138480a28c14db7a136bf0Adam Langley                            CRYPTO_EX_dup *dup_func,
488d9e397b599b13d642138480a28c14db7a136bf0Adam Langley                            CRYPTO_EX_free *free_func) {
489e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  int index;
490e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp, new_func,
491e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley                               dup_func, free_func)) {
492e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return -1;
493e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
494e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  return index;
495d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
496d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
497d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint EC_KEY_set_ex_data(EC_KEY *d, int idx, void *arg) {
498d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return CRYPTO_set_ex_data(&d->ex_data, idx, arg);
499d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
500d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
501d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyvoid *EC_KEY_get_ex_data(const EC_KEY *d, int idx) {
502d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return CRYPTO_get_ex_data(&d->ex_data, idx);
503d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
504f7e890d94bfb2ecad87621eed301e1897b5a6aefAdam Langley
505f7e890d94bfb2ecad87621eed301e1897b5a6aefAdam Langleyvoid EC_KEY_set_asn1_flag(EC_KEY *key, int flag) {}
506