os/ossrv/ssl/libcrypto/src/crypto/dh/dh_key.c
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
/* crypto/dh/dh_key.c */
sl@0
     2
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
sl@0
     3
 * All rights reserved.
sl@0
     4
 *
sl@0
     5
 * This package is an SSL implementation written
sl@0
     6
 * by Eric Young (eay@cryptsoft.com).
sl@0
     7
 * The implementation was written so as to conform with Netscapes SSL.
sl@0
     8
 * 
sl@0
     9
 * This library is free for commercial and non-commercial use as long as
sl@0
    10
 * the following conditions are aheared to.  The following conditions
sl@0
    11
 * apply to all code found in this distribution, be it the RC4, RSA,
sl@0
    12
 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
sl@0
    13
 * included with this distribution is covered by the same copyright terms
sl@0
    14
 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
sl@0
    15
 * 
sl@0
    16
 * Copyright remains Eric Young's, and as such any Copyright notices in
sl@0
    17
 * the code are not to be removed.
sl@0
    18
 * If this package is used in a product, Eric Young should be given attribution
sl@0
    19
 * as the author of the parts of the library used.
sl@0
    20
 * This can be in the form of a textual message at program startup or
sl@0
    21
 * in documentation (online or textual) provided with the package.
sl@0
    22
 * 
sl@0
    23
 * Redistribution and use in source and binary forms, with or without
sl@0
    24
 * modification, are permitted provided that the following conditions
sl@0
    25
 * are met:
sl@0
    26
 * 1. Redistributions of source code must retain the copyright
sl@0
    27
 *    notice, this list of conditions and the following disclaimer.
sl@0
    28
 * 2. Redistributions in binary form must reproduce the above copyright
sl@0
    29
 *    notice, this list of conditions and the following disclaimer in the
sl@0
    30
 *    documentation and/or other materials provided with the distribution.
sl@0
    31
 * 3. All advertising materials mentioning features or use of this software
sl@0
    32
 *    must display the following acknowledgement:
sl@0
    33
 *    "This product includes cryptographic software written by
sl@0
    34
 *     Eric Young (eay@cryptsoft.com)"
sl@0
    35
 *    The word 'cryptographic' can be left out if the rouines from the library
sl@0
    36
 *    being used are not cryptographic related :-).
sl@0
    37
 * 4. If you include any Windows specific code (or a derivative thereof) from 
sl@0
    38
 *    the apps directory (application code) you must include an acknowledgement:
sl@0
    39
 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
sl@0
    40
 * 
sl@0
    41
 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
sl@0
    42
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
sl@0
    43
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
sl@0
    44
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
sl@0
    45
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
sl@0
    46
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
sl@0
    47
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
sl@0
    48
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
sl@0
    49
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
sl@0
    50
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
sl@0
    51
 * SUCH DAMAGE.
sl@0
    52
 * 
sl@0
    53
 * The licence and distribution terms for any publically available version or
sl@0
    54
 * derivative of this code cannot be changed.  i.e. this code cannot simply be
sl@0
    55
 * copied and put under another distribution licence
sl@0
    56
 * [including the GNU Public Licence.]
sl@0
    57
 */
sl@0
    58
 
sl@0
    59
/*
sl@0
    60
 © Portions copyright (c) 2006 Nokia Corporation.  All rights reserved.
sl@0
    61
 */
sl@0
    62
sl@0
    63
sl@0
    64
#include <stdio.h>
sl@0
    65
#include "cryptlib.h"
sl@0
    66
#include <openssl/bn.h>
sl@0
    67
#include <openssl/rand.h>
sl@0
    68
#include <openssl/dh.h>
sl@0
    69
#if (defined(SYMBIAN) && (defined(__WINSCW__) || defined(__WINS__)))
sl@0
    70
#include "libcrypto_wsd_macros.h"
sl@0
    71
#include "libcrypto_wsd.h"
sl@0
    72
#endif
sl@0
    73
sl@0
    74
sl@0
    75
static int generate_key(DH *dh);
sl@0
    76
static int compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh);
sl@0
    77
static int dh_bn_mod_exp(const DH *dh, BIGNUM *r,
sl@0
    78
			const BIGNUM *a, const BIGNUM *p,
sl@0
    79
			const BIGNUM *m, BN_CTX *ctx,
sl@0
    80
			BN_MONT_CTX *m_ctx);
sl@0
    81
static int dh_init(DH *dh);
sl@0
    82
static int dh_finish(DH *dh);
sl@0
    83
sl@0
    84
EXPORT_C int DH_generate_key(DH *dh)
sl@0
    85
	{
sl@0
    86
	return dh->meth->generate_key(dh);
sl@0
    87
	}
sl@0
    88
sl@0
    89
EXPORT_C int DH_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh)
sl@0
    90
	{
sl@0
    91
	return dh->meth->compute_key(key, pub_key, dh);
sl@0
    92
	}
