10Sstevel@tonic-gate /* crypto/dh/dh_key.c */ 20Sstevel@tonic-gate /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 30Sstevel@tonic-gate * All rights reserved. 40Sstevel@tonic-gate * 50Sstevel@tonic-gate * This package is an SSL implementation written 60Sstevel@tonic-gate * by Eric Young (eay@cryptsoft.com). 70Sstevel@tonic-gate * The implementation was written so as to conform with Netscapes SSL. 80Sstevel@tonic-gate * 90Sstevel@tonic-gate * This library is free for commercial and non-commercial use as long as 100Sstevel@tonic-gate * the following conditions are aheared to. The following conditions 110Sstevel@tonic-gate * apply to all code found in this distribution, be it the RC4, RSA, 120Sstevel@tonic-gate * lhash, DES, etc., code; not just the SSL code. The SSL documentation 130Sstevel@tonic-gate * included with this distribution is covered by the same copyright terms 140Sstevel@tonic-gate * except that the holder is Tim Hudson (tjh@cryptsoft.com). 150Sstevel@tonic-gate * 160Sstevel@tonic-gate * Copyright remains Eric Young's, and as such any Copyright notices in 170Sstevel@tonic-gate * the code are not to be removed. 180Sstevel@tonic-gate * If this package is used in a product, Eric Young should be given attribution 190Sstevel@tonic-gate * as the author of the parts of the library used. 200Sstevel@tonic-gate * This can be in the form of a textual message at program startup or 210Sstevel@tonic-gate * in documentation (online or textual) provided with the package. 220Sstevel@tonic-gate * 230Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 240Sstevel@tonic-gate * modification, are permitted provided that the following conditions 250Sstevel@tonic-gate * are met: 260Sstevel@tonic-gate * 1. Redistributions of source code must retain the copyright 270Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 280Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 290Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the 300Sstevel@tonic-gate * documentation and/or other materials provided with the distribution. 310Sstevel@tonic-gate * 3. All advertising materials mentioning features or use of this software 320Sstevel@tonic-gate * must display the following acknowledgement: 330Sstevel@tonic-gate * "This product includes cryptographic software written by 340Sstevel@tonic-gate * Eric Young (eay@cryptsoft.com)" 350Sstevel@tonic-gate * The word 'cryptographic' can be left out if the rouines from the library 360Sstevel@tonic-gate * being used are not cryptographic related :-). 370Sstevel@tonic-gate * 4. If you include any Windows specific code (or a derivative thereof) from 380Sstevel@tonic-gate * the apps directory (application code) you must include an acknowledgement: 390Sstevel@tonic-gate * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 400Sstevel@tonic-gate * 410Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 420Sstevel@tonic-gate * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 430Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 440Sstevel@tonic-gate * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 450Sstevel@tonic-gate * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 460Sstevel@tonic-gate * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 470Sstevel@tonic-gate * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 480Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 490Sstevel@tonic-gate * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 500Sstevel@tonic-gate * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 510Sstevel@tonic-gate * SUCH DAMAGE. 520Sstevel@tonic-gate * 530Sstevel@tonic-gate * The licence and distribution terms for any publically available version or 540Sstevel@tonic-gate * derivative of this code cannot be changed. i.e. this code cannot simply be 550Sstevel@tonic-gate * copied and put under another distribution licence 560Sstevel@tonic-gate * [including the GNU Public Licence.] 570Sstevel@tonic-gate */ 580Sstevel@tonic-gate 590Sstevel@tonic-gate #include <stdio.h> 600Sstevel@tonic-gate #include "cryptlib.h" 610Sstevel@tonic-gate #include <openssl/bn.h> 620Sstevel@tonic-gate #include <openssl/rand.h> 630Sstevel@tonic-gate #include <openssl/dh.h> 640Sstevel@tonic-gate 650Sstevel@tonic-gate static int generate_key(DH *dh); 660Sstevel@tonic-gate static int compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh); 670Sstevel@tonic-gate static int dh_bn_mod_exp(const DH *dh, BIGNUM *r, 680Sstevel@tonic-gate const BIGNUM *a, const BIGNUM *p, 690Sstevel@tonic-gate const BIGNUM *m, BN_CTX *ctx, 700Sstevel@tonic-gate BN_MONT_CTX *m_ctx); 710Sstevel@tonic-gate static int dh_init(DH *dh); 720Sstevel@tonic-gate static int dh_finish(DH *dh); 730Sstevel@tonic-gate 740Sstevel@tonic-gate int DH_generate_key(DH *dh) 750Sstevel@tonic-gate { 760Sstevel@tonic-gate return dh->meth->generate_key(dh); 770Sstevel@tonic-gate } 780Sstevel@tonic-gate 790Sstevel@tonic-gate int DH_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh) 800Sstevel@tonic-gate { 810Sstevel@tonic-gate return dh->meth->compute_key(key, pub_key, dh); 820Sstevel@tonic-gate } 830Sstevel@tonic-gate 840Sstevel@tonic-gate static DH_METHOD dh_ossl = { 850Sstevel@tonic-gate "OpenSSL DH Method", 860Sstevel@tonic-gate generate_key, 870Sstevel@tonic-gate compute_key, 880Sstevel@tonic-gate dh_bn_mod_exp, 890Sstevel@tonic-gate dh_init, 900Sstevel@tonic-gate dh_finish, 910Sstevel@tonic-gate 0, 92*2139Sjp161948 NULL, 930Sstevel@tonic-gate NULL 940Sstevel@tonic-gate }; 950Sstevel@tonic-gate 960Sstevel@tonic-gate const DH_METHOD *DH_OpenSSL(void) 970Sstevel@tonic-gate { 980Sstevel@tonic-gate return &dh_ossl; 990Sstevel@tonic-gate } 1000Sstevel@tonic-gate 1010Sstevel@tonic-gate static int generate_key(DH *dh) 1020Sstevel@tonic-gate { 1030Sstevel@tonic-gate int ok=0; 1040Sstevel@tonic-gate int generate_new_key=0; 1050Sstevel@tonic-gate unsigned l; 1060Sstevel@tonic-gate BN_CTX *ctx; 107*2139Sjp161948 BN_MONT_CTX *mont=NULL; 1080Sstevel@tonic-gate BIGNUM *pub_key=NULL,*priv_key=NULL; 1090Sstevel@tonic-gate 1100Sstevel@tonic-gate ctx = BN_CTX_new(); 1110Sstevel@tonic-gate if (ctx == NULL) goto err; 1120Sstevel@tonic-gate 1130Sstevel@tonic-gate if (dh->priv_key == NULL) 1140Sstevel@tonic-gate { 1150Sstevel@tonic-gate priv_key=BN_new(); 1160Sstevel@tonic-gate if (priv_key == NULL) goto err; 1170Sstevel@tonic-gate generate_new_key=1; 1180Sstevel@tonic-gate } 1190Sstevel@tonic-gate else 1200Sstevel@tonic-gate priv_key=dh->priv_key; 1210Sstevel@tonic-gate 1220Sstevel@tonic-gate if (dh->pub_key == NULL) 1230Sstevel@tonic-gate { 1240Sstevel@tonic-gate pub_key=BN_new(); 1250Sstevel@tonic-gate if (pub_key == NULL) goto err; 1260Sstevel@tonic-gate } 1270Sstevel@tonic-gate else 1280Sstevel@tonic-gate pub_key=dh->pub_key; 1290Sstevel@tonic-gate 130*2139Sjp161948 131*2139Sjp161948 if (dh->flags & DH_FLAG_CACHE_MONT_P) 1320Sstevel@tonic-gate { 133*2139Sjp161948 mont = BN_MONT_CTX_set_locked(&dh->method_mont_p, 134*2139Sjp161948 CRYPTO_LOCK_DH, dh->p, ctx); 135*2139Sjp161948 if (!mont) 136*2139Sjp161948 goto err; 1370Sstevel@tonic-gate } 1380Sstevel@tonic-gate 1390Sstevel@tonic-gate if (generate_new_key) 1400Sstevel@tonic-gate { 1410Sstevel@tonic-gate l = dh->length ? dh->length : BN_num_bits(dh->p)-1; /* secret exponent length */ 1420Sstevel@tonic-gate if (!BN_rand(priv_key, l, 0, 0)) goto err; 1430Sstevel@tonic-gate } 144*2139Sjp161948 145*2139Sjp161948 { 146*2139Sjp161948 BIGNUM local_prk; 147*2139Sjp161948 BIGNUM *prk; 148*2139Sjp161948 149*2139Sjp161948 if ((dh->flags & DH_FLAG_NO_EXP_CONSTTIME) == 0) 150*2139Sjp161948 { 151*2139Sjp161948 BN_init(&local_prk); 152*2139Sjp161948 prk = &local_prk; 153*2139Sjp161948 BN_with_flags(prk, priv_key, BN_FLG_EXP_CONSTTIME); 154*2139Sjp161948 } 155*2139Sjp161948 else 156*2139Sjp161948 prk = priv_key; 157*2139Sjp161948 158*2139Sjp161948 if (!dh->meth->bn_mod_exp(dh, pub_key, dh->g, prk, dh->p, ctx, mont)) goto err; 159*2139Sjp161948 } 1600Sstevel@tonic-gate 1610Sstevel@tonic-gate dh->pub_key=pub_key; 1620Sstevel@tonic-gate dh->priv_key=priv_key; 1630Sstevel@tonic-gate ok=1; 1640Sstevel@tonic-gate err: 1650Sstevel@tonic-gate if (ok != 1) 166*2139Sjp161948 DHerr(DH_F_GENERATE_KEY,ERR_R_BN_LIB); 1670Sstevel@tonic-gate 1680Sstevel@tonic-gate if ((pub_key != NULL) && (dh->pub_key == NULL)) BN_free(pub_key); 1690Sstevel@tonic-gate if ((priv_key != NULL) && (dh->priv_key == NULL)) BN_free(priv_key); 1700Sstevel@tonic-gate BN_CTX_free(ctx); 1710Sstevel@tonic-gate return(ok); 1720Sstevel@tonic-gate } 1730Sstevel@tonic-gate 1740Sstevel@tonic-gate static int compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh) 1750Sstevel@tonic-gate { 1760Sstevel@tonic-gate BN_CTX *ctx; 177*2139Sjp161948 BN_MONT_CTX *mont=NULL; 1780Sstevel@tonic-gate BIGNUM *tmp; 1790Sstevel@tonic-gate int ret= -1; 180*2139Sjp161948 int check_result; 1810Sstevel@tonic-gate 1820Sstevel@tonic-gate ctx = BN_CTX_new(); 1830Sstevel@tonic-gate if (ctx == NULL) goto err; 1840Sstevel@tonic-gate BN_CTX_start(ctx); 1850Sstevel@tonic-gate tmp = BN_CTX_get(ctx); 1860Sstevel@tonic-gate 1870Sstevel@tonic-gate if (dh->priv_key == NULL) 1880Sstevel@tonic-gate { 189*2139Sjp161948 DHerr(DH_F_COMPUTE_KEY,DH_R_NO_PRIVATE_VALUE); 1900Sstevel@tonic-gate goto err; 1910Sstevel@tonic-gate } 192*2139Sjp161948 193*2139Sjp161948 if (dh->flags & DH_FLAG_CACHE_MONT_P) 1940Sstevel@tonic-gate { 195*2139Sjp161948 mont = BN_MONT_CTX_set_locked(&dh->method_mont_p, 196*2139Sjp161948 CRYPTO_LOCK_DH, dh->p, ctx); 197*2139Sjp161948 if ((dh->flags & DH_FLAG_NO_EXP_CONSTTIME) == 0) 198*2139Sjp161948 { 199*2139Sjp161948 /* XXX */ 200*2139Sjp161948 BN_set_flags(dh->priv_key, BN_FLG_EXP_CONSTTIME); 201*2139Sjp161948 } 202*2139Sjp161948 if (!mont) 203*2139Sjp161948 goto err; 2040Sstevel@tonic-gate } 2050Sstevel@tonic-gate 206*2139Sjp161948 if (!DH_check_pub_key(dh, pub_key, &check_result) || check_result) 207*2139Sjp161948 { 208*2139Sjp161948 DHerr(DH_F_COMPUTE_KEY,DH_R_INVALID_PUBKEY); 209*2139Sjp161948 goto err; 210*2139Sjp161948 } 211*2139Sjp161948 2120Sstevel@tonic-gate if (!dh->meth->bn_mod_exp(dh, tmp, pub_key, dh->priv_key,dh->p,ctx,mont)) 2130Sstevel@tonic-gate { 214*2139Sjp161948 DHerr(DH_F_COMPUTE_KEY,ERR_R_BN_LIB); 2150Sstevel@tonic-gate goto err; 2160Sstevel@tonic-gate } 2170Sstevel@tonic-gate 2180Sstevel@tonic-gate ret=BN_bn2bin(tmp,key); 2190Sstevel@tonic-gate err: 2200Sstevel@tonic-gate BN_CTX_end(ctx); 2210Sstevel@tonic-gate BN_CTX_free(ctx); 2220Sstevel@tonic-gate return(ret); 2230Sstevel@tonic-gate } 2240Sstevel@tonic-gate 2250Sstevel@tonic-gate static int dh_bn_mod_exp(const DH *dh, BIGNUM *r, 2260Sstevel@tonic-gate const BIGNUM *a, const BIGNUM *p, 2270Sstevel@tonic-gate const BIGNUM *m, BN_CTX *ctx, 2280Sstevel@tonic-gate BN_MONT_CTX *m_ctx) 2290Sstevel@tonic-gate { 230*2139Sjp161948 /* If a is only one word long and constant time is false, use the faster 231*2139Sjp161948 * exponenentiation function. 232*2139Sjp161948 */ 233*2139Sjp161948 if (a->top == 1 && ((dh->flags & DH_FLAG_NO_EXP_CONSTTIME) != 0)) 2340Sstevel@tonic-gate { 2350Sstevel@tonic-gate BN_ULONG A = a->d[0]; 2360Sstevel@tonic-gate return BN_mod_exp_mont_word(r,A,p,m,ctx,m_ctx); 2370Sstevel@tonic-gate } 2380Sstevel@tonic-gate else 2390Sstevel@tonic-gate return BN_mod_exp_mont(r,a,p,m,ctx,m_ctx); 2400Sstevel@tonic-gate } 2410Sstevel@tonic-gate 2420Sstevel@tonic-gate 2430Sstevel@tonic-gate static int dh_init(DH *dh) 2440Sstevel@tonic-gate { 2450Sstevel@tonic-gate dh->flags |= DH_FLAG_CACHE_MONT_P; 2460Sstevel@tonic-gate return(1); 2470Sstevel@tonic-gate } 2480Sstevel@tonic-gate 2490Sstevel@tonic-gate static int dh_finish(DH *dh) 2500Sstevel@tonic-gate { 2510Sstevel@tonic-gate if(dh->method_mont_p) 252*2139Sjp161948 BN_MONT_CTX_free(dh->method_mont_p); 2530Sstevel@tonic-gate return(1); 2540Sstevel@tonic-gate } 255