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