sl@0
    93
sl@0
    94
#ifndef EMULATOR
sl@0
    95
static DH_METHOD dh_ossl = {
sl@0
    96
"OpenSSL DH Method",
sl@0
    97
generate_key,
sl@0
    98
compute_key,
sl@0
    99
dh_bn_mod_exp,
sl@0
   100
dh_init,
sl@0
   101
dh_finish,
sl@0
   102
0,
sl@0
   103
NULL,
sl@0
   104
NULL
sl@0
   105
};
sl@0
   106
#else
sl@0
   107
GET_STATIC_VAR_FROM_TLS(dh_ossl,dh_key,DH_METHOD)
sl@0
   108
#define dh_ossl (*GET_WSD_VAR_NAME(dh_ossl,dh_key, s)())
sl@0
   109
const DH_METHOD temp_s_dh_ossl = {
sl@0
   110
"OpenSSL DH Method",
sl@0
   111
generate_key,
sl@0
   112
compute_key,
sl@0
   113
dh_bn_mod_exp,
sl@0
   114
dh_init,
sl@0
   115
dh_finish,
sl@0
   116
0,
sl@0
   117
NULL,
sl@0
   118
NULL
sl@0
   119
};
sl@0
   120
sl@0
   121
#endif
sl@0
   122
EXPORT_C const DH_METHOD *DH_OpenSSL(void)
sl@0
   123
{
sl@0
   124
	return &dh_ossl;
sl@0
   125
}
sl@0
   126
sl@0
   127
static int generate_key(DH *dh)
sl@0
   128
	{
sl@0
   129
	int ok=0;
sl@0
   130
	int generate_new_key=0;
sl@0
   131
	unsigned l;
sl@0
   132
	BN_CTX *ctx;
sl@0
   133
	BN_MONT_CTX *mont=NULL;
sl@0
   134
	BIGNUM *pub_key=NULL,*priv_key=NULL;
sl@0
   135
sl@0
   136
	ctx = BN_CTX_new();
sl@0
   137
	if (ctx == NULL) goto err;
sl@0
   138
sl@0
   139
	if (dh->priv_key == NULL)
sl@0
   140
		{
sl@0
   141
		priv_key=BN_new();
sl@0
   142
		if (priv_key == NULL) goto err;
sl@0
   143
		generate_new_key=1;
sl@0
   144
		}
sl@0
   145
	else
sl@0
   146
		priv_key=dh->priv_key;
sl@0
   147
sl@0
   148
	if (dh->pub_key == NULL)
sl@0
   149
		{
sl@0
   150
		pub_key=BN_new();
sl@0
   151
		if (pub_key == NULL) goto err;
sl@0
   152
		}
sl@0
   153
	else
sl@0
   154
		pub_key=dh->pub_key;
sl@0
   155
sl@0
   156
sl@0
   157
	if (dh->flags & DH_FLAG_CACHE_MONT_P)
sl@0
   158
		{
sl@0
   159
		mont = BN_MONT_CTX_set_locked(&dh->method_mont_p,
sl@0
   160
				CRYPTO_LOCK_DH, dh->p, ctx);
sl@0
   161
		if (!mont)
sl@0
   162
			goto err;
sl@0
   163
		}
sl@0
   164
sl@0
   165
	if (generate_new_key)
sl@0
   166
		{
sl@0
   167
		l = dh->length ? dh->length : BN_num_bits(dh->p)-1; /* secret exponent length */
sl@0
   168
		if (!BN_rand(priv_key, l, 0, 0)) goto err;
sl@0
   169
		}
sl@0
   170
sl@0
   171
	{
sl@0
   172
		BIGNUM local_prk;
sl@0
   173
		BIGNUM *prk;
sl@0
   174
sl@0
   175
		if ((dh->flags & DH_FLAG_NO_EXP_CONSTTIME) == 0)
sl@0
   176
			{
sl@0
   177
			BN_init(&local_prk);
sl@0
   178
			prk = &local_prk;
sl@0
   179
			BN_with_flags(prk, priv_key, BN_FLG_CONSTTIME);
sl@0
   180
			}
sl@0
   181
		else
sl@0
   182
			prk = priv_key;
sl@0
   183
sl@0
   184
		if (!dh->meth->bn_mod_exp(dh, pub_key, dh->g, prk, dh->p, ctx, mont)) goto err;
sl@0
   185
	}
sl@0
   186
		
sl@0
   187
	dh->pub_key=pub_key;
sl@0
   188
	dh->priv_key=priv_key;
sl@0
   189
	ok=1;
sl@0
   190
err:
sl@0
   191
	if (ok != 1)
sl@0
   192
		DHerr(DH_F_GENERATE_KEY,ERR_R_BN_LIB);
sl@0
   193
sl@0
   194
	if ((pub_key != NULL)  && (dh->pub_key == NULL))  BN_free(pub_key);
sl@0
   195
	if ((priv_key != NULL) && (dh->priv_key == NULL)) BN_free(priv_key);
sl@0
   196
	BN_CTX_free(ctx);
sl@0
   197
	return(ok);
sl@0
   198
	}
