1/*
2 * Copyright (c) 2011-12 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
25 * All rights reserved.
26 *
27 * This package is an SSL implementation written
28 * by Eric Young (eay@cryptsoft.com).
29 * The implementation was written so as to conform with Netscapes SSL.
30 *
31 * This library is free for commercial and non-commercial use as long as
32 * the following conditions are aheared to.  The following conditions
33 * apply to all code found in this distribution, be it the RC4, RSA,
34 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
35 * included with this distribution is covered by the same copyright terms
36 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
37 *
38 * Copyright remains Eric Young's, and as such any Copyright notices in
39 * the code are not to be removed.
40 * If this package is used in a product, Eric Young should be given attribution
41 * as the author of the parts of the library used.
42 * This can be in the form of a textual message at program startup or
43 * in documentation (online or textual) provided with the package.
44 *
45 * Redistribution and use in source and binary forms, with or without
46 * modification, are permitted provided that the following conditions
47 * are met:
48 * 1. Redistributions of source code must retain the copyright
49 *    notice, this list of conditions and the following disclaimer.
50 * 2. Redistributions in binary form must reproduce the above copyright
51 *    notice, this list of conditions and the following disclaimer in the
52 *    documentation and/or other materials provided with the distribution.
53 * 3. All advertising materials mentioning features or use of this software
54 *    must display the following acknowledgement:
55 *    "This product includes cryptographic software written by
56 *     Eric Young (eay@cryptsoft.com)"
57 *    The word 'cryptographic' can be left out if the rouines from the library
58 *    being used are not cryptographic related :-).
59 * 4. If you include any Windows specific code (or a derivative thereof) from
60 *    the apps directory (application code) you must include an acknowledgement:
61 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
62 *
63 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
64 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
65 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
66 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
67 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
68 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
69 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
70 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
71 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
72 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
73 * SUCH DAMAGE.
74 *
75 * The licence and distribution terms for any publically available version or
76 * derivative of this code cannot be changed.  i.e. this code cannot simply be
77 * copied and put under another distribution licence
78 * [including the GNU Public Licence.]
79 */
80
81
82#include "ossl-config.h"
83
84
85#include <stdio.h>
86
87#include "ossl-bn.h"
88#include "ossl-rand.h"
89#include "ossl-dh.h"
90
91#if !defined(PR_10771223_FIXED) || !defined(PR_10771188_FIXED)
92
93/*
94 * EAY Diffie-Hellman key exchange
95 */
96
97#define  DH_MAX_MODULUS_BITS    10000
98
99static int eay_dh_generate_key(DH *dh);
100static int eay_dh_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh);
101static int eay_dh_bn_mod_exp(const DH *dh, BIGNUM *r,
102    const BIGNUM *a, const BIGNUM *p,
103    const BIGNUM *m, BN_CTX *ctx
104    /*,  BN_MONT_CTX *m_ctx */);
105static int eay_dh_init(DH *dh);
106static int eay_dh_finish(DH *dh);
107
108static int
109eay_dh_generate_key(DH *dh)
110{
111	int ok = 0;
112	int generate_new_key = 0;
113	unsigned l;
114	BN_CTX *ctx;
115
116#if 0
117	BN_MONT_CTX *mont = NULL;
118#endif
119	BIGNUM *pub_key = NULL, *priv_key = NULL;
120
121	ctx = BN_CTX_new();
122	if (ctx == NULL) {
123		goto err;
124	}
125
126	if (dh->priv_key == NULL) {
127		priv_key = BN_new();
128		if (priv_key == NULL) {
129			goto err;
130		}
131		generate_new_key = 1;
132	} else{
133		priv_key = dh->priv_key;
134	}
135
136	if (dh->pub_key == NULL) {
137		pub_key = BN_new();
138		if (pub_key == NULL) {
139			goto err;
140		}
141	} else{
142		pub_key = dh->pub_key;
143	}
144
145
146#if 0
147	if (dh->flags & DH_FLAG_CACHE_MONT_P) {
148		mont = BN_MONT_CTX_set_locked(&dh->method_mont_p,
149			CRYPTO_LOCK_DH, dh->p, ctx);
150		if (!mont) {
151			goto err;
152		}
153	}
154#endif
155
156	if (generate_new_key) {
157		l = dh->length ? dh->length : BN_num_bits(dh->p) - 1; /* secret exponent length */
158		if (!BN_rand(priv_key, l, 0, 0)) {
159			goto err;
160		}
161	}
162
163	{
164		BIGNUM local_prk;
165		BIGNUM *prk;
166
167#if 0
168		if ((dh->flags & DH_FLAG_NO_EXP_CONSTTIME) == 0) {
169			BN_init(&local_prk);
170			prk = &local_prk;
171			BN_with_flags(prk, priv_key, BN_FLG_CONSTTIME);
172		} else
173#endif
174		prk = priv_key;
175
176		if (!dh->meth->bn_mod_exp(dh, pub_key, dh->g, prk, dh->p, ctx /* , mont */)) {
177			goto err;
178		}
179	}
180
181	dh->pub_key = pub_key;
182	dh->priv_key = priv_key;
183	ok = 1;
184err:
185
186	/*
187	 * if (ok != 1)
188	 *      DHerr(DH_F_GENERATE_KEY,ERR_R_BN_LIB);
189	 */
190
191	if ((pub_key != NULL) && (dh->pub_key == NULL)) {
192		BN_clear_free(pub_key);
193	}
194	if ((priv_key != NULL) && (dh->priv_key == NULL)) {
195		BN_clear_free(priv_key);
196	}
197	BN_CTX_free(ctx);
198	return (ok);
199}
200
201
202static int
203eay_dh_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh)
204{
205	BN_CTX *ctx = NULL;
206
207#if 0
208	BN_MONT_CTX *mont = NULL;
209#endif
210	BIGNUM *tmp;
211	int ret = -1;
212	int check_result;
213
214	if (BN_num_bits(dh->p) > DH_MAX_MODULUS_BITS) {
215		/* DHerr(DH_F_COMPUTE_KEY,DH_R_MODULUS_TOO_LARGE); */
216		goto err;
217	}
218
219	ctx = BN_CTX_new();
220	if (ctx == NULL) {
221		goto err;
222	}
223	BN_CTX_start(ctx);
224	tmp = BN_CTX_get(ctx);
225
226	if (dh->priv_key == NULL) {
227		/* DHerr(DH_F_COMPUTE_KEY,DH_R_NO_PRIVATE_VALUE); */
228		goto err;
229	}
230
231#if 0
232	if (dh->flags & DH_FLAG_CACHE_MONT_P) {
233		mont = BN_MONT_CTX_set_locked(&dh->method_mont_p,
234			CRYPTO_LOCK_DH, dh->p, ctx);
235		if ((dh->flags & DH_FLAG_NO_EXP_CONSTTIME) == 0) {
236			/* XXX */
237			BN_set_flags(dh->priv_key, BN_FLG_CONSTTIME);
238		}
239		if (!mont) {
240			goto err;
241		}
242	}
243#endif
244
245	if (!DH_check_pubkey(dh, pub_key, &check_result) || check_result) {
246		/* DHerr(DH_F_COMPUTE_KEY,DH_R_INVALID_PUBKEY); */
247		goto err;
248	}
249
250	if (!dh->meth->bn_mod_exp(dh, tmp, pub_key, dh->priv_key, dh->p, ctx /*, mont */)) {
251		/* DHerr(DH_F_COMPUTE_KEY,ERR_R_BN_LIB); */
252		goto err;
253	}
254
255	ret = BN_bn2bin(tmp, key);
256
257err:
258	if (ctx != NULL) {
259		BN_CTX_end(ctx);
260		BN_CTX_free(ctx);
261	}
262	return (ret);
263}
264
265
266static int
267eay_dh_bn_mod_exp(const DH *dh, BIGNUM *r,
268    const BIGNUM *a, const BIGNUM *p,
269    const BIGNUM *m, BN_CTX *ctx
270    /*,  BN_MONT_CTX *m_ctx */)
271{
272	/* If a is only one word long and constant time is false, use the faster
273	 * exponenentiation function.
274	 */
275	if ((a->top == 1) && ((dh->flags & DH_FLAG_NO_EXP_CONSTTIME) != 0)) {
276		BN_ULONG A = a->d[0];
277		/* return BN_mod_exp_mont_word(r,A,p,m,ctx,m_ctx); */
278		return (BN_mod_exp_mont_word(r, A, p, m, ctx, NULL));
279	} else {
280		/* return BN_mod_exp_mont(r,a,p,m,ctx,m_ctx); */
281		return (BN_mod_exp(r, a, p, m, ctx));
282	}
283}
284
285
286static int
287eay_dh_generate_params(DH *dh, int a, int b, BN_GENCB *callback)
288{
289	/* groups should already be known, we don't care about this */
290	return (0);
291}
292
293
294static int
295eay_dh_init(DH *dh)
296{
297#if 0
298	dh->flags |= DH_FLAG_CACHE_MONT_P;
299#endif
300	return (1);
301}
302
303
304static int
305eay_dh_finish(DH *dh)
306{
307#if 0
308	if (dh->method_mont_p) {
309		BN_MONT_CTX_free(dh->method_mont_p);
310	}
311#endif
312	return (1);
313}
314
315
316const DH_METHOD _ossl_dh_eay_method =
317{
318	.name			= "EAY DH",
319	.generate_key		= eay_dh_generate_key,
320	.compute_key		= eay_dh_compute_key,
321	.bn_mod_exp		= eay_dh_bn_mod_exp,
322	.init			= eay_dh_init,
323	.finish			= eay_dh_finish,
324	.flags			=	     0,
325	.app_data		= NULL,
326	.generate_params	= eay_dh_generate_params
327};
328#endif /*  ! defined(PR_10771223_FIXED) || ! defined(PR_10771188_FIXED) */
329
330const DH_METHOD *
331DH_eay_method(void)
332{
333#if  !defined(PR_10771223_FIXED) || !defined(PR_10771188_FIXED)
334	return (&_ossl_dh_eay_method);
335
336#else
337	return (NULL);
338#endif
339}
340