static void dh(dns_name_t *name1, int id1, dns_name_t *name2, int id2, isc_mem_t *mctx) { dst_key_t *key1 = NULL, *key2 = NULL; isc_result_t ret; isc_buffer_t b1, b2; isc_region_t r1, r2; unsigned char array1[1024], array2[1024]; int alg = DST_ALG_DH; int type = DST_TYPE_PUBLIC|DST_TYPE_PRIVATE|DST_TYPE_KEY; ret = dst_key_fromfile(name1, id1, alg, type, current, mctx, &key1); printf("read(%d) returned: %s\n", alg, isc_result_totext(ret)); if (ret != 0) return; ret = dst_key_fromfile(name2, id2, alg, type, current, mctx, &key2); printf("read(%d) returned: %s\n", alg, isc_result_totext(ret)); if (ret != 0) return; ret = dst_key_tofile(key1, type, tmp); printf("write(%d) returned: %s\n", alg, isc_result_totext(ret)); if (ret != 0) return; ret = dst_key_tofile(key2, type, tmp); printf("write(%d) returned: %s\n", alg, isc_result_totext(ret)); if (ret != 0) return; isc_buffer_init(&b1, array1, sizeof(array1)); ret = dst_key_computesecret(key1, key2, &b1); printf("computesecret() returned: %s\n", isc_result_totext(ret)); if (ret != 0) return; isc_buffer_init(&b2, array2, sizeof(array2)); ret = dst_key_computesecret(key2, key1, &b2); printf("computesecret() returned: %s\n", isc_result_totext(ret)); if (ret != 0) return; isc_buffer_usedregion(&b1, &r1); isc_buffer_usedregion(&b2, &r2); if (r1.length != r2.length || memcmp(r1.base, r2.base, r1.length) != 0) { int i; printf("secrets don't match\n"); printf("secret 1: %d bytes\n", r1.length); for (i = 0; i < (int) r1.length; i++) printf("%02x ", r1.base[i]); printf("\n"); printf("secret 2: %d bytes\n", r2.length); for (i = 0; i < (int) r2.length; i++) printf("%02x ", r2.base[i]); printf("\n"); } dst_key_free(&key1); dst_key_free(&key2); }
ATF_TC_BODY(isc_dh_computesecret, tc) { dst_key_t *key = NULL; isc_buffer_t buf; unsigned char array[1024]; isc_result_t ret; dns_fixedname_t fname; dns_name_t *name; UNUSED(tc); ret = dns_test_begin(NULL, ISC_FALSE); ATF_REQUIRE_EQ(ret, ISC_R_SUCCESS); dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); isc_buffer_constinit(&buf, "dh.", 3); isc_buffer_add(&buf, 3); ret = dns_name_fromtext(name, &buf, NULL, 0, NULL); ATF_REQUIRE_EQ(ret, ISC_R_SUCCESS); ret = dst_key_fromfile(name, 18602, DST_ALG_DH, DST_TYPE_PUBLIC | DST_TYPE_KEY, "./", mctx, &key); ATF_REQUIRE_EQ(ret, ISC_R_SUCCESS); isc_buffer_init(&buf, array, sizeof(array)); ret = dst_key_computesecret(key, key, &buf); ATF_REQUIRE_EQ(ret, DST_R_NOTPRIVATEKEY); ret = key->func->computesecret(key, key, &buf); ATF_REQUIRE_EQ(ret, DST_R_COMPUTESECRETFAILURE); dst_key_free(&key); dns_test_end(); }
static isc_result_t process_dhtkey(dns_message_t *msg, dns_name_t *signer, dns_name_t *name, dns_rdata_tkey_t *tkeyin, dns_tkeyctx_t *tctx, dns_rdata_tkey_t *tkeyout, dns_tsig_keyring_t *ring, dns_namelist_t *namelist) { isc_result_t result = ISC_R_SUCCESS; dns_name_t *keyname, ourname; dns_rdataset_t *keyset = NULL; dns_rdata_t keyrdata = DNS_RDATA_INIT, ourkeyrdata = DNS_RDATA_INIT; isc_boolean_t found_key = ISC_FALSE, found_incompatible = ISC_FALSE; dst_key_t *pubkey = NULL; isc_buffer_t ourkeybuf, *shared = NULL; isc_region_t r, r2, ourkeyr; unsigned char keydata[DST_KEY_MAXSIZE]; unsigned int sharedsize; isc_buffer_t secret; unsigned char *randomdata = NULL, secretdata[256]; dns_ttl_t ttl = 0; if (tctx->dhkey == NULL) { tkey_log("process_dhtkey: tkey-dhkey not defined"); tkeyout->error = dns_tsigerror_badalg; return (DNS_R_REFUSED); } if (!dns_name_equal(&tkeyin->algorithm, DNS_TSIG_HMACMD5_NAME)) { tkey_log("process_dhtkey: algorithms other than " "hmac-md5 are not supported"); tkeyout->error = dns_tsigerror_badalg; return (ISC_R_SUCCESS); } /* * Look for a DH KEY record that will work with ours. */ for (result = dns_message_firstname(msg, DNS_SECTION_ADDITIONAL); result == ISC_R_SUCCESS && !found_key; result = dns_message_nextname(msg, DNS_SECTION_ADDITIONAL)) { keyname = NULL; dns_message_currentname(msg, DNS_SECTION_ADDITIONAL, &keyname); keyset = NULL; result = dns_message_findtype(keyname, dns_rdatatype_key, 0, &keyset); if (result != ISC_R_SUCCESS) continue; for (result = dns_rdataset_first(keyset); result == ISC_R_SUCCESS && !found_key; result = dns_rdataset_next(keyset)) { dns_rdataset_current(keyset, &keyrdata); pubkey = NULL; result = dns_dnssec_keyfromrdata(keyname, &keyrdata, msg->mctx, &pubkey); if (result != ISC_R_SUCCESS) { dns_rdata_reset(&keyrdata); continue; } if (dst_key_alg(pubkey) == DNS_KEYALG_DH) { if (dst_key_paramcompare(pubkey, tctx->dhkey)) { found_key = ISC_TRUE; ttl = keyset->ttl; break; } else found_incompatible = ISC_TRUE; } dst_key_free(&pubkey); dns_rdata_reset(&keyrdata); } } if (!found_key) { if (found_incompatible) { tkey_log("process_dhtkey: found an incompatible key"); tkeyout->error = dns_tsigerror_badkey; return (ISC_R_SUCCESS); } else { tkey_log("process_dhtkey: failed to find a key"); return (DNS_R_FORMERR); } } RETERR(add_rdata_to_list(msg, keyname, &keyrdata, ttl, namelist)); isc_buffer_init(&ourkeybuf, keydata, sizeof(keydata)); RETERR(dst_key_todns(tctx->dhkey, &ourkeybuf)); isc_buffer_usedregion(&ourkeybuf, &ourkeyr); dns_rdata_fromregion(&ourkeyrdata, dns_rdataclass_any, dns_rdatatype_key, &ourkeyr); dns_name_init(&ourname, NULL); dns_name_clone(dst_key_name(tctx->dhkey), &ourname); /* * XXXBEW The TTL should be obtained from the database, if it exists. */ RETERR(add_rdata_to_list(msg, &ourname, &ourkeyrdata, 0, namelist)); RETERR(dst_key_secretsize(tctx->dhkey, &sharedsize)); RETERR(isc_buffer_allocate(msg->mctx, &shared, sharedsize)); result = dst_key_computesecret(pubkey, tctx->dhkey, shared); if (result != ISC_R_SUCCESS) { tkey_log("process_dhtkey: failed to compute shared secret: %s", isc_result_totext(result)); goto failure; } dst_key_free(&pubkey); isc_buffer_init(&secret, secretdata, sizeof(secretdata)); randomdata = isc_mem_get(tkeyout->mctx, TKEY_RANDOM_AMOUNT); if (randomdata == NULL) goto failure; result = dst__entropy_getdata(randomdata, TKEY_RANDOM_AMOUNT, ISC_FALSE); if (result != ISC_R_SUCCESS) { tkey_log("process_dhtkey: failed to obtain entropy: %s", isc_result_totext(result)); goto failure; } r.base = randomdata; r.length = TKEY_RANDOM_AMOUNT; r2.base = tkeyin->key; r2.length = tkeyin->keylen; RETERR(compute_secret(shared, &r2, &r, &secret)); isc_buffer_free(&shared); RETERR(dns_tsigkey_create(name, &tkeyin->algorithm, isc_buffer_base(&secret), isc_buffer_usedlength(&secret), ISC_TRUE, signer, tkeyin->inception, tkeyin->expire, ring->mctx, ring, NULL)); /* This key is good for a long time */ tkeyout->inception = tkeyin->inception; tkeyout->expire = tkeyin->expire; tkeyout->key = randomdata; tkeyout->keylen = TKEY_RANDOM_AMOUNT; return (ISC_R_SUCCESS); failure: if (!ISC_LIST_EMPTY(*namelist)) free_namelist(msg, namelist); if (shared != NULL) isc_buffer_free(&shared); if (pubkey != NULL) dst_key_free(&pubkey); if (randomdata != NULL) isc_mem_put(tkeyout->mctx, randomdata, TKEY_RANDOM_AMOUNT); return (result); }