xref: /minix3/crypto/external/bsd/heimdal/dist/lib/hcrypto/dh.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /*	$NetBSD: dh.c,v 1.1.1.2 2014/04/24 12:45:30 pettai Exp $	*/
2ebfedea0SLionel Sambuc 
3ebfedea0SLionel Sambuc /*
4ebfedea0SLionel Sambuc  * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan
5ebfedea0SLionel Sambuc  * (Royal Institute of Technology, Stockholm, Sweden).
6ebfedea0SLionel Sambuc  * All rights reserved.
7ebfedea0SLionel Sambuc  *
8ebfedea0SLionel Sambuc  * Redistribution and use in source and binary forms, with or without
9ebfedea0SLionel Sambuc  * modification, are permitted provided that the following conditions
10ebfedea0SLionel Sambuc  * are met:
11ebfedea0SLionel Sambuc  *
12ebfedea0SLionel Sambuc  * 1. Redistributions of source code must retain the above copyright
13ebfedea0SLionel Sambuc  *    notice, this list of conditions and the following disclaimer.
14ebfedea0SLionel Sambuc  *
15ebfedea0SLionel Sambuc  * 2. Redistributions in binary form must reproduce the above copyright
16ebfedea0SLionel Sambuc  *    notice, this list of conditions and the following disclaimer in the
17ebfedea0SLionel Sambuc  *    documentation and/or other materials provided with the distribution.
18ebfedea0SLionel Sambuc  *
19ebfedea0SLionel Sambuc  * 3. Neither the name of the Institute nor the names of its contributors
20ebfedea0SLionel Sambuc  *    may be used to endorse or promote products derived from this software
21ebfedea0SLionel Sambuc  *    without specific prior written permission.
22ebfedea0SLionel Sambuc  *
23ebfedea0SLionel Sambuc  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24ebfedea0SLionel Sambuc  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25ebfedea0SLionel Sambuc  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26ebfedea0SLionel Sambuc  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27ebfedea0SLionel Sambuc  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28ebfedea0SLionel Sambuc  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29ebfedea0SLionel Sambuc  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30ebfedea0SLionel Sambuc  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31ebfedea0SLionel Sambuc  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32ebfedea0SLionel Sambuc  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33ebfedea0SLionel Sambuc  * SUCH DAMAGE.
34ebfedea0SLionel Sambuc  */
35ebfedea0SLionel Sambuc 
36ebfedea0SLionel Sambuc #ifdef HAVE_CONFIG_H
37ebfedea0SLionel Sambuc #include <config.h>
38ebfedea0SLionel Sambuc #endif
39ebfedea0SLionel Sambuc 
40ebfedea0SLionel Sambuc #include <stdio.h>
41ebfedea0SLionel Sambuc #include <stdlib.h>
42ebfedea0SLionel Sambuc #include <krb5/krb5-types.h>
43ebfedea0SLionel Sambuc #include <krb5/rfc2459_asn1.h>
44ebfedea0SLionel Sambuc 
45ebfedea0SLionel Sambuc #include <dh.h>
46ebfedea0SLionel Sambuc 
47ebfedea0SLionel Sambuc #include <krb5/roken.h>
48ebfedea0SLionel Sambuc 
49ebfedea0SLionel Sambuc /**
50ebfedea0SLionel Sambuc  * @page page_dh DH - Diffie-Hellman key exchange
51ebfedea0SLionel Sambuc  *
52ebfedea0SLionel Sambuc  * Diffie-Hellman key exchange is a protocol that allows two parties
53ebfedea0SLionel Sambuc  * to establish a shared secret key.
54ebfedea0SLionel Sambuc  *
55ebfedea0SLionel Sambuc  * Include and example how to use DH_new() and friends here.
56ebfedea0SLionel Sambuc  *
57ebfedea0SLionel Sambuc  * See the library functions here: @ref hcrypto_dh
58ebfedea0SLionel Sambuc  */
59ebfedea0SLionel Sambuc 
60ebfedea0SLionel Sambuc /**
61ebfedea0SLionel Sambuc  * Create a new DH object using DH_new_method(NULL), see DH_new_method().
62ebfedea0SLionel Sambuc  *
63ebfedea0SLionel Sambuc  * @return a newly allocated DH object.
64ebfedea0SLionel Sambuc  *
65ebfedea0SLionel Sambuc  * @ingroup hcrypto_dh
66ebfedea0SLionel Sambuc  */
67ebfedea0SLionel Sambuc 
68ebfedea0SLionel Sambuc DH *
DH_new(void)69ebfedea0SLionel Sambuc DH_new(void)
70ebfedea0SLionel Sambuc {
71ebfedea0SLionel Sambuc     return DH_new_method(NULL);
72ebfedea0SLionel Sambuc }
73ebfedea0SLionel Sambuc 
74ebfedea0SLionel Sambuc /**
75ebfedea0SLionel Sambuc  * Create a new DH object from the given engine, if the NULL is used,
76ebfedea0SLionel Sambuc  * the default engine is used. Free the DH object with DH_free().
77ebfedea0SLionel Sambuc  *
78ebfedea0SLionel Sambuc  * @param engine The engine to use to allocate the DH object.
79ebfedea0SLionel Sambuc  *
80ebfedea0SLionel Sambuc  * @return a newly allocated DH object.
81ebfedea0SLionel Sambuc  *
82ebfedea0SLionel Sambuc  * @ingroup hcrypto_dh
83ebfedea0SLionel Sambuc  */
84ebfedea0SLionel Sambuc 
85ebfedea0SLionel Sambuc DH *
DH_new_method(ENGINE * engine)86ebfedea0SLionel Sambuc DH_new_method(ENGINE *engine)
87ebfedea0SLionel Sambuc {
88ebfedea0SLionel Sambuc     DH *dh;
89ebfedea0SLionel Sambuc 
90ebfedea0SLionel Sambuc     dh = calloc(1, sizeof(*dh));
91ebfedea0SLionel Sambuc     if (dh == NULL)
92ebfedea0SLionel Sambuc 	return NULL;
93ebfedea0SLionel Sambuc 
94ebfedea0SLionel Sambuc     dh->references = 1;
95ebfedea0SLionel Sambuc 
96ebfedea0SLionel Sambuc     if (engine) {
97ebfedea0SLionel Sambuc 	ENGINE_up_ref(engine);
98ebfedea0SLionel Sambuc 	dh->engine = engine;
99ebfedea0SLionel Sambuc     } else {
100ebfedea0SLionel Sambuc 	dh->engine = ENGINE_get_default_DH();
101ebfedea0SLionel Sambuc     }
102ebfedea0SLionel Sambuc 
103ebfedea0SLionel Sambuc     if (dh->engine) {
104ebfedea0SLionel Sambuc 	dh->meth = ENGINE_get_DH(dh->engine);
105ebfedea0SLionel Sambuc 	if (dh->meth == NULL) {
106ebfedea0SLionel Sambuc 	    ENGINE_finish(engine);
107ebfedea0SLionel Sambuc 	    free(dh);
108ebfedea0SLionel Sambuc 	    return 0;
109ebfedea0SLionel Sambuc 	}
110ebfedea0SLionel Sambuc     }
111ebfedea0SLionel Sambuc 
112ebfedea0SLionel Sambuc     if (dh->meth == NULL)
113ebfedea0SLionel Sambuc 	dh->meth = DH_get_default_method();
114ebfedea0SLionel Sambuc 
115ebfedea0SLionel Sambuc     (*dh->meth->init)(dh);
116ebfedea0SLionel Sambuc 
117ebfedea0SLionel Sambuc     return dh;
118ebfedea0SLionel Sambuc }
119ebfedea0SLionel Sambuc 
120ebfedea0SLionel Sambuc /**
121ebfedea0SLionel Sambuc  * Free a DH object and release related resources, like ENGINE, that
122ebfedea0SLionel Sambuc  * the object was using.
123ebfedea0SLionel Sambuc  *
124ebfedea0SLionel Sambuc  * @param dh object to be freed.
125ebfedea0SLionel Sambuc  *
126ebfedea0SLionel Sambuc  * @ingroup hcrypto_dh
127ebfedea0SLionel Sambuc  */
128ebfedea0SLionel Sambuc 
129ebfedea0SLionel Sambuc void
DH_free(DH * dh)130ebfedea0SLionel Sambuc DH_free(DH *dh)
131ebfedea0SLionel Sambuc {
132ebfedea0SLionel Sambuc     if (dh->references <= 0)
133ebfedea0SLionel Sambuc 	abort();
134ebfedea0SLionel Sambuc 
135ebfedea0SLionel Sambuc     if (--dh->references > 0)
136ebfedea0SLionel Sambuc 	return;
137ebfedea0SLionel Sambuc 
138ebfedea0SLionel Sambuc     (*dh->meth->finish)(dh);
139ebfedea0SLionel Sambuc 
140ebfedea0SLionel Sambuc     if (dh->engine)
141ebfedea0SLionel Sambuc 	ENGINE_finish(dh->engine);
142ebfedea0SLionel Sambuc 
143ebfedea0SLionel Sambuc #define free_if(f) if (f) { BN_free(f); }
144ebfedea0SLionel Sambuc     free_if(dh->p);
145ebfedea0SLionel Sambuc     free_if(dh->g);
146ebfedea0SLionel Sambuc     free_if(dh->pub_key);
147ebfedea0SLionel Sambuc     free_if(dh->priv_key);
148ebfedea0SLionel Sambuc     free_if(dh->q);
149ebfedea0SLionel Sambuc     free_if(dh->j);
150ebfedea0SLionel Sambuc     free_if(dh->counter);
151ebfedea0SLionel Sambuc #undef free_if
152ebfedea0SLionel Sambuc 
153ebfedea0SLionel Sambuc     memset(dh, 0, sizeof(*dh));
154ebfedea0SLionel Sambuc     free(dh);
155ebfedea0SLionel Sambuc }
156ebfedea0SLionel Sambuc 
157ebfedea0SLionel Sambuc /**
158ebfedea0SLionel Sambuc  * Add a reference to the DH object. The object should be free with
159ebfedea0SLionel Sambuc  * DH_free() to drop the reference.
160ebfedea0SLionel Sambuc  *
161ebfedea0SLionel Sambuc  * @param dh the object to increase the reference count too.
162ebfedea0SLionel Sambuc  *
163ebfedea0SLionel Sambuc  * @return the updated reference count, can't safely be used except
164ebfedea0SLionel Sambuc  * for debug printing.
165ebfedea0SLionel Sambuc  *
166ebfedea0SLionel Sambuc  * @ingroup hcrypto_dh
167ebfedea0SLionel Sambuc  */
168ebfedea0SLionel Sambuc 
169ebfedea0SLionel Sambuc int
DH_up_ref(DH * dh)170ebfedea0SLionel Sambuc DH_up_ref(DH *dh)
171ebfedea0SLionel Sambuc {
172ebfedea0SLionel Sambuc     return ++dh->references;
173ebfedea0SLionel Sambuc }
174ebfedea0SLionel Sambuc 
175ebfedea0SLionel Sambuc /**
176ebfedea0SLionel Sambuc  * The maximum output size of the DH_compute_key() function.
177ebfedea0SLionel Sambuc  *
178ebfedea0SLionel Sambuc  * @param dh The DH object to get the size from.
179ebfedea0SLionel Sambuc  *
180ebfedea0SLionel Sambuc  * @return the maximum size in bytes of the out data.
181ebfedea0SLionel Sambuc  *
182ebfedea0SLionel Sambuc  * @ingroup hcrypto_dh
183ebfedea0SLionel Sambuc  */
184ebfedea0SLionel Sambuc 
185ebfedea0SLionel Sambuc int
DH_size(const DH * dh)186ebfedea0SLionel Sambuc DH_size(const DH *dh)
187ebfedea0SLionel Sambuc {
188ebfedea0SLionel Sambuc     return BN_num_bytes(dh->p);
189ebfedea0SLionel Sambuc }
190ebfedea0SLionel Sambuc 
191ebfedea0SLionel Sambuc /**
192ebfedea0SLionel Sambuc  * Set the data index idx in the DH object to data.
193ebfedea0SLionel Sambuc  *
194ebfedea0SLionel Sambuc  * @param dh DH object.
195ebfedea0SLionel Sambuc  * @param idx index to set the data for.
196ebfedea0SLionel Sambuc  * @param data data to store for the index idx.
197ebfedea0SLionel Sambuc  *
198ebfedea0SLionel Sambuc  * @return 1 on success.
199ebfedea0SLionel Sambuc  *
200ebfedea0SLionel Sambuc  * @ingroup hcrypto_dh
201ebfedea0SLionel Sambuc  */
202ebfedea0SLionel Sambuc 
203ebfedea0SLionel Sambuc int
DH_set_ex_data(DH * dh,int idx,void * data)204ebfedea0SLionel Sambuc DH_set_ex_data(DH *dh, int idx, void *data)
205ebfedea0SLionel Sambuc {
206ebfedea0SLionel Sambuc     dh->ex_data.sk = data;
207ebfedea0SLionel Sambuc     return 1;
208ebfedea0SLionel Sambuc }
209ebfedea0SLionel Sambuc 
210ebfedea0SLionel Sambuc /**
211ebfedea0SLionel Sambuc  * Get the data for index idx in the DH object.
212ebfedea0SLionel Sambuc  *
213ebfedea0SLionel Sambuc  * @param dh DH object.
214ebfedea0SLionel Sambuc  * @param idx index to get the data for.
215ebfedea0SLionel Sambuc  *
216ebfedea0SLionel Sambuc  * @return the object store in index idx
217ebfedea0SLionel Sambuc  *
218ebfedea0SLionel Sambuc  * @ingroup hcrypto_dh
219ebfedea0SLionel Sambuc  */
220ebfedea0SLionel Sambuc 
221ebfedea0SLionel Sambuc void *
DH_get_ex_data(DH * dh,int idx)222ebfedea0SLionel Sambuc DH_get_ex_data(DH *dh, int idx)
223ebfedea0SLionel Sambuc {
224ebfedea0SLionel Sambuc     return dh->ex_data.sk;
225ebfedea0SLionel Sambuc }
226ebfedea0SLionel Sambuc 
227ebfedea0SLionel Sambuc /**
228ebfedea0SLionel Sambuc  * Generate DH parameters for the DH object give parameters.
229ebfedea0SLionel Sambuc  *
230ebfedea0SLionel Sambuc  * @param dh The DH object to generate parameters for.
231ebfedea0SLionel Sambuc  * @param prime_len length of the prime
232ebfedea0SLionel Sambuc  * @param generator generator, g
233ebfedea0SLionel Sambuc  * @param cb Callback parameters to show progress, can be NULL.
234ebfedea0SLionel Sambuc  *
235ebfedea0SLionel Sambuc  * @return the maximum size in bytes of the out data.
236ebfedea0SLionel Sambuc  *
237ebfedea0SLionel Sambuc  * @ingroup hcrypto_dh
238ebfedea0SLionel Sambuc  */
239ebfedea0SLionel Sambuc 
240ebfedea0SLionel Sambuc int
DH_generate_parameters_ex(DH * dh,int prime_len,int generator,BN_GENCB * cb)241ebfedea0SLionel Sambuc DH_generate_parameters_ex(DH *dh, int prime_len, int generator, BN_GENCB *cb)
242ebfedea0SLionel Sambuc {
243ebfedea0SLionel Sambuc     if (dh->meth->generate_params)
244ebfedea0SLionel Sambuc 	return dh->meth->generate_params(dh, prime_len, generator, cb);
245ebfedea0SLionel Sambuc     return 0;
246ebfedea0SLionel Sambuc }
247ebfedea0SLionel Sambuc 
248ebfedea0SLionel Sambuc /**
249ebfedea0SLionel Sambuc  * Check that the public key is sane.
250ebfedea0SLionel Sambuc  *
251ebfedea0SLionel Sambuc  * @param dh the local peer DH parameters.
252ebfedea0SLionel Sambuc  * @param pub_key the remote peer public key parameters.
253ebfedea0SLionel Sambuc  * @param codes return that the failures of the pub_key are.
254ebfedea0SLionel Sambuc  *
255ebfedea0SLionel Sambuc  * @return 1 on success, 0 on failure and *codes is set the the
256ebfedea0SLionel Sambuc  * combined fail check for the public key
257ebfedea0SLionel Sambuc  *
258ebfedea0SLionel Sambuc  * @ingroup hcrypto_dh
259ebfedea0SLionel Sambuc  */
260ebfedea0SLionel Sambuc 
261ebfedea0SLionel Sambuc int
DH_check_pubkey(const DH * dh,const BIGNUM * pub_key,int * codes)262ebfedea0SLionel Sambuc DH_check_pubkey(const DH *dh, const BIGNUM *pub_key, int *codes)
263ebfedea0SLionel Sambuc {
264ebfedea0SLionel Sambuc     BIGNUM *bn = NULL, *sum = NULL;
265ebfedea0SLionel Sambuc     int ret = 0;
266ebfedea0SLionel Sambuc 
267ebfedea0SLionel Sambuc     *codes = 0;
268ebfedea0SLionel Sambuc 
269ebfedea0SLionel Sambuc     /**
270ebfedea0SLionel Sambuc      * Checks that the function performs are:
271ebfedea0SLionel Sambuc      * - pub_key is not negative
272ebfedea0SLionel Sambuc      */
273ebfedea0SLionel Sambuc 
274ebfedea0SLionel Sambuc     if (BN_is_negative(pub_key))
275ebfedea0SLionel Sambuc 	goto out;
276ebfedea0SLionel Sambuc 
277ebfedea0SLionel Sambuc     /**
278ebfedea0SLionel Sambuc      * - pub_key > 1    and    pub_key < p - 1,
279ebfedea0SLionel Sambuc      *    to avoid small subgroups attack.
280ebfedea0SLionel Sambuc      */
281ebfedea0SLionel Sambuc 
282ebfedea0SLionel Sambuc     bn = BN_new();
283ebfedea0SLionel Sambuc     if (bn == NULL)
284ebfedea0SLionel Sambuc 	goto out;
285ebfedea0SLionel Sambuc 
286ebfedea0SLionel Sambuc     if (!BN_set_word(bn, 1))
287ebfedea0SLionel Sambuc 	goto out;
288ebfedea0SLionel Sambuc 
289ebfedea0SLionel Sambuc     if (BN_cmp(bn, pub_key) >= 0)
290ebfedea0SLionel Sambuc 	*codes |= DH_CHECK_PUBKEY_TOO_SMALL;
291ebfedea0SLionel Sambuc 
292ebfedea0SLionel Sambuc     sum = BN_new();
293ebfedea0SLionel Sambuc     if (sum == NULL)
294ebfedea0SLionel Sambuc 	goto out;
295ebfedea0SLionel Sambuc 
296ebfedea0SLionel Sambuc     BN_uadd(sum, pub_key, bn);
297ebfedea0SLionel Sambuc 
298ebfedea0SLionel Sambuc     if (BN_cmp(sum, dh->p) >= 0)
299ebfedea0SLionel Sambuc 	*codes |= DH_CHECK_PUBKEY_TOO_LARGE;
300ebfedea0SLionel Sambuc 
301ebfedea0SLionel Sambuc     /**
302ebfedea0SLionel Sambuc      * - if g == 2, pub_key have more then one bit set,
303ebfedea0SLionel Sambuc      *   if bits set is 1, log_2(pub_key) is trival
304ebfedea0SLionel Sambuc      */
305ebfedea0SLionel Sambuc 
306ebfedea0SLionel Sambuc     if (!BN_set_word(bn, 2))
307ebfedea0SLionel Sambuc 	goto out;
308ebfedea0SLionel Sambuc 
309ebfedea0SLionel Sambuc     if (BN_cmp(bn, dh->g) == 0) {
310ebfedea0SLionel Sambuc 	unsigned i, n = BN_num_bits(pub_key);
311ebfedea0SLionel Sambuc 	unsigned bits = 0;
312ebfedea0SLionel Sambuc 
313ebfedea0SLionel Sambuc 	for (i = 0; i <= n; i++)
314ebfedea0SLionel Sambuc 	    if (BN_is_bit_set(pub_key, i))
315ebfedea0SLionel Sambuc 		bits++;
316ebfedea0SLionel Sambuc 
317ebfedea0SLionel Sambuc 	if (bits < 2) {
318ebfedea0SLionel Sambuc 	    *codes |= DH_CHECK_PUBKEY_TOO_SMALL;
319ebfedea0SLionel Sambuc 	    goto out;
320ebfedea0SLionel Sambuc 	}
321ebfedea0SLionel Sambuc     }
322ebfedea0SLionel Sambuc 
323ebfedea0SLionel Sambuc     ret = 1;
324ebfedea0SLionel Sambuc out:
325ebfedea0SLionel Sambuc     if (bn)
326ebfedea0SLionel Sambuc 	BN_free(bn);
327ebfedea0SLionel Sambuc     if (sum)
328ebfedea0SLionel Sambuc 	BN_free(sum);
329ebfedea0SLionel Sambuc 
330ebfedea0SLionel Sambuc     return ret;
331ebfedea0SLionel Sambuc }
332ebfedea0SLionel Sambuc 
333ebfedea0SLionel Sambuc /**
334ebfedea0SLionel Sambuc  * Generate a new DH private-public key pair. The dh parameter must be
335ebfedea0SLionel Sambuc  * allocted first with DH_new(). dh->p and dp->g must be set.
336ebfedea0SLionel Sambuc  *
337ebfedea0SLionel Sambuc  * @param dh dh parameter.
338ebfedea0SLionel Sambuc  *
339ebfedea0SLionel Sambuc  * @return 1 on success.
340ebfedea0SLionel Sambuc  *
341ebfedea0SLionel Sambuc  * @ingroup hcrypto_dh
342ebfedea0SLionel Sambuc  */
343ebfedea0SLionel Sambuc 
344ebfedea0SLionel Sambuc int
DH_generate_key(DH * dh)345ebfedea0SLionel Sambuc DH_generate_key(DH *dh)
346ebfedea0SLionel Sambuc {
347ebfedea0SLionel Sambuc     return dh->meth->generate_key(dh);
348ebfedea0SLionel Sambuc }
349ebfedea0SLionel Sambuc 
350ebfedea0SLionel Sambuc /**
351ebfedea0SLionel Sambuc  * Complute the shared secret key.
352ebfedea0SLionel Sambuc  *
353ebfedea0SLionel Sambuc  * @param shared_key the resulting shared key, need to be at least
354ebfedea0SLionel Sambuc  * DH_size() large.
355ebfedea0SLionel Sambuc  * @param peer_pub_key the peer's public key.
356ebfedea0SLionel Sambuc  * @param dh the dh key pair.
357ebfedea0SLionel Sambuc  *
358ebfedea0SLionel Sambuc  * @return 1 on success.
359ebfedea0SLionel Sambuc  *
360ebfedea0SLionel Sambuc  * @ingroup hcrypto_dh
361ebfedea0SLionel Sambuc  */
362ebfedea0SLionel Sambuc 
363ebfedea0SLionel Sambuc int
DH_compute_key(unsigned char * shared_key,const BIGNUM * peer_pub_key,DH * dh)364ebfedea0SLionel Sambuc DH_compute_key(unsigned char *shared_key,
365ebfedea0SLionel Sambuc 	       const BIGNUM *peer_pub_key, DH *dh)
366ebfedea0SLionel Sambuc {
367ebfedea0SLionel Sambuc     int codes;
368ebfedea0SLionel Sambuc 
369ebfedea0SLionel Sambuc     /**
370ebfedea0SLionel Sambuc      * Checks that the pubkey passed in is valid using
371ebfedea0SLionel Sambuc      * DH_check_pubkey().
372ebfedea0SLionel Sambuc      */
373ebfedea0SLionel Sambuc 
374ebfedea0SLionel Sambuc     if (!DH_check_pubkey(dh, peer_pub_key, &codes) || codes != 0)
375ebfedea0SLionel Sambuc 	return -1;
376ebfedea0SLionel Sambuc 
377ebfedea0SLionel Sambuc     return dh->meth->compute_key(shared_key, peer_pub_key, dh);
378ebfedea0SLionel Sambuc }
379ebfedea0SLionel Sambuc 
380ebfedea0SLionel Sambuc /**
381ebfedea0SLionel Sambuc  * Set a new method for the DH keypair.
382ebfedea0SLionel Sambuc  *
383ebfedea0SLionel Sambuc  * @param dh dh parameter.
384ebfedea0SLionel Sambuc  * @param method the new method for the DH parameter.
385ebfedea0SLionel Sambuc  *
386ebfedea0SLionel Sambuc  * @return 1 on success.
387ebfedea0SLionel Sambuc  *
388ebfedea0SLionel Sambuc  * @ingroup hcrypto_dh
389ebfedea0SLionel Sambuc  */
390ebfedea0SLionel Sambuc 
391ebfedea0SLionel Sambuc int
DH_set_method(DH * dh,const DH_METHOD * method)392ebfedea0SLionel Sambuc DH_set_method(DH *dh, const DH_METHOD *method)
393ebfedea0SLionel Sambuc {
394ebfedea0SLionel Sambuc     (*dh->meth->finish)(dh);
395ebfedea0SLionel Sambuc     if (dh->engine) {
396ebfedea0SLionel Sambuc 	ENGINE_finish(dh->engine);
397ebfedea0SLionel Sambuc 	dh->engine = NULL;
398ebfedea0SLionel Sambuc     }
399ebfedea0SLionel Sambuc     dh->meth = method;
400ebfedea0SLionel Sambuc     (*dh->meth->init)(dh);
401ebfedea0SLionel Sambuc     return 1;
402ebfedea0SLionel Sambuc }
403ebfedea0SLionel Sambuc 
404ebfedea0SLionel Sambuc /*
405ebfedea0SLionel Sambuc  *
406ebfedea0SLionel Sambuc  */
407ebfedea0SLionel Sambuc 
408ebfedea0SLionel Sambuc static int
dh_null_generate_key(DH * dh)409ebfedea0SLionel Sambuc dh_null_generate_key(DH *dh)
410ebfedea0SLionel Sambuc {
411ebfedea0SLionel Sambuc     return 0;
412ebfedea0SLionel Sambuc }
413ebfedea0SLionel Sambuc 
414ebfedea0SLionel Sambuc static int
dh_null_compute_key(unsigned char * shared,const BIGNUM * pub,DH * dh)415ebfedea0SLionel Sambuc dh_null_compute_key(unsigned char *shared,const BIGNUM *pub, DH *dh)
416ebfedea0SLionel Sambuc {
417ebfedea0SLionel Sambuc     return 0;
418ebfedea0SLionel Sambuc }
419ebfedea0SLionel Sambuc 
420ebfedea0SLionel Sambuc static int
dh_null_init(DH * dh)421ebfedea0SLionel Sambuc dh_null_init(DH *dh)
422ebfedea0SLionel Sambuc {
423ebfedea0SLionel Sambuc     return 1;
424ebfedea0SLionel Sambuc }
425ebfedea0SLionel Sambuc 
426ebfedea0SLionel Sambuc static int
dh_null_finish(DH * dh)427ebfedea0SLionel Sambuc dh_null_finish(DH *dh)
428ebfedea0SLionel Sambuc {
429ebfedea0SLionel Sambuc     return 1;
430ebfedea0SLionel Sambuc }
431ebfedea0SLionel Sambuc 
432ebfedea0SLionel Sambuc static int
dh_null_generate_params(DH * dh,int prime_num,int len,BN_GENCB * cb)433ebfedea0SLionel Sambuc dh_null_generate_params(DH *dh, int prime_num, int len, BN_GENCB *cb)
434ebfedea0SLionel Sambuc {
435ebfedea0SLionel Sambuc     return 0;
436ebfedea0SLionel Sambuc }
437ebfedea0SLionel Sambuc 
438ebfedea0SLionel Sambuc static const DH_METHOD dh_null_method = {
439ebfedea0SLionel Sambuc     "hcrypto null DH",
440ebfedea0SLionel Sambuc     dh_null_generate_key,
441ebfedea0SLionel Sambuc     dh_null_compute_key,
442ebfedea0SLionel Sambuc     NULL,
443ebfedea0SLionel Sambuc     dh_null_init,
444ebfedea0SLionel Sambuc     dh_null_finish,
445ebfedea0SLionel Sambuc     0,
446ebfedea0SLionel Sambuc     NULL,
447ebfedea0SLionel Sambuc     dh_null_generate_params
448ebfedea0SLionel Sambuc };
449ebfedea0SLionel Sambuc 
450ebfedea0SLionel Sambuc extern const DH_METHOD _hc_dh_ltm_method;
451ebfedea0SLionel Sambuc static const DH_METHOD *dh_default_method = &_hc_dh_ltm_method;
452ebfedea0SLionel Sambuc 
453ebfedea0SLionel Sambuc /**
454ebfedea0SLionel Sambuc  * Return the dummy DH implementation.
455ebfedea0SLionel Sambuc  *
456ebfedea0SLionel Sambuc  * @return pointer to a DH_METHOD.
457ebfedea0SLionel Sambuc  *
458ebfedea0SLionel Sambuc  * @ingroup hcrypto_dh
459ebfedea0SLionel Sambuc  */
460ebfedea0SLionel Sambuc 
461ebfedea0SLionel Sambuc const DH_METHOD *
DH_null_method(void)462ebfedea0SLionel Sambuc DH_null_method(void)
463ebfedea0SLionel Sambuc {
464ebfedea0SLionel Sambuc     return &dh_null_method;
465ebfedea0SLionel Sambuc }
466ebfedea0SLionel Sambuc 
467ebfedea0SLionel Sambuc /**
468ebfedea0SLionel Sambuc  * Set the default DH implementation.
469ebfedea0SLionel Sambuc  *
470ebfedea0SLionel Sambuc  * @param meth pointer to a DH_METHOD.
471ebfedea0SLionel Sambuc  *
472ebfedea0SLionel Sambuc  * @ingroup hcrypto_dh
473ebfedea0SLionel Sambuc  */
474ebfedea0SLionel Sambuc 
475ebfedea0SLionel Sambuc void
DH_set_default_method(const DH_METHOD * meth)476ebfedea0SLionel Sambuc DH_set_default_method(const DH_METHOD *meth)
477ebfedea0SLionel Sambuc {
478ebfedea0SLionel Sambuc     dh_default_method = meth;
479ebfedea0SLionel Sambuc }
480ebfedea0SLionel Sambuc 
481ebfedea0SLionel Sambuc /**
482ebfedea0SLionel Sambuc  * Return the default DH implementation.
483ebfedea0SLionel Sambuc  *
484ebfedea0SLionel Sambuc  * @return pointer to a DH_METHOD.
485ebfedea0SLionel Sambuc  *
486ebfedea0SLionel Sambuc  * @ingroup hcrypto_dh
487ebfedea0SLionel Sambuc  */
488ebfedea0SLionel Sambuc 
489ebfedea0SLionel Sambuc const DH_METHOD *
DH_get_default_method(void)490ebfedea0SLionel Sambuc DH_get_default_method(void)
491ebfedea0SLionel Sambuc {
492ebfedea0SLionel Sambuc     return dh_default_method;
493ebfedea0SLionel Sambuc }
494ebfedea0SLionel Sambuc 
495ebfedea0SLionel Sambuc /*
496ebfedea0SLionel Sambuc  *
497ebfedea0SLionel Sambuc  */
498ebfedea0SLionel Sambuc 
499ebfedea0SLionel Sambuc static int
bn2heim_int(BIGNUM * bn,heim_integer * integer)500ebfedea0SLionel Sambuc bn2heim_int(BIGNUM *bn, heim_integer *integer)
501ebfedea0SLionel Sambuc {
502ebfedea0SLionel Sambuc     integer->length = BN_num_bytes(bn);
503ebfedea0SLionel Sambuc     integer->data = malloc(integer->length);
504ebfedea0SLionel Sambuc     if (integer->data == NULL) {
505ebfedea0SLionel Sambuc 	integer->length = 0;
506ebfedea0SLionel Sambuc 	return ENOMEM;
507ebfedea0SLionel Sambuc     }
508ebfedea0SLionel Sambuc     BN_bn2bin(bn, integer->data);
509ebfedea0SLionel Sambuc     integer->negative = BN_is_negative(bn);
510ebfedea0SLionel Sambuc     return 0;
511ebfedea0SLionel Sambuc }
512ebfedea0SLionel Sambuc 
513ebfedea0SLionel Sambuc /**
514ebfedea0SLionel Sambuc  *
515ebfedea0SLionel Sambuc  */
516ebfedea0SLionel Sambuc 
517ebfedea0SLionel Sambuc int
i2d_DHparams(DH * dh,unsigned char ** pp)518ebfedea0SLionel Sambuc i2d_DHparams(DH *dh, unsigned char **pp)
519ebfedea0SLionel Sambuc {
520ebfedea0SLionel Sambuc     DHParameter data;
521ebfedea0SLionel Sambuc     size_t size;
522ebfedea0SLionel Sambuc     int ret;
523ebfedea0SLionel Sambuc 
524ebfedea0SLionel Sambuc     memset(&data, 0, sizeof(data));
525ebfedea0SLionel Sambuc 
526ebfedea0SLionel Sambuc     if (bn2heim_int(dh->p, &data.prime) ||
527ebfedea0SLionel Sambuc 	bn2heim_int(dh->g, &data.base))
528ebfedea0SLionel Sambuc     {
529ebfedea0SLionel Sambuc 	free_DHParameter(&data);
530ebfedea0SLionel Sambuc 	return -1;
531ebfedea0SLionel Sambuc     }
532ebfedea0SLionel Sambuc 
533ebfedea0SLionel Sambuc     if (pp == NULL) {
534ebfedea0SLionel Sambuc 	size = length_DHParameter(&data);
535ebfedea0SLionel Sambuc 	free_DHParameter(&data);
536ebfedea0SLionel Sambuc     } else {
537ebfedea0SLionel Sambuc 	void *p;
538ebfedea0SLionel Sambuc 	size_t len;
539ebfedea0SLionel Sambuc 
540ebfedea0SLionel Sambuc 	ASN1_MALLOC_ENCODE(DHParameter, p, len, &data, &size, ret);
541ebfedea0SLionel Sambuc 	free_DHParameter(&data);
542ebfedea0SLionel Sambuc 	if (ret)
543ebfedea0SLionel Sambuc 	    return -1;
544*0a6a1f1dSLionel Sambuc 	if (len != size) {
545ebfedea0SLionel Sambuc 	    abort();
546*0a6a1f1dSLionel Sambuc             return -1;
547*0a6a1f1dSLionel Sambuc         }
548ebfedea0SLionel Sambuc 
549ebfedea0SLionel Sambuc 	memcpy(*pp, p, size);
550ebfedea0SLionel Sambuc 	free(p);
551ebfedea0SLionel Sambuc 
552ebfedea0SLionel Sambuc 	*pp += size;
553ebfedea0SLionel Sambuc     }
554ebfedea0SLionel Sambuc 
555ebfedea0SLionel Sambuc     return size;
556ebfedea0SLionel Sambuc }
557