1 /* $NetBSD: dh.c,v 1.2 2017/01/28 21:31:47 christos Exp $ */ 2 3 /* 4 * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan 5 * (Royal Institute of Technology, Stockholm, Sweden). 6 * 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 the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * 3. Neither the name of the Institute nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #ifdef HAVE_CONFIG_H 37 #include <config.h> 38 #endif 39 #include <krb5/roken.h> 40 41 #include <krb5/krb5-types.h> 42 #include <krb5/rfc2459_asn1.h> 43 44 #include <dh.h> 45 46 /** 47 * @page page_dh DH - Diffie-Hellman key exchange 48 * 49 * Diffie-Hellman key exchange is a protocol that allows two parties 50 * to establish a shared secret key. 51 * 52 * Include and example how to use DH_new() and friends here. 53 * 54 * See the library functions here: @ref hcrypto_dh 55 */ 56 57 /** 58 * Create a new DH object using DH_new_method(NULL), see DH_new_method(). 59 * 60 * @return a newly allocated DH object. 61 * 62 * @ingroup hcrypto_dh 63 */ 64 65 DH * 66 DH_new(void) 67 { 68 return DH_new_method(NULL); 69 } 70 71 /** 72 * Create a new DH object from the given engine, if the NULL is used, 73 * the default engine is used. Free the DH object with DH_free(). 74 * 75 * @param engine The engine to use to allocate the DH object. 76 * 77 * @return a newly allocated DH object. 78 * 79 * @ingroup hcrypto_dh 80 */ 81 82 DH * 83 DH_new_method(ENGINE *engine) 84 { 85 DH *dh; 86 87 dh = calloc(1, sizeof(*dh)); 88 if (dh == NULL) 89 return NULL; 90 91 dh->references = 1; 92 93 if (engine) { 94 ENGINE_up_ref(engine); 95 dh->engine = engine; 96 } else { 97 dh->engine = ENGINE_get_default_DH(); 98 } 99 100 if (dh->engine) { 101 dh->meth = ENGINE_get_DH(dh->engine); 102 if (dh->meth == NULL) { 103 ENGINE_finish(engine); 104 free(dh); 105 return 0; 106 } 107 } 108 109 if (dh->meth == NULL) 110 dh->meth = DH_get_default_method(); 111 112 (*dh->meth->init)(dh); 113 114 return dh; 115 } 116 117 /** 118 * Free a DH object and release related resources, like ENGINE, that 119 * the object was using. 120 * 121 * @param dh object to be freed. 122 * 123 * @ingroup hcrypto_dh 124 */ 125 126 void 127 DH_free(DH *dh) 128 { 129 if (dh->references <= 0) 130 abort(); 131 132 if (--dh->references > 0) 133 return; 134 135 (*dh->meth->finish)(dh); 136 137 if (dh->engine) 138 ENGINE_finish(dh->engine); 139 140 #define free_if(f) if (f) { BN_free(f); } 141 free_if(dh->p); 142 free_if(dh->g); 143 free_if(dh->pub_key); 144 free_if(dh->priv_key); 145 free_if(dh->q); 146 free_if(dh->j); 147 free_if(dh->counter); 148 #undef free_if 149 150 memset(dh, 0, sizeof(*dh)); 151 free(dh); 152 } 153 154 /** 155 * Add a reference to the DH object. The object should be free with 156 * DH_free() to drop the reference. 157 * 158 * @param dh the object to increase the reference count too. 159 * 160 * @return the updated reference count, can't safely be used except 161 * for debug printing. 162 * 163 * @ingroup hcrypto_dh 164 */ 165 166 int 167 DH_up_ref(DH *dh) 168 { 169 return ++dh->references; 170 } 171 172 /** 173 * The maximum output size of the DH_compute_key() function. 174 * 175 * @param dh The DH object to get the size from. 176 * 177 * @return the maximum size in bytes of the out data. 178 * 179 * @ingroup hcrypto_dh 180 */ 181 182 int 183 DH_size(const DH *dh) 184 { 185 return BN_num_bytes(dh->p); 186 } 187 188 /** 189 * Set the data index idx in the DH object to data. 190 * 191 * @param dh DH object. 192 * @param idx index to set the data for. 193 * @param data data to store for the index idx. 194 * 195 * @return 1 on success. 196 * 197 * @ingroup hcrypto_dh 198 */ 199 200 int 201 DH_set_ex_data(DH *dh, int idx, void *data) 202 { 203 dh->ex_data.sk = data; 204 return 1; 205 } 206 207 /** 208 * Get the data for index idx in the DH object. 209 * 210 * @param dh DH object. 211 * @param idx index to get the data for. 212 * 213 * @return the object store in index idx 214 * 215 * @ingroup hcrypto_dh 216 */ 217 218 void * 219 DH_get_ex_data(DH *dh, int idx) 220 { 221 return dh->ex_data.sk; 222 } 223 224 /** 225 * Generate DH parameters for the DH object give parameters. 226 * 227 * @param dh The DH object to generate parameters for. 228 * @param prime_len length of the prime 229 * @param generator generator, g 230 * @param cb Callback parameters to show progress, can be NULL. 231 * 232 * @return the maximum size in bytes of the out data. 233 * 234 * @ingroup hcrypto_dh 235 */ 236 237 int 238 DH_generate_parameters_ex(DH *dh, int prime_len, int generator, BN_GENCB *cb) 239 { 240 if (dh->meth->generate_params) 241 return dh->meth->generate_params(dh, prime_len, generator, cb); 242 return 0; 243 } 244 245 /** 246 * Check that the public key is sane. 247 * 248 * @param dh the local peer DH parameters. 249 * @param pub_key the remote peer public key parameters. 250 * @param codes return that the failures of the pub_key are. 251 * 252 * @return 1 on success, 0 on failure and *codes is set the the 253 * combined fail check for the public key 254 * 255 * @ingroup hcrypto_dh 256 */ 257 258 int 259 DH_check_pubkey(const DH *dh, const BIGNUM *pub_key, int *codes) 260 { 261 BIGNUM *bn = NULL, *sum = NULL; 262 int ret = 0; 263 264 *codes = 0; 265 266 /** 267 * Checks that the function performs are: 268 * - pub_key is not negative 269 */ 270 271 if (BN_is_negative(pub_key)) 272 goto out; 273 274 /** 275 * - pub_key > 1 and pub_key < p - 1, 276 * to avoid small subgroups attack. 277 */ 278 279 bn = BN_new(); 280 if (bn == NULL) 281 goto out; 282 283 if (!BN_set_word(bn, 1)) 284 goto out; 285 286 if (BN_cmp(bn, pub_key) >= 0) 287 *codes |= DH_CHECK_PUBKEY_TOO_SMALL; 288 289 sum = BN_new(); 290 if (sum == NULL) 291 goto out; 292 293 BN_uadd(sum, pub_key, bn); 294 295 if (BN_cmp(sum, dh->p) >= 0) 296 *codes |= DH_CHECK_PUBKEY_TOO_LARGE; 297 298 /** 299 * - if g == 2, pub_key have more then one bit set, 300 * if bits set is 1, log_2(pub_key) is trival 301 */ 302 303 if (!BN_set_word(bn, 2)) 304 goto out; 305 306 if (BN_cmp(bn, dh->g) == 0) { 307 unsigned i, n = BN_num_bits(pub_key); 308 unsigned bits = 0; 309 310 for (i = 0; i <= n; i++) 311 if (BN_is_bit_set(pub_key, i)) 312 bits++; 313 314 if (bits < 2) { 315 *codes |= DH_CHECK_PUBKEY_TOO_SMALL; 316 goto out; 317 } 318 } 319 320 ret = 1; 321 out: 322 if (bn) 323 BN_free(bn); 324 if (sum) 325 BN_free(sum); 326 327 return ret; 328 } 329 330 /** 331 * Generate a new DH private-public key pair. The dh parameter must be 332 * allocted first with DH_new(). dh->p and dp->g must be set. 333 * 334 * @param dh dh parameter. 335 * 336 * @return 1 on success. 337 * 338 * @ingroup hcrypto_dh 339 */ 340 341 int 342 DH_generate_key(DH *dh) 343 { 344 return dh->meth->generate_key(dh); 345 } 346 347 /** 348 * Complute the shared secret key. 349 * 350 * @param shared_key the resulting shared key, need to be at least 351 * DH_size() large. 352 * @param peer_pub_key the peer's public key. 353 * @param dh the dh key pair. 354 * 355 * @return 1 on success. 356 * 357 * @ingroup hcrypto_dh 358 */ 359 360 int 361 DH_compute_key(unsigned char *shared_key, 362 const BIGNUM *peer_pub_key, DH *dh) 363 { 364 int codes; 365 366 /** 367 * Checks that the pubkey passed in is valid using 368 * DH_check_pubkey(). 369 */ 370 371 if (!DH_check_pubkey(dh, peer_pub_key, &codes) || codes != 0) 372 return -1; 373 374 return dh->meth->compute_key(shared_key, peer_pub_key, dh); 375 } 376 377 /** 378 * Set a new method for the DH keypair. 379 * 380 * @param dh dh parameter. 381 * @param method the new method for the DH parameter. 382 * 383 * @return 1 on success. 384 * 385 * @ingroup hcrypto_dh 386 */ 387 388 int 389 DH_set_method(DH *dh, const DH_METHOD *method) 390 { 391 (*dh->meth->finish)(dh); 392 if (dh->engine) { 393 ENGINE_finish(dh->engine); 394 dh->engine = NULL; 395 } 396 dh->meth = method; 397 (*dh->meth->init)(dh); 398 return 1; 399 } 400 401 /* 402 * 403 */ 404 405 static int 406 dh_null_generate_key(DH *dh) 407 { 408 return 0; 409 } 410 411 static int 412 dh_null_compute_key(unsigned char *shared,const BIGNUM *pub, DH *dh) 413 { 414 return 0; 415 } 416 417 static int 418 dh_null_init(DH *dh) 419 { 420 return 1; 421 } 422 423 static int 424 dh_null_finish(DH *dh) 425 { 426 return 1; 427 } 428 429 static int 430 dh_null_generate_params(DH *dh, int prime_num, int len, BN_GENCB *cb) 431 { 432 return 0; 433 } 434 435 static const DH_METHOD dh_null_method = { 436 "hcrypto null DH", 437 dh_null_generate_key, 438 dh_null_compute_key, 439 NULL, 440 dh_null_init, 441 dh_null_finish, 442 0, 443 NULL, 444 dh_null_generate_params 445 }; 446 447 extern const DH_METHOD _hc_dh_ltm_method; 448 static const DH_METHOD *dh_default_method = &_hc_dh_ltm_method; 449 450 /** 451 * Return the dummy DH implementation. 452 * 453 * @return pointer to a DH_METHOD. 454 * 455 * @ingroup hcrypto_dh 456 */ 457 458 const DH_METHOD * 459 DH_null_method(void) 460 { 461 return &dh_null_method; 462 } 463 464 /** 465 * Set the default DH implementation. 466 * 467 * @param meth pointer to a DH_METHOD. 468 * 469 * @ingroup hcrypto_dh 470 */ 471 472 void 473 DH_set_default_method(const DH_METHOD *meth) 474 { 475 dh_default_method = meth; 476 } 477 478 /** 479 * Return the default DH implementation. 480 * 481 * @return pointer to a DH_METHOD. 482 * 483 * @ingroup hcrypto_dh 484 */ 485 486 const DH_METHOD * 487 DH_get_default_method(void) 488 { 489 return dh_default_method; 490 } 491 492 /* 493 * 494 */ 495 496 static int 497 bn2heim_int(BIGNUM *bn, heim_integer *integer) 498 { 499 integer->length = BN_num_bytes(bn); 500 integer->data = malloc(integer->length); 501 if (integer->data == NULL) { 502 integer->length = 0; 503 return ENOMEM; 504 } 505 BN_bn2bin(bn, integer->data); 506 integer->negative = BN_is_negative(bn); 507 return 0; 508 } 509 510 /** 511 * 512 */ 513 514 int 515 i2d_DHparams(DH *dh, unsigned char **pp) 516 { 517 DHParameter data; 518 size_t size; 519 int ret; 520 521 memset(&data, 0, sizeof(data)); 522 523 if (bn2heim_int(dh->p, &data.prime) || 524 bn2heim_int(dh->g, &data.base)) 525 { 526 free_DHParameter(&data); 527 return -1; 528 } 529 530 if (pp == NULL) { 531 size = length_DHParameter(&data); 532 free_DHParameter(&data); 533 } else { 534 void *p; 535 size_t len; 536 537 ASN1_MALLOC_ENCODE(DHParameter, p, len, &data, &size, ret); 538 free_DHParameter(&data); 539 if (ret) 540 return -1; 541 if (len != size) { 542 abort(); 543 return -1; 544 } 545 546 memcpy(*pp, p, size); 547 free(p); 548 549 *pp += size; 550 } 551 552 return size; 553 } 554