1/* 2 * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project 3 * 2006. 4 */ 5/* ==================================================================== 6 * Copyright (c) 2006 The OpenSSL Project. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in 17 * the documentation and/or other materials provided with the 18 * distribution. 19 * 20 * 3. All advertising materials mentioning features or use of this 21 * software must display the following acknowledgment: 22 * "This product includes software developed by the OpenSSL Project 23 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 24 * 25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 26 * endorse or promote products derived from this software without 27 * prior written permission. For written permission, please contact 28 * licensing@OpenSSL.org. 29 * 30 * 5. Products derived from this software may not be called "OpenSSL" 31 * nor may "OpenSSL" appear in their names without prior written 32 * permission of the OpenSSL Project. 33 * 34 * 6. Redistributions of any form whatsoever must retain the following 35 * acknowledgment: 36 * "This product includes software developed by the OpenSSL Project 37 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 38 * 39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 50 * OF THE POSSIBILITY OF SUCH DAMAGE. 51 * ==================================================================== 52 * 53 * This product includes cryptographic software written by Eric Young 54 * (eay@cryptsoft.com). This product includes software written by Tim 55 * Hudson (tjh@cryptsoft.com). 56 * 57 */ 58 59#include <stdio.h> 60#include "cryptlib.h" 61#include <openssl/asn1t.h> 62#include <openssl/x509.h> 63#include <openssl/evp.h> 64#include <openssl/dh.h> 65#include <openssl/bn.h> 66#ifndef OPENSSL_NO_DSA 67# include <openssl/dsa.h> 68#endif 69#include <openssl/objects.h> 70#include "evp_locl.h" 71 72/* DH pkey context structure */ 73 74typedef struct { 75 /* Parameter gen parameters */ 76 int prime_len; 77 int generator; 78 int use_dsa; 79 int subprime_len; 80 /* message digest used for parameter generation */ 81 const EVP_MD *md; 82 int rfc5114_param; 83 /* Keygen callback info */ 84 int gentmp[2]; 85 /* KDF (if any) to use for DH */ 86 char kdf_type; 87 /* OID to use for KDF */ 88 ASN1_OBJECT *kdf_oid; 89 /* Message digest to use for key derivation */ 90 const EVP_MD *kdf_md; 91 /* User key material */ 92 unsigned char *kdf_ukm; 93 size_t kdf_ukmlen; 94 /* KDF output length */ 95 size_t kdf_outlen; 96} DH_PKEY_CTX; 97 98static int pkey_dh_init(EVP_PKEY_CTX *ctx) 99{ 100 DH_PKEY_CTX *dctx; 101 dctx = OPENSSL_malloc(sizeof(DH_PKEY_CTX)); 102 if (!dctx) 103 return 0; 104 dctx->prime_len = 1024; 105 dctx->subprime_len = -1; 106 dctx->generator = 2; 107 dctx->use_dsa = 0; 108 dctx->md = NULL; 109 dctx->rfc5114_param = 0; 110 111 dctx->kdf_type = EVP_PKEY_DH_KDF_NONE; 112 dctx->kdf_oid = NULL; 113 dctx->kdf_md = NULL; 114 dctx->kdf_ukm = NULL; 115 dctx->kdf_ukmlen = 0; 116 dctx->kdf_outlen = 0; 117 118 ctx->data = dctx; 119 ctx->keygen_info = dctx->gentmp; 120 ctx->keygen_info_count = 2; 121 122 return 1; 123} 124 125static int pkey_dh_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) 126{ 127 DH_PKEY_CTX *dctx, *sctx; 128 if (!pkey_dh_init(dst)) 129 return 0; 130 sctx = src->data; 131 dctx = dst->data; 132 dctx->prime_len = sctx->prime_len; 133 dctx->subprime_len = sctx->subprime_len; 134 dctx->generator = sctx->generator; 135 dctx->use_dsa = sctx->use_dsa; 136 dctx->md = sctx->md; 137 dctx->rfc5114_param = sctx->rfc5114_param; 138 139 dctx->kdf_type = sctx->kdf_type; 140 dctx->kdf_oid = OBJ_dup(sctx->kdf_oid); 141 if (!dctx->kdf_oid) 142 return 0; 143 dctx->kdf_md = sctx->kdf_md; 144 if (dctx->kdf_ukm) { 145 dctx->kdf_ukm = BUF_memdup(sctx->kdf_ukm, sctx->kdf_ukmlen); 146 dctx->kdf_ukmlen = sctx->kdf_ukmlen; 147 } 148 dctx->kdf_outlen = sctx->kdf_outlen; 149 return 1; 150} 151 152static void pkey_dh_cleanup(EVP_PKEY_CTX *ctx) 153{ 154 DH_PKEY_CTX *dctx = ctx->data; 155 if (dctx) { 156 if (dctx->kdf_ukm) 157 OPENSSL_free(dctx->kdf_ukm); 158 if (dctx->kdf_oid) 159 ASN1_OBJECT_free(dctx->kdf_oid); 160 OPENSSL_free(dctx); 161 } 162} 163 164static int pkey_dh_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) 165{ 166 DH_PKEY_CTX *dctx = ctx->data; 167 switch (type) { 168 case EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN: 169 if (p1 < 256) 170 return -2; 171 dctx->prime_len = p1; 172 return 1; 173 174 case EVP_PKEY_CTRL_DH_PARAMGEN_SUBPRIME_LEN: 175 if (dctx->use_dsa == 0) 176 return -2; 177 dctx->subprime_len = p1; 178 return 1; 179 180 case EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR: 181 if (dctx->use_dsa) 182 return -2; 183 dctx->generator = p1; 184 return 1; 185 186 case EVP_PKEY_CTRL_DH_PARAMGEN_TYPE: 187#ifdef OPENSSL_NO_DSA 188 if (p1 != 0) 189 return -2; 190#else 191 if (p1 < 0 || p1 > 2) 192 return -2; 193#endif 194 dctx->use_dsa = p1; 195 return 1; 196 197 case EVP_PKEY_CTRL_DH_RFC5114: 198 if (p1 < 1 || p1 > 3) 199 return -2; 200 dctx->rfc5114_param = p1; 201 return 1; 202 203 case EVP_PKEY_CTRL_PEER_KEY: 204 /* Default behaviour is OK */ 205 return 1; 206 207 case EVP_PKEY_CTRL_DH_KDF_TYPE: 208 if (p1 == -2) 209 return dctx->kdf_type; 210 if (p1 != EVP_PKEY_DH_KDF_NONE && p1 != EVP_PKEY_DH_KDF_X9_42) 211 return -2; 212 dctx->kdf_type = p1; 213 return 1; 214 215 case EVP_PKEY_CTRL_DH_KDF_MD: 216 dctx->kdf_md = p2; 217 return 1; 218 219 case EVP_PKEY_CTRL_GET_DH_KDF_MD: 220 *(const EVP_MD **)p2 = dctx->kdf_md; 221 return 1; 222 223 case EVP_PKEY_CTRL_DH_KDF_OUTLEN: 224 if (p1 <= 0) 225 return -2; 226 dctx->kdf_outlen = (size_t)p1; 227 return 1; 228 229 case EVP_PKEY_CTRL_GET_DH_KDF_OUTLEN: 230 *(int *)p2 = dctx->kdf_outlen; 231 return 1; 232 233 case EVP_PKEY_CTRL_DH_KDF_UKM: 234 if (dctx->kdf_ukm) 235 OPENSSL_free(dctx->kdf_ukm); 236 dctx->kdf_ukm = p2; 237 if (p2) 238 dctx->kdf_ukmlen = p1; 239 else 240 dctx->kdf_ukmlen = 0; 241 return 1; 242 243 case EVP_PKEY_CTRL_GET_DH_KDF_UKM: 244 *(unsigned char **)p2 = dctx->kdf_ukm; 245 return dctx->kdf_ukmlen; 246 247 case EVP_PKEY_CTRL_DH_KDF_OID: 248 if (dctx->kdf_oid) 249 ASN1_OBJECT_free(dctx->kdf_oid); 250 dctx->kdf_oid = p2; 251 return 1; 252 253 case EVP_PKEY_CTRL_GET_DH_KDF_OID: 254 *(ASN1_OBJECT **)p2 = dctx->kdf_oid; 255 return 1; 256 257 default: 258 return -2; 259 260 } 261} 262 263static int pkey_dh_ctrl_str(EVP_PKEY_CTX *ctx, 264 const char *type, const char *value) 265{ 266 if (!strcmp(type, "dh_paramgen_prime_len")) { 267 int len; 268 len = atoi(value); 269 return EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, len); 270 } 271 if (!strcmp(type, "dh_rfc5114")) { 272 DH_PKEY_CTX *dctx = ctx->data; 273 int len; 274 len = atoi(value); 275 if (len < 0 || len > 3) 276 return -2; 277 dctx->rfc5114_param = len; 278 return 1; 279 } 280 if (!strcmp(type, "dh_paramgen_generator")) { 281 int len; 282 len = atoi(value); 283 return EVP_PKEY_CTX_set_dh_paramgen_generator(ctx, len); 284 } 285 if (!strcmp(type, "dh_paramgen_subprime_len")) { 286 int len; 287 len = atoi(value); 288 return EVP_PKEY_CTX_set_dh_paramgen_subprime_len(ctx, len); 289 } 290 if (!strcmp(type, "dh_paramgen_type")) { 291 int typ; 292 typ = atoi(value); 293 return EVP_PKEY_CTX_set_dh_paramgen_type(ctx, typ); 294 } 295 return -2; 296} 297 298#ifndef OPENSSL_NO_DSA 299 300extern int dsa_builtin_paramgen(DSA *ret, size_t bits, size_t qbits, 301 const EVP_MD *evpmd, 302 const unsigned char *seed_in, size_t seed_len, 303 unsigned char *seed_out, int *counter_ret, 304 unsigned long *h_ret, BN_GENCB *cb); 305 306extern int dsa_builtin_paramgen2(DSA *ret, size_t L, size_t N, 307 const EVP_MD *evpmd, 308 const unsigned char *seed_in, 309 size_t seed_len, int idx, 310 unsigned char *seed_out, int *counter_ret, 311 unsigned long *h_ret, BN_GENCB *cb); 312 313static DSA *dsa_dh_generate(DH_PKEY_CTX *dctx, BN_GENCB *pcb) 314{ 315 DSA *ret; 316 int rv = 0; 317 int prime_len = dctx->prime_len; 318 int subprime_len = dctx->subprime_len; 319 const EVP_MD *md = dctx->md; 320 if (dctx->use_dsa > 2) 321 return NULL; 322 ret = DSA_new(); 323 if (!ret) 324 return NULL; 325 if (subprime_len == -1) { 326 if (prime_len >= 2048) 327 subprime_len = 256; 328 else 329 subprime_len = 160; 330 } 331 if (md == NULL) { 332 if (prime_len >= 2048) 333 md = EVP_sha256(); 334 else 335 md = EVP_sha1(); 336 } 337 if (dctx->use_dsa == 1) 338 rv = dsa_builtin_paramgen(ret, prime_len, subprime_len, md, 339 NULL, 0, NULL, NULL, NULL, pcb); 340 else if (dctx->use_dsa == 2) 341 rv = dsa_builtin_paramgen2(ret, prime_len, subprime_len, md, 342 NULL, 0, -1, NULL, NULL, NULL, pcb); 343 if (rv <= 0) { 344 DSA_free(ret); 345 return NULL; 346 } 347 return ret; 348} 349 350#endif 351 352static int pkey_dh_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) 353{ 354 DH *dh = NULL; 355 DH_PKEY_CTX *dctx = ctx->data; 356 BN_GENCB *pcb, cb; 357 int ret; 358 if (dctx->rfc5114_param) { 359 switch (dctx->rfc5114_param) { 360 case 1: 361 dh = DH_get_1024_160(); 362 break; 363 364 case 2: 365 dh = DH_get_2048_224(); 366 break; 367 368 case 3: 369 dh = DH_get_2048_256(); 370 break; 371 372 default: 373 return -2; 374 } 375 EVP_PKEY_assign(pkey, EVP_PKEY_DHX, dh); 376 return 1; 377 } 378 379 if (ctx->pkey_gencb) { 380 pcb = &cb; 381 evp_pkey_set_cb_translate(pcb, ctx); 382 } else 383 pcb = NULL; 384#ifndef OPENSSL_NO_DSA 385 if (dctx->use_dsa) { 386 DSA *dsa_dh; 387 dsa_dh = dsa_dh_generate(dctx, pcb); 388 if (!dsa_dh) 389 return 0; 390 dh = DSA_dup_DH(dsa_dh); 391 DSA_free(dsa_dh); 392 if (!dh) 393 return 0; 394 EVP_PKEY_assign(pkey, EVP_PKEY_DHX, dh); 395 return 1; 396 } 397#endif 398 dh = DH_new(); 399 if (!dh) 400 return 0; 401 ret = DH_generate_parameters_ex(dh, 402 dctx->prime_len, dctx->generator, pcb); 403 404 if (ret) 405 EVP_PKEY_assign_DH(pkey, dh); 406 else 407 DH_free(dh); 408 return ret; 409} 410 411static int pkey_dh_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) 412{ 413 DH *dh = NULL; 414 if (ctx->pkey == NULL) { 415 DHerr(DH_F_PKEY_DH_KEYGEN, DH_R_NO_PARAMETERS_SET); 416 return 0; 417 } 418 dh = DH_new(); 419 if (!dh) 420 return 0; 421 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, dh); 422 /* Note: if error return, pkey is freed by parent routine */ 423 if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey)) 424 return 0; 425 return DH_generate_key(pkey->pkey.dh); 426} 427 428static int pkey_dh_derive(EVP_PKEY_CTX *ctx, unsigned char *key, 429 size_t *keylen) 430{ 431 int ret; 432 DH *dh; 433 DH_PKEY_CTX *dctx = ctx->data; 434 BIGNUM *dhpub; 435 if (!ctx->pkey || !ctx->peerkey) { 436 DHerr(DH_F_PKEY_DH_DERIVE, DH_R_KEYS_NOT_SET); 437 return 0; 438 } 439 dh = ctx->pkey->pkey.dh; 440 dhpub = ctx->peerkey->pkey.dh->pub_key; 441 if (dctx->kdf_type == EVP_PKEY_DH_KDF_NONE) { 442 if (key == NULL) { 443 *keylen = DH_size(dh); 444 return 1; 445 } 446 ret = DH_compute_key(key, dhpub, dh); 447 if (ret < 0) 448 return ret; 449 *keylen = ret; 450 return 1; 451 } else if (dctx->kdf_type == EVP_PKEY_DH_KDF_X9_42) { 452 unsigned char *Z = NULL; 453 size_t Zlen = 0; 454 if (!dctx->kdf_outlen || !dctx->kdf_oid) 455 return 0; 456 if (key == NULL) { 457 *keylen = dctx->kdf_outlen; 458 return 1; 459 } 460 if (*keylen != dctx->kdf_outlen) 461 return 0; 462 ret = 0; 463 Zlen = DH_size(dh); 464 Z = OPENSSL_malloc(Zlen); 465 if (!Z) { 466 goto err; 467 } 468 if (DH_compute_key_padded(Z, dhpub, dh) <= 0) 469 goto err; 470 if (!DH_KDF_X9_42(key, *keylen, Z, Zlen, dctx->kdf_oid, 471 dctx->kdf_ukm, dctx->kdf_ukmlen, dctx->kdf_md)) 472 goto err; 473 *keylen = dctx->kdf_outlen; 474 ret = 1; 475 err: 476 if (Z) { 477 OPENSSL_cleanse(Z, Zlen); 478 OPENSSL_free(Z); 479 } 480 return ret; 481 } 482 return 1; 483} 484 485const EVP_PKEY_METHOD dh_pkey_meth = { 486 EVP_PKEY_DH, 487 0, 488 pkey_dh_init, 489 pkey_dh_copy, 490 pkey_dh_cleanup, 491 492 0, 493 pkey_dh_paramgen, 494 495 0, 496 pkey_dh_keygen, 497 498 0, 499 0, 500 501 0, 502 0, 503 504 0, 0, 505 506 0, 0, 0, 0, 507 508 0, 0, 509 510 0, 0, 511 512 0, 513 pkey_dh_derive, 514 515 pkey_dh_ctrl, 516 pkey_dh_ctrl_str 517}; 518 519const EVP_PKEY_METHOD dhx_pkey_meth = { 520 EVP_PKEY_DHX, 521 0, 522 pkey_dh_init, 523 pkey_dh_copy, 524 pkey_dh_cleanup, 525 526 0, 527 pkey_dh_paramgen, 528 529 0, 530 pkey_dh_keygen, 531 532 0, 533 0, 534 535 0, 536 0, 537 538 0, 0, 539 540 0, 0, 0, 0, 541 542 0, 0, 543 544 0, 0, 545 546 0, 547 pkey_dh_derive, 548 549 pkey_dh_ctrl, 550 pkey_dh_ctrl_str 551}; 552