sl@0
   199
sl@0
   200
static int compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh)
sl@0
   201
	{
sl@0
   202
	BN_CTX *ctx=NULL;
sl@0
   203
	BN_MONT_CTX *mont=NULL;
sl@0
   204
	BIGNUM *tmp;
sl@0
   205
	int ret= -1;
sl@0
   206
        int check_result;
sl@0
   207
	if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS)
sl@0
   208
		{
sl@0
   209
		DHerr(DH_F_COMPUTE_KEY,DH_R_MODULUS_TOO_LARGE);
sl@0
   210
		goto err;
sl@0
   211
		}
sl@0
   212
	ctx = BN_CTX_new();
sl@0
   213
	if (ctx == NULL) goto err;
sl@0
   214
	BN_CTX_start(ctx);
sl@0
   215
	tmp = BN_CTX_get(ctx);
sl@0
   216
	
sl@0
   217
	if (dh->priv_key == NULL)
sl@0
   218
		{
sl@0
   219
		DHerr(DH_F_COMPUTE_KEY,DH_R_NO_PRIVATE_VALUE);
sl@0
   220
		goto err;
sl@0
   221
		}
sl@0
   222
sl@0
   223
	if (dh->flags & DH_FLAG_CACHE_MONT_P)
sl@0
   224
		{
sl@0
   225
		mont = BN_MONT_CTX_set_locked(&dh->method_mont_p,
sl@0
   226
				CRYPTO_LOCK_DH, dh->p, ctx);
sl@0
   227
		if ((dh->flags & DH_FLAG_NO_EXP_CONSTTIME) == 0)
sl@0
   228
			{
sl@0
   229
			/* XXX */
sl@0
   230
			BN_set_flags(dh->priv_key, BN_FLG_CONSTTIME);
sl@0
   231
			}
sl@0
   232
		if (!mont)
sl@0
   233
			goto err;
sl@0
   234
		}
sl@0
   235
sl@0
   236
        if (!DH_check_pub_key(dh, pub_key, &check_result) || check_result)
sl@0
   237
		{
sl@0
   238
		DHerr(DH_F_COMPUTE_KEY,DH_R_INVALID_PUBKEY);
sl@0
   239
		goto err;
sl@0
   240
		}
sl@0
   241
sl@0
   242
	if (!dh->meth->bn_mod_exp(dh, tmp, pub_key, dh->priv_key,dh->p,ctx,mont))
sl@0
   243
		{
sl@0
   244
		DHerr(DH_F_COMPUTE_KEY,ERR_R_BN_LIB);
sl@0
   245
		goto err;
sl@0
   246
		}
sl@0
   247
sl@0
   248
	ret=BN_bn2bin(tmp,key);
sl@0
   249
err:
sl@0
   250
	if (ctx != NULL)
sl@0
   251
		{
sl@0
   252
		BN_CTX_end(ctx);
sl@0
   253
		BN_CTX_free(ctx);
sl@0
   254
		}
sl@0
   255
	return(ret);
sl@0
   256
	}
sl@0
   257
sl@0
   258
static int dh_bn_mod_exp(const DH *dh, BIGNUM *r,
sl@0
   259
			const BIGNUM *a, const BIGNUM *p,
sl@0
   260
			const BIGNUM *m, BN_CTX *ctx,
sl@0
   261
			BN_MONT_CTX *m_ctx)
sl@0
   262
	{
sl@0
   263
	/* If a is only one word long and constant time is false, use the faster
sl@0
   264
	 * exponenentiation function.
sl@0
   265
	 */
sl@0
   266
	if (a->top == 1 && ((dh->flags & DH_FLAG_NO_EXP_CONSTTIME) != 0))
sl@0
   267
		{
sl@0
   268
		BN_ULONG A = a->d[0];
sl@0
   269
		return BN_mod_exp_mont_word(r,A,p,m,ctx,m_ctx);
sl@0
   270
		}
sl@0
   271
	else
sl@0
   272
		return BN_mod_exp_mont(r,a,p,m,ctx,m_ctx);
sl@0
   273
	}
sl@0
   274
sl@0
   275
sl@0
   276
static int dh_init(DH *dh)
sl@0
   277
	{
sl@0
   278
	dh->flags |= DH_FLAG_CACHE_MONT_P;
sl@0
   279
	return(1);
sl@0
   280
	}
sl@0
   281
sl@0
   282
static int dh_finish(DH *dh)
sl@0
   283
	{
sl@0
   284
	if(dh->method_mont_p)
sl@0
   285
		BN_MONT_CTX_free(dh->method_mont_p);
sl@0
   286
	return(1);
sl@0
   287
	}