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