172c33676SMaxim Ag /* $OpenBSD: ech_lib.c,v 1.14 2018/04/14 07:09:21 tb Exp $ */
2f5b1c8a1SJohn Marino /* ====================================================================
3f5b1c8a1SJohn Marino * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
4f5b1c8a1SJohn Marino *
5f5b1c8a1SJohn Marino * The Elliptic Curve Public-Key Crypto Library (ECC Code) included
6f5b1c8a1SJohn Marino * herein is developed by SUN MICROSYSTEMS, INC., and is contributed
7f5b1c8a1SJohn Marino * to the OpenSSL project.
8f5b1c8a1SJohn Marino *
9f5b1c8a1SJohn Marino * The ECC Code is licensed pursuant to the OpenSSL open source
10f5b1c8a1SJohn Marino * license provided below.
11f5b1c8a1SJohn Marino *
12f5b1c8a1SJohn Marino * The ECDH software is originally written by Douglas Stebila of
13f5b1c8a1SJohn Marino * Sun Microsystems Laboratories.
14f5b1c8a1SJohn Marino *
15f5b1c8a1SJohn Marino */
16f5b1c8a1SJohn Marino /* ====================================================================
17f5b1c8a1SJohn Marino * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved.
18f5b1c8a1SJohn Marino *
19f5b1c8a1SJohn Marino * Redistribution and use in source and binary forms, with or without
20f5b1c8a1SJohn Marino * modification, are permitted provided that the following conditions
21f5b1c8a1SJohn Marino * are met:
22f5b1c8a1SJohn Marino *
23f5b1c8a1SJohn Marino * 1. Redistributions of source code must retain the above copyright
24f5b1c8a1SJohn Marino * notice, this list of conditions and the following disclaimer.
25f5b1c8a1SJohn Marino *
26f5b1c8a1SJohn Marino * 2. Redistributions in binary form must reproduce the above copyright
27f5b1c8a1SJohn Marino * notice, this list of conditions and the following disclaimer in
28f5b1c8a1SJohn Marino * the documentation and/or other materials provided with the
29f5b1c8a1SJohn Marino * distribution.
30f5b1c8a1SJohn Marino *
31f5b1c8a1SJohn Marino * 3. All advertising materials mentioning features or use of this
32f5b1c8a1SJohn Marino * software must display the following acknowledgment:
33f5b1c8a1SJohn Marino * "This product includes software developed by the OpenSSL Project
34f5b1c8a1SJohn Marino * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
35f5b1c8a1SJohn Marino *
36f5b1c8a1SJohn Marino * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
37f5b1c8a1SJohn Marino * endorse or promote products derived from this software without
38f5b1c8a1SJohn Marino * prior written permission. For written permission, please contact
39f5b1c8a1SJohn Marino * openssl-core@OpenSSL.org.
40f5b1c8a1SJohn Marino *
41f5b1c8a1SJohn Marino * 5. Products derived from this software may not be called "OpenSSL"
42f5b1c8a1SJohn Marino * nor may "OpenSSL" appear in their names without prior written
43f5b1c8a1SJohn Marino * permission of the OpenSSL Project.
44f5b1c8a1SJohn Marino *
45f5b1c8a1SJohn Marino * 6. Redistributions of any form whatsoever must retain the following
46f5b1c8a1SJohn Marino * acknowledgment:
47f5b1c8a1SJohn Marino * "This product includes software developed by the OpenSSL Project
48f5b1c8a1SJohn Marino * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
49f5b1c8a1SJohn Marino *
50f5b1c8a1SJohn Marino * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
51f5b1c8a1SJohn Marino * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52f5b1c8a1SJohn Marino * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
53f5b1c8a1SJohn Marino * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
54f5b1c8a1SJohn Marino * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
55f5b1c8a1SJohn Marino * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
56f5b1c8a1SJohn Marino * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
57f5b1c8a1SJohn Marino * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58f5b1c8a1SJohn Marino * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
59f5b1c8a1SJohn Marino * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
60f5b1c8a1SJohn Marino * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
61f5b1c8a1SJohn Marino * OF THE POSSIBILITY OF SUCH DAMAGE.
62f5b1c8a1SJohn Marino * ====================================================================
63f5b1c8a1SJohn Marino *
64f5b1c8a1SJohn Marino * This product includes cryptographic software written by Eric Young
65f5b1c8a1SJohn Marino * (eay@cryptsoft.com). This product includes software written by Tim
66f5b1c8a1SJohn Marino * Hudson (tjh@cryptsoft.com).
67f5b1c8a1SJohn Marino *
68f5b1c8a1SJohn Marino */
69f5b1c8a1SJohn Marino
70f5b1c8a1SJohn Marino #include <string.h>
71f5b1c8a1SJohn Marino
72f5b1c8a1SJohn Marino #include <openssl/opensslconf.h>
73f5b1c8a1SJohn Marino
74f5b1c8a1SJohn Marino #include "ech_locl.h"
75f5b1c8a1SJohn Marino #ifndef OPENSSL_NO_ENGINE
76f5b1c8a1SJohn Marino #include <openssl/engine.h>
77f5b1c8a1SJohn Marino #endif
78f5b1c8a1SJohn Marino #include <openssl/err.h>
79f5b1c8a1SJohn Marino
80f5b1c8a1SJohn Marino static const ECDH_METHOD *default_ECDH_method = NULL;
81f5b1c8a1SJohn Marino
82f5b1c8a1SJohn Marino static void *ecdh_data_new(void);
83f5b1c8a1SJohn Marino static void *ecdh_data_dup(void *);
84f5b1c8a1SJohn Marino static void ecdh_data_free(void *);
85f5b1c8a1SJohn Marino
86f5b1c8a1SJohn Marino void
ECDH_set_default_method(const ECDH_METHOD * meth)87f5b1c8a1SJohn Marino ECDH_set_default_method(const ECDH_METHOD *meth)
88f5b1c8a1SJohn Marino {
89f5b1c8a1SJohn Marino default_ECDH_method = meth;
90f5b1c8a1SJohn Marino }
91f5b1c8a1SJohn Marino
92f5b1c8a1SJohn Marino const ECDH_METHOD *
ECDH_get_default_method(void)93f5b1c8a1SJohn Marino ECDH_get_default_method(void)
94f5b1c8a1SJohn Marino {
95f5b1c8a1SJohn Marino if (!default_ECDH_method) {
96f5b1c8a1SJohn Marino default_ECDH_method = ECDH_OpenSSL();
97f5b1c8a1SJohn Marino }
98f5b1c8a1SJohn Marino return default_ECDH_method;
99f5b1c8a1SJohn Marino }
100f5b1c8a1SJohn Marino
101f5b1c8a1SJohn Marino int
ECDH_set_method(EC_KEY * eckey,const ECDH_METHOD * meth)102f5b1c8a1SJohn Marino ECDH_set_method(EC_KEY *eckey, const ECDH_METHOD *meth)
103f5b1c8a1SJohn Marino {
104f5b1c8a1SJohn Marino ECDH_DATA *ecdh;
105f5b1c8a1SJohn Marino
106f5b1c8a1SJohn Marino ecdh = ecdh_check(eckey);
107f5b1c8a1SJohn Marino
108f5b1c8a1SJohn Marino if (ecdh == NULL)
109f5b1c8a1SJohn Marino return 0;
110f5b1c8a1SJohn Marino
111f5b1c8a1SJohn Marino #ifndef OPENSSL_NO_ENGINE
112f5b1c8a1SJohn Marino ENGINE_finish(ecdh->engine);
113f5b1c8a1SJohn Marino ecdh->engine = NULL;
114f5b1c8a1SJohn Marino #endif
115f5b1c8a1SJohn Marino ecdh->meth = meth;
116f5b1c8a1SJohn Marino return 1;
117f5b1c8a1SJohn Marino }
118f5b1c8a1SJohn Marino
119f5b1c8a1SJohn Marino static ECDH_DATA *
ECDH_DATA_new_method(ENGINE * engine)120f5b1c8a1SJohn Marino ECDH_DATA_new_method(ENGINE *engine)
121f5b1c8a1SJohn Marino {
122f5b1c8a1SJohn Marino ECDH_DATA *ret;
123f5b1c8a1SJohn Marino
124f5b1c8a1SJohn Marino ret = malloc(sizeof(ECDH_DATA));
125f5b1c8a1SJohn Marino if (ret == NULL) {
12672c33676SMaxim Ag ECDHerror(ERR_R_MALLOC_FAILURE);
127f5b1c8a1SJohn Marino return (NULL);
128f5b1c8a1SJohn Marino }
129f5b1c8a1SJohn Marino
130f5b1c8a1SJohn Marino ret->init = NULL;
131f5b1c8a1SJohn Marino
132f5b1c8a1SJohn Marino ret->meth = ECDH_get_default_method();
133f5b1c8a1SJohn Marino ret->engine = engine;
134f5b1c8a1SJohn Marino #ifndef OPENSSL_NO_ENGINE
135f5b1c8a1SJohn Marino if (!ret->engine)
136f5b1c8a1SJohn Marino ret->engine = ENGINE_get_default_ECDH();
137f5b1c8a1SJohn Marino if (ret->engine) {
138f5b1c8a1SJohn Marino ret->meth = ENGINE_get_ECDH(ret->engine);
13972c33676SMaxim Ag if (ret->meth == NULL) {
14072c33676SMaxim Ag ECDHerror(ERR_R_ENGINE_LIB);
141f5b1c8a1SJohn Marino ENGINE_finish(ret->engine);
142f5b1c8a1SJohn Marino free(ret);
143f5b1c8a1SJohn Marino return NULL;
144f5b1c8a1SJohn Marino }
145f5b1c8a1SJohn Marino }
146f5b1c8a1SJohn Marino #endif
147f5b1c8a1SJohn Marino
148f5b1c8a1SJohn Marino ret->flags = ret->meth->flags;
149f5b1c8a1SJohn Marino CRYPTO_new_ex_data(CRYPTO_EX_INDEX_ECDH, ret, &ret->ex_data);
150f5b1c8a1SJohn Marino return (ret);
151f5b1c8a1SJohn Marino }
152f5b1c8a1SJohn Marino
153f5b1c8a1SJohn Marino static void *
ecdh_data_new(void)154f5b1c8a1SJohn Marino ecdh_data_new(void)
155f5b1c8a1SJohn Marino {
156f5b1c8a1SJohn Marino return (void *)ECDH_DATA_new_method(NULL);
157f5b1c8a1SJohn Marino }
158f5b1c8a1SJohn Marino
159f5b1c8a1SJohn Marino static void *
ecdh_data_dup(void * data)160f5b1c8a1SJohn Marino ecdh_data_dup(void *data)
161f5b1c8a1SJohn Marino {
162f5b1c8a1SJohn Marino ECDH_DATA *r = (ECDH_DATA *)data;
163f5b1c8a1SJohn Marino
164f5b1c8a1SJohn Marino /* XXX: dummy operation */
165f5b1c8a1SJohn Marino if (r == NULL)
166f5b1c8a1SJohn Marino return NULL;
167f5b1c8a1SJohn Marino
168f5b1c8a1SJohn Marino return (void *)ecdh_data_new();
169f5b1c8a1SJohn Marino }
170f5b1c8a1SJohn Marino
171f5b1c8a1SJohn Marino void
ecdh_data_free(void * data)172f5b1c8a1SJohn Marino ecdh_data_free(void *data)
173f5b1c8a1SJohn Marino {
174f5b1c8a1SJohn Marino ECDH_DATA *r = (ECDH_DATA *)data;
175f5b1c8a1SJohn Marino
176f5b1c8a1SJohn Marino #ifndef OPENSSL_NO_ENGINE
177f5b1c8a1SJohn Marino ENGINE_finish(r->engine);
178f5b1c8a1SJohn Marino #endif
179f5b1c8a1SJohn Marino
180f5b1c8a1SJohn Marino CRYPTO_free_ex_data(CRYPTO_EX_INDEX_ECDH, r, &r->ex_data);
181f5b1c8a1SJohn Marino
18272c33676SMaxim Ag freezero(r, sizeof(ECDH_DATA));
183f5b1c8a1SJohn Marino }
184f5b1c8a1SJohn Marino
185f5b1c8a1SJohn Marino ECDH_DATA *
ecdh_check(EC_KEY * key)186f5b1c8a1SJohn Marino ecdh_check(EC_KEY *key)
187f5b1c8a1SJohn Marino {
188f5b1c8a1SJohn Marino ECDH_DATA *ecdh_data;
189f5b1c8a1SJohn Marino
190f5b1c8a1SJohn Marino void *data = EC_KEY_get_key_method_data(key, ecdh_data_dup,
191f5b1c8a1SJohn Marino ecdh_data_free, ecdh_data_free);
192f5b1c8a1SJohn Marino if (data == NULL) {
193f5b1c8a1SJohn Marino ecdh_data = (ECDH_DATA *)ecdh_data_new();
194f5b1c8a1SJohn Marino if (ecdh_data == NULL)
195f5b1c8a1SJohn Marino return NULL;
196f5b1c8a1SJohn Marino data = EC_KEY_insert_key_method_data(key, (void *)ecdh_data,
197f5b1c8a1SJohn Marino ecdh_data_dup, ecdh_data_free, ecdh_data_free);
198f5b1c8a1SJohn Marino if (data != NULL) {
199f5b1c8a1SJohn Marino /* Another thread raced us to install the key_method
200f5b1c8a1SJohn Marino * data and won. */
201f5b1c8a1SJohn Marino ecdh_data_free(ecdh_data);
202f5b1c8a1SJohn Marino ecdh_data = (ECDH_DATA *)data;
203f5b1c8a1SJohn Marino }
204f5b1c8a1SJohn Marino } else
205f5b1c8a1SJohn Marino ecdh_data = (ECDH_DATA *)data;
206f5b1c8a1SJohn Marino
207f5b1c8a1SJohn Marino return ecdh_data;
208f5b1c8a1SJohn Marino }
209f5b1c8a1SJohn Marino
210f5b1c8a1SJohn Marino int
ECDH_get_ex_new_index(long argl,void * argp,CRYPTO_EX_new * new_func,CRYPTO_EX_dup * dup_func,CRYPTO_EX_free * free_func)211f5b1c8a1SJohn Marino ECDH_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
212f5b1c8a1SJohn Marino CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
213f5b1c8a1SJohn Marino {
214f5b1c8a1SJohn Marino return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_ECDH, argl, argp,
215f5b1c8a1SJohn Marino new_func, dup_func, free_func);
216f5b1c8a1SJohn Marino }
217f5b1c8a1SJohn Marino
218f5b1c8a1SJohn Marino int
ECDH_set_ex_data(EC_KEY * d,int idx,void * arg)219f5b1c8a1SJohn Marino ECDH_set_ex_data(EC_KEY *d, int idx, void *arg)
220f5b1c8a1SJohn Marino {
221f5b1c8a1SJohn Marino ECDH_DATA *ecdh;
222f5b1c8a1SJohn Marino ecdh = ecdh_check(d);
223f5b1c8a1SJohn Marino if (ecdh == NULL)
224f5b1c8a1SJohn Marino return 0;
225f5b1c8a1SJohn Marino return (CRYPTO_set_ex_data(&ecdh->ex_data, idx, arg));
226f5b1c8a1SJohn Marino }
227f5b1c8a1SJohn Marino
228f5b1c8a1SJohn Marino void *
ECDH_get_ex_data(EC_KEY * d,int idx)229f5b1c8a1SJohn Marino ECDH_get_ex_data(EC_KEY *d, int idx)
230f5b1c8a1SJohn Marino {
231f5b1c8a1SJohn Marino ECDH_DATA *ecdh;
232f5b1c8a1SJohn Marino ecdh = ecdh_check(d);
233f5b1c8a1SJohn Marino if (ecdh == NULL)
234f5b1c8a1SJohn Marino return NULL;
235f5b1c8a1SJohn Marino return (CRYPTO_get_ex_data(&ecdh->ex_data, idx));
236f5b1c8a1SJohn Marino }
237f5b1c8a1SJohn Marino
238f5b1c8a1SJohn Marino int
ECDH_size(const EC_KEY * d)239f5b1c8a1SJohn Marino ECDH_size(const EC_KEY *d)
240f5b1c8a1SJohn Marino {
241f5b1c8a1SJohn Marino return ((EC_GROUP_get_degree(EC_KEY_get0_group(d)) + 7) / 8);
242f5b1c8a1SJohn Marino }
243