1143731Sdougb/* 2262706Serwin * Portions Copyright (C) 2004-2009, 2011-2013 Internet Systems Consortium, Inc. ("ISC") 3143731Sdougb * Portions Copyright (C) 1999-2002 Internet Software Consortium. 4193149Sdougb * 5193149Sdougb * Permission to use, copy, modify, and/or distribute this software for any 6193149Sdougb * purpose with or without fee is hereby granted, provided that the above 7193149Sdougb * copyright notice and this permission notice appear in all copies. 8193149Sdougb * 9193149Sdougb * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS 10193149Sdougb * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11193149Sdougb * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE 12193149Sdougb * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13193149Sdougb * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14193149Sdougb * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 15193149Sdougb * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16193149Sdougb * 17143731Sdougb * Portions Copyright (C) 1995-2000 by Network Associates, Inc. 18143731Sdougb * 19174187Sdougb * Permission to use, copy, modify, and/or distribute this software for any 20143731Sdougb * purpose with or without fee is hereby granted, provided that the above 21143731Sdougb * copyright notice and this permission notice appear in all copies. 22143731Sdougb * 23143731Sdougb * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS 24143731Sdougb * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 25143731Sdougb * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE 26143731Sdougb * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 27143731Sdougb * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 28143731Sdougb * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 29143731Sdougb * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 30143731Sdougb */ 31143731Sdougb 32143731Sdougb/* 33143731Sdougb * Principal Author: Brian Wellington 34234010Sdougb * $Id: openssldh_link.c,v 1.20 2011/01/11 23:47:13 tbox Exp $ 35143731Sdougb */ 36143731Sdougb 37143731Sdougb#ifdef OPENSSL 38143731Sdougb 39143731Sdougb#include <config.h> 40143731Sdougb 41143731Sdougb#include <ctype.h> 42143731Sdougb 43143731Sdougb#include <isc/mem.h> 44143731Sdougb#include <isc/string.h> 45143731Sdougb#include <isc/util.h> 46143731Sdougb 47143731Sdougb#include <dst/result.h> 48143731Sdougb 49143731Sdougb#include "dst_internal.h" 50143731Sdougb#include "dst_openssl.h" 51143731Sdougb#include "dst_parse.h" 52143731Sdougb 53143731Sdougb#define PRIME768 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088" \ 54143731Sdougb "A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25" \ 55143731Sdougb "F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF" 56143731Sdougb 57143731Sdougb#define PRIME1024 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08" \ 58143731Sdougb "8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF2" \ 59143731Sdougb "5F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406" \ 60143731Sdougb "B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF" 61143731Sdougb 62143731Sdougb#define PRIME1536 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ 63143731Sdougb "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ 64143731Sdougb "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ 65143731Sdougb "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ 66143731Sdougb "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ 67143731Sdougb "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ 68143731Sdougb "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ 69143731Sdougb "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF" 70143731Sdougb 71143731Sdougb 72143731Sdougbstatic isc_result_t openssldh_todns(const dst_key_t *key, isc_buffer_t *data); 73143731Sdougb 74143731Sdougbstatic BIGNUM bn2, bn768, bn1024, bn1536; 75143731Sdougb 76143731Sdougbstatic isc_result_t 77143731Sdougbopenssldh_computesecret(const dst_key_t *pub, const dst_key_t *priv, 78143731Sdougb isc_buffer_t *secret) 79143731Sdougb{ 80143731Sdougb DH *dhpub, *dhpriv; 81143731Sdougb int ret; 82143731Sdougb isc_region_t r; 83143731Sdougb unsigned int len; 84143731Sdougb 85193149Sdougb REQUIRE(pub->keydata.dh != NULL); 86193149Sdougb REQUIRE(priv->keydata.dh != NULL); 87143731Sdougb 88193149Sdougb dhpub = pub->keydata.dh; 89193149Sdougb dhpriv = priv->keydata.dh; 90143731Sdougb 91143731Sdougb len = DH_size(dhpriv); 92143731Sdougb isc_buffer_availableregion(secret, &r); 93143731Sdougb if (r.length < len) 94143731Sdougb return (ISC_R_NOSPACE); 95143731Sdougb ret = DH_compute_key(r.base, dhpub->pub_key, dhpriv); 96143731Sdougb if (ret == 0) 97245163Serwin return (dst__openssl_toresult2("DH_compute_key", 98245163Serwin DST_R_COMPUTESECRETFAILURE)); 99143731Sdougb isc_buffer_add(secret, len); 100143731Sdougb return (ISC_R_SUCCESS); 101143731Sdougb} 102143731Sdougb 103143731Sdougbstatic isc_boolean_t 104143731Sdougbopenssldh_compare(const dst_key_t *key1, const dst_key_t *key2) { 105143731Sdougb int status; 106143731Sdougb DH *dh1, *dh2; 107143731Sdougb 108193149Sdougb dh1 = key1->keydata.dh; 109193149Sdougb dh2 = key2->keydata.dh; 110143731Sdougb 111143731Sdougb if (dh1 == NULL && dh2 == NULL) 112143731Sdougb return (ISC_TRUE); 113143731Sdougb else if (dh1 == NULL || dh2 == NULL) 114143731Sdougb return (ISC_FALSE); 115143731Sdougb 116143731Sdougb status = BN_cmp(dh1->p, dh2->p) || 117143731Sdougb BN_cmp(dh1->g, dh2->g) || 118143731Sdougb BN_cmp(dh1->pub_key, dh2->pub_key); 119143731Sdougb 120143731Sdougb if (status != 0) 121143731Sdougb return (ISC_FALSE); 122143731Sdougb 123143731Sdougb if (dh1->priv_key != NULL || dh2->priv_key != NULL) { 124143731Sdougb if (dh1->priv_key == NULL || dh2->priv_key == NULL) 125143731Sdougb return (ISC_FALSE); 126143731Sdougb if (BN_cmp(dh1->priv_key, dh2->priv_key) != 0) 127143731Sdougb return (ISC_FALSE); 128143731Sdougb } 129143731Sdougb return (ISC_TRUE); 130143731Sdougb} 131143731Sdougb 132143731Sdougbstatic isc_boolean_t 133143731Sdougbopenssldh_paramcompare(const dst_key_t *key1, const dst_key_t *key2) { 134143731Sdougb int status; 135143731Sdougb DH *dh1, *dh2; 136143731Sdougb 137193149Sdougb dh1 = key1->keydata.dh; 138193149Sdougb dh2 = key2->keydata.dh; 139143731Sdougb 140143731Sdougb if (dh1 == NULL && dh2 == NULL) 141143731Sdougb return (ISC_TRUE); 142143731Sdougb else if (dh1 == NULL || dh2 == NULL) 143143731Sdougb return (ISC_FALSE); 144143731Sdougb 145143731Sdougb status = BN_cmp(dh1->p, dh2->p) || 146143731Sdougb BN_cmp(dh1->g, dh2->g); 147143731Sdougb 148143731Sdougb if (status != 0) 149143731Sdougb return (ISC_FALSE); 150143731Sdougb return (ISC_TRUE); 151143731Sdougb} 152143731Sdougb 153224092Sdougb#if OPENSSL_VERSION_NUMBER > 0x00908000L 154224092Sdougbstatic int 155224092Sdougbprogress_cb(int p, int n, BN_GENCB *cb) 156224092Sdougb{ 157224092Sdougb union { 158224092Sdougb void *dptr; 159224092Sdougb void (*fptr)(int); 160224092Sdougb } u; 161224092Sdougb 162224092Sdougb UNUSED(n); 163224092Sdougb 164224092Sdougb u.dptr = cb->arg; 165224092Sdougb if (u.fptr != NULL) 166224092Sdougb u.fptr(p); 167224092Sdougb return (1); 168224092Sdougb} 169224092Sdougb#endif 170224092Sdougb 171170222Sdougbstatic isc_result_t 172224092Sdougbopenssldh_generate(dst_key_t *key, int generator, void (*callback)(int)) { 173224092Sdougb DH *dh = NULL; 174170222Sdougb#if OPENSSL_VERSION_NUMBER > 0x00908000L 175193149Sdougb BN_GENCB cb; 176224092Sdougb union { 177224092Sdougb void *dptr; 178224092Sdougb void (*fptr)(int); 179224092Sdougb } u; 180224092Sdougb#else 181224092Sdougb 182224092Sdougb UNUSED(callback); 183165071Sdougb#endif 184143731Sdougb 185143731Sdougb if (generator == 0) { 186143731Sdougb if (key->key_size == 768 || 187143731Sdougb key->key_size == 1024 || 188143731Sdougb key->key_size == 1536) 189143731Sdougb { 190143731Sdougb dh = DH_new(); 191143731Sdougb if (dh == NULL) 192170222Sdougb return (dst__openssl_toresult(ISC_R_NOMEMORY)); 193143731Sdougb if (key->key_size == 768) 194143731Sdougb dh->p = &bn768; 195143731Sdougb else if (key->key_size == 1024) 196143731Sdougb dh->p = &bn1024; 197143731Sdougb else 198143731Sdougb dh->p = &bn1536; 199143731Sdougb dh->g = &bn2; 200170222Sdougb } else 201143731Sdougb generator = 2; 202143731Sdougb } 203143731Sdougb 204170222Sdougb if (generator != 0) { 205170222Sdougb#if OPENSSL_VERSION_NUMBER > 0x00908000L 206170222Sdougb dh = DH_new(); 207170222Sdougb if (dh == NULL) 208245163Serwin return (dst__openssl_toresult(ISC_R_NOMEMORY)); 209170222Sdougb 210224092Sdougb if (callback == NULL) { 211224092Sdougb BN_GENCB_set_old(&cb, NULL, NULL); 212224092Sdougb } else { 213224092Sdougb u.fptr = callback; 214224092Sdougb BN_GENCB_set(&cb, &progress_cb, u.dptr); 215224092Sdougb } 216170222Sdougb 217170222Sdougb if (!DH_generate_parameters_ex(dh, key->key_size, generator, 218170222Sdougb &cb)) { 219170222Sdougb DH_free(dh); 220245163Serwin return (dst__openssl_toresult2( 221245163Serwin "DH_generate_parameters_ex", 222245163Serwin DST_R_OPENSSLFAILURE)); 223170222Sdougb } 224170222Sdougb#else 225143731Sdougb dh = DH_generate_parameters(key->key_size, generator, 226143731Sdougb NULL, NULL); 227170222Sdougb#endif 228170222Sdougb } 229143731Sdougb 230143731Sdougb if (dh == NULL) 231245163Serwin return (dst__openssl_toresult2("DH_generate_parameters", 232245163Serwin DST_R_OPENSSLFAILURE)); 233143731Sdougb 234143731Sdougb if (DH_generate_key(dh) == 0) { 235143731Sdougb DH_free(dh); 236245163Serwin return (dst__openssl_toresult2("DH_generate_key", 237245163Serwin DST_R_OPENSSLFAILURE)); 238143731Sdougb } 239143731Sdougb dh->flags &= ~DH_FLAG_CACHE_MONT_P; 240143731Sdougb 241193149Sdougb key->keydata.dh = dh; 242143731Sdougb 243143731Sdougb return (ISC_R_SUCCESS); 244143731Sdougb} 245143731Sdougb 246143731Sdougbstatic isc_boolean_t 247143731Sdougbopenssldh_isprivate(const dst_key_t *key) { 248193149Sdougb DH *dh = key->keydata.dh; 249143731Sdougb return (ISC_TF(dh != NULL && dh->priv_key != NULL)); 250143731Sdougb} 251143731Sdougb 252143731Sdougbstatic void 253143731Sdougbopenssldh_destroy(dst_key_t *key) { 254193149Sdougb DH *dh = key->keydata.dh; 255143731Sdougb 256143731Sdougb if (dh == NULL) 257143731Sdougb return; 258143731Sdougb 259143731Sdougb if (dh->p == &bn768 || dh->p == &bn1024 || dh->p == &bn1536) 260143731Sdougb dh->p = NULL; 261143731Sdougb if (dh->g == &bn2) 262143731Sdougb dh->g = NULL; 263143731Sdougb DH_free(dh); 264193149Sdougb key->keydata.dh = NULL; 265143731Sdougb} 266143731Sdougb 267143731Sdougbstatic void 268143731Sdougbuint16_toregion(isc_uint16_t val, isc_region_t *region) { 269287410Sdelphij *region->base = (val & 0xff00) >> 8; 270287410Sdelphij isc_region_consume(region, 1); 271287410Sdelphij *region->base = (val & 0x00ff); 272287410Sdelphij isc_region_consume(region, 1); 273143731Sdougb} 274143731Sdougb 275143731Sdougbstatic isc_uint16_t 276143731Sdougbuint16_fromregion(isc_region_t *region) { 277143731Sdougb isc_uint16_t val; 278143731Sdougb unsigned char *cp = region->base; 279143731Sdougb 280143731Sdougb val = ((unsigned int)(cp[0])) << 8; 281143731Sdougb val |= ((unsigned int)(cp[1])); 282143731Sdougb 283287410Sdelphij isc_region_consume(region, 2); 284287410Sdelphij 285143731Sdougb return (val); 286143731Sdougb} 287143731Sdougb 288143731Sdougbstatic isc_result_t 289143731Sdougbopenssldh_todns(const dst_key_t *key, isc_buffer_t *data) { 290143731Sdougb DH *dh; 291143731Sdougb isc_region_t r; 292143731Sdougb isc_uint16_t dnslen, plen, glen, publen; 293143731Sdougb 294193149Sdougb REQUIRE(key->keydata.dh != NULL); 295143731Sdougb 296193149Sdougb dh = key->keydata.dh; 297143731Sdougb 298143731Sdougb isc_buffer_availableregion(data, &r); 299143731Sdougb 300143731Sdougb if (dh->g == &bn2 && 301143731Sdougb (dh->p == &bn768 || dh->p == &bn1024 || dh->p == &bn1536)) { 302143731Sdougb plen = 1; 303143731Sdougb glen = 0; 304143731Sdougb } 305143731Sdougb else { 306143731Sdougb plen = BN_num_bytes(dh->p); 307143731Sdougb glen = BN_num_bytes(dh->g); 308143731Sdougb } 309143731Sdougb publen = BN_num_bytes(dh->pub_key); 310143731Sdougb dnslen = plen + glen + publen + 6; 311143731Sdougb if (r.length < (unsigned int) dnslen) 312143731Sdougb return (ISC_R_NOSPACE); 313143731Sdougb 314143731Sdougb uint16_toregion(plen, &r); 315143731Sdougb if (plen == 1) { 316143731Sdougb if (dh->p == &bn768) 317143731Sdougb *r.base = 1; 318143731Sdougb else if (dh->p == &bn1024) 319143731Sdougb *r.base = 2; 320143731Sdougb else 321143731Sdougb *r.base = 3; 322143731Sdougb } 323143731Sdougb else 324143731Sdougb BN_bn2bin(dh->p, r.base); 325287410Sdelphij isc_region_consume(&r, plen); 326143731Sdougb 327143731Sdougb uint16_toregion(glen, &r); 328143731Sdougb if (glen > 0) 329143731Sdougb BN_bn2bin(dh->g, r.base); 330287410Sdelphij isc_region_consume(&r, glen); 331143731Sdougb 332143731Sdougb uint16_toregion(publen, &r); 333143731Sdougb BN_bn2bin(dh->pub_key, r.base); 334287410Sdelphij isc_region_consume(&r, publen); 335143731Sdougb 336143731Sdougb isc_buffer_add(data, dnslen); 337143731Sdougb 338143731Sdougb return (ISC_R_SUCCESS); 339143731Sdougb} 340143731Sdougb 341143731Sdougbstatic isc_result_t 342143731Sdougbopenssldh_fromdns(dst_key_t *key, isc_buffer_t *data) { 343143731Sdougb DH *dh; 344143731Sdougb isc_region_t r; 345143731Sdougb isc_uint16_t plen, glen, publen; 346143731Sdougb int special = 0; 347143731Sdougb 348143731Sdougb isc_buffer_remainingregion(data, &r); 349143731Sdougb if (r.length == 0) 350143731Sdougb return (ISC_R_SUCCESS); 351143731Sdougb 352143731Sdougb dh = DH_new(); 353143731Sdougb if (dh == NULL) 354170222Sdougb return (dst__openssl_toresult(ISC_R_NOMEMORY)); 355143731Sdougb dh->flags &= ~DH_FLAG_CACHE_MONT_P; 356143731Sdougb 357143731Sdougb /* 358143731Sdougb * Read the prime length. 1 & 2 are table entries, > 16 means a 359143731Sdougb * prime follows, otherwise an error. 360143731Sdougb */ 361143731Sdougb if (r.length < 2) { 362143731Sdougb DH_free(dh); 363143731Sdougb return (DST_R_INVALIDPUBLICKEY); 364143731Sdougb } 365143731Sdougb plen = uint16_fromregion(&r); 366143731Sdougb if (plen < 16 && plen != 1 && plen != 2) { 367143731Sdougb DH_free(dh); 368143731Sdougb return (DST_R_INVALIDPUBLICKEY); 369143731Sdougb } 370143731Sdougb if (r.length < plen) { 371143731Sdougb DH_free(dh); 372143731Sdougb return (DST_R_INVALIDPUBLICKEY); 373143731Sdougb } 374143731Sdougb if (plen == 1 || plen == 2) { 375287410Sdelphij if (plen == 1) { 376287410Sdelphij special = *r.base; 377287410Sdelphij isc_region_consume(&r, 1); 378287410Sdelphij } else { 379143731Sdougb special = uint16_fromregion(&r); 380287410Sdelphij } 381143731Sdougb switch (special) { 382143731Sdougb case 1: 383143731Sdougb dh->p = &bn768; 384143731Sdougb break; 385143731Sdougb case 2: 386143731Sdougb dh->p = &bn1024; 387143731Sdougb break; 388143731Sdougb case 3: 389143731Sdougb dh->p = &bn1536; 390143731Sdougb break; 391143731Sdougb default: 392143731Sdougb DH_free(dh); 393143731Sdougb return (DST_R_INVALIDPUBLICKEY); 394143731Sdougb } 395287410Sdelphij } else { 396143731Sdougb dh->p = BN_bin2bn(r.base, plen, NULL); 397287410Sdelphij isc_region_consume(&r, plen); 398143731Sdougb } 399143731Sdougb 400143731Sdougb /* 401143731Sdougb * Read the generator length. This should be 0 if the prime was 402143731Sdougb * special, but it might not be. If it's 0 and the prime is not 403143731Sdougb * special, we have a problem. 404143731Sdougb */ 405143731Sdougb if (r.length < 2) { 406143731Sdougb DH_free(dh); 407143731Sdougb return (DST_R_INVALIDPUBLICKEY); 408143731Sdougb } 409143731Sdougb glen = uint16_fromregion(&r); 410143731Sdougb if (r.length < glen) { 411143731Sdougb DH_free(dh); 412143731Sdougb return (DST_R_INVALIDPUBLICKEY); 413143731Sdougb } 414143731Sdougb if (special != 0) { 415143731Sdougb if (glen == 0) 416143731Sdougb dh->g = &bn2; 417143731Sdougb else { 418143731Sdougb dh->g = BN_bin2bn(r.base, glen, NULL); 419143731Sdougb if (BN_cmp(dh->g, &bn2) == 0) { 420143731Sdougb BN_free(dh->g); 421143731Sdougb dh->g = &bn2; 422143731Sdougb } 423143731Sdougb else { 424143731Sdougb DH_free(dh); 425143731Sdougb return (DST_R_INVALIDPUBLICKEY); 426143731Sdougb } 427143731Sdougb } 428287410Sdelphij } else { 429143731Sdougb if (glen == 0) { 430143731Sdougb DH_free(dh); 431143731Sdougb return (DST_R_INVALIDPUBLICKEY); 432143731Sdougb } 433143731Sdougb dh->g = BN_bin2bn(r.base, glen, NULL); 434143731Sdougb } 435287410Sdelphij isc_region_consume(&r, glen); 436143731Sdougb 437143731Sdougb if (r.length < 2) { 438143731Sdougb DH_free(dh); 439143731Sdougb return (DST_R_INVALIDPUBLICKEY); 440143731Sdougb } 441143731Sdougb publen = uint16_fromregion(&r); 442143731Sdougb if (r.length < publen) { 443143731Sdougb DH_free(dh); 444143731Sdougb return (DST_R_INVALIDPUBLICKEY); 445143731Sdougb } 446143731Sdougb dh->pub_key = BN_bin2bn(r.base, publen, NULL); 447287410Sdelphij isc_region_consume(&r, publen); 448143731Sdougb 449143731Sdougb key->key_size = BN_num_bits(dh->p); 450143731Sdougb 451143731Sdougb isc_buffer_forward(data, plen + glen + publen + 6); 452143731Sdougb 453193149Sdougb key->keydata.dh = dh; 454143731Sdougb 455143731Sdougb return (ISC_R_SUCCESS); 456143731Sdougb} 457143731Sdougb 458143731Sdougbstatic isc_result_t 459143731Sdougbopenssldh_tofile(const dst_key_t *key, const char *directory) { 460143731Sdougb int i; 461143731Sdougb DH *dh; 462143731Sdougb dst_private_t priv; 463143731Sdougb unsigned char *bufs[4]; 464143731Sdougb isc_result_t result; 465143731Sdougb 466193149Sdougb if (key->keydata.dh == NULL) 467143731Sdougb return (DST_R_NULLKEY); 468143731Sdougb 469193149Sdougb dh = key->keydata.dh; 470143731Sdougb 471245163Serwin memset(bufs, 0, sizeof(bufs)); 472143731Sdougb for (i = 0; i < 4; i++) { 473143731Sdougb bufs[i] = isc_mem_get(key->mctx, BN_num_bytes(dh->p)); 474143731Sdougb if (bufs[i] == NULL) { 475143731Sdougb result = ISC_R_NOMEMORY; 476143731Sdougb goto fail; 477143731Sdougb } 478143731Sdougb } 479143731Sdougb 480143731Sdougb i = 0; 481143731Sdougb 482143731Sdougb priv.elements[i].tag = TAG_DH_PRIME; 483143731Sdougb priv.elements[i].length = BN_num_bytes(dh->p); 484143731Sdougb BN_bn2bin(dh->p, bufs[i]); 485143731Sdougb priv.elements[i].data = bufs[i]; 486143731Sdougb i++; 487143731Sdougb 488143731Sdougb priv.elements[i].tag = TAG_DH_GENERATOR; 489143731Sdougb priv.elements[i].length = BN_num_bytes(dh->g); 490143731Sdougb BN_bn2bin(dh->g, bufs[i]); 491143731Sdougb priv.elements[i].data = bufs[i]; 492143731Sdougb i++; 493143731Sdougb 494143731Sdougb priv.elements[i].tag = TAG_DH_PRIVATE; 495143731Sdougb priv.elements[i].length = BN_num_bytes(dh->priv_key); 496143731Sdougb BN_bn2bin(dh->priv_key, bufs[i]); 497143731Sdougb priv.elements[i].data = bufs[i]; 498143731Sdougb i++; 499143731Sdougb 500143731Sdougb priv.elements[i].tag = TAG_DH_PUBLIC; 501143731Sdougb priv.elements[i].length = BN_num_bytes(dh->pub_key); 502143731Sdougb BN_bn2bin(dh->pub_key, bufs[i]); 503143731Sdougb priv.elements[i].data = bufs[i]; 504143731Sdougb i++; 505143731Sdougb 506143731Sdougb priv.nelements = i; 507143731Sdougb result = dst__privstruct_writefile(key, &priv, directory); 508143731Sdougb fail: 509143731Sdougb for (i = 0; i < 4; i++) { 510143731Sdougb if (bufs[i] == NULL) 511143731Sdougb break; 512143731Sdougb isc_mem_put(key->mctx, bufs[i], BN_num_bytes(dh->p)); 513143731Sdougb } 514143731Sdougb return (result); 515143731Sdougb} 516143731Sdougb 517143731Sdougbstatic isc_result_t 518224092Sdougbopenssldh_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { 519143731Sdougb dst_private_t priv; 520143731Sdougb isc_result_t ret; 521143731Sdougb int i; 522143731Sdougb DH *dh = NULL; 523143731Sdougb isc_mem_t *mctx; 524143731Sdougb#define DST_RET(a) {ret = a; goto err;} 525143731Sdougb 526224092Sdougb UNUSED(pub); 527143731Sdougb mctx = key->mctx; 528143731Sdougb 529143731Sdougb /* read private key file */ 530143731Sdougb ret = dst__privstruct_parse(key, DST_ALG_DH, lexer, mctx, &priv); 531143731Sdougb if (ret != ISC_R_SUCCESS) 532143731Sdougb return (ret); 533143731Sdougb 534143731Sdougb dh = DH_new(); 535143731Sdougb if (dh == NULL) 536143731Sdougb DST_RET(ISC_R_NOMEMORY); 537143731Sdougb dh->flags &= ~DH_FLAG_CACHE_MONT_P; 538193149Sdougb key->keydata.dh = dh; 539143731Sdougb 540143731Sdougb for (i = 0; i < priv.nelements; i++) { 541143731Sdougb BIGNUM *bn; 542143731Sdougb bn = BN_bin2bn(priv.elements[i].data, 543143731Sdougb priv.elements[i].length, NULL); 544143731Sdougb if (bn == NULL) 545143731Sdougb DST_RET(ISC_R_NOMEMORY); 546143731Sdougb 547143731Sdougb switch (priv.elements[i].tag) { 548143731Sdougb case TAG_DH_PRIME: 549143731Sdougb dh->p = bn; 550143731Sdougb break; 551143731Sdougb case TAG_DH_GENERATOR: 552143731Sdougb dh->g = bn; 553143731Sdougb break; 554143731Sdougb case TAG_DH_PRIVATE: 555143731Sdougb dh->priv_key = bn; 556143731Sdougb break; 557143731Sdougb case TAG_DH_PUBLIC: 558143731Sdougb dh->pub_key = bn; 559143731Sdougb break; 560143731Sdougb } 561143731Sdougb } 562143731Sdougb dst__privstruct_free(&priv, mctx); 563143731Sdougb 564143731Sdougb key->key_size = BN_num_bits(dh->p); 565143731Sdougb 566143731Sdougb if ((key->key_size == 768 || 567143731Sdougb key->key_size == 1024 || 568143731Sdougb key->key_size == 1536) && 569143731Sdougb BN_cmp(dh->g, &bn2) == 0) 570143731Sdougb { 571143731Sdougb if (key->key_size == 768 && BN_cmp(dh->p, &bn768) == 0) { 572143731Sdougb BN_free(dh->p); 573143731Sdougb BN_free(dh->g); 574143731Sdougb dh->p = &bn768; 575143731Sdougb dh->g = &bn2; 576143731Sdougb } else if (key->key_size == 1024 && 577143731Sdougb BN_cmp(dh->p, &bn1024) == 0) { 578143731Sdougb BN_free(dh->p); 579143731Sdougb BN_free(dh->g); 580143731Sdougb dh->p = &bn1024; 581143731Sdougb dh->g = &bn2; 582143731Sdougb } else if (key->key_size == 1536 && 583143731Sdougb BN_cmp(dh->p, &bn1536) == 0) { 584143731Sdougb BN_free(dh->p); 585143731Sdougb BN_free(dh->g); 586143731Sdougb dh->p = &bn1536; 587143731Sdougb dh->g = &bn2; 588143731Sdougb } 589143731Sdougb } 590143731Sdougb 591143731Sdougb return (ISC_R_SUCCESS); 592143731Sdougb 593143731Sdougb err: 594143731Sdougb openssldh_destroy(key); 595143731Sdougb dst__privstruct_free(&priv, mctx); 596143731Sdougb memset(&priv, 0, sizeof(priv)); 597143731Sdougb return (ret); 598143731Sdougb} 599143731Sdougb 600143731Sdougbstatic void 601143731SdougbBN_fromhex(BIGNUM *b, const char *str) { 602143731Sdougb static const char hexdigits[] = "0123456789abcdef"; 603143731Sdougb unsigned char data[512]; 604143731Sdougb unsigned int i; 605143731Sdougb BIGNUM *out; 606143731Sdougb 607143731Sdougb RUNTIME_CHECK(strlen(str) < 1024U && strlen(str) % 2 == 0U); 608143731Sdougb for (i = 0; i < strlen(str); i += 2) { 609143731Sdougb char *s; 610143731Sdougb unsigned int high, low; 611143731Sdougb 612143731Sdougb s = strchr(hexdigits, tolower((unsigned char)str[i])); 613143731Sdougb RUNTIME_CHECK(s != NULL); 614262706Serwin high = (unsigned int)(s - hexdigits); 615143731Sdougb 616143731Sdougb s = strchr(hexdigits, tolower((unsigned char)str[i + 1])); 617143731Sdougb RUNTIME_CHECK(s != NULL); 618262706Serwin low = (unsigned int)(s - hexdigits); 619143731Sdougb 620143731Sdougb data[i/2] = (unsigned char)((high << 4) + low); 621143731Sdougb } 622143731Sdougb out = BN_bin2bn(data, strlen(str)/2, b); 623143731Sdougb RUNTIME_CHECK(out != NULL); 624143731Sdougb} 625143731Sdougb 626143731Sdougbstatic void 627143731Sdougbopenssldh_cleanup(void) { 628143731Sdougb BN_free(&bn2); 629143731Sdougb BN_free(&bn768); 630143731Sdougb BN_free(&bn1024); 631143731Sdougb BN_free(&bn1536); 632143731Sdougb} 633143731Sdougb 634143731Sdougbstatic dst_func_t openssldh_functions = { 635170222Sdougb NULL, /*%< createctx */ 636170222Sdougb NULL, /*%< destroyctx */ 637170222Sdougb NULL, /*%< adddata */ 638170222Sdougb NULL, /*%< openssldh_sign */ 639170222Sdougb NULL, /*%< openssldh_verify */ 640254897Serwin NULL, /*%< openssldh_verify2 */ 641143731Sdougb openssldh_computesecret, 642143731Sdougb openssldh_compare, 643143731Sdougb openssldh_paramcompare, 644143731Sdougb openssldh_generate, 645143731Sdougb openssldh_isprivate, 646143731Sdougb openssldh_destroy, 647143731Sdougb openssldh_todns, 648143731Sdougb openssldh_fromdns, 649143731Sdougb openssldh_tofile, 650143731Sdougb openssldh_parse, 651143731Sdougb openssldh_cleanup, 652193149Sdougb NULL, /*%< fromlabel */ 653224092Sdougb NULL, /*%< dump */ 654224092Sdougb NULL, /*%< restore */ 655143731Sdougb}; 656143731Sdougb 657143731Sdougbisc_result_t 658143731Sdougbdst__openssldh_init(dst_func_t **funcp) { 659143731Sdougb REQUIRE(funcp != NULL); 660143731Sdougb if (*funcp == NULL) { 661143731Sdougb BN_init(&bn2); 662143731Sdougb BN_init(&bn768); 663143731Sdougb BN_init(&bn1024); 664143731Sdougb BN_init(&bn1536); 665143731Sdougb BN_set_word(&bn2, 2); 666143731Sdougb BN_fromhex(&bn768, PRIME768); 667143731Sdougb BN_fromhex(&bn1024, PRIME1024); 668143731Sdougb BN_fromhex(&bn1536, PRIME1536); 669143731Sdougb *funcp = &openssldh_functions; 670143731Sdougb } 671143731Sdougb return (ISC_R_SUCCESS); 672143731Sdougb} 673143731Sdougb 674143731Sdougb#else /* OPENSSL */ 675143731Sdougb 676143731Sdougb#include <isc/util.h> 677143731Sdougb 678143731SdougbEMPTY_TRANSLATION_UNIT 679143731Sdougb 680143731Sdougb#endif /* OPENSSL */ 681170222Sdougb/*! \file */ 682