00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #ifdef OPENSSL
00038
00039 #include <config.h>
00040
00041 #include <ctype.h>
00042
00043 #include <isc/mem.h>
00044 #include <isc/string.h>
00045 #include <isc/util.h>
00046
00047 #include <dst/result.h>
00048
00049 #include "dst_internal.h"
00050 #include "dst_openssl.h"
00051 #include "dst_parse.h"
00052
00053 #define PRIME768 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088" \
00054 "A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25" \
00055 "F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF"
00056
00057 #define PRIME1024 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08" \
00058 "8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF2" \
00059 "5F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406" \
00060 "B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF"
00061
00062 #define PRIME1536 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \
00063 "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \
00064 "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \
00065 "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \
00066 "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \
00067 "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \
00068 "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \
00069 "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF"
00070
00071
00072 static isc_result_t openssldh_todns(const dst_key_t *key, isc_buffer_t *data);
00073
00074 static BIGNUM bn2, bn768, bn1024, bn1536;
00075
00076 static isc_result_t
00077 openssldh_computesecret(const dst_key_t *pub, const dst_key_t *priv,
00078 isc_buffer_t *secret)
00079 {
00080 DH *dhpub, *dhpriv;
00081 int ret;
00082 isc_region_t r;
00083 unsigned int len;
00084
00085 REQUIRE(pub->keydata.dh != NULL);
00086 REQUIRE(priv->keydata.dh != NULL);
00087
00088 dhpub = pub->keydata.dh;
00089 dhpriv = priv->keydata.dh;
00090
00091 len = DH_size(dhpriv);
00092 isc_buffer_availableregion(secret, &r);
00093 if (r.length < len)
00094 return (ISC_R_NOSPACE);
00095 ret = DH_compute_key(r.base, dhpub->pub_key, dhpriv);
00096 if (ret <= 0)
00097 return (dst__openssl_toresult2("DH_compute_key",
00098 DST_R_COMPUTESECRETFAILURE));
00099 isc_buffer_add(secret, len);
00100 return (ISC_R_SUCCESS);
00101 }
00102
00103 static isc_boolean_t
00104 openssldh_compare(const dst_key_t *key1, const dst_key_t *key2) {
00105 int status;
00106 DH *dh1, *dh2;
00107
00108 dh1 = key1->keydata.dh;
00109 dh2 = key2->keydata.dh;
00110
00111 if (dh1 == NULL && dh2 == NULL)
00112 return (ISC_TRUE);
00113 else if (dh1 == NULL || dh2 == NULL)
00114 return (ISC_FALSE);
00115
00116 status = BN_cmp(dh1->p, dh2->p) ||
00117 BN_cmp(dh1->g, dh2->g) ||
00118 BN_cmp(dh1->pub_key, dh2->pub_key);
00119
00120 if (status != 0)
00121 return (ISC_FALSE);
00122
00123 if (dh1->priv_key != NULL || dh2->priv_key != NULL) {
00124 if (dh1->priv_key == NULL || dh2->priv_key == NULL)
00125 return (ISC_FALSE);
00126 if (BN_cmp(dh1->priv_key, dh2->priv_key) != 0)
00127 return (ISC_FALSE);
00128 }
00129 return (ISC_TRUE);
00130 }
00131
00132 static isc_boolean_t
00133 openssldh_paramcompare(const dst_key_t *key1, const dst_key_t *key2) {
00134 int status;
00135 DH *dh1, *dh2;
00136
00137 dh1 = key1->keydata.dh;
00138 dh2 = key2->keydata.dh;
00139
00140 if (dh1 == NULL && dh2 == NULL)
00141 return (ISC_TRUE);
00142 else if (dh1 == NULL || dh2 == NULL)
00143 return (ISC_FALSE);
00144
00145 status = BN_cmp(dh1->p, dh2->p) ||
00146 BN_cmp(dh1->g, dh2->g);
00147
00148 if (status != 0)
00149 return (ISC_FALSE);
00150 return (ISC_TRUE);
00151 }
00152
00153 #if OPENSSL_VERSION_NUMBER > 0x00908000L
00154 static int
00155 progress_cb(int p, int n, BN_GENCB *cb)
00156 {
00157 union {
00158 void *dptr;
00159 void (*fptr)(int);
00160 } u;
00161
00162 UNUSED(n);
00163
00164 u.dptr = cb->arg;
00165 if (u.fptr != NULL)
00166 u.fptr(p);
00167 return (1);
00168 }
00169 #endif
00170
00171 static isc_result_t
00172 openssldh_generate(dst_key_t *key, int generator, void (*callback)(int)) {
00173 DH *dh = NULL;
00174 #if OPENSSL_VERSION_NUMBER > 0x00908000L
00175 BN_GENCB cb;
00176 union {
00177 void *dptr;
00178 void (*fptr)(int);
00179 } u;
00180 #else
00181
00182 UNUSED(callback);
00183 #endif
00184
00185 if (generator == 0) {
00186 if (key->key_size == 768 ||
00187 key->key_size == 1024 ||
00188 key->key_size == 1536)
00189 {
00190 dh = DH_new();
00191 if (dh == NULL)
00192 return (dst__openssl_toresult(ISC_R_NOMEMORY));
00193 if (key->key_size == 768)
00194 dh->p = &bn768;
00195 else if (key->key_size == 1024)
00196 dh->p = &bn1024;
00197 else
00198 dh->p = &bn1536;
00199 dh->g = &bn2;
00200 } else
00201 generator = 2;
00202 }
00203
00204 if (generator != 0) {
00205 #if OPENSSL_VERSION_NUMBER > 0x00908000L
00206 dh = DH_new();
00207 if (dh == NULL)
00208 return (dst__openssl_toresult(ISC_R_NOMEMORY));
00209
00210 if (callback == NULL) {
00211 BN_GENCB_set_old(&cb, NULL, NULL);
00212 } else {
00213 u.fptr = callback;
00214 BN_GENCB_set(&cb, &progress_cb, u.dptr);
00215 }
00216
00217 if (!DH_generate_parameters_ex(dh, key->key_size, generator,
00218 &cb)) {
00219 DH_free(dh);
00220 return (dst__openssl_toresult2(
00221 "DH_generate_parameters_ex",
00222 DST_R_OPENSSLFAILURE));
00223 }
00224 #else
00225 dh = DH_generate_parameters(key->key_size, generator,
00226 NULL, NULL);
00227 #endif
00228 }
00229
00230 if (dh == NULL)
00231 return (dst__openssl_toresult2("DH_generate_parameters",
00232 DST_R_OPENSSLFAILURE));
00233
00234 if (DH_generate_key(dh) == 0) {
00235 DH_free(dh);
00236 return (dst__openssl_toresult2("DH_generate_key",
00237 DST_R_OPENSSLFAILURE));
00238 }
00239 dh->flags &= ~DH_FLAG_CACHE_MONT_P;
00240
00241 key->keydata.dh = dh;
00242
00243 return (ISC_R_SUCCESS);
00244 }
00245
00246 static isc_boolean_t
00247 openssldh_isprivate(const dst_key_t *key) {
00248 DH *dh = key->keydata.dh;
00249 return (ISC_TF(dh != NULL && dh->priv_key != NULL));
00250 }
00251
00252 static void
00253 openssldh_destroy(dst_key_t *key) {
00254 DH *dh = key->keydata.dh;
00255
00256 if (dh == NULL)
00257 return;
00258
00259 if (dh->p == &bn768 || dh->p == &bn1024 || dh->p == &bn1536)
00260 dh->p = NULL;
00261 if (dh->g == &bn2)
00262 dh->g = NULL;
00263 DH_free(dh);
00264 key->keydata.dh = NULL;
00265 }
00266
00267 static void
00268 uint16_toregion(isc_uint16_t val, isc_region_t *region) {
00269 *region->base++ = (val & 0xff00) >> 8;
00270 *region->base++ = (val & 0x00ff);
00271 }
00272
00273 static isc_uint16_t
00274 uint16_fromregion(isc_region_t *region) {
00275 isc_uint16_t val;
00276 unsigned char *cp = region->base;
00277
00278 val = ((unsigned int)(cp[0])) << 8;
00279 val |= ((unsigned int)(cp[1]));
00280
00281 region->base += 2;
00282 return (val);
00283 }
00284
00285 static isc_result_t
00286 openssldh_todns(const dst_key_t *key, isc_buffer_t *data) {
00287 DH *dh;
00288 isc_region_t r;
00289 isc_uint16_t dnslen, plen, glen, publen;
00290
00291 REQUIRE(key->keydata.dh != NULL);
00292
00293 dh = key->keydata.dh;
00294
00295 isc_buffer_availableregion(data, &r);
00296
00297 if (dh->g == &bn2 &&
00298 (dh->p == &bn768 || dh->p == &bn1024 || dh->p == &bn1536)) {
00299 plen = 1;
00300 glen = 0;
00301 }
00302 else {
00303 plen = BN_num_bytes(dh->p);
00304 glen = BN_num_bytes(dh->g);
00305 }
00306 publen = BN_num_bytes(dh->pub_key);
00307 dnslen = plen + glen + publen + 6;
00308 if (r.length < (unsigned int) dnslen)
00309 return (ISC_R_NOSPACE);
00310
00311 uint16_toregion(plen, &r);
00312 if (plen == 1) {
00313 if (dh->p == &bn768)
00314 *r.base = 1;
00315 else if (dh->p == &bn1024)
00316 *r.base = 2;
00317 else
00318 *r.base = 3;
00319 }
00320 else
00321 BN_bn2bin(dh->p, r.base);
00322 r.base += plen;
00323
00324 uint16_toregion(glen, &r);
00325 if (glen > 0)
00326 BN_bn2bin(dh->g, r.base);
00327 r.base += glen;
00328
00329 uint16_toregion(publen, &r);
00330 BN_bn2bin(dh->pub_key, r.base);
00331 r.base += publen;
00332
00333 isc_buffer_add(data, dnslen);
00334
00335 return (ISC_R_SUCCESS);
00336 }
00337
00338 static isc_result_t
00339 openssldh_fromdns(dst_key_t *key, isc_buffer_t *data) {
00340 DH *dh;
00341 isc_region_t r;
00342 isc_uint16_t plen, glen, publen;
00343 int special = 0;
00344
00345 isc_buffer_remainingregion(data, &r);
00346 if (r.length == 0)
00347 return (ISC_R_SUCCESS);
00348
00349 dh = DH_new();
00350 if (dh == NULL)
00351 return (dst__openssl_toresult(ISC_R_NOMEMORY));
00352 dh->flags &= ~DH_FLAG_CACHE_MONT_P;
00353
00354
00355
00356
00357
00358 if (r.length < 2) {
00359 DH_free(dh);
00360 return (DST_R_INVALIDPUBLICKEY);
00361 }
00362 plen = uint16_fromregion(&r);
00363 if (plen < 16 && plen != 1 && plen != 2) {
00364 DH_free(dh);
00365 return (DST_R_INVALIDPUBLICKEY);
00366 }
00367 if (r.length < plen) {
00368 DH_free(dh);
00369 return (DST_R_INVALIDPUBLICKEY);
00370 }
00371 if (plen == 1 || plen == 2) {
00372 if (plen == 1)
00373 special = *r.base++;
00374 else
00375 special = uint16_fromregion(&r);
00376 switch (special) {
00377 case 1:
00378 dh->p = &bn768;
00379 break;
00380 case 2:
00381 dh->p = &bn1024;
00382 break;
00383 case 3:
00384 dh->p = &bn1536;
00385 break;
00386 default:
00387 DH_free(dh);
00388 return (DST_R_INVALIDPUBLICKEY);
00389 }
00390 }
00391 else {
00392 dh->p = BN_bin2bn(r.base, plen, NULL);
00393 r.base += plen;
00394 }
00395
00396
00397
00398
00399
00400
00401 if (r.length < 2) {
00402 DH_free(dh);
00403 return (DST_R_INVALIDPUBLICKEY);
00404 }
00405 glen = uint16_fromregion(&r);
00406 if (r.length < glen) {
00407 DH_free(dh);
00408 return (DST_R_INVALIDPUBLICKEY);
00409 }
00410 if (special != 0) {
00411 if (glen == 0)
00412 dh->g = &bn2;
00413 else {
00414 dh->g = BN_bin2bn(r.base, glen, NULL);
00415 if (BN_cmp(dh->g, &bn2) == 0) {
00416 BN_free(dh->g);
00417 dh->g = &bn2;
00418 }
00419 else {
00420 DH_free(dh);
00421 return (DST_R_INVALIDPUBLICKEY);
00422 }
00423 }
00424 }
00425 else {
00426 if (glen == 0) {
00427 DH_free(dh);
00428 return (DST_R_INVALIDPUBLICKEY);
00429 }
00430 dh->g = BN_bin2bn(r.base, glen, NULL);
00431 }
00432 r.base += glen;
00433
00434 if (r.length < 2) {
00435 DH_free(dh);
00436 return (DST_R_INVALIDPUBLICKEY);
00437 }
00438 publen = uint16_fromregion(&r);
00439 if (r.length < publen) {
00440 DH_free(dh);
00441 return (DST_R_INVALIDPUBLICKEY);
00442 }
00443 dh->pub_key = BN_bin2bn(r.base, publen, NULL);
00444 r.base += publen;
00445
00446 key->key_size = BN_num_bits(dh->p);
00447
00448 isc_buffer_forward(data, plen + glen + publen + 6);
00449
00450 key->keydata.dh = dh;
00451
00452 return (ISC_R_SUCCESS);
00453 }
00454
00455 static isc_result_t
00456 openssldh_tofile(const dst_key_t *key, const char *directory) {
00457 int i;
00458 DH *dh;
00459 dst_private_t priv;
00460 unsigned char *bufs[4];
00461 isc_result_t result;
00462
00463 if (key->keydata.dh == NULL)
00464 return (DST_R_NULLKEY);
00465
00466 if (key->external)
00467 return (DST_R_EXTERNALKEY);
00468
00469 dh = key->keydata.dh;
00470
00471 memset(bufs, 0, sizeof(bufs));
00472 for (i = 0; i < 4; i++) {
00473 bufs[i] = isc_mem_get(key->mctx, BN_num_bytes(dh->p));
00474 if (bufs[i] == NULL) {
00475 result = ISC_R_NOMEMORY;
00476 goto fail;
00477 }
00478 }
00479
00480 i = 0;
00481
00482 priv.elements[i].tag = TAG_DH_PRIME;
00483 priv.elements[i].length = BN_num_bytes(dh->p);
00484 BN_bn2bin(dh->p, bufs[i]);
00485 priv.elements[i].data = bufs[i];
00486 i++;
00487
00488 priv.elements[i].tag = TAG_DH_GENERATOR;
00489 priv.elements[i].length = BN_num_bytes(dh->g);
00490 BN_bn2bin(dh->g, bufs[i]);
00491 priv.elements[i].data = bufs[i];
00492 i++;
00493
00494 priv.elements[i].tag = TAG_DH_PRIVATE;
00495 priv.elements[i].length = BN_num_bytes(dh->priv_key);
00496 BN_bn2bin(dh->priv_key, bufs[i]);
00497 priv.elements[i].data = bufs[i];
00498 i++;
00499
00500 priv.elements[i].tag = TAG_DH_PUBLIC;
00501 priv.elements[i].length = BN_num_bytes(dh->pub_key);
00502 BN_bn2bin(dh->pub_key, bufs[i]);
00503 priv.elements[i].data = bufs[i];
00504 i++;
00505
00506 priv.nelements = i;
00507 result = dst__privstruct_writefile(key, &priv, directory);
00508 fail:
00509 for (i = 0; i < 4; i++) {
00510 if (bufs[i] == NULL)
00511 break;
00512 isc_mem_put(key->mctx, bufs[i], BN_num_bytes(dh->p));
00513 }
00514 return (result);
00515 }
00516
00517 static isc_result_t
00518 openssldh_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
00519 dst_private_t priv;
00520 isc_result_t ret;
00521 int i;
00522 DH *dh = NULL;
00523 isc_mem_t *mctx;
00524 #define DST_RET(a) {ret = a; goto err;}
00525
00526 UNUSED(pub);
00527 mctx = key->mctx;
00528
00529
00530 ret = dst__privstruct_parse(key, DST_ALG_DH, lexer, mctx, &priv);
00531 if (ret != ISC_R_SUCCESS)
00532 return (ret);
00533
00534 if (key->external)
00535 DST_RET(DST_R_EXTERNALKEY);
00536
00537 dh = DH_new();
00538 if (dh == NULL)
00539 DST_RET(ISC_R_NOMEMORY);
00540 dh->flags &= ~DH_FLAG_CACHE_MONT_P;
00541 key->keydata.dh = dh;
00542
00543 for (i = 0; i < priv.nelements; i++) {
00544 BIGNUM *bn;
00545 bn = BN_bin2bn(priv.elements[i].data,
00546 priv.elements[i].length, NULL);
00547 if (bn == NULL)
00548 DST_RET(ISC_R_NOMEMORY);
00549
00550 switch (priv.elements[i].tag) {
00551 case TAG_DH_PRIME:
00552 dh->p = bn;
00553 break;
00554 case TAG_DH_GENERATOR:
00555 dh->g = bn;
00556 break;
00557 case TAG_DH_PRIVATE:
00558 dh->priv_key = bn;
00559 break;
00560 case TAG_DH_PUBLIC:
00561 dh->pub_key = bn;
00562 break;
00563 }
00564 }
00565 dst__privstruct_free(&priv, mctx);
00566
00567 key->key_size = BN_num_bits(dh->p);
00568
00569 if ((key->key_size == 768 ||
00570 key->key_size == 1024 ||
00571 key->key_size == 1536) &&
00572 BN_cmp(dh->g, &bn2) == 0)
00573 {
00574 if (key->key_size == 768 && BN_cmp(dh->p, &bn768) == 0) {
00575 BN_free(dh->p);
00576 BN_free(dh->g);
00577 dh->p = &bn768;
00578 dh->g = &bn2;
00579 } else if (key->key_size == 1024 &&
00580 BN_cmp(dh->p, &bn1024) == 0) {
00581 BN_free(dh->p);
00582 BN_free(dh->g);
00583 dh->p = &bn1024;
00584 dh->g = &bn2;
00585 } else if (key->key_size == 1536 &&
00586 BN_cmp(dh->p, &bn1536) == 0) {
00587 BN_free(dh->p);
00588 BN_free(dh->g);
00589 dh->p = &bn1536;
00590 dh->g = &bn2;
00591 }
00592 }
00593
00594 return (ISC_R_SUCCESS);
00595
00596 err:
00597 openssldh_destroy(key);
00598 dst__privstruct_free(&priv, mctx);
00599 memset(&priv, 0, sizeof(priv));
00600 return (ret);
00601 }
00602
00603 static void
00604 BN_fromhex(BIGNUM *b, const char *str) {
00605 static const char hexdigits[] = "0123456789abcdef";
00606 unsigned char data[512];
00607 unsigned int i;
00608 BIGNUM *out;
00609
00610 RUNTIME_CHECK(strlen(str) < 1024U && strlen(str) % 2 == 0U);
00611 for (i = 0; i < strlen(str); i += 2) {
00612 char *s;
00613 unsigned int high, low;
00614
00615 s = strchr(hexdigits, tolower((unsigned char)str[i]));
00616 RUNTIME_CHECK(s != NULL);
00617 high = (unsigned int)(s - hexdigits);
00618
00619 s = strchr(hexdigits, tolower((unsigned char)str[i + 1]));
00620 RUNTIME_CHECK(s != NULL);
00621 low = (unsigned int)(s - hexdigits);
00622
00623 data[i/2] = (unsigned char)((high << 4) + low);
00624 }
00625 out = BN_bin2bn(data, strlen(str)/2, b);
00626 RUNTIME_CHECK(out != NULL);
00627 }
00628
00629 static void
00630 openssldh_cleanup(void) {
00631 BN_free(&bn2);
00632 BN_free(&bn768);
00633 BN_free(&bn1024);
00634 BN_free(&bn1536);
00635 }
00636
00637 static dst_func_t openssldh_functions = {
00638 NULL,
00639 NULL,
00640 NULL,
00641 NULL,
00642 NULL,
00643 NULL,
00644 NULL,
00645 openssldh_computesecret,
00646 openssldh_compare,
00647 openssldh_paramcompare,
00648 openssldh_generate,
00649 openssldh_isprivate,
00650 openssldh_destroy,
00651 openssldh_todns,
00652 openssldh_fromdns,
00653 openssldh_tofile,
00654 openssldh_parse,
00655 openssldh_cleanup,
00656 NULL,
00657 NULL,
00658 NULL,
00659 };
00660
00661 isc_result_t
00662 dst__openssldh_init(dst_func_t **funcp) {
00663 REQUIRE(funcp != NULL);
00664 if (*funcp == NULL) {
00665 BN_init(&bn2);
00666 BN_init(&bn768);
00667 BN_init(&bn1024);
00668 BN_init(&bn1536);
00669 BN_set_word(&bn2, 2);
00670 BN_fromhex(&bn768, PRIME768);
00671 BN_fromhex(&bn1024, PRIME1024);
00672 BN_fromhex(&bn1536, PRIME1536);
00673 *funcp = &openssldh_functions;
00674 }
00675 return (ISC_R_SUCCESS);
00676 }
00677
00678 #else
00679
00680 #include <isc/util.h>
00681
00682 EMPTY_TRANSLATION_UNIT
00683
00684 #endif
00685