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