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