155714Skris/* crypto/dh/dh_lib.c */
255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
355714Skris * All rights reserved.
455714Skris *
555714Skris * This package is an SSL implementation written
655714Skris * by Eric Young (eay@cryptsoft.com).
755714Skris * The implementation was written so as to conform with Netscapes SSL.
855714Skris *
955714Skris * This library is free for commercial and non-commercial use as long as
1055714Skris * the following conditions are aheared to.  The following conditions
1155714Skris * apply to all code found in this distribution, be it the RC4, RSA,
1255714Skris * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1355714Skris * included with this distribution is covered by the same copyright terms
1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com).
1555714Skris *
1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in
1755714Skris * the code are not to be removed.
1855714Skris * If this package is used in a product, Eric Young should be given attribution
1955714Skris * as the author of the parts of the library used.
2055714Skris * This can be in the form of a textual message at program startup or
2155714Skris * in documentation (online or textual) provided with the package.
2255714Skris *
2355714Skris * Redistribution and use in source and binary forms, with or without
2455714Skris * modification, are permitted provided that the following conditions
2555714Skris * are met:
2655714Skris * 1. Redistributions of source code must retain the copyright
2755714Skris *    notice, this list of conditions and the following disclaimer.
2855714Skris * 2. Redistributions in binary form must reproduce the above copyright
2955714Skris *    notice, this list of conditions and the following disclaimer in the
3055714Skris *    documentation and/or other materials provided with the distribution.
3155714Skris * 3. All advertising materials mentioning features or use of this software
3255714Skris *    must display the following acknowledgement:
3355714Skris *    "This product includes cryptographic software written by
3455714Skris *     Eric Young (eay@cryptsoft.com)"
3555714Skris *    The word 'cryptographic' can be left out if the rouines from the library
3655714Skris *    being used are not cryptographic related :-).
3755714Skris * 4. If you include any Windows specific code (or a derivative thereof) from
3855714Skris *    the apps directory (application code) you must include an acknowledgement:
3955714Skris *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
4055714Skris *
4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4455714Skris * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5155714Skris * SUCH DAMAGE.
5255714Skris *
5355714Skris * The licence and distribution terms for any publically available version or
5455714Skris * derivative of this code cannot be changed.  i.e. this code cannot simply be
5555714Skris * copied and put under another distribution licence
5655714Skris * [including the GNU Public Licence.]
5755714Skris */
5855714Skris
5955714Skris#include <stdio.h>
6055714Skris#include "cryptlib.h"
6155714Skris#include <openssl/bn.h>
6255714Skris#include <openssl/dh.h>
63111147Snectar#ifndef OPENSSL_NO_ENGINE
64109998Smarkm#include <openssl/engine.h>
65111147Snectar#endif
6655714Skris
67238405Sjkim#ifdef OPENSSL_FIPS
68238405Sjkim#include <openssl/fips.h>
69238405Sjkim#endif
70238405Sjkim
71167612Ssimonconst char DH_version[]="Diffie-Hellman" OPENSSL_VERSION_PTEXT;
7255714Skris
73109998Smarkmstatic const DH_METHOD *default_DH_method = NULL;
7459191Skris
75109998Smarkmvoid DH_set_default_method(const DH_METHOD *meth)
76109998Smarkm	{
7759191Skris	default_DH_method = meth;
78109998Smarkm	}
7959191Skris
80109998Smarkmconst DH_METHOD *DH_get_default_method(void)
81109998Smarkm	{
82109998Smarkm	if(!default_DH_method)
83238405Sjkim		{
84238405Sjkim#ifdef OPENSSL_FIPS
85238405Sjkim		if (FIPS_mode())
86238405Sjkim			return FIPS_dh_openssl();
87238405Sjkim		else
88238405Sjkim			return DH_OpenSSL();
89238405Sjkim#else
90109998Smarkm		default_DH_method = DH_OpenSSL();
91238405Sjkim#endif
92238405Sjkim		}
9359191Skris	return default_DH_method;
94109998Smarkm	}
9559191Skris
96109998Smarkmint DH_set_method(DH *dh, const DH_METHOD *meth)
97109998Smarkm	{
98109998Smarkm	/* NB: The caller is specifically setting a method, so it's not up to us
99109998Smarkm	 * to deal with which ENGINE it comes from. */
100109998Smarkm        const DH_METHOD *mtmp;
10159191Skris        mtmp = dh->meth;
10259191Skris        if (mtmp->finish) mtmp->finish(dh);
103111147Snectar#ifndef OPENSSL_NO_ENGINE
104109998Smarkm	if (dh->engine)
105109998Smarkm		{
106109998Smarkm		ENGINE_finish(dh->engine);
107109998Smarkm		dh->engine = NULL;
108109998Smarkm		}
109111147Snectar#endif
11059191Skris        dh->meth = meth;
11159191Skris        if (meth->init) meth->init(dh);
112109998Smarkm        return 1;
113109998Smarkm	}
11459191Skris
11555714SkrisDH *DH_new(void)
116109998Smarkm	{
11759191Skris	return DH_new_method(NULL);
118109998Smarkm	}
11959191Skris
120109998SmarkmDH *DH_new_method(ENGINE *engine)
12155714Skris	{
12255714Skris	DH *ret;
123109998Smarkm
12468651Skris	ret=(DH *)OPENSSL_malloc(sizeof(DH));
12555714Skris	if (ret == NULL)
12655714Skris		{
127109998Smarkm		DHerr(DH_F_DH_NEW_METHOD,ERR_R_MALLOC_FAILURE);
12855714Skris		return(NULL);
12955714Skris		}
130109998Smarkm
131109998Smarkm	ret->meth = DH_get_default_method();
132111147Snectar#ifndef OPENSSL_NO_ENGINE
133109998Smarkm	if (engine)
134109998Smarkm		{
135109998Smarkm		if (!ENGINE_init(engine))
136109998Smarkm			{
137109998Smarkm			DHerr(DH_F_DH_NEW_METHOD, ERR_R_ENGINE_LIB);
138109998Smarkm			OPENSSL_free(ret);
139109998Smarkm			return NULL;
140109998Smarkm			}
141109998Smarkm		ret->engine = engine;
142109998Smarkm		}
143109998Smarkm	else
144109998Smarkm		ret->engine = ENGINE_get_default_DH();
145109998Smarkm	if(ret->engine)
146109998Smarkm		{
147109998Smarkm		ret->meth = ENGINE_get_DH(ret->engine);
148109998Smarkm		if(!ret->meth)
149109998Smarkm			{
150109998Smarkm			DHerr(DH_F_DH_NEW_METHOD,ERR_R_ENGINE_LIB);
151109998Smarkm			ENGINE_finish(ret->engine);
152109998Smarkm			OPENSSL_free(ret);
153109998Smarkm			return NULL;
154109998Smarkm			}
155109998Smarkm		}
156111147Snectar#endif
157109998Smarkm
15855714Skris	ret->pad=0;
15955714Skris	ret->version=0;
16055714Skris	ret->p=NULL;
16155714Skris	ret->g=NULL;
16255714Skris	ret->length=0;
16355714Skris	ret->pub_key=NULL;
16455714Skris	ret->priv_key=NULL;
16559191Skris	ret->q=NULL;
16659191Skris	ret->j=NULL;
16759191Skris	ret->seed = NULL;
16859191Skris	ret->seedlen = 0;
16959191Skris	ret->counter = NULL;
17055714Skris	ret->method_mont_p=NULL;
17159191Skris	ret->references = 1;
172238405Sjkim	ret->flags=ret->meth->flags & ~DH_FLAG_NON_FIPS_ALLOW;
173109998Smarkm	CRYPTO_new_ex_data(CRYPTO_EX_INDEX_DH, ret, &ret->ex_data);
17459191Skris	if ((ret->meth->init != NULL) && !ret->meth->init(ret))
17559191Skris		{
176111147Snectar#ifndef OPENSSL_NO_ENGINE
177109998Smarkm		if (ret->engine)
178109998Smarkm			ENGINE_finish(ret->engine);
179111147Snectar#endif
180109998Smarkm		CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DH, ret, &ret->ex_data);
18168651Skris		OPENSSL_free(ret);
18259191Skris		ret=NULL;
18359191Skris		}
18455714Skris	return(ret);
18555714Skris	}
18655714Skris
18755714Skrisvoid DH_free(DH *r)
18855714Skris	{
18959191Skris	int i;
19055714Skris	if(r == NULL) return;
19159191Skris	i = CRYPTO_add(&r->references, -1, CRYPTO_LOCK_DH);
19259191Skris#ifdef REF_PRINT
19359191Skris	REF_PRINT("DH",r);
19459191Skris#endif
19559191Skris	if (i > 0) return;
19659191Skris#ifdef REF_CHECK
19759191Skris	if (i < 0)
19859191Skris		{
19959191Skris		fprintf(stderr,"DH_free, bad reference count\n");
20059191Skris		abort();
20159191Skris	}
20259191Skris#endif
20359191Skris
204109998Smarkm	if (r->meth->finish)
205109998Smarkm		r->meth->finish(r);
206111147Snectar#ifndef OPENSSL_NO_ENGINE
207109998Smarkm	if (r->engine)
208109998Smarkm		ENGINE_finish(r->engine);
209111147Snectar#endif
21076866Skris
211109998Smarkm	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DH, r, &r->ex_data);
21259191Skris
21355714Skris	if (r->p != NULL) BN_clear_free(r->p);
21455714Skris	if (r->g != NULL) BN_clear_free(r->g);
21559191Skris	if (r->q != NULL) BN_clear_free(r->q);
21659191Skris	if (r->j != NULL) BN_clear_free(r->j);
21768651Skris	if (r->seed) OPENSSL_free(r->seed);
21859191Skris	if (r->counter != NULL) BN_clear_free(r->counter);
21955714Skris	if (r->pub_key != NULL) BN_clear_free(r->pub_key);
22055714Skris	if (r->priv_key != NULL) BN_clear_free(r->priv_key);
22168651Skris	OPENSSL_free(r);
22255714Skris	}
22355714Skris
224109998Smarkmint DH_up_ref(DH *r)
225109998Smarkm	{
226109998Smarkm	int i = CRYPTO_add(&r->references, 1, CRYPTO_LOCK_DH);
227109998Smarkm#ifdef REF_PRINT
228109998Smarkm	REF_PRINT("DH",r);
229109998Smarkm#endif
230109998Smarkm#ifdef REF_CHECK
231109998Smarkm	if (i < 2)
232109998Smarkm		{
233109998Smarkm		fprintf(stderr, "DH_up, bad reference count\n");
234109998Smarkm		abort();
235109998Smarkm		}
236109998Smarkm#endif
237109998Smarkm	return ((i > 1) ? 1 : 0);
238109998Smarkm	}
239109998Smarkm
24059191Skrisint DH_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
24159191Skris	     CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
24259191Skris        {
243109998Smarkm	return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_DH, argl, argp,
244109998Smarkm				new_func, dup_func, free_func);
24559191Skris        }
24659191Skris
24759191Skrisint DH_set_ex_data(DH *d, int idx, void *arg)
24859191Skris	{
24959191Skris	return(CRYPTO_set_ex_data(&d->ex_data,idx,arg));
25059191Skris	}
25159191Skris
25259191Skrisvoid *DH_get_ex_data(DH *d, int idx)
25359191Skris	{
25459191Skris	return(CRYPTO_get_ex_data(&d->ex_data,idx));
25559191Skris	}
25659191Skris
257109998Smarkmint DH_size(const DH *dh)
25855714Skris	{
25955714Skris	return(BN_num_bytes(dh->p));
26055714Skris	}
261