dh_lib.c revision 296341
1139749Simp/* crypto/dh/dh_lib.c */
265942Sgibbs/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
365942Sgibbs * All rights reserved.
465942Sgibbs *
565942Sgibbs * This package is an SSL implementation written
695378Sgibbs * by Eric Young (eay@cryptsoft.com).
795378Sgibbs * The implementation was written so as to conform with Netscapes SSL.
865942Sgibbs *
965942Sgibbs * This library is free for commercial and non-commercial use as long as
1065942Sgibbs * the following conditions are aheared to.  The following conditions
1165942Sgibbs * apply to all code found in this distribution, be it the RC4, RSA,
1265942Sgibbs * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1365942Sgibbs * included with this distribution is covered by the same copyright terms
1465942Sgibbs * except that the holder is Tim Hudson (tjh@cryptsoft.com).
1595378Sgibbs *
1695378Sgibbs * Copyright remains Eric Young's, and as such any Copyright notices in
1795378Sgibbs * the code are not to be removed.
1895378Sgibbs * If this package is used in a product, Eric Young should be given attribution
1995378Sgibbs * as the author of the parts of the library used.
2095378Sgibbs * This can be in the form of a textual message at program startup or
2195378Sgibbs * in documentation (online or textual) provided with the package.
2295378Sgibbs *
2395378Sgibbs * Redistribution and use in source and binary forms, with or without
2465942Sgibbs * modification, are permitted provided that the following conditions
2565942Sgibbs * are met:
2695378Sgibbs * 1. Redistributions of source code must retain the copyright
2795378Sgibbs *    notice, this list of conditions and the following disclaimer.
2865942Sgibbs * 2. Redistributions in binary form must reproduce the above copyright
2995378Sgibbs *    notice, this list of conditions and the following disclaimer in the
3095378Sgibbs *    documentation and/or other materials provided with the distribution.
3195378Sgibbs * 3. All advertising materials mentioning features or use of this software
3295378Sgibbs *    must display the following acknowledgement:
3395378Sgibbs *    "This product includes cryptographic software written by
3495378Sgibbs *     Eric Young (eay@cryptsoft.com)"
3565942Sgibbs *    The word 'cryptographic' can be left out if the rouines from the library
3665942Sgibbs *    being used are not cryptographic related :-).
3795378Sgibbs * 4. If you include any Windows specific code (or a derivative thereof) from
3895378Sgibbs *    the apps directory (application code) you must include an acknowledgement:
3995378Sgibbs *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
4095378Sgibbs *
4165942Sgibbs * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42123579Sgibbs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4365942Sgibbs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4465942Sgibbs * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4595378Sgibbs * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4695378Sgibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4795378Sgibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4895378Sgibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4995378Sgibbs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50123579Sgibbs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51123579Sgibbs * SUCH DAMAGE.
5295378Sgibbs *
5365942Sgibbs * The licence and distribution terms for any publically available version or
5465942Sgibbs * derivative of this code cannot be changed.  i.e. this code cannot simply be
5595378Sgibbs * copied and put under another distribution licence
5665942Sgibbs * [including the GNU Public Licence.]
5765942Sgibbs */
5865942Sgibbs
5965942Sgibbs#include <stdio.h>
6065942Sgibbs#include "cryptlib.h"
6165942Sgibbs#include <openssl/bn.h>
6265942Sgibbs#include <openssl/dh.h>
6365942Sgibbs#ifndef OPENSSL_NO_ENGINE
6465942Sgibbs# include <openssl/engine.h>
6565942Sgibbs#endif
6665942Sgibbs
6765942Sgibbs#ifdef OPENSSL_FIPS
6865942Sgibbs# include <openssl/fips.h>
6965942Sgibbs#endif
7074094Sgibbs
7174094Sgibbsconst char DH_version[] = "Diffie-Hellman" OPENSSL_VERSION_PTEXT;
7274094Sgibbs
7374094Sgibbsstatic const DH_METHOD *default_DH_method = NULL;
7474094Sgibbs
7574094Sgibbsvoid DH_set_default_method(const DH_METHOD *meth)
76115338Sgibbs{
7774094Sgibbs    default_DH_method = meth;
7874094Sgibbs}
7974094Sgibbs
8074094Sgibbsconst DH_METHOD *DH_get_default_method(void)
8174094Sgibbs{
8274094Sgibbs    if (!default_DH_method) {
8374094Sgibbs#ifdef OPENSSL_FIPS
8474094Sgibbs        if (FIPS_mode())
8574094Sgibbs            return FIPS_dh_openssl();
8674094Sgibbs        else
8765942Sgibbs            return DH_OpenSSL();
8874094Sgibbs#else
8974094Sgibbs        default_DH_method = DH_OpenSSL();
9074094Sgibbs#endif
9174094Sgibbs    }
9274094Sgibbs    return default_DH_method;
9374094Sgibbs}
9474094Sgibbs
9565942Sgibbsint DH_set_method(DH *dh, const DH_METHOD *meth)
9674094Sgibbs{
9774094Sgibbs    /*
9874094Sgibbs     * NB: The caller is specifically setting a method, so it's not up to us
9974094Sgibbs     * to deal with which ENGINE it comes from.
10074094Sgibbs     */
10174094Sgibbs    const DH_METHOD *mtmp;
10274094Sgibbs    mtmp = dh->meth;
10374094Sgibbs    if (mtmp->finish)
10474094Sgibbs        mtmp->finish(dh);
10574094Sgibbs#ifndef OPENSSL_NO_ENGINE
10674094Sgibbs    if (dh->engine) {
10774094Sgibbs        ENGINE_finish(dh->engine);
10865942Sgibbs        dh->engine = NULL;
10974094Sgibbs    }
11074094Sgibbs#endif
11174094Sgibbs    dh->meth = meth;
11274094Sgibbs    if (meth->init)
11374094Sgibbs        meth->init(dh);
11474094Sgibbs    return 1;
11565942Sgibbs}
11674094Sgibbs
11774094SgibbsDH *DH_new(void)
11874094Sgibbs{
11974094Sgibbs    return DH_new_method(NULL);
12074094Sgibbs}
12174094Sgibbs
12274094SgibbsDH *DH_new_method(ENGINE *engine)
12374094Sgibbs{
12465942Sgibbs    DH *ret;
12574094Sgibbs
12674094Sgibbs    ret = (DH *)OPENSSL_malloc(sizeof(DH));
12774094Sgibbs    if (ret == NULL) {
12874094Sgibbs        DHerr(DH_F_DH_NEW_METHOD, ERR_R_MALLOC_FAILURE);
12974094Sgibbs        return (NULL);
13074094Sgibbs    }
13174094Sgibbs
13274094Sgibbs    ret->meth = DH_get_default_method();
133123579Sgibbs#ifndef OPENSSL_NO_ENGINE
13465942Sgibbs    if (engine) {
13574094Sgibbs        if (!ENGINE_init(engine)) {
13674094Sgibbs            DHerr(DH_F_DH_NEW_METHOD, ERR_R_ENGINE_LIB);
13774094Sgibbs            OPENSSL_free(ret);
13874094Sgibbs            return NULL;
13974094Sgibbs        }
14074094Sgibbs        ret->engine = engine;
14165942Sgibbs    } else
14274094Sgibbs        ret->engine = ENGINE_get_default_DH();
14374094Sgibbs    if (ret->engine) {
14474094Sgibbs        ret->meth = ENGINE_get_DH(ret->engine);
14574094Sgibbs        if (!ret->meth) {
14665942Sgibbs            DHerr(DH_F_DH_NEW_METHOD, ERR_R_ENGINE_LIB);
14774094Sgibbs            ENGINE_finish(ret->engine);
14874094Sgibbs            OPENSSL_free(ret);
14965942Sgibbs            return NULL;
15072325Sgibbs        }
15172325Sgibbs    }
15272325Sgibbs#endif
15395378Sgibbs
15472325Sgibbs    ret->pad = 0;
15572325Sgibbs    ret->version = 0;
15672325Sgibbs    ret->p = NULL;
15772325Sgibbs    ret->g = NULL;
15872325Sgibbs    ret->length = 0;
15972325Sgibbs    ret->pub_key = NULL;
16072325Sgibbs    ret->priv_key = NULL;
16172325Sgibbs    ret->q = NULL;
16272325Sgibbs    ret->j = NULL;
16372325Sgibbs    ret->seed = NULL;
16472325Sgibbs    ret->seedlen = 0;
16572325Sgibbs    ret->counter = NULL;
16672325Sgibbs    ret->method_mont_p = NULL;
16770693Sgibbs    ret->references = 1;
16870693Sgibbs    ret->flags = ret->meth->flags & ~DH_FLAG_NON_FIPS_ALLOW;
16970693Sgibbs    CRYPTO_new_ex_data(CRYPTO_EX_INDEX_DH, ret, &ret->ex_data);
17070693Sgibbs    if ((ret->meth->init != NULL) && !ret->meth->init(ret)) {
17170693Sgibbs#ifndef OPENSSL_NO_ENGINE
17270204Sgibbs        if (ret->engine)
17372811Sgibbs            ENGINE_finish(ret->engine);
17472811Sgibbs#endif
17572811Sgibbs        CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DH, ret, &ret->ex_data);
17672811Sgibbs        OPENSSL_free(ret);
17772811Sgibbs        ret = NULL;
17872811Sgibbs    }
17970693Sgibbs    return (ret);
18070693Sgibbs}
18170693Sgibbs
18270693Sgibbsvoid DH_free(DH *r)
18370693Sgibbs{
18470693Sgibbs    int i;
18570693Sgibbs    if (r == NULL)
18670693Sgibbs        return;
18770693Sgibbs    i = CRYPTO_add(&r->references, -1, CRYPTO_LOCK_DH);
18870693Sgibbs#ifdef REF_PRINT
18970693Sgibbs    REF_PRINT("DH", r);
19070693Sgibbs#endif
19170693Sgibbs    if (i > 0)
19270693Sgibbs        return;
19370693Sgibbs#ifdef REF_CHECK
19470693Sgibbs    if (i < 0) {
19570693Sgibbs        fprintf(stderr, "DH_free, bad reference count\n");
19670693Sgibbs        abort();
19770693Sgibbs    }
19870693Sgibbs#endif
19970693Sgibbs
20070693Sgibbs    if (r->meth->finish)
20170693Sgibbs        r->meth->finish(r);
20270693Sgibbs#ifndef OPENSSL_NO_ENGINE
20370693Sgibbs    if (r->engine)
20470693Sgibbs        ENGINE_finish(r->engine);
20570693Sgibbs#endif
20670693Sgibbs
20770693Sgibbs    CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DH, r, &r->ex_data);
20870693Sgibbs
20970693Sgibbs    if (r->p != NULL)
21070693Sgibbs        BN_clear_free(r->p);
21170693Sgibbs    if (r->g != NULL)
21270693Sgibbs        BN_clear_free(r->g);
21370693Sgibbs    if (r->q != NULL)
21495378Sgibbs        BN_clear_free(r->q);
21570693Sgibbs    if (r->j != NULL)
21670693Sgibbs        BN_clear_free(r->j);
21770693Sgibbs    if (r->seed)
21870693Sgibbs        OPENSSL_free(r->seed);
21970693Sgibbs    if (r->counter != NULL)
22074094Sgibbs        BN_clear_free(r->counter);
22165942Sgibbs    if (r->pub_key != NULL)
22271390Sgibbs        BN_clear_free(r->pub_key);
22365942Sgibbs    if (r->priv_key != NULL)
22465942Sgibbs        BN_clear_free(r->priv_key);
22565942Sgibbs    OPENSSL_free(r);
22665942Sgibbs}
22765942Sgibbs
22871390Sgibbsint DH_up_ref(DH *r)
22965942Sgibbs{
23065942Sgibbs    int i = CRYPTO_add(&r->references, 1, CRYPTO_LOCK_DH);
23165942Sgibbs#ifdef REF_PRINT
23265942Sgibbs    REF_PRINT("DH", r);
23365942Sgibbs#endif
23465942Sgibbs#ifdef REF_CHECK
23565942Sgibbs    if (i < 2) {
23671390Sgibbs        fprintf(stderr, "DH_up, bad reference count\n");
23765942Sgibbs        abort();
23865942Sgibbs    }
23965942Sgibbs#endif
24065942Sgibbs    return ((i > 1) ? 1 : 0);
24165942Sgibbs}
24265942Sgibbs
24365942Sgibbsint DH_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
24465942Sgibbs                        CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
24565942Sgibbs{
246115338Sgibbs    return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_DH, argl, argp,
24765942Sgibbs                                   new_func, dup_func, free_func);
248115338Sgibbs}
24974094Sgibbs
25065942Sgibbsint DH_set_ex_data(DH *d, int idx, void *arg)
25165942Sgibbs{
25265942Sgibbs    return (CRYPTO_set_ex_data(&d->ex_data, idx, arg));
25365942Sgibbs}
25465942Sgibbs
25565942Sgibbsvoid *DH_get_ex_data(DH *d, int idx)
25665942Sgibbs{
25765942Sgibbs    return (CRYPTO_get_ex_data(&d->ex_data, idx));
25865942Sgibbs}
25965942Sgibbs
26065942Sgibbsint DH_size(const DH *dh)
26165942Sgibbs{
26271390Sgibbs    return (BN_num_bytes(dh->p));
26365942Sgibbs}
26465942Sgibbs