mirror of
https://github.com/isc-projects/bind9.git
synced 2026-06-10 04:10:00 -04:00
new: usr: "Add code paths to fully support PRIVATEDNS and PRIVATEOID keys"
Added support for PRIVATEDNS and PRIVATEOID key usage. Added PRIVATEOID test algorithms using the assigned OIDs for RSASHA256 and RSASHA512. Added code to support proposed DS digest types that encode the PRIVATEDNS and PRIVATEOID identifiers at the start of the digest field of the DS record. This code is disabled by default. Closes #3240 Merge branch '3240-add-privatedns-and-privateoid-support' into 'main' See merge request isc-projects/bind9!10341
This commit is contained in:
commit
119f511a45
52 changed files with 2014 additions and 358 deletions
|
|
@ -482,7 +482,7 @@ match_key_dsset(keyinfo_t *ki, dns_rdataset_t *dsset, strictness_t strictness) {
|
|||
}
|
||||
|
||||
result = dns_ds_buildrdata(name, &ki->rdata, ds.digest_type,
|
||||
dsbuf, &newdsrdata);
|
||||
dsbuf, sizeof(dsbuf), &newdsrdata);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
vbprintf(3,
|
||||
"dns_ds_buildrdata("
|
||||
|
|
@ -769,7 +769,7 @@ ds_from_cdnskey(isc_buffer_t *buf, dns_rdata_t *ds, dns_dsdigest_t dt,
|
|||
return ISC_R_NOSPACE;
|
||||
}
|
||||
|
||||
result = dns_ds_buildrdata(name, cdnskey, dt, r.base, ds);
|
||||
result = dns_ds_buildrdata(name, cdnskey, dt, r.base, r.length, ds);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
isc_buffer_add(buf, DNS_DS_BUFFERSIZE);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -270,7 +270,7 @@ emit(dns_dsdigest_t dt, bool showall, bool cds, dns_rdata_t *rdata) {
|
|||
return;
|
||||
}
|
||||
|
||||
result = dns_ds_buildrdata(name, rdata, dt, buf, &ds);
|
||||
result = dns_ds_buildrdata(name, rdata, dt, buf, sizeof(buf), &ds);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
fatal("can't build record");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ main(int argc, char **argv) {
|
|||
dns_fixedname_t fname;
|
||||
dns_name_t *name;
|
||||
uint16_t flags = 0, kskflag = 0, revflag = 0;
|
||||
dns_secalg_t alg;
|
||||
dst_algorithm_t alg;
|
||||
bool oldstyle = false;
|
||||
isc_mem_t *mctx = NULL;
|
||||
int ch;
|
||||
|
|
@ -382,7 +382,7 @@ main(int argc, char **argv) {
|
|||
|
||||
r.base = algname;
|
||||
r.length = strlen(algname);
|
||||
ret = dns_secalg_fromtext(&alg, &r);
|
||||
ret = dst_algorithm_fromtext(&alg, &r);
|
||||
if (ret != ISC_R_SUCCESS) {
|
||||
fatal("unknown algorithm %s", algname);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ struct keygen_ctx {
|
|||
bool wantzsk;
|
||||
bool wantksk;
|
||||
bool wantrev;
|
||||
dns_secalg_t alg;
|
||||
dst_algorithm_t alg;
|
||||
/* timing data */
|
||||
int prepub;
|
||||
isc_stdtime_t now;
|
||||
|
|
@ -245,7 +245,7 @@ keygen(keygen_ctx_t *ctx, isc_mem_t *mctx, int argc, char **argv) {
|
|||
|
||||
UNUSED(argc);
|
||||
|
||||
dns_secalg_format(ctx->alg, algstr, sizeof(algstr));
|
||||
dst_algorithm_format(ctx->alg, algstr, sizeof(algstr));
|
||||
|
||||
if (ctx->predecessor == NULL) {
|
||||
if (ctx->prepub == -1) {
|
||||
|
|
@ -286,6 +286,8 @@ keygen(keygen_ctx_t *ctx, isc_mem_t *mctx, int argc, char **argv) {
|
|||
case DST_ALG_NSEC3RSASHA1:
|
||||
case DST_ALG_RSASHA256:
|
||||
case DST_ALG_RSASHA512:
|
||||
case DST_ALG_RSASHA256PRIVATEOID:
|
||||
case DST_ALG_RSASHA512PRIVATEOID:
|
||||
case DST_ALG_ECDSA256:
|
||||
case DST_ALG_ECDSA384:
|
||||
case DST_ALG_ED25519:
|
||||
|
|
@ -309,6 +311,8 @@ keygen(keygen_ctx_t *ctx, isc_mem_t *mctx, int argc, char **argv) {
|
|||
FALLTHROUGH;
|
||||
case DST_ALG_RSASHA256:
|
||||
case DST_ALG_RSASHA512:
|
||||
case DST_ALG_RSASHA256PRIVATEOID:
|
||||
case DST_ALG_RSASHA512PRIVATEOID:
|
||||
ctx->size = 2048;
|
||||
if (verbose > 0) {
|
||||
fprintf(stderr,
|
||||
|
|
@ -454,14 +458,16 @@ keygen(keygen_ctx_t *ctx, isc_mem_t *mctx, int argc, char **argv) {
|
|||
}
|
||||
|
||||
switch (ctx->alg) {
|
||||
case DNS_KEYALG_RSASHA1:
|
||||
case DNS_KEYALG_NSEC3RSASHA1:
|
||||
case DST_ALG_RSASHA1:
|
||||
case DST_ALG_NSEC3RSASHA1:
|
||||
if (isc_crypto_fips_mode()) {
|
||||
fatal("SHA1 based keys not supported in FIPS mode");
|
||||
}
|
||||
FALLTHROUGH;
|
||||
case DNS_KEYALG_RSASHA256:
|
||||
case DNS_KEYALG_RSASHA512:
|
||||
case DST_ALG_RSASHA256:
|
||||
case DST_ALG_RSASHA512:
|
||||
case DST_ALG_RSASHA256PRIVATEOID:
|
||||
case DST_ALG_RSASHA512PRIVATEOID:
|
||||
if (ctx->size != 0 &&
|
||||
(ctx->size < min_rsa || ctx->size > MAX_RSA))
|
||||
{
|
||||
|
|
@ -480,6 +486,8 @@ keygen(keygen_ctx_t *ctx, isc_mem_t *mctx, int argc, char **argv) {
|
|||
case DST_ALG_ED448:
|
||||
ctx->size = 456;
|
||||
break;
|
||||
default:
|
||||
fatal("not a dnskey algorithm %u\n", ctx->alg);
|
||||
}
|
||||
|
||||
if ((ctx->options & DST_TYPE_KEY) == 0) {
|
||||
|
|
@ -502,10 +510,10 @@ keygen(keygen_ctx_t *ctx, isc_mem_t *mctx, int argc, char **argv) {
|
|||
}
|
||||
|
||||
switch (ctx->alg) {
|
||||
case DNS_KEYALG_RSASHA1:
|
||||
case DNS_KEYALG_NSEC3RSASHA1:
|
||||
case DNS_KEYALG_RSASHA256:
|
||||
case DNS_KEYALG_RSASHA512:
|
||||
case DST_ALG_RSASHA1:
|
||||
case DST_ALG_NSEC3RSASHA1:
|
||||
case DST_ALG_RSASHA256:
|
||||
case DST_ALG_RSASHA512:
|
||||
show_progress = true;
|
||||
break;
|
||||
|
||||
|
|
@ -515,6 +523,8 @@ keygen(keygen_ctx_t *ctx, isc_mem_t *mctx, int argc, char **argv) {
|
|||
case DST_ALG_ED448:
|
||||
show_progress = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if ((flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY &&
|
||||
|
|
@ -1072,7 +1082,7 @@ main(int argc, char **argv) {
|
|||
}
|
||||
r.base = algname;
|
||||
r.length = strlen(algname);
|
||||
ret = dns_secalg_fromtext(&ctx.alg, &r);
|
||||
ret = dst_algorithm_fromtext(&ctx.alg, &r);
|
||||
if (ret != ISC_R_SUCCESS) {
|
||||
fatal("unknown algorithm %s", algname);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ struct ksr_ctx {
|
|||
/* keygen */
|
||||
bool ksk;
|
||||
dns_ttl_t ttl;
|
||||
dns_secalg_t alg;
|
||||
dst_algorithm_t alg;
|
||||
int size;
|
||||
time_t lifetime;
|
||||
time_t parentpropagation;
|
||||
|
|
@ -341,7 +341,7 @@ create_key(ksr_ctx_t *ksr, dns_kasp_t *kasp, dns_kasp_key_t *kaspkey,
|
|||
}
|
||||
|
||||
/* Check algorithm and size. */
|
||||
dns_secalg_format(ksr->alg, algstr, sizeof(algstr));
|
||||
dst_algorithm_format(ksr->alg, algstr, sizeof(algstr));
|
||||
if (!dst_algorithm_supported(ksr->alg)) {
|
||||
fatal("unsupported algorithm: %s", algstr);
|
||||
}
|
||||
|
|
@ -356,6 +356,8 @@ create_key(ksr_ctx_t *ksr, dns_kasp_t *kasp, dns_kasp_key_t *kaspkey,
|
|||
FALLTHROUGH;
|
||||
case DST_ALG_RSASHA256:
|
||||
case DST_ALG_RSASHA512:
|
||||
case DST_ALG_RSASHA256PRIVATEOID:
|
||||
case DST_ALG_RSASHA512PRIVATEOID:
|
||||
if (ksr->size != 0 &&
|
||||
(ksr->size < min_rsa || ksr->size > MAX_RSA))
|
||||
{
|
||||
|
|
@ -851,7 +853,7 @@ get_keymaterial(ksr_ctx_t *ksr, dns_kasp_t *kasp, isc_stdtime_t inception,
|
|||
dns_rdata_init(rdata2);
|
||||
|
||||
CHECK(dns_ds_buildrdata(name, rdata, alg->digest,
|
||||
cdsbuf, &cds));
|
||||
cdsbuf, sizeof(cdsbuf), &cds));
|
||||
cds.type = dns_rdatatype_cds;
|
||||
dns_rdata_toregion(&cds, &rcds);
|
||||
isc_buffer_allocate(mctx, &newbuf2, rcds.length);
|
||||
|
|
|
|||
|
|
@ -348,9 +348,12 @@ iszsk(dns_dnsseckey_t *key) {
|
|||
*/
|
||||
static dns_dnsseckey_t *
|
||||
keythatsigned_unlocked(dns_rdata_rrsig_t *rrsig) {
|
||||
dst_algorithm_t algorithm = dst_algorithm_fromdata(
|
||||
rrsig->algorithm, rrsig->signature, rrsig->siglen);
|
||||
|
||||
ISC_LIST_FOREACH (keylist, key, link) {
|
||||
if (rrsig->keyid == dst_key_id(key->key) &&
|
||||
rrsig->algorithm == dst_key_alg(key->key) &&
|
||||
algorithm == dst_key_alg(key->key) &&
|
||||
dns_name_equal(&rrsig->signer, dst_key_name(key->key)))
|
||||
{
|
||||
return key;
|
||||
|
|
@ -1070,7 +1073,7 @@ loadds(dns_name_t *name, uint32_t ttl, dns_rdataset_t *dsset) {
|
|||
dns_rdata_t ds = DNS_RDATA_INIT;
|
||||
dns_rdataset_current(&keyset, &key);
|
||||
result = dns_ds_buildrdata(name, &key, DNS_DSDIGEST_SHA256,
|
||||
dsbuf, &ds);
|
||||
dsbuf, sizeof(dsbuf), &ds);
|
||||
check_result(result, "dns_ds_buildrdata");
|
||||
|
||||
dns_difftuple_create(mctx, DNS_DIFFOP_ADDRESIGN, name, ttl, &ds,
|
||||
|
|
@ -3052,7 +3055,7 @@ writeset(const char *prefix, dns_rdatatype_t type) {
|
|||
if (type != dns_rdatatype_dnskey) {
|
||||
result = dns_ds_buildrdata(gorigin, &rdata,
|
||||
DNS_DSDIGEST_SHA256, dsbuf,
|
||||
&ds);
|
||||
sizeof(dsbuf), &ds);
|
||||
check_result(result, "dns_ds_buildrdata");
|
||||
dns_difftuple_create(mctx, DNS_DIFFOP_ADDRESIGN, name,
|
||||
0, &ds, &tuple);
|
||||
|
|
|
|||
|
|
@ -120,9 +120,11 @@ void
|
|||
sig_format(dns_rdata_rrsig_t *sig, char *cp, unsigned int size) {
|
||||
char namestr[DNS_NAME_FORMATSIZE];
|
||||
char algstr[DNS_NAME_FORMATSIZE];
|
||||
dst_algorithm_t algorithm = dst_algorithm_fromdata(
|
||||
sig->algorithm, sig->signature, sig->siglen);
|
||||
|
||||
dns_name_format(&sig->signer, namestr, sizeof(namestr));
|
||||
dns_secalg_format(sig->algorithm, algstr, sizeof(algstr));
|
||||
dst_algorithm_format(algorithm, algstr, sizeof(algstr));
|
||||
snprintf(cp, size, "%s/%s/%d", namestr, algstr, sig->keyid);
|
||||
}
|
||||
|
||||
|
|
@ -361,7 +363,10 @@ strtodsdigest(const char *str) {
|
|||
r.length = strlen(str);
|
||||
result = dns_dsdigest_fromtext(&alg, &r);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
fatal("unknown DS algorithm %s", str);
|
||||
fatal("unknown DS digest %s", str);
|
||||
}
|
||||
if (!dst_ds_digest_supported(alg)) {
|
||||
fatal("unsupported DS digest %s", str);
|
||||
}
|
||||
return alg;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -424,7 +424,7 @@ list_dnssec_algorithms(isc_buffer_t *b) {
|
|||
}
|
||||
if (dst_algorithm_supported(i)) {
|
||||
isc_buffer_putstr(b, " ");
|
||||
(void)dns_secalg_totext(i, b);
|
||||
dst_algorithm_totext(i, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -154,11 +154,11 @@
|
|||
#endif /* HAVE_LMDB */
|
||||
|
||||
#ifndef SIZE_MAX
|
||||
#define SIZE_MAX ((size_t)-1)
|
||||
#define SIZE_MAX ((size_t)(-1))
|
||||
#endif /* ifndef SIZE_MAX */
|
||||
|
||||
#ifndef SIZE_AS_PERCENT
|
||||
#define SIZE_AS_PERCENT ((size_t)-2)
|
||||
#define SIZE_AS_PERCENT ((size_t)(-2))
|
||||
#endif /* ifndef SIZE_AS_PERCENT */
|
||||
|
||||
/* RFC7828 defines timeout as 16-bit value specified in units of 100
|
||||
|
|
@ -677,7 +677,7 @@ cleanup:
|
|||
|
||||
static isc_result_t
|
||||
ta_fromconfig(const cfg_obj_t *key, bool *initialp, const char **namestrp,
|
||||
unsigned char *digest, dns_rdata_ds_t *ds) {
|
||||
unsigned char *digest, size_t digest_len, dns_rdata_ds_t *ds) {
|
||||
isc_result_t result;
|
||||
dns_rdata_dnskey_t keystruct;
|
||||
dns_rdata_t rdata = DNS_RDATA_INIT;
|
||||
|
|
@ -699,6 +699,7 @@ ta_fromconfig(const cfg_obj_t *key, bool *initialp, const char **namestrp,
|
|||
STATIC_DS,
|
||||
TRUSTED
|
||||
} anchortype;
|
||||
dst_algorithm_t algorithm;
|
||||
|
||||
REQUIRE(namestrp != NULL && *namestrp == NULL);
|
||||
REQUIRE(ds != NULL);
|
||||
|
|
@ -787,22 +788,24 @@ ta_fromconfig(const cfg_obj_t *key, bool *initialp, const char **namestrp,
|
|||
keystruct.flags = (uint16_t)rdata1;
|
||||
keystruct.protocol = (uint8_t)rdata2;
|
||||
keystruct.algorithm = (uint8_t)rdata3;
|
||||
|
||||
if (!dst_algorithm_supported(keystruct.algorithm)) {
|
||||
CHECK(DST_R_UNSUPPORTEDALG);
|
||||
}
|
||||
|
||||
datastr = cfg_obj_asstring(cfg_tuple_get(key, "data"));
|
||||
CHECK(isc_base64_decodestring(datastr, &databuf));
|
||||
isc_buffer_usedregion(&databuf, &r);
|
||||
keystruct.datalen = r.length;
|
||||
keystruct.data = r.base;
|
||||
|
||||
algorithm = dst_algorithm_fromdata(
|
||||
keystruct.algorithm, keystruct.data, keystruct.datalen);
|
||||
|
||||
if (!dst_algorithm_supported(algorithm)) {
|
||||
CHECK(DST_R_UNSUPPORTEDALG);
|
||||
}
|
||||
|
||||
CHECK(dns_rdata_fromstruct(&rdata, keystruct.common.rdclass,
|
||||
keystruct.common.rdtype, &keystruct,
|
||||
&rrdatabuf));
|
||||
CHECK(dns_ds_fromkeyrdata(name, &rdata, DNS_DSDIGEST_SHA256,
|
||||
digest, ds));
|
||||
digest, digest_len, ds));
|
||||
break;
|
||||
|
||||
case INIT_DS:
|
||||
|
|
@ -841,6 +844,20 @@ ta_fromconfig(const cfg_obj_t *key, bool *initialp, const char **namestrp,
|
|||
CHECK(ISC_R_UNEXPECTEDEND);
|
||||
}
|
||||
break;
|
||||
#if defined(DNS_DSDIGEST_SHA256PRIVATE)
|
||||
case DNS_DSDIGEST_SHA256PRIVATE:
|
||||
if (r.length < ISC_SHA256_DIGESTLENGTH) {
|
||||
CHECK(ISC_R_UNEXPECTEDEND);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#if defined(DNS_DSDIGEST_SHA384PRIVATE)
|
||||
case DNS_DSDIGEST_SHA384PRIVATE:
|
||||
if (r.length < ISC_SHA384_DIGESTLENGTH) {
|
||||
CHECK(ISC_R_UNEXPECTEDEND);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
cfg_obj_log(key, ISC_LOG_ERROR,
|
||||
"key '%s': "
|
||||
|
|
@ -851,10 +868,49 @@ ta_fromconfig(const cfg_obj_t *key, bool *initialp, const char **namestrp,
|
|||
break;
|
||||
}
|
||||
|
||||
if (r.length > digest_len) {
|
||||
CHECK(ISC_R_NOSPACE);
|
||||
}
|
||||
ds->length = r.length;
|
||||
ds->digest = digest;
|
||||
memmove(ds->digest, r.base, r.length);
|
||||
|
||||
algorithm = ds->algorithm;
|
||||
|
||||
#if defined(DNS_DSDIGEST_SHA256PRIVATE) && defined(DNS_DSDIGEST_SHA384PRIVATE)
|
||||
/*
|
||||
* Extract the private algorithm from the start
|
||||
* of the hash field.
|
||||
*/
|
||||
switch (ds->digest_type) {
|
||||
/*
|
||||
* Digest types that do not encode the private DNSSEC algorithm
|
||||
* at the start of the digest field.
|
||||
*/
|
||||
case DNS_DSDIGEST_SHA1:
|
||||
case DNS_DSDIGEST_SHA256:
|
||||
case DNS_DSDIGEST_SHA384:
|
||||
break;
|
||||
/*
|
||||
* Digest types that encode the private DNSSEC algorithm
|
||||
* at the start of the digest field.
|
||||
*/
|
||||
case DNS_DSDIGEST_SHA256PRIVATE:
|
||||
case DNS_DSDIGEST_SHA384PRIVATE:
|
||||
algorithm = dst_algorithm_fromdata(
|
||||
ds->algorithm, ds->digest, ds->length);
|
||||
break;
|
||||
/*
|
||||
* Unknown digest types.
|
||||
*/
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
if (!dst_algorithm_supported(algorithm)) {
|
||||
CHECK(DST_R_UNSUPPORTEDALG);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
@ -894,10 +950,11 @@ process_key(const cfg_obj_t *key, dns_keytable_t *secroots,
|
|||
dns_rdata_ds_t ds;
|
||||
isc_result_t result;
|
||||
bool initializing = managed;
|
||||
unsigned char digest[ISC_MAX_MD_SIZE];
|
||||
unsigned char digest[DNS_DS_BUFFERSIZE];
|
||||
isc_buffer_t b;
|
||||
|
||||
result = ta_fromconfig(key, &initializing, &namestr, digest, &ds);
|
||||
result = ta_fromconfig(key, &initializing, &namestr, digest,
|
||||
sizeof(digest), &ds);
|
||||
|
||||
switch (result) {
|
||||
case ISC_R_SUCCESS:
|
||||
|
|
@ -950,7 +1007,7 @@ process_key(const cfg_obj_t *key, dns_keytable_t *secroots,
|
|||
* warning, but do not prevent further keys from being processed.
|
||||
*/
|
||||
if (!dns_resolver_algorithm_supported(view->resolver, keyname,
|
||||
ds.algorithm))
|
||||
ds.algorithm, NULL, 0))
|
||||
{
|
||||
cfg_obj_log(key, ISC_LOG_WARNING,
|
||||
"ignoring %s for '%s': algorithm is disabled",
|
||||
|
|
@ -1592,17 +1649,11 @@ disable_algorithms(const cfg_obj_t *disabled, dns_resolver_t *resolver) {
|
|||
algorithms = cfg_tuple_get(disabled, "algorithms");
|
||||
CFG_LIST_FOREACH (algorithms, element) {
|
||||
isc_textregion_t r;
|
||||
dns_secalg_t alg;
|
||||
dst_algorithm_t alg;
|
||||
|
||||
r.base = UNCONST(cfg_obj_asstring(cfg_listelt_value(element)));
|
||||
r.length = strlen(r.base);
|
||||
|
||||
result = dns_secalg_fromtext(&alg, &r);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
uint8_t ui;
|
||||
result = isc_parse_uint8(&ui, r.base, 10);
|
||||
alg = ui;
|
||||
}
|
||||
result = dst_algorithm_fromtext(&alg, &r);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
cfg_obj_log(cfg_listelt_value(element), ISC_LOG_ERROR,
|
||||
"invalid algorithm");
|
||||
|
|
@ -14358,7 +14409,7 @@ named_server_dnssec(named_server_t *server, isc_lex_t *lex,
|
|||
/* variables for -key */
|
||||
bool use_keyid = false;
|
||||
dns_keytag_t keyid = 0;
|
||||
uint8_t algorithm = 0;
|
||||
dst_algorithm_t algorithm = 0;
|
||||
/* variables for -status */
|
||||
bool status = false;
|
||||
char output[4096];
|
||||
|
|
@ -14414,7 +14465,7 @@ named_server_dnssec(named_server_t *server, isc_lex_t *lex,
|
|||
}
|
||||
alg.base = ptr;
|
||||
alg.length = strlen(alg.base);
|
||||
result = dns_secalg_fromtext(
|
||||
result = dst_algorithm_fromtext(
|
||||
&algorithm, (isc_textregion_t *)&alg);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
msg = "Bad algorithm";
|
||||
|
|
|
|||
|
|
@ -31,12 +31,13 @@ showprivate() {
|
|||
$DIG $DIGOPTS +nodnssec +short @$2 -t ${4:-type65534} $1 | cut -f3 -d' ' \
|
||||
| while read record; do
|
||||
$PERL -e 'my $rdata = pack("H*", @ARGV[0]);
|
||||
die "invalid record" unless length($rdata) == 5;
|
||||
my ($alg, $key, $remove, $complete) = unpack("CnCC", $rdata);
|
||||
die "invalid record" unless length($rdata) == 5 || length($rdata) == 7;
|
||||
my ($dns, $key, $remove, $complete, $alg) = unpack("CnCCn", $rdata);
|
||||
my $action = "signing";
|
||||
$action = "removing" if $remove;
|
||||
my $state = " (incomplete)";
|
||||
$state = " (complete)" if $complete;
|
||||
$alg = $dns if ! defined($alg);
|
||||
print ("$action: alg: $alg, key: $key$state\n");' $record
|
||||
done
|
||||
}
|
||||
|
|
|
|||
|
|
@ -211,10 +211,19 @@ private_type_record() {
|
|||
_zone=$1
|
||||
_algorithm=$2
|
||||
_keyfile=$3
|
||||
_secalg=$2
|
||||
case $_secalg in
|
||||
256) _secalg=254 ;; # RSASHA256OID
|
||||
257) _secalg=254 ;; # RSASHA512OID
|
||||
esac
|
||||
|
||||
_id=$(keyfile_to_key_id "$_keyfile")
|
||||
|
||||
printf "%s. 0 IN TYPE65534 %s 5 %02x%04x0000\n" "$_zone" "\\#" "$_algorithm" "$_id"
|
||||
if test "$_algorithm" -lt 256; then
|
||||
printf "%s. 0 IN TYPE65534 %s 5 %02x%04x0000\n" "$_zone" "\\#" "$_secalg" "$_id"
|
||||
else
|
||||
printf "%s. 0 IN TYPE65534 %s 7 %02x%04x0000%04x\n" "$_zone" "\\#" "$_secalg" "$_id" "$_algorithm"
|
||||
fi
|
||||
}
|
||||
|
||||
# nextpart*() - functions for reading files incrementally
|
||||
|
|
@ -518,13 +527,16 @@ copy_setports() {
|
|||
-e "s/@CONTROLPORT@/${CONTROLPORT}/g" \
|
||||
-e "s/@DEFAULT_ALGORITHM@/${DEFAULT_ALGORITHM}/g" \
|
||||
-e "s/@DEFAULT_ALGORITHM_NUMBER@/${DEFAULT_ALGORITHM_NUMBER}/g" \
|
||||
-e "s/@DEFAULT_ALGORITHM_DST_NUMBER@/${DEFAULT_ALGORITHM_DST_NUMBER}/g" \
|
||||
-e "s/@DEFAULT_BITS@/${DEFAULT_BITS}/g" \
|
||||
-e "s/@ALTERNATIVE_ALGORITHM@/${ALTERNATIVE_ALGORITHM}/g" \
|
||||
-e "s/@ALTERNATIVE_ALGORITHM_NUMBER@/${ALTERNATIVE_ALGORITHM_NUMBER}/g" \
|
||||
-e "s/@ALTERNATIVE_ALGORITHM_DST_NUMBER@/${ALTERNATIVE_ALGORITHM_DST_NUMBER}/g" \
|
||||
-e "s/@ALTERNATIVE_BITS@/${ALTERNATIVE_BITS}/g" \
|
||||
-e "s/@DEFAULT_HMAC@/${DEFAULT_HMAC}/g" \
|
||||
-e "s/@DISABLED_ALGORITHM@/${DISABLED_ALGORITHM}/g" \
|
||||
-e "s/@DISABLED_ALGORITHM_NUMBER@/${DISABLED_ALGORITHM_NUMBER}/g" \
|
||||
-e "s/@DISABLED_ALGORITHM_NUMBER@/${DISABLED_ALGORITHM_DST_NUMBER}/g" \
|
||||
-e "s/@DISABLED_BITS@/${DISABLED_BITS}/g" \
|
||||
$1 >$2
|
||||
}
|
||||
|
|
|
|||
|
|
@ -181,3 +181,21 @@ rsasha1-1024 NS ns.rsasha1-1024
|
|||
ns.rsasha1-1024 A 10.53.0.3
|
||||
|
||||
dname-at-apex-nsec3 NS ns3
|
||||
|
||||
rsasha256oid NS ns.rsasha256oid
|
||||
ns.rsasha256oid A 10.53.0.3
|
||||
|
||||
rsasha512oid NS ns.rsasha512oid
|
||||
ns.rsasha512oid A 10.53.0.3
|
||||
|
||||
unknownoid NS ns.unknownoid
|
||||
ns.unknownoid A 10.53.0.3
|
||||
|
||||
extradsoid NS ns.extradsoid
|
||||
ns.extradsoid A 10.53.0.3
|
||||
|
||||
extradsunknownoid NS ns.extradsunknownoid
|
||||
ns.extradsunknownoid A 10.53.0.3
|
||||
|
||||
extended-ds-unknown-oid NS ns.extended-ds-unknown-oid
|
||||
ns.extended-ds-unknown-oid A 10.53.0.3
|
||||
|
|
|
|||
|
|
@ -65,7 +65,9 @@ for subdomain in digest-alg-unsupported ds-unsupported secure badds \
|
|||
ttlpatch split-dnssec split-smart expired expiring upper lower \
|
||||
dnskey-unknown dnskey-unsupported dnskey-unsupported-2 \
|
||||
dnskey-nsec3-unknown managed-future future revkey \
|
||||
dname-at-apex-nsec3 occluded rsasha1 rsasha1-1024; do
|
||||
dname-at-apex-nsec3 occluded rsasha1 rsasha1-1024 \
|
||||
rsasha256oid rsasha512oid unknownoid extradsoid extradsunknownoid \
|
||||
extended-ds-unknown-oid; do
|
||||
cp "../ns3/dsset-$subdomain.example." .
|
||||
done
|
||||
|
||||
|
|
@ -87,7 +89,7 @@ zonefiletmp=$(mktemp "$zonefile.XXXXXX") || exit 1
|
|||
| awk '
|
||||
tolower($1) == "bad-cname.example." && $4 == "RRSIG" && $5 == "CNAME" {
|
||||
for (i = 1; i <= NF; i++ ) {
|
||||
if (i <= 12) {
|
||||
if (i <= 13) {
|
||||
printf("%s ", $i);
|
||||
continue;
|
||||
}
|
||||
|
|
@ -106,7 +108,7 @@ tolower($1) == "bad-cname.example." && $4 == "RRSIG" && $5 == "CNAME" {
|
|||
|
||||
tolower($1) == "bad-dname.example." && $4 == "RRSIG" && $5 == "DNAME" {
|
||||
for (i = 1; i <= NF; i++ ) {
|
||||
if (i <= 12) {
|
||||
if (i <= 13) {
|
||||
printf("%s ", $i);
|
||||
continue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
;
|
||||
; SPDX-License-Identifier: MPL-2.0
|
||||
;
|
||||
; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
; file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
;
|
||||
; See the COPYRIGHT file distributed with this work for additional
|
||||
; information regarding copyright ownership.
|
||||
|
||||
$TTL 300 ; 5 minutes
|
||||
@ IN SOA mname1. . (
|
||||
2009102722 ; serial
|
||||
20 ; refresh (20 seconds)
|
||||
20 ; retry (20 seconds)
|
||||
1814400 ; expire (3 weeks)
|
||||
3600 ; minimum (1 hour)
|
||||
)
|
||||
NS ns
|
||||
ns A 10.53.0.3
|
||||
|
||||
a A 10.0.0.1
|
||||
b A 10.0.0.2
|
||||
d A 10.0.0.4
|
||||
z A 10.0.0.26
|
||||
a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27
|
||||
x CNAME a
|
||||
28
bin/tests/system/dnssec/ns3/extradsoid.example.db.in
Normal file
28
bin/tests/system/dnssec/ns3/extradsoid.example.db.in
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
;
|
||||
; SPDX-License-Identifier: MPL-2.0
|
||||
;
|
||||
; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
; file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
;
|
||||
; See the COPYRIGHT file distributed with this work for additional
|
||||
; information regarding copyright ownership.
|
||||
|
||||
$TTL 300 ; 5 minutes
|
||||
@ IN SOA mname1. . (
|
||||
2009102722 ; serial
|
||||
20 ; refresh (20 seconds)
|
||||
20 ; retry (20 seconds)
|
||||
1814400 ; expire (3 weeks)
|
||||
3600 ; minimum (1 hour)
|
||||
)
|
||||
NS ns
|
||||
ns A 10.53.0.3
|
||||
|
||||
a A 10.0.0.1
|
||||
b A 10.0.0.2
|
||||
d A 10.0.0.4
|
||||
z A 10.0.0.26
|
||||
a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27
|
||||
x CNAME a
|
||||
28
bin/tests/system/dnssec/ns3/extradsunknownoid.example.db.in
Normal file
28
bin/tests/system/dnssec/ns3/extradsunknownoid.example.db.in
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
;
|
||||
; SPDX-License-Identifier: MPL-2.0
|
||||
;
|
||||
; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
; file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
;
|
||||
; See the COPYRIGHT file distributed with this work for additional
|
||||
; information regarding copyright ownership.
|
||||
|
||||
$TTL 300 ; 5 minutes
|
||||
@ IN SOA mname1. . (
|
||||
2009102722 ; serial
|
||||
20 ; refresh (20 seconds)
|
||||
20 ; retry (20 seconds)
|
||||
1814400 ; expire (3 weeks)
|
||||
3600 ; minimum (1 hour)
|
||||
)
|
||||
NS ns
|
||||
ns A 10.53.0.3
|
||||
|
||||
a A 10.0.0.1
|
||||
b A 10.0.0.2
|
||||
d A 10.0.0.4
|
||||
z A 10.0.0.26
|
||||
a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27
|
||||
x CNAME a
|
||||
|
|
@ -429,11 +429,41 @@ zone "rsasha1-1024.example" {
|
|||
file "rsasha1-1024.example.db";
|
||||
};
|
||||
|
||||
zone "rsasha256oid.example" {
|
||||
type primary;
|
||||
file "rsasha256oid.example.db.signed";
|
||||
};
|
||||
|
||||
zone "rsasha512oid.example" {
|
||||
type primary;
|
||||
file "rsasha512oid.example.db.signed";
|
||||
};
|
||||
|
||||
zone "unknownoid.example" {
|
||||
type primary;
|
||||
file "unknownoid.example.db.signed";
|
||||
};
|
||||
|
||||
zone "target.peer-ns-spoof" {
|
||||
type primary;
|
||||
file "target.peer-ns-spoof.db.signed";
|
||||
};
|
||||
|
||||
zone "extradsoid.example" {
|
||||
type primary;
|
||||
file "extradsoid.example.db.signed";
|
||||
};
|
||||
|
||||
zone "extradsunknownoid.example" {
|
||||
type primary;
|
||||
file "extradsunknownoid.example.db.signed";
|
||||
};
|
||||
|
||||
zone "extended-ds-unknown-oid.example" {
|
||||
type primary;
|
||||
file "extended-ds-unknown-oid.example.db.signed";
|
||||
};
|
||||
|
||||
dnssec-policy "siginterval1" {
|
||||
keys {
|
||||
ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@;
|
||||
|
|
|
|||
28
bin/tests/system/dnssec/ns3/rsasha256oid.example.db.in
Normal file
28
bin/tests/system/dnssec/ns3/rsasha256oid.example.db.in
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
;
|
||||
; SPDX-License-Identifier: MPL-2.0
|
||||
;
|
||||
; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
; file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
;
|
||||
; See the COPYRIGHT file distributed with this work for additional
|
||||
; information regarding copyright ownership.
|
||||
|
||||
$TTL 300 ; 5 minutes
|
||||
@ IN SOA mname1. . (
|
||||
2009102722 ; serial
|
||||
20 ; refresh (20 seconds)
|
||||
20 ; retry (20 seconds)
|
||||
1814400 ; expire (3 weeks)
|
||||
3600 ; minimum (1 hour)
|
||||
)
|
||||
NS ns
|
||||
ns A 10.53.0.3
|
||||
|
||||
a A 10.0.0.1
|
||||
b A 10.0.0.2
|
||||
d A 10.0.0.4
|
||||
z A 10.0.0.26
|
||||
a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27
|
||||
x CNAME a
|
||||
28
bin/tests/system/dnssec/ns3/rsasha512oid.example.db.in
Normal file
28
bin/tests/system/dnssec/ns3/rsasha512oid.example.db.in
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
;
|
||||
; SPDX-License-Identifier: MPL-2.0
|
||||
;
|
||||
; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
; file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
;
|
||||
; See the COPYRIGHT file distributed with this work for additional
|
||||
; information regarding copyright ownership.
|
||||
|
||||
$TTL 300 ; 5 minutes
|
||||
@ IN SOA mname1. . (
|
||||
2009102722 ; serial
|
||||
20 ; refresh (20 seconds)
|
||||
20 ; retry (20 seconds)
|
||||
1814400 ; expire (3 weeks)
|
||||
3600 ; minimum (1 hour)
|
||||
)
|
||||
NS ns
|
||||
ns A 10.53.0.3
|
||||
|
||||
a A 10.0.0.1
|
||||
b A 10.0.0.2
|
||||
d A 10.0.0.4
|
||||
z A 10.0.0.26
|
||||
a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27
|
||||
x CNAME a
|
||||
|
|
@ -424,6 +424,146 @@ cat "$infile" "$keyname.key" >"$zonefile"
|
|||
|
||||
"$SIGNER" -P -o "$zone" "$zonefile" >/dev/null
|
||||
|
||||
#
|
||||
# A RSASHA256OID zone.
|
||||
#
|
||||
zone=rsasha256oid.example.
|
||||
infile=rsasha256oid.example.db.in
|
||||
zonefile=rsasha256oid.example.db
|
||||
|
||||
keyname=$("$KEYGEN" -q -a RSASHA256OID "$zone")
|
||||
|
||||
cat "$infile" "$keyname.key" >"$zonefile"
|
||||
|
||||
"$SIGNER" -z -o "$zone" "$zonefile" >/dev/null
|
||||
|
||||
#
|
||||
# A RSASHA512OID zone.
|
||||
#
|
||||
zone=rsasha512oid.example.
|
||||
infile=rsasha512oid.example.db.in
|
||||
zonefile=rsasha512oid.example.db
|
||||
|
||||
keyname=$("$KEYGEN" -q -a RSASHA512OID "$zone")
|
||||
|
||||
cat "$infile" "$keyname.key" >"$zonefile"
|
||||
|
||||
"$SIGNER" -z -o "$zone" "$zonefile" >/dev/null
|
||||
|
||||
#
|
||||
# A UNKNOWNOID zone. Sign the zone using RSASHA512OID then
|
||||
# update the OID in the DNSKEY and RRSIGS to the unknown OID
|
||||
# 1.2.840.113549.1.1.14
|
||||
#
|
||||
zone=unknownoid.example
|
||||
infile=unknownoid.example.db.in
|
||||
zonefile=unknownoid.example.db
|
||||
|
||||
keyname=$("$KEYGEN" -q -a RSASHA512OID "$zone")
|
||||
|
||||
cat "$infile" "$keyname.key" >"$zonefile"
|
||||
|
||||
# Sign with known OID RSASHA512OID
|
||||
"$SIGNER" -z -o "$zone" -f "${zonefile}.stage1" "$zonefile" >/dev/null
|
||||
|
||||
# Change OID from 1.2.840.113549.1.1.13 to 1.2.840.113549.1.1.14
|
||||
sed 's/CwYJKoZIhvcN/CwYJKoZIhvcO/' <"${zonefile}.stage1" >"${zonefile}.stage2"
|
||||
|
||||
"$DSFROMKEY" -2A -f "${zonefile}.stage2" "$zone" >"dsset-${zone}."
|
||||
|
||||
# extract the updated DNSKEY's tag
|
||||
tag=$(awk '{print $4}' "dsset-${zone}.")
|
||||
|
||||
# Update RRSIG tags
|
||||
sed "s/\(2[0-9]* 2[0-9]*\) [1-9][0-9]* unknownoid.example./\1 ${tag} unknownoid.example./" <"${zonefile}.stage2" >"${zonefile}.signed"
|
||||
|
||||
#
|
||||
# A PRIVATEOID zone with a extra DS record for a non-existent DNSKEY.
|
||||
#
|
||||
zone=extradsoid.example.
|
||||
infile=extradsoid.example.db.in
|
||||
zonefile=extradsoid.example.db
|
||||
|
||||
keyname=$("$KEYGEN" -q -a RSASHA512OID "$zone")
|
||||
|
||||
cat "$infile" "$keyname.key" >"$zonefile"
|
||||
|
||||
"$SIGNER" -z -o "$zone" "$zonefile" >/dev/null
|
||||
|
||||
# add a DS for a second key with the same algorithm
|
||||
keyname=$("$KEYGEN" -q -a RSASHA512OID "$zone")
|
||||
|
||||
"$DSFROMKEY" -2A "$keyname.key" >>"dsset-$zone"
|
||||
|
||||
#
|
||||
# A UNKNOWNOID with an extra DS zone. Sign the zone using RSASHA512OID
|
||||
# then update the OID in the DNSKEY and RRSIGS to the unknown OID
|
||||
# 1.2.840.113549.1.1.14. Add an additional DS which does not match
|
||||
# the DNSKEY RRset with using this unknown OID.
|
||||
#
|
||||
zone=extradsunknownoid.example
|
||||
infile=extradsunknownoid.example.db.in
|
||||
zonefile=extradsunknownoid.example.db
|
||||
|
||||
keyname=$("$KEYGEN" -q -a RSASHA512OID "$zone")
|
||||
|
||||
cat "$infile" "$keyname.key" >"$zonefile"
|
||||
|
||||
# Sign with known OID RSASHA512OID
|
||||
"$SIGNER" -z -o "$zone" -f "${zonefile}.stage1" "$zonefile" >/dev/null
|
||||
|
||||
# Change OID from 1.2.840.113549.1.1.13 to 1.2.840.113549.1.1.14
|
||||
sed 's/CwYJKoZIhvcN/CwYJKoZIhvcO/' <"${zonefile}.stage1" >"${zonefile}.stage2"
|
||||
|
||||
"$DSFROMKEY" -2A -f "${zonefile}.stage2" "$zone" >"dsset-${zone}."
|
||||
tag=$(awk '{print $4}' "dsset-${zone}.")
|
||||
|
||||
# Update RRSIG tags
|
||||
sed "s/\(2[0-9]* 2[0-9]*\) [1-9][0-9]* extradsunknownoid.example./\1 ${tag} extradsunknownoid.example./" <"${zonefile}.stage2" >"${zonefile}.signed"
|
||||
|
||||
# add a DS for a second key with the same algorithm
|
||||
keyname=$("$KEYGEN" -L 300 -q -a RSASHA512OID "$zone")
|
||||
|
||||
# Change OID from 1.2.840.113549.1.1.13 to 1.2.840.113549.1.1.14 and
|
||||
# add the resulting DS to the dsset.
|
||||
sed 's/CwYJKoZIhvcN/CwYJKoZIhvcO/' <"$keyname.key" | "$DSFROMKEY" -2A -f - "$zone" >>"dsset-${zone}."
|
||||
|
||||
#
|
||||
# A UNKNOWNOID with an extra DS zone. Sign the zone using RSASHA512OID
|
||||
# then update the OID in the DNSKEY and RRSIGS to the unknown OID
|
||||
# 1.2.840.113549.1.1.14. Add an additional DS with an extended digest
|
||||
# type that encoded the DNSKEY's private type identifier which does not
|
||||
# match the DNSKEY RRset with using this unknown OID.
|
||||
#
|
||||
zone=extended-ds-unknown-oid.example
|
||||
infile=extended-ds-unknown-oid.example.db.in
|
||||
zonefile=extended-ds-unknown-oid.example.db
|
||||
|
||||
keyname=$("$KEYGEN" -q -a RSASHA512OID "$zone")
|
||||
|
||||
cat "$infile" "$keyname.key" >"$zonefile"
|
||||
|
||||
# Sign with known OID RSASHA512OID
|
||||
"$SIGNER" -z -o "$zone" -f "${zonefile}.stage1" "$zonefile" >/dev/null
|
||||
|
||||
# Change OID from 1.2.840.113549.1.1.13 to 1.2.840.113549.1.1.14
|
||||
sed 's/CwYJKoZIhvcN/CwYJKoZIhvcO/' <"${zonefile}.stage1" >"${zonefile}.stage2"
|
||||
|
||||
"$DSFROMKEY" -2A -f "${zonefile}.stage2" "$zone" >"dsset-${zone}."
|
||||
tag=$(awk '{print $4}' "dsset-${zone}.")
|
||||
|
||||
# Update RRSIG tags
|
||||
sed "s/\(2[0-9]* 2[0-9]*\) [1-9][0-9]* ${zone}./\1 ${tag} ${zone}./" <"${zonefile}.stage2" >"${zonefile}.signed"
|
||||
|
||||
if $FEATURETEST --extended-ds-digest; then
|
||||
# add a DS for a second key with the same algorithm
|
||||
keyname=$("$KEYGEN" -L 300 -q -a RSASHA512OID "$zone")
|
||||
|
||||
# Change OID from 1.2.840.113549.1.1.13 to 1.2.840.113549.1.1.14 and
|
||||
# add the resulting DS using digest type SHA-256-PRIVATE to the dsset.
|
||||
sed 's/CwYJKoZIhvcN/CwYJKoZIhvcO/' <"$keyname.key" | "$DSFROMKEY" -a SHA-256-PRIVATE -A -f - "$zone" >>"dsset-${zone}."
|
||||
fi
|
||||
|
||||
#
|
||||
# A zone with the DNSKEY set only signed by the KSK
|
||||
#
|
||||
|
|
|
|||
28
bin/tests/system/dnssec/ns3/unknownoid.example.db.in
Normal file
28
bin/tests/system/dnssec/ns3/unknownoid.example.db.in
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
;
|
||||
; SPDX-License-Identifier: MPL-2.0
|
||||
;
|
||||
; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
; file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
;
|
||||
; See the COPYRIGHT file distributed with this work for additional
|
||||
; information regarding copyright ownership.
|
||||
|
||||
$TTL 300 ; 5 minutes
|
||||
@ IN SOA mname1. . (
|
||||
2009102722 ; serial
|
||||
20 ; refresh (20 seconds)
|
||||
20 ; retry (20 seconds)
|
||||
1814400 ; expire (3 weeks)
|
||||
3600 ; minimum (1 hour)
|
||||
)
|
||||
NS ns
|
||||
ns A 10.53.0.3
|
||||
|
||||
a A 10.0.0.1
|
||||
b A 10.0.0.2
|
||||
d A 10.0.0.4
|
||||
z A 10.0.0.26
|
||||
a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27
|
||||
x CNAME a
|
||||
|
|
@ -53,18 +53,20 @@ dnssec_loadkeys_on() {
|
|||
# convert private-type records to readable form
|
||||
showprivate() {
|
||||
echo "-- $* --"
|
||||
dig_with_opts +nodnssec +short "@$2" -t type65534 "$1" | cut -f3 -d' ' \
|
||||
| while read -r record; do
|
||||
# shellcheck disable=SC2016
|
||||
$PERL -e 'my $rdata = pack("H*", @ARGV[0]);
|
||||
die "invalid record" unless length($rdata) == 5;
|
||||
my ($alg, $key, $remove, $complete) = unpack("CnCC", $rdata);
|
||||
my $action = "signing";
|
||||
$action = "removing" if $remove;
|
||||
my $state = " (incomplete)";
|
||||
$state = " (complete)" if $complete;
|
||||
print ("$action: alg: $alg, key: $key$state\n");' "$record"
|
||||
done
|
||||
dig_with_opts +nodnssec +short "@$2" -t type65534 "$1" >dig.out.$1.test$n
|
||||
cut -f3 -d' ' <dig.out.$1.$n | while read -r record; do
|
||||
# shellcheck disable=SC2016
|
||||
$PERL -e 'my $rdata = pack("H*", @ARGV[0]);
|
||||
die "invalid record" unless length($rdata) == 5 || length($rdata) == 7;
|
||||
my ($dns, $key, $remove, $complete, $alg) = unpack("CnCCn", $rdata);
|
||||
die "invalid record" unless $dns != 0;
|
||||
my $action = "signing";
|
||||
$action = "removing" if $remove;
|
||||
my $state = " (incomplete)";
|
||||
$state = " (complete)" if $complete;
|
||||
$alg = $dns if ! defined($alg);
|
||||
print ("$action: alg: $alg, key: $key$state\n");' "$record"
|
||||
done
|
||||
}
|
||||
|
||||
# check that signing records are marked as complete
|
||||
|
|
@ -958,6 +960,80 @@ n=$((n + 1))
|
|||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
|
||||
echo_i "checking positive validation with private algorithm works ($n)"
|
||||
ret=0
|
||||
dig_with_opts +noauth a.rsasha256oid.example. \
|
||||
@10.53.0.3 a >dig.out.ns3.test$n || ret=1
|
||||
dig_with_opts +noauth a.rsasha256oid.example. \
|
||||
@10.53.0.4 a >dig.out.ns4.test$n || ret=1
|
||||
digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
|
||||
grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1
|
||||
n=$((n + 1))
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
|
||||
if [ -x "${DELV}" ]; then
|
||||
ret=0
|
||||
echo_i "checking positive validation NSEC3 using dns_client ($n)"
|
||||
delv_with_opts @10.53.0.4 a a.nsec3.example >delv.out$n || ret=1
|
||||
grep "a.nsec3.example..*10.0.0.1" delv.out$n >/dev/null || ret=1
|
||||
grep "a.nsec3.example..*RRSIG.A [0-9][0-9]* 3 300.*" delv.out$n >/dev/null || ret=1
|
||||
n=$((n + 1))
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
fi
|
||||
|
||||
echo_i "checking positive validation with unknown private algorithm works ($n)"
|
||||
ret=0
|
||||
dig_with_opts +noauth a.unknownoid.example. \
|
||||
@10.53.0.3 a >dig.out.ns3.test$n || ret=1
|
||||
dig_with_opts +noauth a.unknownoid.example. \
|
||||
@10.53.0.4 a >dig.out.ns4.test$n || ret=1
|
||||
digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
|
||||
grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1
|
||||
n=$((n + 1))
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
|
||||
echo_i "checking positive validation with extra ds for private algorithm ($n)"
|
||||
ret=0
|
||||
dig_with_opts +noauth a.extradsoid.example. \
|
||||
@10.53.0.3 a >dig.out.ns3.test$n || ret=1
|
||||
dig_with_opts +noauth a.extradsoid.example. \
|
||||
@10.53.0.4 a >dig.out.ns4.test$n || ret=1
|
||||
digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
|
||||
grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1
|
||||
n=$((n + 1))
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
|
||||
echo_i "checking positive validation with extra ds for unknown private algorithm fails ($n)"
|
||||
ret=0
|
||||
dig_with_opts +noauth a.extradsunknownoid.example. \
|
||||
@10.53.0.3 a >dig.out.ns3.test$n || ret=1
|
||||
dig_with_opts +noauth a.extradsunknownoid.example. \
|
||||
@10.53.0.4 a >dig.out.ns4.test$n || ret=1
|
||||
grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1
|
||||
grep "status: SERVFAIL" dig.out.ns4.test$n >/dev/null || ret=1
|
||||
grep 'No DNSKEY for extradsunknownoid.example/DS with PRIVATEOID algorithm, tag [1-9][0-9]*$' ns4/named.run >/dev/null || ret=1
|
||||
n=$((n + 1))
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
|
||||
if $FEATURETEST --extended-ds-digest; then
|
||||
echo_i "checking positive validation with extra ds using extended digest type for unknown private algorithm succeeds ($n)"
|
||||
ret=0
|
||||
dig_with_opts +noauth a.extended-ds-unknown-oid.example. \
|
||||
@10.53.0.3 a >dig.out.ns3.test$n || ret=1
|
||||
dig_with_opts +noauth a.extended-ds-unknown-oid.example. \
|
||||
@10.53.0.4 a >dig.out.ns4.test$n || ret=1
|
||||
digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
|
||||
grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1
|
||||
n=$((n + 1))
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
fi
|
||||
|
||||
# Check the bogus domain
|
||||
|
||||
echo_i "checking failed validation ($n)"
|
||||
|
|
@ -3479,7 +3555,7 @@ status=$((status + ret))
|
|||
echo_i "check that 'dnssec-keygen -S' works for all supported algorithms ($n)"
|
||||
ret=0
|
||||
alg=1
|
||||
until test $alg -eq 256; do
|
||||
until test $alg -eq 258; do
|
||||
zone="keygen-$alg."
|
||||
case $alg in
|
||||
2) # Diffie Helman
|
||||
|
|
@ -3496,10 +3572,20 @@ until test $alg -eq 256; do
|
|||
15 | 16)
|
||||
key1=$($KEYGEN -a "$alg" "$zone" 2>"keygen-$alg.err" || true)
|
||||
;;
|
||||
256)
|
||||
key1=$($KEYGEN -a "RSASHA256OID" "$zone" 2>"keygen-$alg.err" || true)
|
||||
;;
|
||||
257)
|
||||
key1=$($KEYGEN -a "RSASHA512OID" "$zone" 2>"keygen-$alg.err" || true)
|
||||
;;
|
||||
*)
|
||||
key1=$($KEYGEN -a "$alg" "$zone" 2>"keygen-$alg.err" || true)
|
||||
;;
|
||||
esac
|
||||
if grep "unknown algorithm" "keygen-$alg.err" >/dev/null; then
|
||||
alg=$((alg + 1))
|
||||
continue
|
||||
fi
|
||||
if grep "unsupported algorithm" "keygen-$alg.err" >/dev/null; then
|
||||
alg=$((alg + 1))
|
||||
continue
|
||||
|
|
|
|||
|
|
@ -84,6 +84,7 @@ pytestmark = pytest.mark.extra_artifacts(
|
|||
"ns3/auto-nsec3.example.db",
|
||||
"ns3/badds.example.db",
|
||||
"ns3/bogus.example.db",
|
||||
"ns3/digest-alg-unsupported.example.db",
|
||||
"ns3/disabled.managed.db",
|
||||
"ns3/disabled.trusted.db",
|
||||
"ns3/dname-at-apex-nsec3.example.db",
|
||||
|
|
@ -94,13 +95,20 @@ pytestmark = pytest.mark.extra_artifacts(
|
|||
"ns3/dnskey-unsupported-2.example.db",
|
||||
"ns3/dnskey-unsupported.example.db",
|
||||
"ns3/dnskey-unsupported.example.db.tmp",
|
||||
"ns3/ds-unsupported.example.db",
|
||||
"ns3/dynamic.example.db",
|
||||
"ns3/digest-alg-unsupported.example.db",
|
||||
"ns3/enabled.managed.db",
|
||||
"ns3/enabled.trusted.db",
|
||||
"ns3/example.bk",
|
||||
"ns3/expired.example.db",
|
||||
"ns3/expiring.example.db",
|
||||
"ns3/extended-ds-unknown-oid.example.db",
|
||||
"ns3/extended-ds-unknown-oid.example.db.stage1",
|
||||
"ns3/extended-ds-unknown-oid.example.db.stage2",
|
||||
"ns3/extradsoid.example.db",
|
||||
"ns3/extradsunknownoid.example.db",
|
||||
"ns3/extradsunknownoid.example.db.stage1",
|
||||
"ns3/extradsunknownoid.example.db.stage2",
|
||||
"ns3/future.example.db",
|
||||
"ns3/keyless.example.db",
|
||||
"ns3/kskonly.example.db",
|
||||
|
|
@ -123,7 +131,9 @@ pytestmark = pytest.mark.extra_artifacts(
|
|||
"ns3/revoked.trusted.db",
|
||||
"ns3/rfc2335.example.bk",
|
||||
"ns3/rsasha256.example.db",
|
||||
"ns3/rsasha256oid.example.db",
|
||||
"ns3/rsasha512.example.db",
|
||||
"ns3/rsasha512oid.example.db",
|
||||
"ns3/secure.below-cname.example.db",
|
||||
"ns3/secure.example.db",
|
||||
"ns3/secure.managed.db",
|
||||
|
|
@ -138,6 +148,9 @@ pytestmark = pytest.mark.extra_artifacts(
|
|||
"ns3/trusted-future.key",
|
||||
"ns3/ttlpatch.example.db",
|
||||
"ns3/ttlpatch.example.db.patched",
|
||||
"ns3/unknownoid.example.db",
|
||||
"ns3/unknownoid.example.db.stage1",
|
||||
"ns3/unknownoid.example.db.stage2",
|
||||
"ns3/unsupported.managed.db",
|
||||
"ns3/unsupported.managed.db.tmp",
|
||||
"ns3/unsupported.trusted.db",
|
||||
|
|
@ -146,7 +159,6 @@ pytestmark = pytest.mark.extra_artifacts(
|
|||
"ns3/update-nsec3.example.db.signed",
|
||||
"ns3/upper.example.db",
|
||||
"ns3/upper.example.db.lower",
|
||||
"ns3/ds-unsupported.example.db",
|
||||
"ns4/broken.conf",
|
||||
"ns4/managed.conf",
|
||||
"ns4/managed-keys.bind",
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include <isc/net.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
#include <dns/ds.h>
|
||||
#include <dns/edns.h>
|
||||
#include <dns/lib.h>
|
||||
|
||||
|
|
@ -42,6 +43,7 @@ usage(void) {
|
|||
fprintf(stderr, "\t--edns-version\n");
|
||||
fprintf(stderr, "\t--enable-dnstap\n");
|
||||
fprintf(stderr, "\t--enable-querytrace\n");
|
||||
fprintf(stderr, "\t--extended-ds-digest\n");
|
||||
fprintf(stderr, "\t--fips-provider\n");
|
||||
fprintf(stderr, "\t--gethostname\n");
|
||||
fprintf(stderr, "\t--gssapi\n");
|
||||
|
|
@ -93,6 +95,14 @@ main(int argc, char **argv) {
|
|||
#endif /* ifdef WANT_QUERYTRACE */
|
||||
}
|
||||
|
||||
if (strcasecmp(argv[1], "--extended-ds-digest") == 0) {
|
||||
#if defined(DNS_DSDIGEST_SHA256PRIVATE) && defined(DNS_DSDIGEST_SHA384PRIVATE)
|
||||
return 0;
|
||||
#else
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (strcasecmp(argv[1], "--fips-provider") == 0) {
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
OSSL_PROVIDER *fips = OSSL_PROVIDER_load(NULL, "fips");
|
||||
|
|
|
|||
|
|
@ -390,6 +390,14 @@ class Key:
|
|||
|
||||
return ksigning, zsigning
|
||||
|
||||
def get_dnsalg(self) -> int:
|
||||
alg = int(self.get_metadata("Algorithm"))
|
||||
if alg == isctest.vars.algorithms.RSASHA256OID.dst:
|
||||
return isctest.vars.algorithms.RSASHA256OID.number
|
||||
if alg == isctest.vars.algorithms.RSASHA512OID.dst:
|
||||
return isctest.vars.algorithms.RSASHA512OID.number
|
||||
return alg
|
||||
|
||||
def ttl(self) -> int:
|
||||
with open(self.keyfile, "r", encoding="utf-8") as file:
|
||||
for line in file:
|
||||
|
|
@ -810,7 +818,7 @@ def _check_signatures(
|
|||
offline_ksk=offline_ksk, zsk_missing=zsk_missing, smooth=smooth
|
||||
)
|
||||
|
||||
alg = key.get_metadata("Algorithm")
|
||||
alg = key.get_dnsalg()
|
||||
rtype = dns.rdatatype.to_text(covers)
|
||||
|
||||
expect = rf"IN RRSIG {rtype} {alg} (\d) (\d+) (\d+) (\d+) {key.tag} {fqdn}"
|
||||
|
|
|
|||
|
|
@ -30,17 +30,20 @@ ALG_VARS = {
|
|||
"ALGORITHM_SET": "none",
|
||||
"DEFAULT_ALGORITHM": "",
|
||||
"DEFAULT_ALGORITHM_NUMBER": "",
|
||||
"DEFAULT_ALGORITHM_DST_NUMBER": "",
|
||||
"DEFAULT_BITS": "",
|
||||
# Alternative algorithm for test cases that require more than one algorithm
|
||||
# (for example algorithm rollover). Must be different from
|
||||
# DEFAULT_ALGORITHM.
|
||||
"ALTERNATIVE_ALGORITHM": "",
|
||||
"ALTERNATIVE_ALGORITHM_NUMBER": "",
|
||||
"ALTERNATIVE_ALGORITHM_DST_NUMBER": "",
|
||||
"ALTERNATIVE_BITS": "",
|
||||
# Algorithm that is used for tests against the "disable-algorithms"
|
||||
# configuration option. Must be different from above algorithms.
|
||||
"DISABLED_ALGORITHM": "",
|
||||
"DISABLED_ALGORITHM_NUMBER": "",
|
||||
"DISABLED_ALGORITHM_DST_NUMBER": "",
|
||||
"DISABLED_BITS": "",
|
||||
# Default HMAC algorithm. Must match the rndc configuration in
|
||||
# bin/tests/system/_common (rndc.conf, rndc.key)
|
||||
|
|
@ -54,6 +57,7 @@ STABLE_PERIOD = 3600 * 3
|
|||
class Algorithm(NamedTuple):
|
||||
name: str
|
||||
number: int
|
||||
dst: int
|
||||
bits: int
|
||||
|
||||
|
||||
|
|
@ -72,13 +76,15 @@ class AlgorithmSet(NamedTuple):
|
|||
"disable-algorithms" configuration option."""
|
||||
|
||||
|
||||
RSASHA1 = Algorithm("RSASHA1", 5, 2048)
|
||||
RSASHA256 = Algorithm("RSASHA256", 8, 2048)
|
||||
RSASHA512 = Algorithm("RSASHA512", 10, 2048)
|
||||
ECDSAP256SHA256 = Algorithm("ECDSAP256SHA256", 13, 256)
|
||||
ECDSAP384SHA384 = Algorithm("ECDSAP384SHA384", 14, 384)
|
||||
ED25519 = Algorithm("ED25519", 15, 256)
|
||||
ED448 = Algorithm("ED448", 16, 456)
|
||||
RSASHA1 = Algorithm("RSASHA1", 5, 5, 2048)
|
||||
RSASHA256 = Algorithm("RSASHA256", 8, 8, 2048)
|
||||
RSASHA512 = Algorithm("RSASHA512", 10, 10, 2048)
|
||||
ECDSAP256SHA256 = Algorithm("ECDSAP256SHA256", 13, 13, 256)
|
||||
ECDSAP384SHA384 = Algorithm("ECDSAP384SHA384", 14, 14, 384)
|
||||
ED25519 = Algorithm("ED25519", 15, 15, 256)
|
||||
ED448 = Algorithm("ED448", 16, 16, 456)
|
||||
RSASHA256OID = Algorithm("RSASHA256OID", 254, 256, 2048)
|
||||
RSASHA512OID = Algorithm("RSASHA512OID", 254, 257, 2048)
|
||||
|
||||
ALL_ALGORITHMS = [
|
||||
RSASHA1,
|
||||
|
|
@ -88,6 +94,8 @@ ALL_ALGORITHMS = [
|
|||
ECDSAP384SHA384,
|
||||
ED25519,
|
||||
ED448,
|
||||
RSASHA256OID,
|
||||
RSASHA512OID,
|
||||
]
|
||||
|
||||
ALL_ALGORITHMS_BY_NUM = {alg.number: alg for alg in ALL_ALGORITHMS}
|
||||
|
|
@ -149,6 +157,8 @@ CRYPTO_SUPPORTED_VARS = {
|
|||
"ECDSAP384SHA384_SUPPORTED": "0",
|
||||
"ED25519_SUPPORTED": "0",
|
||||
"ED448_SUPPORTED": "0",
|
||||
"RSASHA256OID_SUPPORTED": "0",
|
||||
"RSASHA512OID_SUPPORTED": "0",
|
||||
}
|
||||
|
||||
SUPPORTED_ALGORITHMS: List[Algorithm] = []
|
||||
|
|
@ -250,6 +260,7 @@ def _algorithms_env(algs: AlgorithmSet, name: str) -> Dict[str, str]:
|
|||
def set_alg_env(alg: Algorithm, prefix):
|
||||
algs_env[f"{prefix}_ALGORITHM"] = alg.name
|
||||
algs_env[f"{prefix}_ALGORITHM_NUMBER"] = str(alg.number)
|
||||
algs_env[f"{prefix}_ALGORITHM_DST_NUMBER"] = str(alg.dst)
|
||||
algs_env[f"{prefix}_BITS"] = str(alg.bits)
|
||||
|
||||
assert isinstance(algs.default, Algorithm)
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ def ksr(zone, policy, action, options="", raise_on_exception=True):
|
|||
def check_keys(
|
||||
keys,
|
||||
lifetime,
|
||||
alg=os.environ["DEFAULT_ALGORITHM_NUMBER"],
|
||||
alg=os.environ["DEFAULT_ALGORITHM_DST_NUMBER"],
|
||||
size=os.environ["DEFAULT_BITS"],
|
||||
offset=0,
|
||||
with_state=False,
|
||||
|
|
@ -246,7 +246,7 @@ def check_rrsig_bundle(bundle_keys, bundle_lines, zone, rrtype, sigend, sigstart
|
|||
count = 0
|
||||
for key in bundle_keys:
|
||||
found = False
|
||||
alg = key.get_metadata("Algorithm")
|
||||
alg = key.get_dnsalg()
|
||||
expect = f"{zone}. 3600 IN RRSIG {rrtype} {alg} 2 3600 {sigend} {sigstart} {key.tag} {zone}."
|
||||
# there must be a signature of this ksk
|
||||
for line in bundle_lines:
|
||||
|
|
@ -1125,9 +1125,9 @@ def test_ksr_twotone(servers):
|
|||
ksks_altalg = []
|
||||
for ksk in ksks:
|
||||
alg = ksk.get_metadata("Algorithm")
|
||||
if alg == os.environ.get("DEFAULT_ALGORITHM_NUMBER"):
|
||||
if alg == os.environ.get("DEFAULT_ALGORITHM_DST_NUMBER"):
|
||||
ksks_defalg.append(ksk)
|
||||
elif alg == os.environ.get("ALTERNATIVE_ALGORITHM_NUMBER"):
|
||||
elif alg == os.environ.get("ALTERNATIVE_ALGORITHM_DST_NUMBER"):
|
||||
ksks_altalg.append(ksk)
|
||||
|
||||
assert len(ksks_defalg) == 1
|
||||
|
|
@ -1135,7 +1135,7 @@ def test_ksr_twotone(servers):
|
|||
|
||||
check_keys(ksks_defalg, None)
|
||||
|
||||
alg = os.environ.get("ALTERNATIVE_ALGORITHM_NUMBER")
|
||||
alg = os.environ.get("ALTERNATIVE_ALGORITHM_DST_NUMBER")
|
||||
size = os.environ.get("ALTERNATIVE_BITS")
|
||||
check_keys(ksks_altalg, None, alg, size)
|
||||
|
||||
|
|
@ -1154,9 +1154,9 @@ def test_ksr_twotone(servers):
|
|||
zsks_altalg = []
|
||||
for zsk in zsks:
|
||||
alg = zsk.get_metadata("Algorithm")
|
||||
if alg == os.environ.get("DEFAULT_ALGORITHM_NUMBER"):
|
||||
if alg == os.environ.get("DEFAULT_ALGORITHM_DST_NUMBER"):
|
||||
zsks_defalg.append(zsk)
|
||||
elif alg == os.environ.get("ALTERNATIVE_ALGORITHM_NUMBER"):
|
||||
elif alg == os.environ.get("ALTERNATIVE_ALGORITHM_DST_NUMBER"):
|
||||
zsks_altalg.append(zsk)
|
||||
|
||||
assert len(zsks_defalg) == 4
|
||||
|
|
@ -1165,7 +1165,7 @@ def test_ksr_twotone(servers):
|
|||
lifetime = timedelta(days=31 * 3)
|
||||
check_keys(zsks_defalg, lifetime)
|
||||
|
||||
alg = os.environ.get("ALTERNATIVE_ALGORITHM_NUMBER")
|
||||
alg = os.environ.get("ALTERNATIVE_ALGORITHM_DST_NUMBER")
|
||||
size = os.environ.get("ALTERNATIVE_BITS")
|
||||
lifetime = timedelta(days=31 * 5)
|
||||
check_keys(zsks_altalg, lifetime, alg, size)
|
||||
|
|
@ -1216,7 +1216,7 @@ def test_ksr_twotone(servers):
|
|||
lifetime = timedelta(days=31 * 3)
|
||||
check_keys(zsks_defalg, lifetime, with_state=True)
|
||||
|
||||
alg = os.environ.get("ALTERNATIVE_ALGORITHM_NUMBER")
|
||||
alg = os.environ.get("ALTERNATIVE_ALGORITHM_DST_NUMBER")
|
||||
size = os.environ.get("ALTERNATIVE_BITS")
|
||||
lifetime = timedelta(days=31 * 5)
|
||||
check_keys(zsks_altalg, lifetime, alg, size, with_state=True)
|
||||
|
|
|
|||
|
|
@ -224,7 +224,7 @@ dns_dnssec_sign(const dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
|
|||
dns_name_clone(dns_fixedname_name(&fsigner), &sig.signer);
|
||||
|
||||
sig.covered = set->type;
|
||||
sig.algorithm = dst_key_alg(key);
|
||||
sig.algorithm = dst_algorithm_tosecalg(dst_key_alg(key));
|
||||
sig.labels = dns_name_countlabels(name) - 1;
|
||||
if (dns_name_iswildcard(name)) {
|
||||
sig.labels--;
|
||||
|
|
@ -762,7 +762,7 @@ dns_dnssec_signmessage(dns_message_t *msg, dst_key_t *key) {
|
|||
ISC_LINK_INIT(&sig.common, link);
|
||||
|
||||
sig.covered = 0;
|
||||
sig.algorithm = dst_key_alg(key);
|
||||
sig.algorithm = dst_algorithm_tosecalg(dst_key_alg(key));
|
||||
sig.labels = 0; /* the root name */
|
||||
sig.originalttl = 0;
|
||||
|
||||
|
|
@ -1469,7 +1469,7 @@ mark_active_keys(dns_dnsseckeylist_t *keylist, dns_rdataset_t *rrsigs) {
|
|||
dns_rdataset_clone(rrsigs, &sigs);
|
||||
ISC_LIST_FOREACH (*keylist, key, link) {
|
||||
uint16_t keyid, sigid;
|
||||
dns_secalg_t keyalg, sigalg;
|
||||
dst_algorithm_t keyalg, sigalg;
|
||||
keyid = dst_key_id(key->key);
|
||||
keyalg = dst_key_alg(key->key);
|
||||
|
||||
|
|
@ -1480,7 +1480,8 @@ mark_active_keys(dns_dnsseckeylist_t *keylist, dns_rdataset_t *rrsigs) {
|
|||
dns_rdataset_current(&sigs, &rdata);
|
||||
result = dns_rdata_tostruct(&rdata, &sig, NULL);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
sigalg = sig.algorithm;
|
||||
sigalg = dst_algorithm_fromdata(
|
||||
sig.algorithm, sig.signature, sig.siglen);
|
||||
sigid = sig.keyid;
|
||||
if (keyid == sigid && keyalg == sigalg) {
|
||||
key->is_active = true;
|
||||
|
|
@ -1544,14 +1545,23 @@ dns_dnssec_keylistfromrdataset(const dns_name_t *origin, dns_kasp_t *kasp,
|
|||
dns_rdataset_clone(keyset, &keys);
|
||||
DNS_RDATASET_FOREACH (&keys) {
|
||||
dns_rdata_t rdata = DNS_RDATA_INIT;
|
||||
dst_algorithm_t algorithm;
|
||||
dns_rdata_dnskey_t keystruct;
|
||||
|
||||
dns_rdataset_current(&keys, &rdata);
|
||||
|
||||
REQUIRE(rdata.type == dns_rdatatype_key ||
|
||||
rdata.type == dns_rdatatype_dnskey);
|
||||
REQUIRE(rdata.length > 3);
|
||||
|
||||
result = dns_rdata_tostruct(&rdata, &keystruct, NULL);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
|
||||
algorithm = dst_algorithm_fromdata(
|
||||
keystruct.algorithm, keystruct.data, keystruct.datalen);
|
||||
|
||||
/* Skip unsupported algorithms */
|
||||
if (!dst_algorithm_supported(rdata.data[3])) {
|
||||
if (!dst_algorithm_supported(algorithm)) {
|
||||
goto skip;
|
||||
}
|
||||
|
||||
|
|
@ -1831,7 +1841,8 @@ add_cds(dns_dnsseckey_t *key, dns_rdata_t *keyrdata, const char *keystr,
|
|||
dns_rdata_t cdsrdata = DNS_RDATA_INIT;
|
||||
dns_name_t *origin = dst_key_name(key->key);
|
||||
|
||||
r = dns_ds_buildrdata(origin, keyrdata, digesttype, dsbuf, &cdsrdata);
|
||||
r = dns_ds_buildrdata(origin, keyrdata, digesttype, dsbuf,
|
||||
sizeof(dsbuf), &cdsrdata);
|
||||
if (r != ISC_R_SUCCESS) {
|
||||
char algbuf[DNS_DSDIGEST_FORMATSIZE];
|
||||
dns_dsdigest_format(digesttype, algbuf,
|
||||
|
|
@ -1866,7 +1877,8 @@ delete_cds(dns_dnsseckey_t *key, dns_rdata_t *keyrdata, const char *keystr,
|
|||
dns_rdata_t cdsrdata = DNS_RDATA_INIT;
|
||||
dns_name_t *origin = dst_key_name(key->key);
|
||||
|
||||
r = dns_ds_buildrdata(origin, keyrdata, digesttype, dsbuf, &cdsrdata);
|
||||
r = dns_ds_buildrdata(origin, keyrdata, digesttype, dsbuf,
|
||||
sizeof(dsbuf), &cdsrdata);
|
||||
if (r != ISC_R_SUCCESS) {
|
||||
return r;
|
||||
}
|
||||
|
|
@ -2354,7 +2366,7 @@ dns_dnssec_matchdskey(dns_name_t *name, dns_rdata_t *dsrdata,
|
|||
}
|
||||
|
||||
result = dns_ds_buildrdata(name, keyrdata, ds.digest_type, buf,
|
||||
&newdsrdata);
|
||||
sizeof(buf), &newdsrdata);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
|||
79
lib/dns/ds.c
79
lib/dns/ds.c
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include <dns/ds.h>
|
||||
#include <dns/fixedname.h>
|
||||
#include <dns/keyvalues.h>
|
||||
#include <dns/name.h>
|
||||
#include <dns/rdata.h>
|
||||
#include <dns/rdatastruct.h>
|
||||
|
|
@ -32,11 +33,12 @@
|
|||
isc_result_t
|
||||
dns_ds_fromkeyrdata(const dns_name_t *owner, dns_rdata_t *key,
|
||||
dns_dsdigest_t digest_type, unsigned char *digest,
|
||||
dns_rdata_ds_t *dsrdata) {
|
||||
size_t len, dns_rdata_ds_t *dsrdata) {
|
||||
isc_result_t result;
|
||||
dns_fixedname_t fname;
|
||||
dns_name_t *name;
|
||||
unsigned int digestlen;
|
||||
unsigned int digestlen = 0;
|
||||
unsigned int privatelen = 0;
|
||||
isc_region_t r;
|
||||
isc_md_t *md;
|
||||
const isc_md_type_t *md_type = NULL;
|
||||
|
|
@ -44,6 +46,7 @@ dns_ds_fromkeyrdata(const dns_name_t *owner, dns_rdata_t *key,
|
|||
REQUIRE(key != NULL);
|
||||
REQUIRE(key->type == dns_rdatatype_dnskey ||
|
||||
key->type == dns_rdatatype_cdnskey);
|
||||
REQUIRE(digest != NULL);
|
||||
|
||||
if (!dst_ds_digest_supported(digest_type)) {
|
||||
return ISC_R_NOTIMPLEMENTED;
|
||||
|
|
@ -55,10 +58,16 @@ dns_ds_fromkeyrdata(const dns_name_t *owner, dns_rdata_t *key,
|
|||
break;
|
||||
|
||||
case DNS_DSDIGEST_SHA384:
|
||||
#ifdef DNS_DSDIGEST_SHA384PRIVATE
|
||||
case DNS_DSDIGEST_SHA384PRIVATE:
|
||||
#endif
|
||||
md_type = ISC_MD_SHA384;
|
||||
break;
|
||||
|
||||
case DNS_DSDIGEST_SHA256:
|
||||
#ifdef DNS_DSDIGEST_SHA256PRIVATE
|
||||
case DNS_DSDIGEST_SHA256PRIVATE:
|
||||
#endif
|
||||
md_type = ISC_MD_SHA256;
|
||||
break;
|
||||
|
||||
|
|
@ -91,6 +100,64 @@ dns_ds_fromkeyrdata(const dns_name_t *owner, dns_rdata_t *key,
|
|||
goto end;
|
||||
}
|
||||
|
||||
#if defined(DNS_DSDIGEST_SHA256PRIVATE) && defined(DNS_DSDIGEST_SHA384PRIVATE)
|
||||
/*
|
||||
* Insert PRIVATE algorithm identify at start of digest.
|
||||
*/
|
||||
switch (digest_type) {
|
||||
case DNS_DSDIGEST_SHA1:
|
||||
case DNS_DSDIGEST_SHA256:
|
||||
case DNS_DSDIGEST_SHA384:
|
||||
break;
|
||||
case DNS_DSDIGEST_SHA256PRIVATE:
|
||||
case DNS_DSDIGEST_SHA384PRIVATE:
|
||||
switch (r.base[3]) {
|
||||
case DNS_KEYALG_PRIVATEDNS: {
|
||||
isc_region_t r2 = r;
|
||||
INSIST(r2.length >= 5);
|
||||
isc_region_consume(&r2, 4);
|
||||
dns_name_fromregion(name, &r2);
|
||||
dns_name_toregion(name, &r2);
|
||||
privatelen = r2.length;
|
||||
if (r2.length > len) {
|
||||
result = ISC_R_NOSPACE;
|
||||
goto end;
|
||||
}
|
||||
memmove(digest, r2.base, privatelen);
|
||||
digest += privatelen;
|
||||
len -= privatelen;
|
||||
break;
|
||||
}
|
||||
case DNS_KEYALG_PRIVATEOID: {
|
||||
isc_region_t r2 = r;
|
||||
INSIST(r2.length >= 5);
|
||||
isc_region_consume(&r2, 4);
|
||||
privatelen = r2.base[0] + 1;
|
||||
if (r2.base[0] > len) {
|
||||
result = ISC_R_NOSPACE;
|
||||
goto end;
|
||||
}
|
||||
INSIST(r2.length >= privatelen);
|
||||
memmove(digest, r2.base, privatelen);
|
||||
digest += privatelen;
|
||||
len -= privatelen;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t mdsize = isc_md_get_size(md);
|
||||
if (mdsize > len) {
|
||||
result = ISC_R_NOSPACE;
|
||||
goto end;
|
||||
}
|
||||
|
||||
result = isc_md_final(md, digest, &digestlen);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto end;
|
||||
|
|
@ -102,8 +169,8 @@ dns_ds_fromkeyrdata(const dns_name_t *owner, dns_rdata_t *key,
|
|||
dsrdata->algorithm = r.base[3];
|
||||
dsrdata->key_tag = dst_region_computeid(&r);
|
||||
dsrdata->digest_type = digest_type;
|
||||
dsrdata->digest = digest;
|
||||
dsrdata->length = digestlen;
|
||||
dsrdata->digest = digest - privatelen;
|
||||
dsrdata->length = digestlen + privatelen;
|
||||
|
||||
end:
|
||||
isc_md_free(md);
|
||||
|
|
@ -112,14 +179,14 @@ end:
|
|||
|
||||
isc_result_t
|
||||
dns_ds_buildrdata(dns_name_t *owner, dns_rdata_t *key,
|
||||
dns_dsdigest_t digest_type, unsigned char *buffer,
|
||||
dns_dsdigest_t digest_type, unsigned char *buffer, size_t len,
|
||||
dns_rdata_t *rdata) {
|
||||
isc_result_t result;
|
||||
unsigned char digest[ISC_MAX_MD_SIZE];
|
||||
dns_rdata_ds_t ds;
|
||||
isc_buffer_t b;
|
||||
|
||||
result = dns_ds_fromkeyrdata(owner, key, digest_type, digest, &ds);
|
||||
result = dns_ds_fromkeyrdata(owner, key, digest_type, digest, len, &ds);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -140,6 +140,14 @@ static const char *keystates[KEYSTATES_NVALUES] = {
|
|||
|
||||
static dst_func_t *dst_t_func[DST_MAX_ALGS] = { 0 };
|
||||
|
||||
/* length byte + 1.2.840.113549.1.1.11 BER encoded RFC 4055 */
|
||||
static unsigned char oid_rsasha256[] = { 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48,
|
||||
0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b };
|
||||
|
||||
/* length byte + 1.2.840.113549.1.1.13 BER encoded RFC 4055 */
|
||||
static unsigned char oid_rsasha512[] = { 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48,
|
||||
0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0d };
|
||||
|
||||
void
|
||||
gss_log(int level, const char *fmt, ...) ISC_FORMAT_PRINTF(2, 3);
|
||||
|
||||
|
|
@ -215,6 +223,18 @@ dst__lib_initialize(void) {
|
|||
#if HAVE_GSSAPI
|
||||
dst__gssapi_init(&dst_t_func[DST_ALG_GSSAPI]);
|
||||
#endif /* HAVE_GSSAPI */
|
||||
/*
|
||||
* RSASHA256 using assigned OID 1.2.840.113549.1.1.11 as
|
||||
* a private OID example.
|
||||
*/
|
||||
dst__opensslrsa_init(&dst_t_func[DST_ALG_RSASHA256PRIVATEOID],
|
||||
DST_ALG_RSASHA256PRIVATEOID);
|
||||
/*
|
||||
* RSASHA512 using assigned OID 1.2.840.113549.1.1.13 as
|
||||
* a private OID example.
|
||||
*/
|
||||
dst__opensslrsa_init(&dst_t_func[DST_ALG_RSASHA512PRIVATEOID],
|
||||
DST_ALG_RSASHA512PRIVATEOID);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -233,7 +253,13 @@ dst_algorithm_supported(unsigned int alg) {
|
|||
bool
|
||||
dst_ds_digest_supported(unsigned int digest_type) {
|
||||
return digest_type == DNS_DSDIGEST_SHA1 ||
|
||||
#if defined(DNS_DSDIGEST_SHA256PRIVATE)
|
||||
digest_type == DNS_DSDIGEST_SHA256PRIVATE ||
|
||||
#endif
|
||||
digest_type == DNS_DSDIGEST_SHA256 ||
|
||||
#if defined(DNS_DSDIGEST_SHA256PRIVATE)
|
||||
digest_type == DNS_DSDIGEST_SHA384PRIVATE ||
|
||||
#endif
|
||||
digest_type == DNS_DSDIGEST_SHA384;
|
||||
}
|
||||
|
||||
|
|
@ -645,7 +671,8 @@ dst_key_todns(const dst_key_t *key, isc_buffer_t *target) {
|
|||
}
|
||||
isc_buffer_putuint16(target, (uint16_t)(key->key_flags & 0xffff));
|
||||
isc_buffer_putuint8(target, (uint8_t)key->key_proto);
|
||||
isc_buffer_putuint8(target, (uint8_t)key->key_alg);
|
||||
isc_buffer_putuint8(target,
|
||||
(uint8_t)dst_algorithm_tosecalg(key->key_alg));
|
||||
|
||||
if ((key->key_flags & DNS_KEYFLAG_EXTENDED) != 0) {
|
||||
if (isc_buffer_availablelength(target) < 2) {
|
||||
|
|
@ -1304,6 +1331,12 @@ dst_key_sigsize(const dst_key_t *key, unsigned int *n) {
|
|||
case DST_ALG_RSASHA512:
|
||||
*n = (key->key_size + 7) / 8;
|
||||
break;
|
||||
case DST_ALG_RSASHA256PRIVATEOID:
|
||||
*n = (key->key_size + 7) / 8 + sizeof(oid_rsasha256);
|
||||
break;
|
||||
case DST_ALG_RSASHA512PRIVATEOID:
|
||||
*n = (key->key_size + 7) / 8 + sizeof(oid_rsasha512);
|
||||
break;
|
||||
case DST_ALG_ECDSA256:
|
||||
*n = DNS_SIG_ECDSA256SIZE;
|
||||
break;
|
||||
|
|
@ -1357,10 +1390,10 @@ void
|
|||
dst_key_format(const dst_key_t *key, char *cp, unsigned int size) {
|
||||
char namestr[DNS_NAME_FORMATSIZE];
|
||||
char algstr[DNS_NAME_FORMATSIZE];
|
||||
dst_algorithm_t algorithm = dst_key_alg(key);
|
||||
|
||||
dns_name_format(dst_key_name(key), namestr, sizeof(namestr));
|
||||
dns_secalg_format((dns_secalg_t)dst_key_alg(key), algstr,
|
||||
sizeof(algstr));
|
||||
dst_algorithm_format(algorithm, algstr, sizeof(algstr));
|
||||
snprintf(cp, size, "%s/%s/%d", namestr, algstr, dst_key_id(key));
|
||||
}
|
||||
|
||||
|
|
@ -2107,6 +2140,8 @@ buildfilename(dns_name_t *name, dns_keytag_t id, unsigned int alg,
|
|||
isc_result_t result;
|
||||
|
||||
REQUIRE(out != NULL);
|
||||
REQUIRE(alg != 0 && alg != DST_ALG_PRIVATEOID &&
|
||||
alg != DST_ALG_PRIVATEDNS);
|
||||
|
||||
if ((type & DST_TYPE_PRIVATE) != 0) {
|
||||
suffix = ".private";
|
||||
|
|
@ -2172,6 +2207,22 @@ frombuffer(const dns_name_t *name, unsigned int alg, unsigned int flags,
|
|||
REQUIRE(mctx != NULL);
|
||||
REQUIRE(keyp != NULL && *keyp == NULL);
|
||||
|
||||
if (alg == DNS_KEYALG_PRIVATEDNS) {
|
||||
isc_buffer_t b = *source;
|
||||
alg = dst_algorithm_fromprivatedns(&b);
|
||||
if (alg == 0) {
|
||||
return DST_R_UNSUPPORTEDALG;
|
||||
}
|
||||
}
|
||||
|
||||
if (alg == DNS_KEYALG_PRIVATEOID) {
|
||||
isc_buffer_t b = *source;
|
||||
alg = dst_algorithm_fromprivateoid(&b);
|
||||
if (alg == 0) {
|
||||
return DST_R_UNSUPPORTEDALG;
|
||||
}
|
||||
}
|
||||
|
||||
key = get_key_struct(name, alg, flags, protocol, 0, rdclass, 0, mctx);
|
||||
|
||||
if (isc_buffer_remaininglength(source) > 0) {
|
||||
|
|
@ -2636,3 +2687,115 @@ dst_hmac_algorithm_totext(dst_algorithm_t alg) {
|
|||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
dns_secalg_t
|
||||
dst_algorithm_tosecalg(dst_algorithm_t dst_alg) {
|
||||
static dns_secalg_t dns_alg[DST_MAX_ALGS] = {
|
||||
[DST_ALG_RSASHA256PRIVATEOID] = DNS_KEYALG_PRIVATEOID,
|
||||
[DST_ALG_RSASHA512PRIVATEOID] = DNS_KEYALG_PRIVATEOID,
|
||||
};
|
||||
|
||||
if (dst_alg < 256) {
|
||||
return dst_alg;
|
||||
}
|
||||
if (dst_alg < DST_MAX_ALGS) {
|
||||
return dns_alg[dst_alg];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if TEST_PRIVATEDNS
|
||||
/*
|
||||
* These are examples of specifying an algorithm using
|
||||
* PRIVATEDNS. When creating such an algorithm, use your
|
||||
* organisation's domain name instead of "example.org"
|
||||
* so the identifier will be globally unique.
|
||||
*/
|
||||
static unsigned char rsasha256dns_data[] = "\011rsasha256\007example\003org";
|
||||
static dns_name_t const rsasha256dns = DNS_NAME_INITABSOLUTE(rsasha256dns_data);
|
||||
static unsigned char rsasha512dns_data[] = "\011rsasha512\007example\003org";
|
||||
static dns_name_t const rsasha512dns = DNS_NAME_INITABSOLUTE(rsasha512dns_data);
|
||||
#endif
|
||||
|
||||
dst_algorithm_t
|
||||
dst_algorithm_fromprivatedns(isc_buffer_t *buffer) {
|
||||
dns_fixedname_t fixed;
|
||||
dns_name_t *name = dns_fixedname_initname(&fixed);
|
||||
isc_result_t result;
|
||||
|
||||
result = dns_name_fromwire(name, buffer, DNS_DECOMPRESS_DEFAULT, NULL);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do name to dst_algorithm number mapping here.
|
||||
*/
|
||||
switch (name->length) {
|
||||
#if TEST_PRIVATEDNS
|
||||
case 23:
|
||||
switch (name->ndata[7]) {
|
||||
case '2':
|
||||
if (dns_name_equal(name, &rsasha256dns)) {
|
||||
return DST_ALG_RSASHA256PRIVATEDNS;
|
||||
}
|
||||
break;
|
||||
case '5':
|
||||
if (dns_name_equal(name, &rsasha512dns)) {
|
||||
return DST_ALG_RSASHA512PRIVATEDNS;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
dst_algorithm_t
|
||||
dst_algorithm_fromprivateoid(isc_buffer_t *buffer) {
|
||||
isc_region_t r;
|
||||
|
||||
isc_buffer_remainingregion(buffer, &r);
|
||||
|
||||
/*
|
||||
* Do OID to dst_algorithm number mapping here. There is a
|
||||
* length byte followed by the OID of that length.
|
||||
*/
|
||||
if (r.length > 0 && ((unsigned int)r.base[0] + 1) <= r.length) {
|
||||
if (r.base[0] + 1 == sizeof(oid_rsasha256) &&
|
||||
memcmp(oid_rsasha256, r.base, sizeof(oid_rsasha256)) == 0)
|
||||
{
|
||||
return DST_ALG_RSASHA256PRIVATEOID;
|
||||
}
|
||||
|
||||
if (r.base[0] + 1 == sizeof(oid_rsasha512) &&
|
||||
memcmp(oid_rsasha512, r.base, sizeof(oid_rsasha512)) == 0)
|
||||
{
|
||||
return DST_ALG_RSASHA512PRIVATEOID;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
dst_algorithm_t
|
||||
dst_algorithm_fromdata(dns_secalg_t algorithm, unsigned char *data,
|
||||
unsigned int length) {
|
||||
isc_buffer_t b;
|
||||
switch (algorithm) {
|
||||
case DNS_KEYALG_PRIVATEDNS:
|
||||
isc_buffer_init(&b, data, length);
|
||||
isc_buffer_add(&b, length);
|
||||
return dst_algorithm_fromprivatedns(&b);
|
||||
case DNS_KEYALG_PRIVATEOID:
|
||||
isc_buffer_init(&b, data, length);
|
||||
isc_buffer_add(&b, length);
|
||||
return dst_algorithm_fromprivateoid(&b);
|
||||
default:
|
||||
return algorithm;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -193,7 +193,7 @@ dst__hmacsha384_init(struct dst_func **funcp);
|
|||
void
|
||||
dst__hmacsha512_init(struct dst_func **funcp);
|
||||
void
|
||||
dst__opensslrsa_init(struct dst_func **funcp, unsigned char algorithm);
|
||||
dst__opensslrsa_init(struct dst_func **funcp, unsigned short algorithm);
|
||||
void
|
||||
dst__opensslecdsa_init(struct dst_func **funcp);
|
||||
void
|
||||
|
|
|
|||
|
|
@ -332,6 +332,8 @@ check_data(const dst_private_t *priv, const unsigned int alg, bool old,
|
|||
case DST_ALG_NSEC3RSASHA1:
|
||||
case DST_ALG_RSASHA256:
|
||||
case DST_ALG_RSASHA512:
|
||||
case DST_ALG_RSASHA256PRIVATEOID:
|
||||
case DST_ALG_RSASHA512PRIVATEOID:
|
||||
return check_rsa(priv, external);
|
||||
case DST_ALG_ECDSA256:
|
||||
case DST_ALG_ECDSA384:
|
||||
|
|
@ -694,6 +696,12 @@ dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv,
|
|||
case DST_ALG_HMACSHA512:
|
||||
fprintf(fp, "(HMAC_SHA512)\n");
|
||||
break;
|
||||
case DST_ALG_RSASHA256PRIVATEOID:
|
||||
fprintf(fp, "(OID:RSASHA256)\n");
|
||||
break;
|
||||
case DST_ALG_RSASHA512PRIVATEOID:
|
||||
fprintf(fp, "(OID:RSASHA512)\n");
|
||||
break;
|
||||
default:
|
||||
fprintf(fp, "(?)\n");
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -16,20 +16,32 @@
|
|||
#include <dns/rdatastruct.h>
|
||||
#include <dns/types.h>
|
||||
|
||||
#define DNS_DSDIGEST_SHA1 (1)
|
||||
#define DNS_DSDIGEST_SHA256 (2)
|
||||
#define DNS_DSDIGEST_GOST (3)
|
||||
#define DNS_DSDIGEST_SHA384 (4)
|
||||
#define DNS_DSDIGEST_SHA1 (1)
|
||||
#define DNS_DSDIGEST_SHA256 (2)
|
||||
#define DNS_DSDIGEST_GOST (3)
|
||||
#define DNS_DSDIGEST_SHA384 (4)
|
||||
#define DNS_DSDIGEST_GOST2012 (5)
|
||||
#define DNS_DSDIGEST_SM3 (6)
|
||||
|
||||
#if TEST_PRIVATE_DSDIGEST
|
||||
/*
|
||||
* Possible future digest types that encode the PRIVATEDNS and
|
||||
* PRIVATEOID identifiers before the cryptographic digest value.
|
||||
*/
|
||||
#define DNS_DSDIGEST_SHA256PRIVATE (7)
|
||||
#define DNS_DSDIGEST_SHA384PRIVATE (8)
|
||||
#define DNS_DSDIGEST_SM3PRIVATE (9)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Assuming SHA-384 digest type.
|
||||
* Assuming SHA-384 digest type + maximal PRIVATEDNS name.
|
||||
*/
|
||||
#define DNS_DS_BUFFERSIZE (52)
|
||||
#define DNS_DS_BUFFERSIZE (52 + 255)
|
||||
|
||||
isc_result_t
|
||||
dns_ds_fromkeyrdata(const dns_name_t *owner, dns_rdata_t *key,
|
||||
dns_dsdigest_t digest_type, unsigned char *digest,
|
||||
dns_rdata_ds_t *dsrdata);
|
||||
size_t len, dns_rdata_ds_t *dsrdata);
|
||||
/*%<
|
||||
* Build a DS rdata structure from a key.
|
||||
*
|
||||
|
|
@ -41,7 +53,7 @@ dns_ds_fromkeyrdata(const dns_name_t *owner, dns_rdata_t *key,
|
|||
|
||||
isc_result_t
|
||||
dns_ds_buildrdata(dns_name_t *owner, dns_rdata_t *key,
|
||||
dns_dsdigest_t digest_type, unsigned char *buffer,
|
||||
dns_dsdigest_t digest_type, unsigned char *buffer, size_t len,
|
||||
dns_rdata_t *rdata);
|
||||
/*%<
|
||||
* Similar to dns_ds_fromkeyrdata(), but copies the DS into a
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ struct dns_kasp_key {
|
|||
/* Configuration */
|
||||
dns_keystore_t *keystore;
|
||||
uint32_t lifetime;
|
||||
uint8_t algorithm;
|
||||
dst_algorithm_t algorithm;
|
||||
int length;
|
||||
uint8_t role;
|
||||
uint16_t tag_min;
|
||||
|
|
|
|||
|
|
@ -434,12 +434,18 @@ dns_resolver_disable_ds_digest(dns_resolver_t *resolver, const dns_name_t *name,
|
|||
|
||||
bool
|
||||
dns_resolver_algorithm_supported(dns_resolver_t *resolver,
|
||||
const dns_name_t *name, unsigned int alg);
|
||||
const dns_name_t *name, unsigned int alg,
|
||||
unsigned char *private, size_t len);
|
||||
/*%<
|
||||
* Check if the given algorithm is supported by this resolver.
|
||||
* This checks whether the algorithm has been disabled via
|
||||
* dns_resolver_disable_algorithm(), then checks the underlying
|
||||
* crypto libraries if it was not specifically disabled.
|
||||
*
|
||||
* The algorithm is specified with the value 'alg' or, if
|
||||
* 'alg' is PRIVATEOID or PRIVATEDNS, then the algorithm is
|
||||
* encoded as a DNS name or OID in the first 'len' bytes of
|
||||
* 'private'.
|
||||
*/
|
||||
|
||||
bool
|
||||
|
|
|
|||
|
|
@ -137,6 +137,7 @@ struct dns_validator {
|
|||
dns_rdataset_t fdsset;
|
||||
dns_rdataset_t frdataset;
|
||||
dns_rdataset_t fsigrdataset;
|
||||
dns_rdataset_t dsrdataset;
|
||||
dns_fixedname_t fname;
|
||||
dns_fixedname_t wild;
|
||||
dns_fixedname_t closest;
|
||||
|
|
|
|||
|
|
@ -2187,8 +2187,8 @@ dns_zone_getsignatures(dns_zone_t *zone);
|
|||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, uint16_t keyid,
|
||||
bool deleteit);
|
||||
dns_zone_signwithkey(dns_zone_t *zone, dst_algorithm_t algorithm,
|
||||
uint16_t keyid, bool deleteit);
|
||||
/*%<
|
||||
* Initiate/resume signing of the entire zone with the zone DNSKEY(s)
|
||||
* that match the given algorithm and keyid.
|
||||
|
|
|
|||
|
|
@ -110,8 +110,15 @@ typedef enum dst_algorithm {
|
|||
DST_ALG_HMAC_LAST = DST_ALG_HMACSHA512,
|
||||
|
||||
DST_ALG_INDIRECT = 252,
|
||||
DST_ALG_PRIVATE = 254,
|
||||
DST_MAX_ALGS = 256,
|
||||
DST_ALG_PRIVATEDNS = 253,
|
||||
DST_ALG_PRIVATEOID = 254,
|
||||
DST_ALG_RESERVED = 255,
|
||||
/*
|
||||
* Put PRIVATE DNS and PRIVATE OID identifiers here.
|
||||
*/
|
||||
DST_ALG_RSASHA256PRIVATEOID = 256, /* 1.2.840.113549.1.1.11 */
|
||||
DST_ALG_RSASHA512PRIVATEOID = 257, /* 1.2.840.113549.1.1.13 */
|
||||
DST_MAX_ALGS = 258,
|
||||
} dst_algorithm_t;
|
||||
|
||||
/*% A buffer of this size is large enough to hold any key */
|
||||
|
|
@ -206,6 +213,20 @@ dst_algorithm_supported(unsigned int alg);
|
|||
* \li false
|
||||
*/
|
||||
|
||||
dst_algorithm_t
|
||||
dst_algorithm_fromprivateoid(isc_buffer_t *buffer);
|
||||
/*
|
||||
* Extract the dst algorithm identifier that matches
|
||||
* the OID value found at the start of 'buffer'.
|
||||
*/
|
||||
|
||||
dst_algorithm_t
|
||||
dst_algorithm_fromprivatedns(isc_buffer_t *buf);
|
||||
/*
|
||||
* Extract the dst algorithm identifier that matches
|
||||
* the DNS name found at the start of 'buffer'.
|
||||
*/
|
||||
|
||||
bool
|
||||
dst_ds_digest_supported(unsigned int digest_type);
|
||||
/*%<
|
||||
|
|
@ -1160,3 +1181,89 @@ dst_hmac_algorithm_totext(dst_algorithm_t alg);
|
|||
* Return the name associtated with the HMAC algorithm 'alg'
|
||||
* or return "unknown".
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dst_algorithm_fromtext(dst_algorithm_t *algp, isc_textregion_t *source);
|
||||
/*%<
|
||||
* Convert the text 'source' refers to into a DST security algorithm value.
|
||||
* The text may contain either a mnemonic algorithm name or a decimal algorithm
|
||||
* number. This supports more algorithms than 'dns_secalg_fromtext' as it
|
||||
* supports private algorithms used with PRIVATEDNS and PRIVATEOID.
|
||||
*
|
||||
* Requires:
|
||||
*\li 'algp' is a valid pointer.
|
||||
*
|
||||
*\li 'source' is a valid text region.
|
||||
*
|
||||
* Returns:
|
||||
*\li ISC_R_SUCCESS on success
|
||||
*\li ISC_R_RANGE numeric type is out of range
|
||||
*\li DNS_R_UNKNOWN mnemonic type is unknown
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dst_algorithm_totext(dst_algorithm_t alg, isc_buffer_t *target);
|
||||
/*%<
|
||||
* Put a textual representation of DST security algorithm 'alg'
|
||||
* into 'target'. This supports a superset of dns_secalg_totext.
|
||||
*
|
||||
* Requires:
|
||||
*\li 'alg' is a valid dst_algorithm_t.
|
||||
*
|
||||
*\li 'target' is a valid text buffer.
|
||||
*
|
||||
* Ensures,
|
||||
* if the result is success:
|
||||
*\li The used space in 'target' is updated.
|
||||
*
|
||||
* Returns:
|
||||
*\li ISC_R_SUCCESS on success
|
||||
*\li ISC_R_NOSPACE target buffer is too small
|
||||
*/
|
||||
|
||||
#define DST_ALGORITHM_FORMATSIZE 20
|
||||
void
|
||||
dst_algorithm_format(dst_algorithm_t dst_alg, char *data, unsigned int length);
|
||||
/*%<
|
||||
* Wrapper for dst_algorithm_totext(), writing text into 'cp'
|
||||
*/
|
||||
|
||||
dns_secalg_t
|
||||
dst_algorithm_tosecalg(dst_algorithm_t dst_alg);
|
||||
/*%<
|
||||
* Return the DNSSEC algorithm identifier that applies for the DST
|
||||
* algorithm. For PRIVATEDNS and PRIVATEOID based algorithms, this
|
||||
* is PRIVATEDNS and PRIVATEOID respectively.
|
||||
*
|
||||
* Zero is returned when there is no mapping.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dst_privatedns_fromtext(dst_algorithm_t *algp, isc_textregion_t *source);
|
||||
|
||||
isc_result_t
|
||||
dns_privatedns_totext(dst_algorithm_t alg, isc_buffer_t *b);
|
||||
|
||||
void
|
||||
dns_privatedns_format(dst_algorithm_t alg, char *buf, unsigned int size);
|
||||
|
||||
isc_result_t
|
||||
dst_privateoid_fromtext(dst_algorithm_t *algp, isc_textregion_t *source);
|
||||
|
||||
isc_result_t
|
||||
dns_privateoid_totext(dst_algorithm_t alg, isc_buffer_t *b);
|
||||
|
||||
void
|
||||
dns_privateoid_format(dst_algorithm_t alg, char *buf, unsigned int size);
|
||||
|
||||
dst_algorithm_t
|
||||
dst_algorithm_fromdata(dns_secalg_t algorithm, unsigned char *data,
|
||||
unsigned int length);
|
||||
/*%<
|
||||
* If 'algorithm' is PRIVATEOID or PRIVATEDNS, extract the DNSSEC private
|
||||
* algorithm encoded at the begining of data and return the DST algorithm
|
||||
* number that corresponds to it; if the algorithm is unknown to DST,
|
||||
* return 0.
|
||||
*
|
||||
* If 'algorithm' is any other value, return it directly.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -426,11 +426,13 @@ dns_kasp_key_size(dns_kasp_key_t *key) {
|
|||
REQUIRE(key != NULL);
|
||||
|
||||
switch (key->algorithm) {
|
||||
case DNS_KEYALG_RSASHA1:
|
||||
case DNS_KEYALG_NSEC3RSASHA1:
|
||||
case DNS_KEYALG_RSASHA256:
|
||||
case DNS_KEYALG_RSASHA512:
|
||||
min = (key->algorithm == DNS_KEYALG_RSASHA512) ? 1024 : 512;
|
||||
case DST_ALG_RSASHA1:
|
||||
case DST_ALG_NSEC3RSASHA1:
|
||||
case DST_ALG_RSASHA256:
|
||||
case DST_ALG_RSASHA512:
|
||||
case DST_ALG_RSASHA256PRIVATEOID:
|
||||
case DST_ALG_RSASHA512PRIVATEOID:
|
||||
min = (key->algorithm == DST_ALG_RSASHA512) ? 1024 : 512;
|
||||
if (key->length > -1) {
|
||||
size = (unsigned int)key->length;
|
||||
if (size < min) {
|
||||
|
|
@ -443,16 +445,16 @@ dns_kasp_key_size(dns_kasp_key_t *key) {
|
|||
size = 2048;
|
||||
}
|
||||
break;
|
||||
case DNS_KEYALG_ECDSA256:
|
||||
case DST_ALG_ECDSA256:
|
||||
size = 256;
|
||||
break;
|
||||
case DNS_KEYALG_ECDSA384:
|
||||
case DST_ALG_ECDSA384:
|
||||
size = 384;
|
||||
break;
|
||||
case DNS_KEYALG_ED25519:
|
||||
case DST_ALG_ED25519:
|
||||
size = 256;
|
||||
break;
|
||||
case DNS_KEYALG_ED448:
|
||||
case DST_ALG_ED448:
|
||||
size = 456;
|
||||
break;
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -453,7 +453,7 @@ dns_keytable_deletekey(dns_keytable_t *keytable, const dns_name_t *keyname,
|
|||
}
|
||||
|
||||
result = dns_ds_fromkeyrdata(keyname, &rdata, DNS_DSDIGEST_SHA256,
|
||||
digest, &ds);
|
||||
digest, sizeof(digest), &ds);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto finish;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,6 +50,14 @@ typedef struct rsa_components {
|
|||
const BIGNUM *e, *n, *d, *p, *q, *dmp1, *dmq1, *iqmp;
|
||||
} rsa_components_t;
|
||||
|
||||
/* length byte + 1.2.840.113549.1.1.11 BER encoded RFC 4055 */
|
||||
static unsigned char oid_rsasha256[] = { 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48,
|
||||
0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b };
|
||||
|
||||
/* length byte + 1.2.840.113549.1.1.13 BER encoded RFC 4055 */
|
||||
static unsigned char oid_rsasha512[] = { 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48,
|
||||
0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0d };
|
||||
|
||||
static isc_result_t
|
||||
opensslrsa_components_get(const dst_key_t *key, rsa_components_t *c,
|
||||
bool private) {
|
||||
|
|
@ -154,6 +162,8 @@ opensslrsa_valid_key_alg(unsigned int key_alg) {
|
|||
case DST_ALG_NSEC3RSASHA1:
|
||||
case DST_ALG_RSASHA256:
|
||||
case DST_ALG_RSASHA512:
|
||||
case DST_ALG_RSASHA256PRIVATEOID:
|
||||
case DST_ALG_RSASHA512PRIVATEOID:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
|
@ -181,12 +191,14 @@ opensslrsa_createctx(dst_key_t *key, dst_context_t *dctx) {
|
|||
}
|
||||
break;
|
||||
case DST_ALG_RSASHA256:
|
||||
case DST_ALG_RSASHA256PRIVATEOID:
|
||||
/* From RFC 5702 */
|
||||
if (dctx->key->key_size < 512 || dctx->key->key_size > 4096) {
|
||||
return ISC_R_FAILURE;
|
||||
}
|
||||
break;
|
||||
case DST_ALG_RSASHA512:
|
||||
case DST_ALG_RSASHA512PRIVATEOID:
|
||||
/* From RFC 5702 */
|
||||
if (dctx->key->key_size < 1024 || dctx->key->key_size > 4096) {
|
||||
return ISC_R_FAILURE;
|
||||
|
|
@ -207,9 +219,11 @@ opensslrsa_createctx(dst_key_t *key, dst_context_t *dctx) {
|
|||
type = isc__crypto_sha1; /* SHA1 + RSA */
|
||||
break;
|
||||
case DST_ALG_RSASHA256:
|
||||
case DST_ALG_RSASHA256PRIVATEOID:
|
||||
type = isc__crypto_sha256; /* SHA256 + RSA */
|
||||
break;
|
||||
case DST_ALG_RSASHA512:
|
||||
case DST_ALG_RSASHA512PRIVATEOID:
|
||||
type = isc__crypto_sha512;
|
||||
break;
|
||||
default:
|
||||
|
|
@ -264,6 +278,7 @@ opensslrsa_sign(dst_context_t *dctx, isc_buffer_t *sig) {
|
|||
unsigned int siglen = 0;
|
||||
EVP_MD_CTX *evp_md_ctx = NULL;
|
||||
EVP_PKEY *pkey = NULL;
|
||||
unsigned int len = 0;
|
||||
|
||||
REQUIRE(dctx != NULL && dctx->key != NULL);
|
||||
REQUIRE(opensslrsa_valid_key_alg(dctx->key->key_alg));
|
||||
|
|
@ -272,17 +287,42 @@ opensslrsa_sign(dst_context_t *dctx, isc_buffer_t *sig) {
|
|||
evp_md_ctx = dctx->ctxdata.evp_md_ctx;
|
||||
pkey = key->keydata.pkeypair.priv;
|
||||
|
||||
/*
|
||||
* Account to the space the OIDs and DNS names consume.
|
||||
*/
|
||||
switch (key->key_alg) {
|
||||
case DST_ALG_RSASHA256PRIVATEOID:
|
||||
len = sizeof(oid_rsasha256);
|
||||
break;
|
||||
case DST_ALG_RSASHA512PRIVATEOID:
|
||||
len = sizeof(oid_rsasha512);
|
||||
break;
|
||||
}
|
||||
|
||||
isc_buffer_availableregion(sig, &r);
|
||||
|
||||
if (r.length < (unsigned int)EVP_PKEY_size(pkey)) {
|
||||
if (r.length < (unsigned int)EVP_PKEY_size(pkey) + len) {
|
||||
return ISC_R_NOSPACE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add OID and DNS names to start of signature.
|
||||
*/
|
||||
switch (key->key_alg) {
|
||||
case DST_ALG_RSASHA256PRIVATEOID:
|
||||
isc_buffer_putmem(sig, oid_rsasha256, sizeof(oid_rsasha256));
|
||||
isc_region_consume(&r, sizeof(oid_rsasha256));
|
||||
break;
|
||||
case DST_ALG_RSASHA512PRIVATEOID:
|
||||
isc_buffer_putmem(sig, oid_rsasha512, sizeof(oid_rsasha512));
|
||||
isc_region_consume(&r, sizeof(oid_rsasha512));
|
||||
break;
|
||||
}
|
||||
|
||||
if (!EVP_SignFinal(evp_md_ctx, r.base, &siglen, pkey)) {
|
||||
return dst__openssl_toresult3(dctx->category, "EVP_SignFinal",
|
||||
ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
isc_buffer_add(sig, siglen);
|
||||
|
||||
return ISC_R_SUCCESS;
|
||||
|
|
@ -317,6 +357,8 @@ opensslrsa_verify(dst_context_t *dctx, const isc_region_t *sig) {
|
|||
int status = 0;
|
||||
EVP_MD_CTX *evp_md_ctx = NULL;
|
||||
EVP_PKEY *pkey = NULL;
|
||||
const unsigned char *base = sig->base;
|
||||
unsigned int length = sig->length;
|
||||
|
||||
REQUIRE(dctx != NULL && dctx->key != NULL);
|
||||
REQUIRE(opensslrsa_valid_key_alg(dctx->key->key_alg));
|
||||
|
|
@ -330,7 +372,31 @@ opensslrsa_verify(dst_context_t *dctx, const isc_region_t *sig) {
|
|||
return DST_R_VERIFYFAILURE;
|
||||
}
|
||||
|
||||
status = EVP_VerifyFinal(evp_md_ctx, sig->base, sig->length, pkey);
|
||||
/*
|
||||
* Check identifying OID in front of public key material.
|
||||
*/
|
||||
switch (key->key_alg) {
|
||||
case DST_ALG_RSASHA256PRIVATEOID:
|
||||
if (length < sizeof(oid_rsasha256) ||
|
||||
memcmp(base, oid_rsasha256, sizeof(oid_rsasha256)) != 0)
|
||||
{
|
||||
return DST_R_VERIFYFAILURE;
|
||||
}
|
||||
base += sizeof(oid_rsasha256);
|
||||
length -= sizeof(oid_rsasha256);
|
||||
break;
|
||||
case DST_ALG_RSASHA512PRIVATEOID:
|
||||
if (length < sizeof(oid_rsasha512) ||
|
||||
memcmp(base, oid_rsasha512, sizeof(oid_rsasha512)) != 0)
|
||||
{
|
||||
return DST_R_VERIFYFAILURE;
|
||||
}
|
||||
base += sizeof(oid_rsasha512);
|
||||
length -= sizeof(oid_rsasha512);
|
||||
break;
|
||||
}
|
||||
|
||||
status = EVP_VerifyFinal(evp_md_ctx, base, length, pkey);
|
||||
switch (status) {
|
||||
case 1:
|
||||
return ISC_R_SUCCESS;
|
||||
|
|
@ -692,12 +758,14 @@ opensslrsa_generate(dst_key_t *key, int unused, void (*callback)(int)) {
|
|||
}
|
||||
break;
|
||||
case DST_ALG_RSASHA256:
|
||||
case DST_ALG_RSASHA256PRIVATEOID:
|
||||
/* From RFC 5702 */
|
||||
if (key->key_size < 512 || key->key_size > 4096) {
|
||||
DST_RET(DST_R_INVALIDPARAM);
|
||||
}
|
||||
break;
|
||||
case DST_ALG_RSASHA512:
|
||||
case DST_ALG_RSASHA512PRIVATEOID:
|
||||
/* From RFC 5702 */
|
||||
if (key->key_size < 1024 || key->key_size > 4096) {
|
||||
DST_RET(DST_R_INVALIDPARAM);
|
||||
|
|
@ -740,6 +808,26 @@ opensslrsa_todns(const dst_key_t *key, isc_buffer_t *data) {
|
|||
|
||||
isc_buffer_availableregion(data, &r);
|
||||
|
||||
/*
|
||||
* Add identifying OID and DNS names to front of public key material.
|
||||
*/
|
||||
switch (key->key_alg) {
|
||||
case DST_ALG_RSASHA256PRIVATEOID:
|
||||
if (r.length < sizeof(oid_rsasha256)) {
|
||||
DST_RET(ISC_R_NOSPACE);
|
||||
}
|
||||
isc_buffer_putmem(data, oid_rsasha256, sizeof(oid_rsasha256));
|
||||
isc_region_consume(&r, sizeof(oid_rsasha256));
|
||||
break;
|
||||
case DST_ALG_RSASHA512PRIVATEOID:
|
||||
if (r.length < sizeof(oid_rsasha512)) {
|
||||
DST_RET(ISC_R_NOSPACE);
|
||||
}
|
||||
isc_buffer_putmem(data, oid_rsasha512, sizeof(oid_rsasha512));
|
||||
isc_region_consume(&r, sizeof(oid_rsasha512));
|
||||
break;
|
||||
}
|
||||
|
||||
ret = opensslrsa_components_get(key, &c, false);
|
||||
if (ret != ISC_R_SUCCESS) {
|
||||
goto err;
|
||||
|
|
@ -794,6 +882,31 @@ opensslrsa_fromdns(dst_key_t *key, isc_buffer_t *data) {
|
|||
if (r.length == 0) {
|
||||
DST_RET(ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check identifying OID in front of public key material.
|
||||
*/
|
||||
switch (key->key_alg) {
|
||||
case DST_ALG_RSASHA256PRIVATEOID:
|
||||
if (r.length < sizeof(oid_rsasha256) ||
|
||||
memcmp(r.base, oid_rsasha256, sizeof(oid_rsasha256)) != 0)
|
||||
{
|
||||
DST_RET(DST_R_INVALIDPUBLICKEY);
|
||||
}
|
||||
isc_region_consume(&r, sizeof(oid_rsasha256));
|
||||
isc_buffer_forward(data, sizeof(oid_rsasha256));
|
||||
break;
|
||||
case DST_ALG_RSASHA512PRIVATEOID:
|
||||
if (r.length < sizeof(oid_rsasha512) ||
|
||||
memcmp(r.base, oid_rsasha512, sizeof(oid_rsasha512)) != 0)
|
||||
{
|
||||
DST_RET(DST_R_INVALIDPUBLICKEY);
|
||||
}
|
||||
isc_region_consume(&r, sizeof(oid_rsasha512));
|
||||
isc_buffer_forward(data, sizeof(oid_rsasha512));
|
||||
break;
|
||||
}
|
||||
|
||||
length = r.length;
|
||||
if (r.length < 1) {
|
||||
DST_RET(DST_R_INVALIDPUBLICKEY);
|
||||
|
|
@ -1214,7 +1327,7 @@ static const unsigned char sha512_sig[] =
|
|||
"\xf1";
|
||||
|
||||
static isc_result_t
|
||||
check_algorithm(unsigned char algorithm) {
|
||||
check_algorithm(unsigned short algorithm) {
|
||||
rsa_components_t c = { .bnfree = true };
|
||||
EVP_MD_CTX *evp_md_ctx = EVP_MD_CTX_create();
|
||||
EVP_PKEY *pkey = NULL;
|
||||
|
|
@ -1231,11 +1344,13 @@ check_algorithm(unsigned char algorithm) {
|
|||
len = sizeof(sha1_sig) - 1;
|
||||
break;
|
||||
case DST_ALG_RSASHA256:
|
||||
case DST_ALG_RSASHA256PRIVATEOID:
|
||||
type = isc__crypto_sha256; /* SHA256 + RSA */
|
||||
sig = sha256_sig;
|
||||
len = sizeof(sha256_sig) - 1;
|
||||
break;
|
||||
case DST_ALG_RSASHA512:
|
||||
case DST_ALG_RSASHA512PRIVATEOID:
|
||||
type = isc__crypto_sha512;
|
||||
sig = sha512_sig;
|
||||
len = sizeof(sha512_sig) - 1;
|
||||
|
|
@ -1272,7 +1387,7 @@ err:
|
|||
}
|
||||
|
||||
void
|
||||
dst__opensslrsa_init(dst_func_t **funcp, unsigned char algorithm) {
|
||||
dst__opensslrsa_init(dst_func_t **funcp, unsigned short algorithm) {
|
||||
REQUIRE(funcp != NULL);
|
||||
|
||||
if (*funcp == NULL) {
|
||||
|
|
|
|||
|
|
@ -354,6 +354,7 @@ dns_private_totext(dns_rdata_t *private, isc_buffer_t *buf) {
|
|||
isc_buffer_putstr(buf, " / creating NSEC chain");
|
||||
}
|
||||
} else if (private->length == 5) {
|
||||
/* Old Form */
|
||||
unsigned char alg = private->data[0];
|
||||
dns_keytag_t keyid = (private->data[2] | private->data[1] << 8);
|
||||
char keybuf[DNS_SECALG_FORMATSIZE + BUFSIZ],
|
||||
|
|
@ -371,6 +372,33 @@ dns_private_totext(dns_rdata_t *private, isc_buffer_t *buf) {
|
|||
isc_buffer_putstr(buf, "Signing with ");
|
||||
}
|
||||
|
||||
dns_secalg_format(alg, algbuf, sizeof(algbuf));
|
||||
snprintf(keybuf, sizeof(keybuf), "key %d/%s", keyid, algbuf);
|
||||
isc_buffer_putstr(buf, keybuf);
|
||||
} else if (private->length == 7) {
|
||||
/* New Form - supports private types */
|
||||
dns_keytag_t keyid = private->data[2] | (private->data[1] << 8);
|
||||
char keybuf[DNS_SECALG_FORMATSIZE + BUFSIZ],
|
||||
algbuf[DNS_SECALG_FORMATSIZE];
|
||||
bool del = private->data[3];
|
||||
bool complete = private->data[4];
|
||||
dst_algorithm_t alg = private->data[6] |
|
||||
(private->data[5] << 8);
|
||||
|
||||
if (dst_algorithm_tosecalg(alg) != private->data[0]) {
|
||||
return ISC_R_NOTFOUND;
|
||||
}
|
||||
|
||||
if (del && complete) {
|
||||
isc_buffer_putstr(buf, "Done removing signatures for ");
|
||||
} else if (del) {
|
||||
isc_buffer_putstr(buf, "Removing signatures for ");
|
||||
} else if (complete) {
|
||||
isc_buffer_putstr(buf, "Done signing with ");
|
||||
} else {
|
||||
isc_buffer_putstr(buf, "Signing with ");
|
||||
}
|
||||
|
||||
dns_secalg_format(alg, algbuf, sizeof(algbuf));
|
||||
snprintf(keybuf, sizeof(keybuf), "key %d/%s", keyid, algbuf);
|
||||
isc_buffer_putstr(buf, keybuf);
|
||||
|
|
|
|||
142
lib/dns/rcode.c
142
lib/dns/rcode.c
|
|
@ -36,6 +36,8 @@
|
|||
#include <dns/secalg.h>
|
||||
#include <dns/secproto.h>
|
||||
|
||||
#include <dst/dst.h>
|
||||
|
||||
#define RETERR(x) \
|
||||
do { \
|
||||
isc_result_t _r = (x); \
|
||||
|
|
@ -47,6 +49,10 @@
|
|||
|
||||
#define TOTEXTONLY 0x01
|
||||
|
||||
/* clang-format off */
|
||||
#define SENTINEL { 0, NULL, 0 }
|
||||
/* clang-format on */
|
||||
|
||||
#define RCODENAMES \
|
||||
/* standard rcodes */ \
|
||||
{ dns_rcode_noerror, "NOERROR", 0 }, \
|
||||
|
|
@ -69,7 +75,7 @@
|
|||
#define ERCODENAMES \
|
||||
/* extended rcodes */ \
|
||||
{ dns_rcode_badvers, "BADVERS", 0 }, \
|
||||
{ dns_rcode_badcookie, "BADCOOKIE", 0 }, { 0, NULL, 0 }
|
||||
{ dns_rcode_badcookie, "BADCOOKIE", 0 }, SENTINEL
|
||||
|
||||
#define TSIGRCODENAMES \
|
||||
/* extended rcodes */ \
|
||||
|
|
@ -79,7 +85,7 @@
|
|||
{ dns_tsigerror_badmode, "BADMODE", 0 }, \
|
||||
{ dns_tsigerror_badname, "BADNAME", 0 }, \
|
||||
{ dns_tsigerror_badalg, "BADALG", 0 }, \
|
||||
{ dns_tsigerror_badtrunc, "BADTRUNC", 0 }, { 0, NULL, 0 }
|
||||
{ dns_tsigerror_badtrunc, "BADTRUNC", 0 }, SENTINEL
|
||||
|
||||
/* RFC4398 section 2.1 */
|
||||
|
||||
|
|
@ -87,7 +93,7 @@
|
|||
{ 1, "PKIX", 0 }, { 2, "SPKI", 0 }, { 3, "PGP", 0 }, \
|
||||
{ 4, "IPKIX", 0 }, { 5, "ISPKI", 0 }, { 6, "IPGP", 0 }, \
|
||||
{ 7, "ACPKIX", 0 }, { 8, "IACPKIX", 0 }, { 253, "URI", 0 }, \
|
||||
{ 254, "OID", 0 }, { 0, NULL, 0 }
|
||||
{ 254, "OID", 0 }, SENTINEL
|
||||
|
||||
/* RFC2535 section 7, RFC3110 */
|
||||
|
||||
|
|
@ -109,26 +115,56 @@
|
|||
{ DNS_KEYALG_ED448, "ED448", 0 }, \
|
||||
{ DNS_KEYALG_INDIRECT, "INDIRECT", 0 }, \
|
||||
{ DNS_KEYALG_PRIVATEDNS, "PRIVATEDNS", 0 }, \
|
||||
{ DNS_KEYALG_PRIVATEOID, "PRIVATEOID", 0 }, { 0, NULL, 0 }
|
||||
{ DNS_KEYALG_PRIVATEOID, "PRIVATEOID", 0 }, SENTINEL
|
||||
|
||||
/*
|
||||
* PRIVATEDNS subtypes we support.
|
||||
*/
|
||||
#define PRIVATEDNSS /* currently empty */
|
||||
|
||||
/*
|
||||
* PRIVATEOID subtypes we support.
|
||||
*/
|
||||
#define PRIVATEOIDS \
|
||||
{ DST_ALG_RSASHA256PRIVATEOID, "RSASHA256OID", 0 }, \
|
||||
{ DST_ALG_RSASHA512PRIVATEOID, "RSASHA512OID", 0 },
|
||||
|
||||
/* RFC2535 section 7.1 */
|
||||
|
||||
#define SECPROTONAMES \
|
||||
{ 0, "NONE", 0 }, { 1, "TLS", 0 }, { 2, "EMAIL", 0 }, \
|
||||
{ 3, "DNSSEC", 0 }, { 4, "IPSEC", 0 }, { 255, "ALL", 0 }, \
|
||||
{ 0, NULL, 0 }
|
||||
SENTINEL
|
||||
|
||||
#define HASHALGNAMES { 1, "SHA-1", 0 }, { 0, NULL, 0 }
|
||||
#define HASHALGNAMES { 1, "SHA-1", 0 }, SENTINEL
|
||||
|
||||
/* RFC3658, RFC4509, RFC5933, RFC6605 */
|
||||
/* RFC3658, RFC4509, RFC5933, RFC6605, RFC9558, RFC9563 */
|
||||
|
||||
#if defined(DNS_DSDIGEST_SHA256PRIVATE) && \
|
||||
defined(DNS_DSDIGEST_SHA384PRIVATE) && \
|
||||
defined(DNS_DSDIGEST_SM3PRIVATE)
|
||||
#define DSDIGESTPRIVATENAMES \
|
||||
{ DNS_DSDIGEST_SHA256PRIVATE, "SHA-256-PRIVATE", 0 }, \
|
||||
{ DNS_DSDIGEST_SHA256PRIVATE, "SHA256PRIVATE", 0 }, \
|
||||
{ DNS_DSDIGEST_SHA384PRIVATE, "SHA-384-PRIVATE", 0 }, \
|
||||
{ DNS_DSDIGEST_SHA384PRIVATE, "SHA384PRIVATE", 0 }, \
|
||||
{ DNS_DSDIGEST_SM3PRIVATE, "SM3-PRIVATE", 0 }, \
|
||||
{ DNS_DSDIGEST_SM3PRIVATE, "SM3PRIVATE", 0 },
|
||||
#else
|
||||
#define DSDIGESTPRIVATENAMES
|
||||
#endif
|
||||
|
||||
#define DSDIGESTNAMES \
|
||||
{ DNS_DSDIGEST_SHA1, "SHA-1", 0 }, { DNS_DSDIGEST_SHA1, "SHA1", 0 }, \
|
||||
{ DNS_DSDIGEST_SHA256, "SHA-256", 0 }, \
|
||||
{ DNS_DSDIGEST_SHA256, "SHA256", 0 }, \
|
||||
{ DNS_DSDIGEST_GOST, "GOST", 0 }, \
|
||||
{ DNS_DSDIGEST_SM3, "SM3", 0 }, \
|
||||
{ DNS_DSDIGEST_SHA384, "SHA-384", 0 }, \
|
||||
{ DNS_DSDIGEST_SHA384, "SHA384", 0 }, { 0, NULL, 0 }
|
||||
{ DNS_DSDIGEST_SHA384, "SHA384", 0 }, \
|
||||
{ DNS_DSDIGEST_GOST2012, "GOST-2012", 0 }, \
|
||||
{ DNS_DSDIGEST_GOST2012, "GOST2012", 0 }, \
|
||||
DSDIGESTPRIVATENAMES SENTINEL
|
||||
|
||||
struct tbl {
|
||||
unsigned int value;
|
||||
|
|
@ -143,6 +179,9 @@ static struct tbl secalgs[] = { SECALGNAMES };
|
|||
static struct tbl secprotos[] = { SECPROTONAMES };
|
||||
static struct tbl hashalgs[] = { HASHALGNAMES };
|
||||
static struct tbl dsdigests[] = { DSDIGESTNAMES };
|
||||
static struct tbl privatednss[] = { PRIVATEDNSS SENTINEL };
|
||||
static struct tbl privateoids[] = { PRIVATEOIDS SENTINEL };
|
||||
static struct tbl dstalgorithms[] = { PRIVATEDNSS PRIVATEOIDS SECALGNAMES };
|
||||
|
||||
static struct keyflag {
|
||||
const char *name;
|
||||
|
|
@ -346,6 +385,64 @@ dns_secalg_format(dns_secalg_t alg, char *cp, unsigned int size) {
|
|||
}
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dst_privatedns_fromtext(dst_algorithm_t *dstalgp, isc_textregion_t *source) {
|
||||
unsigned int value;
|
||||
RETERR(dns_mnemonic_fromtext(&value, source, privatednss, 0));
|
||||
*dstalgp = value;
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_privatedns_totext(dst_algorithm_t alg, isc_buffer_t *target) {
|
||||
return dns_mnemonic_totext(alg, target, privatednss);
|
||||
}
|
||||
|
||||
void
|
||||
dns_privatedns_format(dst_algorithm_t alg, char *cp, unsigned int size) {
|
||||
isc_buffer_t b;
|
||||
isc_region_t r;
|
||||
isc_result_t result;
|
||||
|
||||
REQUIRE(cp != NULL && size > 0);
|
||||
isc_buffer_init(&b, cp, size - 1);
|
||||
result = dns_privatedns_totext(alg, &b);
|
||||
isc_buffer_usedregion(&b, &r);
|
||||
r.base[r.length] = 0;
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
r.base[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dst_privateoid_fromtext(dst_algorithm_t *dstalgp, isc_textregion_t *source) {
|
||||
unsigned int value;
|
||||
RETERR(dns_mnemonic_fromtext(&value, source, privateoids, 0));
|
||||
*dstalgp = value;
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_privateoid_totext(dst_algorithm_t alg, isc_buffer_t *target) {
|
||||
return dns_mnemonic_totext(alg, target, privateoids);
|
||||
}
|
||||
|
||||
void
|
||||
dns_privateoid_format(dst_algorithm_t alg, char *cp, unsigned int size) {
|
||||
isc_buffer_t b;
|
||||
isc_region_t r;
|
||||
isc_result_t result;
|
||||
|
||||
REQUIRE(cp != NULL && size > 0);
|
||||
isc_buffer_init(&b, cp, size - 1);
|
||||
result = dns_privateoid_totext(alg, &b);
|
||||
isc_buffer_usedregion(&b, &r);
|
||||
r.base[r.length] = 0;
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
r.base[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_secproto_fromtext(dns_secproto_t *secprotop, isc_textregion_t *source) {
|
||||
unsigned int value;
|
||||
|
|
@ -572,3 +669,32 @@ dns_rdataclass_format(dns_rdataclass_t rdclass, char *array,
|
|||
strlcpy(array, "<unknown>", size);
|
||||
}
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dst_algorithm_fromtext(dst_algorithm_t *dstalgp, isc_textregion_t *source) {
|
||||
unsigned int value;
|
||||
RETERR(dns_mnemonic_fromtext(&value, source, dstalgorithms, 255));
|
||||
*dstalgp = value;
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dst_algorithm_totext(dst_algorithm_t alg, isc_buffer_t *target) {
|
||||
return dns_mnemonic_totext(alg, target, dstalgorithms);
|
||||
}
|
||||
|
||||
void
|
||||
dst_algorithm_format(dst_algorithm_t alg, char *cp, unsigned int size) {
|
||||
isc_buffer_t b;
|
||||
isc_region_t r;
|
||||
isc_result_t result;
|
||||
|
||||
REQUIRE(cp != NULL && size > 0);
|
||||
isc_buffer_init(&b, cp, size - 1);
|
||||
result = dst_algorithm_totext(alg, &b);
|
||||
isc_buffer_usedregion(&b, &r);
|
||||
r.base[r.length] = 0;
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
r.base[0] = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10593,7 +10593,7 @@ dns_resolver_disable_algorithm(dns_resolver_t *resolver, const dns_name_t *name,
|
|||
unsigned int alg) {
|
||||
REQUIRE(VALID_RESOLVER(resolver));
|
||||
|
||||
if (alg > 255) {
|
||||
if (alg >= DST_MAX_ALGS) {
|
||||
return ISC_R_RANGE;
|
||||
}
|
||||
|
||||
|
|
@ -10614,13 +10614,37 @@ dns_resolver_disable_ds_digest(dns_resolver_t *resolver, const dns_name_t *name,
|
|||
|
||||
bool
|
||||
dns_resolver_algorithm_supported(dns_resolver_t *resolver,
|
||||
const dns_name_t *name, unsigned int alg) {
|
||||
const dns_name_t *name, unsigned int alg,
|
||||
unsigned char *private, size_t len) {
|
||||
REQUIRE(VALID_RESOLVER(resolver));
|
||||
|
||||
if ((alg == DST_ALG_DH) || (alg == DST_ALG_INDIRECT)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Look up the DST algorithm identifier for private-OID
|
||||
* and private-DNS keys.
|
||||
*/
|
||||
if (alg == DST_ALG_PRIVATEDNS && private != NULL) {
|
||||
isc_buffer_t b;
|
||||
isc_buffer_init(&b, private, len);
|
||||
isc_buffer_add(&b, len);
|
||||
alg = dst_algorithm_fromprivatedns(&b);
|
||||
if (alg == 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (alg == DST_ALG_PRIVATEOID && private != NULL) {
|
||||
isc_buffer_t b;
|
||||
isc_buffer_init(&b, private, len);
|
||||
isc_buffer_add(&b, len);
|
||||
alg = dst_algorithm_fromprivateoid(&b);
|
||||
if (alg == 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (dns_nametree_covered(resolver->algorithms, name, NULL, alg)) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -146,7 +146,8 @@ static isc_result_t
|
|||
validate_nx(dns_validator_t *val, bool resume);
|
||||
|
||||
static isc_result_t
|
||||
proveunsecure(dns_validator_t *val, bool have_ds, bool resume);
|
||||
proveunsecure(dns_validator_t *val, bool have_ds, bool have_dnskey,
|
||||
bool resume);
|
||||
|
||||
static void
|
||||
validator_logv(dns_validator_t *val, isc_logcategory_t category,
|
||||
|
|
@ -397,6 +398,13 @@ fetch_callback_dnskey(void *arg) {
|
|||
dns_rdataset_t *rdataset = &val->frdataset;
|
||||
isc_result_t eresult = resp->result;
|
||||
isc_result_t result;
|
||||
bool trustchain;
|
||||
|
||||
/*
|
||||
* Set 'trustchain' to true if we're walking a chain of
|
||||
* trust; false if we're attempting to prove insecurity.
|
||||
*/
|
||||
trustchain = ((val->attributes & VALATTR_INSECURITY) == 0);
|
||||
|
||||
/* Free resources which are not of interest. */
|
||||
if (resp->node != NULL) {
|
||||
|
|
@ -418,34 +426,55 @@ fetch_callback_dnskey(void *arg) {
|
|||
goto cleanup;
|
||||
}
|
||||
|
||||
switch (eresult) {
|
||||
case ISC_R_SUCCESS:
|
||||
case DNS_R_NCACHENXRRSET:
|
||||
/*
|
||||
* We have an answer to our DNSKEY query. Either the DNSKEY
|
||||
* RRset or a NODATA response.
|
||||
*/
|
||||
validator_log(val, ISC_LOG_DEBUG(3), "%s with trust %s",
|
||||
eresult == ISC_R_SUCCESS ? "keyset"
|
||||
: "NCACHENXRRSET",
|
||||
dns_trust_totext(rdataset->trust));
|
||||
/*
|
||||
* Only extract the dst key if the keyset exists and is secure.
|
||||
*/
|
||||
if (eresult == ISC_R_SUCCESS &&
|
||||
rdataset->trust >= dns_trust_secure)
|
||||
{
|
||||
result = validate_helper_run(val,
|
||||
resume_answer_with_key);
|
||||
} else {
|
||||
result = validate_async_run(val, resume_answer);
|
||||
if (trustchain) {
|
||||
switch (eresult) {
|
||||
case ISC_R_SUCCESS:
|
||||
case DNS_R_NCACHENXRRSET:
|
||||
/*
|
||||
* We have an answer to our DNSKEY query. Either the
|
||||
* DNSKEY RRset or a NODATA response.
|
||||
*/
|
||||
validator_log(val, ISC_LOG_DEBUG(3), "%s with trust %s",
|
||||
eresult == ISC_R_SUCCESS
|
||||
? "keyset"
|
||||
: "NCACHENXRRSET",
|
||||
dns_trust_totext(rdataset->trust));
|
||||
/*
|
||||
* Only extract the dst key if the keyset exists and is
|
||||
* secure.
|
||||
*/
|
||||
if (eresult == ISC_R_SUCCESS &&
|
||||
rdataset->trust >= dns_trust_secure)
|
||||
{
|
||||
result = validate_helper_run(
|
||||
val, resume_answer_with_key);
|
||||
} else {
|
||||
result = validate_async_run(val, resume_answer);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
validator_log(val, ISC_LOG_DEBUG(3),
|
||||
"fetch_callback_dnskey: got %s",
|
||||
isc_result_totext(eresult));
|
||||
result = DNS_R_BROKENCHAIN;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (eresult) {
|
||||
case ISC_R_SUCCESS:
|
||||
/*
|
||||
* We have a DS (val->dsrdataset) and
|
||||
* DNSKEY (val->fdataset).
|
||||
*/
|
||||
result = proveunsecure(val, false, true, true);
|
||||
break;
|
||||
default:
|
||||
validator_log(val, ISC_LOG_DEBUG(3),
|
||||
"fetch_callback_dnskey: got %s",
|
||||
isc_result_totext(eresult));
|
||||
result = DNS_R_BROKENCHAIN;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
validator_log(val, ISC_LOG_DEBUG(3),
|
||||
"fetch_callback_dnskey: got %s",
|
||||
isc_result_totext(eresult));
|
||||
result = DNS_R_BROKENCHAIN;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
|
|
@ -518,7 +547,7 @@ fetch_callback_ds(void *arg) {
|
|||
validator_log(val, ISC_LOG_DEBUG(3),
|
||||
"falling back to insecurity proof (%s)",
|
||||
isc_result_totext(eresult));
|
||||
result = proveunsecure(val, false, false);
|
||||
result = proveunsecure(val, false, false, false);
|
||||
break;
|
||||
default:
|
||||
validator_log(val, ISC_LOG_DEBUG(3),
|
||||
|
|
@ -537,7 +566,7 @@ fetch_callback_ds(void *arg) {
|
|||
* trust.
|
||||
*/
|
||||
|
||||
result = proveunsecure(val, false, true);
|
||||
result = proveunsecure(val, false, false, true);
|
||||
break;
|
||||
case ISC_R_SUCCESS:
|
||||
/*
|
||||
|
|
@ -546,7 +575,7 @@ fetch_callback_ds(void *arg) {
|
|||
* so keep looking for the break in the chain
|
||||
* of trust.
|
||||
*/
|
||||
result = proveunsecure(val, true, true);
|
||||
result = proveunsecure(val, true, false, true);
|
||||
break;
|
||||
case DNS_R_NXRRSET:
|
||||
case DNS_R_NCACHENXRRSET:
|
||||
|
|
@ -567,13 +596,14 @@ fetch_callback_ds(void *arg) {
|
|||
* Not a zone cut, so we have to keep looking for
|
||||
* the break point in the chain of trust.
|
||||
*/
|
||||
result = proveunsecure(val, false, true);
|
||||
result = proveunsecure(val, false, false, true);
|
||||
break;
|
||||
default:
|
||||
validator_log(val, ISC_LOG_DEBUG(3),
|
||||
"fetch_callback_ds: got %s",
|
||||
isc_result_totext(eresult));
|
||||
result = DNS_R_BROKENCHAIN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -673,7 +703,7 @@ validator_callback_ds(void *arg) {
|
|||
{
|
||||
result = markanswer(val, "validator_callback_ds");
|
||||
} else if ((val->attributes & VALATTR_INSECURITY) != 0) {
|
||||
result = proveunsecure(val, have_dsset, true);
|
||||
result = proveunsecure(val, have_dsset, false, true);
|
||||
} else {
|
||||
result = validate_async_run(val, validate_dnskey);
|
||||
}
|
||||
|
|
@ -724,7 +754,7 @@ validator_callback_cname(void *arg) {
|
|||
if (eresult == ISC_R_SUCCESS) {
|
||||
validator_log(val, ISC_LOG_DEBUG(3), "cname with trust %s",
|
||||
dns_trust_totext(val->frdataset.trust));
|
||||
result = proveunsecure(val, false, true);
|
||||
result = proveunsecure(val, false, false, true);
|
||||
} else {
|
||||
if (eresult != DNS_R_BROKENCHAIN) {
|
||||
expire_rdatasets(val);
|
||||
|
|
@ -832,6 +862,7 @@ validator_callback_nsec(void *arg) {
|
|||
FALLTHROUGH;
|
||||
default:
|
||||
result = validate_nx(val, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1364,6 +1395,7 @@ selfsigned_dnskey(dns_validator_t *val) {
|
|||
return ISC_R_QUOTA;
|
||||
}
|
||||
consume_validation_fail(val);
|
||||
break;
|
||||
}
|
||||
} else if (rdataset->trust >= dns_trust_secure) {
|
||||
/*
|
||||
|
|
@ -1469,6 +1501,7 @@ again:
|
|||
break;
|
||||
}
|
||||
consume_validation_fail(val);
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
@ -1641,11 +1674,15 @@ validate_answer_process(void *arg) {
|
|||
* At this point we could check that the signature algorithm
|
||||
* was known and "sufficiently good".
|
||||
*/
|
||||
if (!dns_resolver_algorithm_supported(val->view->resolver, val->name,
|
||||
val->siginfo->algorithm))
|
||||
if (!dns_resolver_algorithm_supported(
|
||||
val->view->resolver, val->name, val->siginfo->algorithm,
|
||||
val->siginfo->signature, val->siginfo->siglen))
|
||||
{
|
||||
if (val->unsupported_algorithm == 0) {
|
||||
val->unsupported_algorithm = val->siginfo->algorithm;
|
||||
/*
|
||||
* XXXMPA save PRIVATEOID/PRIVATEDNS identifier here
|
||||
*/
|
||||
}
|
||||
goto next_key;
|
||||
}
|
||||
|
|
@ -1814,7 +1851,7 @@ validate_async_done(dns_validator_t *val, isc_result_t result) {
|
|||
isc_result_t saved_result = result;
|
||||
validator_log(val, ISC_LOG_DEBUG(3),
|
||||
"falling back to insecurity proof");
|
||||
result = proveunsecure(val, false, false);
|
||||
result = proveunsecure(val, false, false, false);
|
||||
if (result == DNS_R_NOTINSECURE) {
|
||||
result = saved_result;
|
||||
}
|
||||
|
|
@ -1975,6 +2012,7 @@ validate_dnskey_dsset_done(dns_validator_t *val, isc_result_t result) {
|
|||
validator_log(val, ISC_LOG_INFO,
|
||||
"no valid signature found (DS)");
|
||||
result = DNS_R_NOVALIDSIG;
|
||||
break;
|
||||
}
|
||||
|
||||
if (val->dsset == &val->fdsset) {
|
||||
|
|
@ -1991,6 +2029,9 @@ validate_dnskey_dsset(dns_validator_t *val) {
|
|||
dns_rdata_t keyrdata = DNS_RDATA_INIT;
|
||||
isc_result_t result;
|
||||
dns_rdata_ds_t ds;
|
||||
dns_rdata_dnskey_t key;
|
||||
unsigned char *data = 0;
|
||||
unsigned int datalen = 0;
|
||||
|
||||
dns_rdata_reset(&dsrdata);
|
||||
dns_rdataset_current(val->dsset, &dsrdata);
|
||||
|
|
@ -2010,13 +2051,37 @@ validate_dnskey_dsset(dns_validator_t *val) {
|
|||
return DNS_R_BADALG;
|
||||
}
|
||||
|
||||
if (!dns_resolver_algorithm_supported(val->view->resolver, val->name,
|
||||
ds.algorithm))
|
||||
{
|
||||
if (val->unsupported_algorithm == 0) {
|
||||
val->unsupported_algorithm = ds.algorithm;
|
||||
switch (ds.algorithm) {
|
||||
case DNS_KEYALG_PRIVATEDNS:
|
||||
case DNS_KEYALG_PRIVATEOID:
|
||||
switch (ds.digest_type) {
|
||||
#if defined(DNS_DSDIGEST_SHA256PRIVATE) && defined(DNS_DSDIGEST_SHA384PRIVATE)
|
||||
case DNS_DSDIGEST_SHA256PRIVATE:
|
||||
case DNS_DSDIGEST_SHA384PRIVATE:
|
||||
data = ds.digest;
|
||||
datalen = ds.length;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (data != NULL || (ds.algorithm != DNS_KEYALG_PRIVATEDNS &&
|
||||
ds.algorithm != DNS_KEYALG_PRIVATEOID))
|
||||
{
|
||||
if (!dns_resolver_algorithm_supported(val->view->resolver,
|
||||
val->name, ds.algorithm,
|
||||
data, datalen))
|
||||
{
|
||||
if (val->unsupported_algorithm == 0) {
|
||||
val->unsupported_algorithm = ds.algorithm;
|
||||
}
|
||||
return DNS_R_BADALG;
|
||||
}
|
||||
return DNS_R_BADALG;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -2029,6 +2094,28 @@ validate_dnskey_dsset(dns_validator_t *val) {
|
|||
return DNS_R_NOKEYMATCH;
|
||||
}
|
||||
|
||||
/*
|
||||
* Figure out if the private algorithm is supported now that we have
|
||||
* found a matching dnskey.
|
||||
*/
|
||||
dns_rdata_tostruct(&keyrdata, &key, NULL);
|
||||
if (data == NULL && (ds.algorithm == DNS_KEYALG_PRIVATEDNS ||
|
||||
ds.algorithm == DNS_KEYALG_PRIVATEOID))
|
||||
{
|
||||
if (!dns_resolver_algorithm_supported(val->view->resolver,
|
||||
val->name, key.algorithm,
|
||||
key.data, key.datalen))
|
||||
{
|
||||
if (val->unsupported_algorithm == 0) {
|
||||
val->unsupported_algorithm = key.algorithm;
|
||||
/*
|
||||
* XXXMPA Save PRIVATEOID / PRIVATEDNS here.
|
||||
*/
|
||||
}
|
||||
return DNS_R_BADALG;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ... and check that it signed the DNSKEY RRset.
|
||||
*/
|
||||
|
|
@ -2213,7 +2300,8 @@ validate_dnskey(void *arg) {
|
|||
}
|
||||
|
||||
if (!dns_resolver_algorithm_supported(val->view->resolver,
|
||||
val->name, ds.algorithm))
|
||||
val->name, ds.algorithm,
|
||||
NULL, 0))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
|
@ -2894,7 +2982,31 @@ validate_nx(dns_validator_t *val, bool resume) {
|
|||
return DNS_R_BROKENCHAIN;
|
||||
}
|
||||
|
||||
return proveunsecure(val, false, false);
|
||||
return proveunsecure(val, false, false, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if any of the DS records has a private DNSSEC algorithm.
|
||||
*/
|
||||
static bool
|
||||
check_ds_private(dns_rdataset_t *rdataset) {
|
||||
dns_rdata_ds_t ds;
|
||||
isc_result_t result;
|
||||
|
||||
for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
|
||||
result = dns_rdataset_next(rdataset))
|
||||
{
|
||||
dns_rdata_t rdata = DNS_RDATA_INIT;
|
||||
dns_rdataset_current(rdataset, &rdata);
|
||||
result = dns_rdata_tostruct(&rdata, &ds, NULL);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
if (ds.algorithm == DNS_KEYALG_PRIVATEDNS ||
|
||||
ds.algorithm == DNS_KEYALG_PRIVATEOID)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*%
|
||||
|
|
@ -2903,21 +3015,72 @@ validate_nx(dns_validator_t *val, bool resume) {
|
|||
*/
|
||||
static bool
|
||||
check_ds_algs(dns_validator_t *val, dns_name_t *name,
|
||||
dns_rdataset_t *rdataset) {
|
||||
dns_rdataset_t *dsrdataset, dns_rdataset_t *dnskeyset) {
|
||||
dns_rdata_ds_t ds;
|
||||
dns_rdata_dnskey_t key;
|
||||
bool seen_private = false;
|
||||
uint16_t key_tag = 0;
|
||||
uint8_t algorithm = 0;
|
||||
|
||||
DNS_RDATASET_FOREACH (rdataset) {
|
||||
DNS_RDATASET_FOREACH (dsrdataset) {
|
||||
isc_result_t result;
|
||||
dns_rdata_t dsrdata = DNS_RDATA_INIT;
|
||||
dns_rdataset_current(rdataset, &dsrdata);
|
||||
dns_rdata_t keyrdata = DNS_RDATA_INIT;
|
||||
unsigned char *data = NULL;
|
||||
size_t datalen = 0;
|
||||
|
||||
dns_rdataset_current(dsrdataset, &dsrdata);
|
||||
result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
|
||||
/*
|
||||
* Look for a matching DNSKEY to find the PRIVATE
|
||||
* DNSSEC algorithm.
|
||||
*/
|
||||
if (ds.algorithm == DNS_KEYALG_PRIVATEOID ||
|
||||
ds.algorithm == DNS_KEYALG_PRIVATEDNS)
|
||||
{
|
||||
switch (ds.digest_type) {
|
||||
#if defined(DNS_DSDIGEST_SHA256PRIVATE) && defined(DNS_DSDIGEST_SHA384PRIVATE)
|
||||
case DNS_DSDIGEST_SHA256PRIVATE:
|
||||
case DNS_DSDIGEST_SHA384PRIVATE:
|
||||
data = ds.digest;
|
||||
datalen = ds.length;
|
||||
break;
|
||||
#endif
|
||||
case DNS_DSDIGEST_SHA1:
|
||||
case DNS_DSDIGEST_SHA256:
|
||||
case DNS_DSDIGEST_SHA384:
|
||||
if (dnskeyset == NULL) {
|
||||
algorithm = ds.algorithm;
|
||||
key_tag = ds.key_tag;
|
||||
seen_private = true;
|
||||
continue;
|
||||
}
|
||||
result = dns_dnssec_matchdskey(
|
||||
name, &dsrdata, dnskeyset, &keyrdata);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
algorithm = ds.algorithm;
|
||||
key_tag = ds.key_tag;
|
||||
seen_private = true;
|
||||
continue;
|
||||
}
|
||||
result = dns_rdata_tostruct(&keyrdata, &key,
|
||||
NULL);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
data = key.data;
|
||||
datalen = key.datalen;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (dns_resolver_ds_digest_supported(val->view->resolver, name,
|
||||
ds.digest_type) &&
|
||||
dns_resolver_algorithm_supported(val->view->resolver, name,
|
||||
ds.algorithm))
|
||||
ds.algorithm, data,
|
||||
datalen))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
@ -2928,8 +3091,26 @@ check_ds_algs(dns_validator_t *val, dns_name_t *name,
|
|||
* unsecure flow always runs after a validate/validatenx flow. So if an
|
||||
* unsupported alg/digest was found while building the chain of trust,
|
||||
* it would be raised already.
|
||||
*
|
||||
* If we have seen a private algorithm for which we couldn't find a
|
||||
* DNSKEY nor extract it from the digest field we must assume the child
|
||||
* zone is secure. With PRIVATEDNS and PRIVATEOID we can make that
|
||||
* determination if we match a DNSKEY for every DS with these algorithms
|
||||
* or extract the algorithm from the digest field. Since we don't know
|
||||
* whether the private algorithm is unsupported or not, we are required
|
||||
* to treat it as supported.
|
||||
*/
|
||||
return false;
|
||||
if (seen_private) {
|
||||
char namebuf[DNS_NAME_FORMATSIZE];
|
||||
dns_name_format(name, namebuf, sizeof(namebuf));
|
||||
validator_log(val, ISC_LOG_INFO,
|
||||
"No DNSKEY for %s/DS with %s algorithm, tag %u",
|
||||
namebuf,
|
||||
algorithm == DNS_KEYALG_PRIVATEDNS ? "PRIVATEDNS"
|
||||
: "PRIVATEOID",
|
||||
key_tag);
|
||||
}
|
||||
return seen_private;
|
||||
}
|
||||
|
||||
/*%
|
||||
|
|
@ -2972,7 +3153,49 @@ seek_ds(dns_validator_t *val, isc_result_t *resp) {
|
|||
* validated, continue walking down labels.
|
||||
*/
|
||||
if (val->frdataset.trust >= dns_trust_secure) {
|
||||
if (!check_ds_algs(val, tname, &val->frdataset)) {
|
||||
dns_rdataset_t *dssetp = &val->frdataset,
|
||||
*keysetp = NULL;
|
||||
|
||||
if (check_ds_private(&val->frdataset)) {
|
||||
if (dns_rdataset_isassociated(&val->dsrdataset))
|
||||
{
|
||||
dns_rdataset_disassociate(
|
||||
&val->dsrdataset);
|
||||
}
|
||||
dns_rdataset_clone(&val->frdataset,
|
||||
&val->dsrdataset);
|
||||
dssetp = &val->dsrdataset;
|
||||
dns_rdataset_disassociate(&val->frdataset);
|
||||
result = view_find(val, tname,
|
||||
dns_rdatatype_dnskey);
|
||||
switch (result) {
|
||||
case ISC_R_SUCCESS:
|
||||
keysetp = &val->frdataset;
|
||||
break;
|
||||
case ISC_R_NOTFOUND:
|
||||
/*
|
||||
* We don't know anything about the
|
||||
* DNSKEY. Find it.
|
||||
*/
|
||||
*resp = DNS_R_WAIT;
|
||||
result = create_fetch(
|
||||
val, tname,
|
||||
dns_rdatatype_dnskey,
|
||||
fetch_callback_dnskey,
|
||||
"seek_ds");
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
*resp = result;
|
||||
}
|
||||
return ISC_R_COMPLETE;
|
||||
break;
|
||||
default:
|
||||
validator_log(val, ISC_LOG_DEBUG(3),
|
||||
"no DNSKEY found (%s/DS)",
|
||||
namebuf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!check_ds_algs(val, tname, dssetp, keysetp)) {
|
||||
validator_log(
|
||||
val, ISC_LOG_DEBUG(3),
|
||||
"no supported algorithm/digest (%s/DS)",
|
||||
|
|
@ -3161,13 +3384,16 @@ seek_ds(dns_validator_t *val, isc_result_t *resp) {
|
|||
* \li DNS_R_BROKENCHAIN
|
||||
*/
|
||||
static isc_result_t
|
||||
proveunsecure(dns_validator_t *val, bool have_ds, bool resume) {
|
||||
proveunsecure(dns_validator_t *val, bool have_ds, bool have_dnskey,
|
||||
bool resume) {
|
||||
isc_result_t result;
|
||||
char namebuf[DNS_NAME_FORMATSIZE];
|
||||
dns_fixedname_t fixedsecroot;
|
||||
dns_name_t *secroot = dns_fixedname_initname(&fixedsecroot);
|
||||
unsigned int labels;
|
||||
|
||||
INSIST(!(have_ds && have_dnskey));
|
||||
|
||||
/*
|
||||
* We're attempting to prove insecurity.
|
||||
*/
|
||||
|
|
@ -3207,17 +3433,65 @@ proveunsecure(dns_validator_t *val, bool have_ds, bool resume) {
|
|||
* it has a supported algorithm combination. If not, this is
|
||||
* an insecure delegation as far as this resolver is concerned.
|
||||
*/
|
||||
if (have_ds && val->frdataset.trust >= dns_trust_secure &&
|
||||
!check_ds_algs(val, dns_fixedname_name(&val->fname),
|
||||
&val->frdataset))
|
||||
if (have_dnskey ||
|
||||
(have_ds && val->frdataset.trust >= dns_trust_secure))
|
||||
{
|
||||
dns_name_format(dns_fixedname_name(&val->fname),
|
||||
namebuf, sizeof(namebuf));
|
||||
validator_log(val, ISC_LOG_DEBUG(3),
|
||||
"no supported algorithm/digest (%s/DS)",
|
||||
namebuf);
|
||||
result = markanswer(val, "proveunsecure (2)");
|
||||
goto out;
|
||||
dns_rdataset_t *dssetp = NULL, *keysetp = NULL;
|
||||
dns_name_t *fname = dns_fixedname_name(&val->fname);
|
||||
if (have_dnskey) {
|
||||
dssetp = &val->dsrdataset;
|
||||
keysetp = &val->frdataset;
|
||||
} else {
|
||||
dssetp = &val->frdataset;
|
||||
}
|
||||
|
||||
if (!have_dnskey && check_ds_private(&val->frdataset)) {
|
||||
if (dns_rdataset_isassociated(&val->dsrdataset))
|
||||
{
|
||||
dns_rdataset_disassociate(
|
||||
&val->dsrdataset);
|
||||
}
|
||||
dns_rdataset_clone(&val->frdataset,
|
||||
&val->dsrdataset);
|
||||
dssetp = &val->dsrdataset;
|
||||
dns_rdataset_disassociate(&val->frdataset);
|
||||
result = view_find(val, fname,
|
||||
dns_rdatatype_dnskey);
|
||||
switch (result) {
|
||||
case ISC_R_SUCCESS:
|
||||
keysetp = &val->frdataset;
|
||||
break;
|
||||
case ISC_R_NOTFOUND:
|
||||
/*
|
||||
* We don't know anything about the
|
||||
* DNSKEY. Find it.
|
||||
*/
|
||||
result = create_fetch(
|
||||
val, fname,
|
||||
dns_rdatatype_dnskey,
|
||||
fetch_callback_dnskey,
|
||||
"seek_ds");
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
result = DNS_R_WAIT;
|
||||
}
|
||||
goto out;
|
||||
default:
|
||||
validator_log(val, ISC_LOG_DEBUG(3),
|
||||
"no DNSKEY found (%s/DS)",
|
||||
namebuf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!check_ds_algs(val, fname, dssetp, keysetp)) {
|
||||
dns_name_format(fname, namebuf,
|
||||
sizeof(namebuf));
|
||||
validator_log(
|
||||
val, ISC_LOG_DEBUG(3),
|
||||
"no supported algorithm/digest (%s/DS)",
|
||||
namebuf);
|
||||
result = markanswer(val, "proveunsecure (2)");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
val->labels++;
|
||||
}
|
||||
|
|
@ -3308,7 +3582,7 @@ validator_start(void *arg) {
|
|||
validator_log(val, ISC_LOG_DEBUG(3),
|
||||
"attempting insecurity proof");
|
||||
|
||||
result = proveunsecure(val, false, false);
|
||||
result = proveunsecure(val, false, false, false);
|
||||
if (result == DNS_R_NOTINSECURE) {
|
||||
validator_log(val, ISC_LOG_INFO,
|
||||
"got insecure response; "
|
||||
|
|
@ -3421,6 +3695,7 @@ dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
|
|||
dns_rdataset_init(&val->fdsset);
|
||||
dns_rdataset_init(&val->frdataset);
|
||||
dns_rdataset_init(&val->fsigrdataset);
|
||||
dns_rdataset_init(&val->dsrdataset);
|
||||
dns_fixedname_init(&val->wild);
|
||||
dns_fixedname_init(&val->closest);
|
||||
val->start = isc_stdtime_now();
|
||||
|
|
@ -3496,6 +3771,9 @@ destroy_validator(dns_validator_t *val) {
|
|||
dns_keytable_detach(&val->keytable);
|
||||
}
|
||||
disassociate_rdatasets(val);
|
||||
if (dns_rdataset_isassociated(&val->dsrdataset)) {
|
||||
dns_rdataset_disassociate(&val->dsrdataset);
|
||||
}
|
||||
mctx = val->view->mctx;
|
||||
if (val->siginfo != NULL) {
|
||||
isc_mem_put(mctx, val->siginfo, sizeof(*val->siginfo));
|
||||
|
|
|
|||
|
|
@ -1648,9 +1648,9 @@ dns_view_istrusted(dns_view_t *view, const dns_name_t *keyname,
|
|||
goto finish;
|
||||
}
|
||||
|
||||
result = dns_ds_fromkeyrdata(keyname, &rdata,
|
||||
DNS_DSDIGEST_SHA256,
|
||||
digest, &ds);
|
||||
result = dns_ds_fromkeyrdata(
|
||||
keyname, &rdata, DNS_DSDIGEST_SHA256, digest,
|
||||
sizeof(digest), &ds);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto finish;
|
||||
}
|
||||
|
|
@ -2311,7 +2311,7 @@ dns_view_addtrustedkey(dns_view_t *view, dns_rdatatype_t rdtype,
|
|||
isc_result_t result;
|
||||
dns_name_t *name = UNCONST(keyname);
|
||||
char rdatabuf[DST_KEY_MAXSIZE];
|
||||
unsigned char digest[ISC_MAX_MD_SIZE];
|
||||
unsigned char digest[DNS_DS_BUFFERSIZE];
|
||||
dns_rdata_ds_t ds;
|
||||
dns_rdata_t rdata;
|
||||
isc_buffer_t b;
|
||||
|
|
@ -2334,7 +2334,7 @@ dns_view_addtrustedkey(dns_view_t *view, dns_rdatatype_t rdtype,
|
|||
CHECK(dns_rdata_tostruct(&rdata, &ds, NULL));
|
||||
} else {
|
||||
CHECK(dns_ds_fromkeyrdata(name, &rdata, DNS_DSDIGEST_SHA256,
|
||||
digest, &ds));
|
||||
digest, sizeof(digest), &ds));
|
||||
}
|
||||
|
||||
CHECK(dns_keytable_add(view->secroots_priv, false, false, name, &ds,
|
||||
|
|
|
|||
257
lib/dns/zone.c
257
lib/dns/zone.c
|
|
@ -728,7 +728,7 @@ struct dns_signing {
|
|||
unsigned int magic;
|
||||
dns_db_t *db;
|
||||
dns_dbiterator_t *dbiterator;
|
||||
dns_secalg_t algorithm;
|
||||
dst_algorithm_t algorithm;
|
||||
uint16_t keyid;
|
||||
bool deleteit;
|
||||
bool done;
|
||||
|
|
@ -972,7 +972,7 @@ zone_notify(dns_zone_t *zone, isc_time_t *now);
|
|||
static void
|
||||
dump_done(void *arg, isc_result_t result);
|
||||
static isc_result_t
|
||||
zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, uint16_t keyid,
|
||||
zone_signwithkey(dns_zone_t *zone, dst_algorithm_t algorithm, uint16_t keyid,
|
||||
bool deleteit);
|
||||
static isc_result_t
|
||||
delete_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
|
||||
|
|
@ -3755,6 +3755,9 @@ cleanup:
|
|||
}
|
||||
}
|
||||
|
||||
#define OLD_SIGNING_RECORD_SIZE 5
|
||||
#define SIGNING_RECORD_SIZE 7
|
||||
|
||||
static void
|
||||
resume_signingwithkey(dns_zone_t *zone) {
|
||||
dns_dbnode_t *node = NULL;
|
||||
|
|
@ -3788,14 +3791,22 @@ resume_signingwithkey(dns_zone_t *zone) {
|
|||
|
||||
DNS_RDATASET_FOREACH (&rdataset) {
|
||||
dns_rdata_t rdata = DNS_RDATA_INIT;
|
||||
dst_algorithm_t alg;
|
||||
|
||||
dns_rdataset_current(&rdataset, &rdata);
|
||||
if (rdata.length != 5 || rdata.data[0] == 0 ||
|
||||
rdata.data[4] != 0)
|
||||
/*
|
||||
* Old or New Forms
|
||||
*/
|
||||
if ((rdata.length != OLD_SIGNING_RECORD_SIZE &&
|
||||
rdata.length != SIGNING_RECORD_SIZE) ||
|
||||
rdata.data[0] == 0 || rdata.data[4] != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
result = zone_signwithkey(zone, rdata.data[0],
|
||||
alg = (rdata.length == OLD_SIGNING_RECORD_SIZE)
|
||||
? rdata.data[0]
|
||||
: ((rdata.data[5] << 8) | rdata.data[6]);
|
||||
result = zone_signwithkey(zone, alg,
|
||||
(rdata.data[1] << 8) | rdata.data[2],
|
||||
rdata.data[3]);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
|
|
@ -4422,7 +4433,7 @@ trust_key(dns_zone_t *zone, dns_name_t *keyname, dns_rdata_dnskey_t *dnskey,
|
|||
bool initial) {
|
||||
isc_result_t result;
|
||||
dns_rdata_t rdata = DNS_RDATA_INIT;
|
||||
unsigned char data[4096], digest[ISC_MAX_MD_SIZE];
|
||||
unsigned char data[4096], digest[DNS_DS_BUFFERSIZE];
|
||||
isc_buffer_t buffer;
|
||||
dns_keytable_t *sr = NULL;
|
||||
dns_rdata_ds_t ds;
|
||||
|
|
@ -4437,7 +4448,7 @@ trust_key(dns_zone_t *zone, dns_name_t *keyname, dns_rdata_dnskey_t *dnskey,
|
|||
dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
|
||||
dns_rdatatype_dnskey, dnskey, &buffer);
|
||||
CHECK(dns_ds_fromkeyrdata(keyname, &rdata, DNS_DSDIGEST_SHA256, digest,
|
||||
&ds));
|
||||
sizeof(digest), &ds));
|
||||
CHECK(dns_keytable_add(sr, true, initial, keyname, &ds, sfd_add,
|
||||
zone->view));
|
||||
|
||||
|
|
@ -6806,6 +6817,10 @@ delsig_ok(dns_rdata_rrsig_t *rrsig_ptr, dst_key_t **keys, unsigned int nkeys,
|
|||
isc_result_t ret;
|
||||
bool have_ksk = false, have_zsk = false;
|
||||
bool have_pksk = false, have_pzsk = false;
|
||||
dst_algorithm_t algorithm;
|
||||
|
||||
algorithm = dst_algorithm_fromdata(
|
||||
rrsig_ptr->algorithm, rrsig_ptr->signature, rrsig_ptr->siglen);
|
||||
|
||||
for (i = 0; i < nkeys; i++) {
|
||||
bool ksk, zsk;
|
||||
|
|
@ -6814,7 +6829,7 @@ delsig_ok(dns_rdata_rrsig_t *rrsig_ptr, dst_key_t **keys, unsigned int nkeys,
|
|||
break;
|
||||
}
|
||||
|
||||
if (rrsig_ptr->algorithm != dst_key_alg(keys[i])) {
|
||||
if (algorithm != dst_key_alg(keys[i])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -6873,7 +6888,7 @@ delsig_ok(dns_rdata_rrsig_t *rrsig_ptr, dst_key_t **keys, unsigned int nkeys,
|
|||
* if the associated public key is still in the DNSKEY RRset
|
||||
*/
|
||||
for (i = 0; i < nkeys; i++) {
|
||||
if ((rrsig_ptr->algorithm == dst_key_alg(keys[i])) &&
|
||||
if ((algorithm == dst_key_alg(keys[i])) &&
|
||||
(rrsig_ptr->keyid == dst_key_id(keys[i])))
|
||||
{
|
||||
return false;
|
||||
|
|
@ -6936,10 +6951,13 @@ del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
|
|||
|
||||
DNS_RDATASET_FOREACH (&rdataset) {
|
||||
dns_rdata_t rdata = DNS_RDATA_INIT;
|
||||
dst_algorithm_t algorithm;
|
||||
|
||||
dns_rdataset_current(&rdataset, &rdata);
|
||||
result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
algorithm = dst_algorithm_fromdata(
|
||||
rrsig.algorithm, rrsig.signature, rrsig.siglen);
|
||||
|
||||
if (!dns_rdatatype_iskeymaterial(type)) {
|
||||
bool warn = false, deleted = false;
|
||||
|
|
@ -6983,9 +7001,8 @@ del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
|
|||
char algbuf[DNS_NAME_FORMATSIZE];
|
||||
dns_name_format(&zone->origin, origin,
|
||||
sizeof(origin));
|
||||
dns_secalg_format(rrsig.algorithm,
|
||||
algbuf,
|
||||
sizeof(algbuf));
|
||||
dst_algorithm_format(algorithm, algbuf,
|
||||
sizeof(algbuf));
|
||||
dns_zone_log(zone, ISC_LOG_WARNING,
|
||||
"Key %s/%s/%d "
|
||||
"missing or inactive "
|
||||
|
|
@ -7005,7 +7022,7 @@ del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
|
|||
*/
|
||||
found = false;
|
||||
for (i = 0; i < nkeys; i++) {
|
||||
if (rrsig.algorithm == dst_key_alg(keys[i]) &&
|
||||
if (algorithm == dst_key_alg(keys[i]) &&
|
||||
rrsig.keyid == dst_key_id(keys[i]))
|
||||
{
|
||||
found = true;
|
||||
|
|
@ -7618,13 +7635,16 @@ signed_with_good_key(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
|
|||
dns_rdataset_current(&rdataset, &rdata);
|
||||
result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
if (rrsig.algorithm == dst_key_alg(key) &&
|
||||
dst_algorithm_t algorithm;
|
||||
algorithm = dst_algorithm_fromdata(
|
||||
rrsig.algorithm, rrsig.signature, rrsig.siglen);
|
||||
if (algorithm == dst_key_alg(key) &&
|
||||
rrsig.keyid == dst_key_id(key))
|
||||
{
|
||||
dns_rdataset_disassociate(&rdataset);
|
||||
return true;
|
||||
}
|
||||
if (rrsig.algorithm == dst_key_alg(key)) {
|
||||
if (algorithm == dst_key_alg(key)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
|
@ -7958,18 +7978,25 @@ updatesignwithkey(dns_zone_t *zone, dns_signing_t *signing,
|
|||
INSIST(!dns_rdataset_isassociated(&rdataset));
|
||||
goto failure;
|
||||
}
|
||||
|
||||
DNS_RDATASET_FOREACH (&rdataset) {
|
||||
dns_rdata_t rdata = DNS_RDATA_INIT;
|
||||
unsigned char alg = dst_algorithm_tosecalg(signing->algorithm);
|
||||
|
||||
dns_rdataset_current(&rdataset, &rdata);
|
||||
/*
|
||||
* If we don't match the algorithm or keyid skip the record.
|
||||
*/
|
||||
if (rdata.length != 5 || rdata.data[0] != signing->algorithm ||
|
||||
if ((rdata.length != SIGNING_RECORD_SIZE &&
|
||||
rdata.length != OLD_SIGNING_RECORD_SIZE) ||
|
||||
rdata.data[0] == 0 || rdata.data[0] != alg ||
|
||||
rdata.data[1] != ((signing->keyid >> 8) & 0xff) ||
|
||||
rdata.data[2] != (signing->keyid & 0xff))
|
||||
rdata.data[2] != (signing->keyid & 0xff) ||
|
||||
(rdata.length == SIGNING_RECORD_SIZE &&
|
||||
(rdata.data[5] != (signing->algorithm >> 8 & 0xff) ||
|
||||
rdata.data[6] != (signing->algorithm & 0xff))))
|
||||
{
|
||||
have_rr = true;
|
||||
dns_rdata_reset(&rdata);
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
|
|
@ -7999,20 +8026,32 @@ updatesignwithkey(dns_zone_t *zone, dns_signing_t *signing,
|
|||
* finished signing the zone with this key. If it is already
|
||||
* there we don't need to add it a second time.
|
||||
*/
|
||||
unsigned char data[5] = {
|
||||
signing->algorithm,
|
||||
unsigned char data[SIGNING_RECORD_SIZE] = {
|
||||
dst_algorithm_tosecalg(signing->algorithm),
|
||||
(signing->keyid >> 8) & 0xff,
|
||||
signing->keyid & 0xff,
|
||||
0,
|
||||
1,
|
||||
(signing->algorithm >> 8) & 0xff,
|
||||
signing->algorithm & 0xff,
|
||||
};
|
||||
dns_rdata_t rdata = (dns_rdata_t){
|
||||
.length = sizeof(data),
|
||||
.length = signing->algorithm < 256
|
||||
? OLD_SIGNING_RECORD_SIZE
|
||||
: sizeof(data),
|
||||
.data = data,
|
||||
.type = zone->privatetype,
|
||||
.rdclass = dns_db_class(signing->db),
|
||||
.link = ISC_LINK_INITIALIZER,
|
||||
};
|
||||
/*
|
||||
* data[0] can't be 0 as that is used to signal that the
|
||||
* record is being used to for NSEC/NSEC3 chains generation.
|
||||
* Set it to 255 instead.
|
||||
*/
|
||||
if (data[0] == 0) {
|
||||
data[0] = 255;
|
||||
}
|
||||
CHECK(update_one_rr(signing->db, version, diff, DNS_DIFFOP_ADD,
|
||||
&zone->origin, rdataset.ttl, &rdata));
|
||||
} else if (!have_rr) {
|
||||
|
|
@ -9341,7 +9380,7 @@ failure:
|
|||
*/
|
||||
static isc_result_t
|
||||
del_sig(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
|
||||
dns_dbnode_t *node, unsigned int nkeys, dns_secalg_t algorithm,
|
||||
dns_dbnode_t *node, unsigned int nkeys, dst_algorithm_t algorithm,
|
||||
uint16_t keyid, bool *has_algp, dns_diff_t *diff) {
|
||||
dns_rdata_rrsig_t rrsig;
|
||||
dns_rdataset_t rdataset;
|
||||
|
|
@ -9382,12 +9421,17 @@ del_sig(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
|
|||
}
|
||||
DNS_RDATASET_FOREACH (&rdataset) {
|
||||
dns_rdata_t rdata = DNS_RDATA_INIT;
|
||||
dst_algorithm_t sigalg;
|
||||
|
||||
dns_rdataset_current(&rdataset, &rdata);
|
||||
CHECK(dns_rdata_tostruct(&rdata, &rrsig, NULL));
|
||||
if (nkeys != 0 && (rrsig.algorithm != algorithm ||
|
||||
rrsig.keyid != keyid))
|
||||
|
||||
sigalg = dst_algorithm_fromdata(
|
||||
rrsig.algorithm, rrsig.signature, rrsig.siglen);
|
||||
if (nkeys != 0 &&
|
||||
(sigalg != algorithm || rrsig.keyid != keyid))
|
||||
{
|
||||
if (rrsig.algorithm == algorithm) {
|
||||
if (sigalg == algorithm) {
|
||||
has_alg = true;
|
||||
}
|
||||
continue;
|
||||
|
|
@ -9752,7 +9796,7 @@ zone_sign(dns_zone_t *zone) {
|
|||
* When adding look for the specific key.
|
||||
*/
|
||||
if (!signing->deleteit &&
|
||||
(dst_key_alg(zone_keys[i]) != signing->algorithm ||
|
||||
(ALG(zone_keys[i]) != signing->algorithm ||
|
||||
dst_key_id(zone_keys[i]) != signing->keyid))
|
||||
{
|
||||
continue;
|
||||
|
|
@ -10288,6 +10332,7 @@ revocable(dns_keyfetch_t *kfetch, dns_rdata_keydata_t *keydata) {
|
|||
unsigned char key_buf[4096];
|
||||
isc_buffer_t keyb;
|
||||
bool answer = false;
|
||||
dst_algorithm_t algorithm;
|
||||
|
||||
REQUIRE(kfetch != NULL && keydata != NULL);
|
||||
REQUIRE(dns_rdataset_isassociated(&kfetch->dnskeysigset));
|
||||
|
|
@ -10315,7 +10360,9 @@ revocable(dns_keyfetch_t *kfetch, dns_rdata_keydata_t *keydata) {
|
|||
result = dns_rdata_tostruct(&sigrr, &sig, NULL);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
|
||||
if (dst_key_alg(dstkey) == sig.algorithm &&
|
||||
algorithm = dst_algorithm_fromdata(sig.algorithm, sig.signature,
|
||||
sig.siglen);
|
||||
if (dst_key_alg(dstkey) == algorithm &&
|
||||
dst_key_rid(dstkey) == sig.keyid)
|
||||
{
|
||||
result = dns_dnssec_verify(keyname, &kfetch->dnskeyset,
|
||||
|
|
@ -16440,7 +16487,8 @@ cds_inuse(dns_zone_t *zone, dns_rdata_t *rdata, dns_dnsseckeylist_t *keylist,
|
|||
unsigned char cdsbuf[DNS_DS_BUFFERSIZE];
|
||||
|
||||
if (dst_key_id(k->key) != cds.key_tag ||
|
||||
dst_key_alg(k->key) != cds.algorithm)
|
||||
dst_algorithm_tosecalg(dst_key_alg(k->key)) !=
|
||||
cds.algorithm)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
|
@ -16453,7 +16501,8 @@ cds_inuse(dns_zone_t *zone, dns_rdata_t *rdata, dns_dnsseckeylist_t *keylist,
|
|||
return result;
|
||||
}
|
||||
result = dns_ds_buildrdata(dns_zone_getorigin(zone), &dnskey,
|
||||
cds.digest_type, cdsbuf, &cdsrdata);
|
||||
cds.digest_type, cdsbuf,
|
||||
sizeof(cdsbuf), &cdsrdata);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
dns_zone_log(zone, ISC_LOG_ERROR,
|
||||
"dns_ds_buildrdata(keytag=%d, algo=%d, "
|
||||
|
|
@ -20093,8 +20142,8 @@ dns_zone_setnotifydelay(dns_zone_t *zone, uint32_t delay) {
|
|||
}
|
||||
|
||||
isc_result_t
|
||||
dns_zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, uint16_t keyid,
|
||||
bool deleteit) {
|
||||
dns_zone_signwithkey(dns_zone_t *zone, dst_algorithm_t algorithm,
|
||||
uint16_t keyid, bool deleteit) {
|
||||
isc_result_t result;
|
||||
REQUIRE(DNS_ZONE_VALID(zone));
|
||||
|
||||
|
|
@ -20178,7 +20227,7 @@ dns_zone_getprivatetype(dns_zone_t *zone) {
|
|||
}
|
||||
|
||||
static isc_result_t
|
||||
zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, uint16_t keyid,
|
||||
zone_signwithkey(dns_zone_t *zone, dst_algorithm_t algorithm, uint16_t keyid,
|
||||
bool deleteit) {
|
||||
dns_signing_t *signing = NULL;
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
|
|
@ -20335,7 +20384,7 @@ add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype,
|
|||
isc_region_t r;
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
uint16_t keyid;
|
||||
unsigned char buf[5];
|
||||
unsigned char data[SIGNING_RECORD_SIZE];
|
||||
dns_name_t *name = dns_db_origin(db);
|
||||
dns_difftuplelist_t add = ISC_LIST_INITIALIZER;
|
||||
dns_difftuplelist_t del = ISC_LIST_INITIALIZER;
|
||||
|
|
@ -20410,17 +20459,23 @@ add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype,
|
|||
* or added.
|
||||
*/
|
||||
ISC_LIST_FOREACH (tuples, tuple, link) {
|
||||
dst_algorithm_t algorithm;
|
||||
dns_rdata_toregion(&tuple->rdata, &r);
|
||||
|
||||
keyid = dst_region_computeid(&r);
|
||||
|
||||
buf[0] = dnskey.algorithm;
|
||||
buf[1] = (keyid & 0xff00) >> 8;
|
||||
buf[2] = (keyid & 0xff);
|
||||
buf[3] = (tuple->op == DNS_DIFFOP_ADD) ? 0 : 1;
|
||||
buf[4] = 0;
|
||||
rdata.data = buf;
|
||||
rdata.length = sizeof(buf);
|
||||
algorithm = dst_algorithm_fromdata(dnskey.algorithm,
|
||||
dnskey.data, dnskey.datalen);
|
||||
data[0] = dnskey.algorithm;
|
||||
data[1] = (keyid & 0xff00) >> 8;
|
||||
data[2] = (keyid & 0xff);
|
||||
data[3] = (tuple->op == DNS_DIFFOP_ADD) ? 0 : 1;
|
||||
data[4] = 0;
|
||||
data[5] = (algorithm & 0xff00) >> 8;
|
||||
data[6] = (algorithm & 0xff);
|
||||
rdata.data = data;
|
||||
rdata.length = algorithm < 256 ? OLD_SIGNING_RECORD_SIZE
|
||||
: sizeof(data);
|
||||
rdata.type = privatetype;
|
||||
rdata.rdclass = tuple->rdata.rdclass;
|
||||
|
||||
|
|
@ -20440,7 +20495,7 @@ add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype,
|
|||
* Remove any record which says this operation has already
|
||||
* completed.
|
||||
*/
|
||||
buf[4] = 1;
|
||||
data[4] = 1;
|
||||
CHECK(rr_exists(db, ver, name, &rdata, &flag));
|
||||
if (flag) {
|
||||
dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL, name,
|
||||
|
|
@ -20609,7 +20664,9 @@ failure:
|
|||
* are any signatures using that algorithm.
|
||||
*/
|
||||
static bool
|
||||
signed_with_alg(dns_rdataset_t *rdataset, dns_secalg_t alg) {
|
||||
signed_with_alg(dns_rdataset_t *rdataset, dst_algorithm_t alg) {
|
||||
dst_algorithm_t sigalg;
|
||||
|
||||
REQUIRE(rdataset == NULL || rdataset->type == dns_rdatatype_rrsig);
|
||||
if (rdataset == NULL || !dns_rdataset_isassociated(rdataset)) {
|
||||
return false;
|
||||
|
|
@ -20621,7 +20678,9 @@ signed_with_alg(dns_rdataset_t *rdataset, dns_secalg_t alg) {
|
|||
|
||||
dns_rdataset_current(rdataset, &rdata);
|
||||
dns_rdata_tostruct(&rdata, &rrsig, NULL);
|
||||
if (rrsig.algorithm == alg) {
|
||||
sigalg = dst_algorithm_fromdata(rrsig.algorithm,
|
||||
rrsig.signature, rrsig.siglen);
|
||||
if (sigalg == alg) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -20967,13 +21026,16 @@ checkds_done(void *arg) {
|
|||
if (dst_key_id(key->key) != ds.key_tag) {
|
||||
continue;
|
||||
}
|
||||
if (dst_key_alg(key->key) != ds.algorithm) {
|
||||
if (dst_algorithm_tosecalg(dst_key_alg(key->key)) !=
|
||||
ds.algorithm)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
/* Derive DS from DNSKEY, see if the rdata is equal. */
|
||||
make_dnskey(key->key, keybuf, sizeof(keybuf), &dnskey);
|
||||
r = dns_ds_buildrdata(&zone->origin, &dnskey,
|
||||
ds.digest_type, dsbuf, &dsrdata);
|
||||
ds.digest_type, dsbuf,
|
||||
sizeof(dsbuf), &dsrdata);
|
||||
if (r != ISC_R_SUCCESS) {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -22804,7 +22866,7 @@ dns_zone_cdscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version) {
|
|||
isc_result_t result;
|
||||
dns_dbnode_t *node = NULL;
|
||||
dns_rdataset_t dnskey, cds, cdnskey;
|
||||
unsigned char algorithms[256];
|
||||
unsigned char algorithms[DST_MAX_ALGS];
|
||||
unsigned int i;
|
||||
bool empty = false;
|
||||
|
||||
|
|
@ -22879,21 +22941,49 @@ dns_zone_cdscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version) {
|
|||
}
|
||||
|
||||
CHECK(dns_rdata_tostruct(&crdata, &structcds, NULL));
|
||||
if (algorithms[structcds.algorithm] == 0) {
|
||||
algorithms[structcds.algorithm] = expected;
|
||||
}
|
||||
DNS_RDATASET_FOREACH (&dnskey) {
|
||||
if (structcds.algorithm != DNS_KEYALG_PRIVATEDNS &&
|
||||
structcds.algorithm != DNS_KEYALG_PRIVATEOID)
|
||||
{
|
||||
if (algorithms[structcds.algorithm] == 0) {
|
||||
algorithms[structcds.algorithm] =
|
||||
expected;
|
||||
}
|
||||
DNS_RDATASET_FOREACH (&dnskey) {
|
||||
dns_rdata_t rdata = DNS_RDATA_INIT;
|
||||
dns_rdata_dnskey_t structdnskey;
|
||||
|
||||
dns_rdataset_current(&dnskey, &rdata);
|
||||
dns_rdata_tostruct(&rdata,
|
||||
&structdnskey, NULL);
|
||||
|
||||
if (structdnskey.algorithm ==
|
||||
structcds.algorithm)
|
||||
{
|
||||
algorithms[structcds.algorithm] =
|
||||
found;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
dns_rdata_t rdata = DNS_RDATA_INIT;
|
||||
dns_rdata_dnskey_t structdnskey;
|
||||
dst_algorithm_t dnskeyalg;
|
||||
|
||||
dns_rdataset_current(&dnskey, &rdata);
|
||||
dns_rdata_tostruct(&rdata, &structdnskey, NULL);
|
||||
|
||||
if (structdnskey.algorithm ==
|
||||
structcds.algorithm)
|
||||
{
|
||||
algorithms[structcds.algorithm] = found;
|
||||
/* Convert CDS to DS */
|
||||
crdata.type = dns_rdatatype_ds;
|
||||
result = dns_dnssec_matchdskey(&zone->origin,
|
||||
&crdata, &dnskey,
|
||||
&rdata);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
result = DNS_R_BADCDS;
|
||||
goto failure;
|
||||
}
|
||||
CHECK(dns_rdata_tostruct(&rdata, &structdnskey,
|
||||
NULL));
|
||||
dnskeyalg = dst_algorithm_fromdata(
|
||||
structdnskey.algorithm,
|
||||
structdnskey.data,
|
||||
structdnskey.datalen);
|
||||
algorithms[dnskeyalg] = found;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < sizeof(algorithms); i++) {
|
||||
|
|
@ -22920,6 +23010,7 @@ dns_zone_cdscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version) {
|
|||
DNS_RDATASET_FOREACH (&cdnskey) {
|
||||
dns_rdata_t crdata = DNS_RDATA_INIT;
|
||||
dns_rdata_cdnskey_t structcdnskey;
|
||||
dst_algorithm_t cdnskeyalg;
|
||||
|
||||
dns_rdataset_current(&cdnskey, &crdata);
|
||||
/*
|
||||
|
|
@ -22942,22 +23033,27 @@ dns_zone_cdscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version) {
|
|||
|
||||
CHECK(dns_rdata_tostruct(&crdata, &structcdnskey,
|
||||
NULL));
|
||||
if (algorithms[structcdnskey.algorithm] == 0) {
|
||||
algorithms[structcdnskey.algorithm] = expected;
|
||||
cdnskeyalg = dst_algorithm_fromdata(
|
||||
structcdnskey.algorithm, structcdnskey.data,
|
||||
structcdnskey.datalen);
|
||||
if (algorithms[cdnskeyalg] == 0) {
|
||||
algorithms[cdnskeyalg] = expected;
|
||||
}
|
||||
DNS_RDATASET_FOREACH (&dnskey) {
|
||||
dns_rdata_t rdata = DNS_RDATA_INIT;
|
||||
dns_rdata_dnskey_t structdnskey;
|
||||
dst_algorithm_t dnskeyalg;
|
||||
|
||||
dns_rdataset_current(&dnskey, &rdata);
|
||||
CHECK(dns_rdata_tostruct(&rdata, &structdnskey,
|
||||
NULL));
|
||||
dnskeyalg = dst_algorithm_fromdata(
|
||||
structdnskey.algorithm,
|
||||
structdnskey.data,
|
||||
structdnskey.datalen);
|
||||
|
||||
if (structdnskey.algorithm ==
|
||||
structcdnskey.algorithm)
|
||||
{
|
||||
algorithms[structcdnskey.algorithm] =
|
||||
found;
|
||||
if (dnskeyalg == cdnskeyalg) {
|
||||
algorithms[cdnskeyalg] = found;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -23211,7 +23307,7 @@ dns_zone_issecure(dns_zone_t *zone) {
|
|||
|
||||
struct keydone {
|
||||
bool all;
|
||||
unsigned char data[5];
|
||||
unsigned char data[SIGNING_RECORD_SIZE];
|
||||
dns_zone_t *zone;
|
||||
};
|
||||
|
||||
|
|
@ -23279,8 +23375,11 @@ keydone(void *arg) {
|
|||
dns_rdataset_current(&rdataset, &rdata);
|
||||
|
||||
if (kd->all) {
|
||||
if (rdata.length == 5 && rdata.data[0] != 0 &&
|
||||
rdata.data[3] == 0 && rdata.data[4] == 1)
|
||||
/* Old (5) and new (7) forms */
|
||||
if ((rdata.length == OLD_SIGNING_RECORD_SIZE ||
|
||||
rdata.length == SIGNING_RECORD_SIZE) &&
|
||||
rdata.data[0] != 0 && rdata.data[3] == 0 &&
|
||||
rdata.data[4] == 1)
|
||||
{
|
||||
found = true;
|
||||
} else if (rdata.data[0] == 0 &&
|
||||
|
|
@ -23289,8 +23388,14 @@ keydone(void *arg) {
|
|||
found = true;
|
||||
clear_pending = true;
|
||||
}
|
||||
} else if (rdata.length == 5 &&
|
||||
memcmp(rdata.data, kd->data, 5) == 0)
|
||||
} else if (rdata.length == OLD_SIGNING_RECORD_SIZE &&
|
||||
memcmp(rdata.data, kd->data,
|
||||
OLD_SIGNING_RECORD_SIZE) == 0)
|
||||
{
|
||||
found = true;
|
||||
} else if (rdata.length == SIGNING_RECORD_SIZE &&
|
||||
memcmp(rdata.data, kd->data, SIGNING_RECORD_SIZE) ==
|
||||
0)
|
||||
{
|
||||
found = true;
|
||||
}
|
||||
|
|
@ -23367,7 +23472,7 @@ dns_zone_keydone(dns_zone_t *zone, const char *keystr) {
|
|||
isc_textregion_t r;
|
||||
const char *algstr = NULL;
|
||||
dns_keytag_t keyid;
|
||||
dns_secalg_t alg;
|
||||
dst_algorithm_t alg;
|
||||
size_t n;
|
||||
|
||||
n = sscanf(keystr, "%hu/", &keyid);
|
||||
|
|
@ -23382,20 +23487,20 @@ dns_zone_keydone(dns_zone_t *zone, const char *keystr) {
|
|||
CHECK(ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
n = sscanf(algstr, "%hhu", &alg);
|
||||
n = sscanf(algstr, "%u", &alg);
|
||||
if (n == 0U) {
|
||||
r.base = UNCONST(algstr);
|
||||
r.length = strlen(algstr);
|
||||
CHECK(dns_secalg_fromtext(&alg, &r));
|
||||
CHECK(dst_algorithm_fromtext(&alg, &r));
|
||||
}
|
||||
|
||||
/* construct a private-type rdata */
|
||||
isc_buffer_init(&b, kd->data, sizeof(kd->data));
|
||||
isc_buffer_putuint8(&b, alg);
|
||||
isc_buffer_putuint8(&b, (keyid & 0xff00) >> 8);
|
||||
isc_buffer_putuint8(&b, (keyid & 0xff));
|
||||
isc_buffer_putuint8(&b, dst_algorithm_tosecalg(alg));
|
||||
isc_buffer_putuint16(&b, keyid);
|
||||
isc_buffer_putuint8(&b, 0);
|
||||
isc_buffer_putuint8(&b, 1);
|
||||
isc_buffer_putuint16(&b, alg);
|
||||
}
|
||||
|
||||
zone_iattach(zone, &kd->zone);
|
||||
|
|
|
|||
|
|
@ -68,14 +68,14 @@ typedef struct vctx {
|
|||
dns_rdataset_t nsecsigs;
|
||||
dns_rdataset_t nsec3paramset;
|
||||
dns_rdataset_t nsec3paramsigs;
|
||||
unsigned char revoked_ksk[256];
|
||||
unsigned char revoked_zsk[256];
|
||||
unsigned char standby_ksk[256];
|
||||
unsigned char standby_zsk[256];
|
||||
unsigned char ksk_algorithms[256];
|
||||
unsigned char zsk_algorithms[256];
|
||||
unsigned char bad_algorithms[256];
|
||||
unsigned char act_algorithms[256];
|
||||
unsigned char revoked_ksk[DST_MAX_ALGS];
|
||||
unsigned char revoked_zsk[DST_MAX_ALGS];
|
||||
unsigned char standby_ksk[DST_MAX_ALGS];
|
||||
unsigned char standby_zsk[DST_MAX_ALGS];
|
||||
unsigned char ksk_algorithms[DST_MAX_ALGS];
|
||||
unsigned char zsk_algorithms[DST_MAX_ALGS];
|
||||
unsigned char bad_algorithms[DST_MAX_ALGS];
|
||||
unsigned char act_algorithms[DST_MAX_ALGS];
|
||||
isc_heap_t *expected_chains;
|
||||
isc_heap_t *found_chains;
|
||||
} vctx_t;
|
||||
|
|
@ -173,12 +173,16 @@ goodsig(const vctx_t *vctx, dns_rdata_t *sigrdata, const dns_name_t *name,
|
|||
dst_key_t **dstkeys, size_t nkeys, dns_rdataset_t *rdataset) {
|
||||
dns_rdata_rrsig_t sig;
|
||||
isc_result_t result;
|
||||
dst_algorithm_t algorithm;
|
||||
|
||||
result = dns_rdata_tostruct(sigrdata, &sig, NULL);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
|
||||
algorithm = dst_algorithm_fromdata(sig.algorithm, sig.signature,
|
||||
sig.siglen);
|
||||
|
||||
for (size_t key = 0; key < nkeys; key++) {
|
||||
if (sig.algorithm != dst_key_alg(dstkeys[key]) ||
|
||||
if (algorithm != dst_key_alg(dstkeys[key]) ||
|
||||
sig.keyid != dst_key_id(dstkeys[key]) ||
|
||||
!dns_name_equal(&sig.signer, vctx->origin))
|
||||
{
|
||||
|
|
@ -792,7 +796,7 @@ verifynsec3s(const vctx_t *vctx, const dns_name_t *name,
|
|||
static isc_result_t
|
||||
verifyset(vctx_t *vctx, dns_rdataset_t *rdataset, const dns_name_t *name,
|
||||
dns_dbnode_t *node, dst_key_t **dstkeys, size_t nkeys) {
|
||||
unsigned char set_algorithms[256] = { 0 };
|
||||
unsigned char set_algorithms[DST_MAX_ALGS] = { 0 };
|
||||
char namebuf[DNS_NAME_FORMATSIZE];
|
||||
char algbuf[DNS_SECALG_FORMATSIZE];
|
||||
char typebuf[DNS_RDATATYPE_FORMATSIZE];
|
||||
|
|
@ -835,6 +839,7 @@ verifyset(vctx_t *vctx, dns_rdataset_t *rdataset, const dns_name_t *name,
|
|||
DNS_RDATASET_FOREACH (&sigrdataset) {
|
||||
dns_rdata_t rdata = DNS_RDATA_INIT;
|
||||
dns_rdata_rrsig_t sig;
|
||||
dst_algorithm_t algorithm;
|
||||
|
||||
dns_rdataset_current(&sigrdataset, &rdata);
|
||||
result = dns_rdata_tostruct(&rdata, &sig, NULL);
|
||||
|
|
@ -849,15 +854,17 @@ verifyset(vctx_t *vctx, dns_rdataset_t *rdataset, const dns_name_t *name,
|
|||
namebuf, typebuf, sig.keyid);
|
||||
continue;
|
||||
}
|
||||
if ((set_algorithms[sig.algorithm] != 0) ||
|
||||
(vctx->act_algorithms[sig.algorithm] == 0))
|
||||
algorithm = dst_algorithm_fromdata(sig.algorithm, sig.signature,
|
||||
sig.siglen);
|
||||
if ((set_algorithms[algorithm] != 0) ||
|
||||
(vctx->act_algorithms[algorithm] == 0))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (goodsig(vctx, &rdata, name, dstkeys, nkeys, rdataset)) {
|
||||
dns_rdataset_settrust(rdataset, dns_trust_secure);
|
||||
dns_rdataset_settrust(&sigrdataset, dns_trust_secure);
|
||||
set_algorithms[sig.algorithm] = 1;
|
||||
set_algorithms[algorithm] = 1;
|
||||
}
|
||||
}
|
||||
result = ISC_R_SUCCESS;
|
||||
|
|
@ -871,7 +878,7 @@ verifyset(vctx_t *vctx, dns_rdataset_t *rdataset, const dns_name_t *name,
|
|||
if ((vctx->act_algorithms[i] != 0) &&
|
||||
(set_algorithms[i] == 0))
|
||||
{
|
||||
dns_secalg_format(i, algbuf, sizeof(algbuf));
|
||||
dst_algorithm_format(i, algbuf, sizeof(algbuf));
|
||||
zoneverify_log_error(vctx,
|
||||
"No correct %s signature "
|
||||
"for %s %s",
|
||||
|
|
@ -1425,10 +1432,13 @@ check_dnskey_sigs(vctx_t *vctx, const dns_rdata_dnskey_t *dnskey,
|
|||
dst_key_t *key = NULL;
|
||||
isc_result_t result;
|
||||
dns_rdataset_t dsset;
|
||||
dst_algorithm_t algorithm;
|
||||
|
||||
active_keys = (is_ksk ? vctx->ksk_algorithms : vctx->zsk_algorithms);
|
||||
standby_keys = (is_ksk ? vctx->standby_ksk : vctx->standby_zsk);
|
||||
goodkey = (is_ksk ? &vctx->goodksk : &vctx->goodzsk);
|
||||
algorithm = dst_algorithm_fromdata(dnskey->algorithm, dnskey->data,
|
||||
dnskey->datalen);
|
||||
|
||||
/*
|
||||
* First, does this key sign the DNSKEY rrset?
|
||||
|
|
@ -1440,19 +1450,19 @@ check_dnskey_sigs(vctx_t *vctx, const dns_rdata_dnskey_t *dnskey,
|
|||
dns_dnssec_signs(keyrdata, vctx->origin, &vctx->soaset,
|
||||
&vctx->soasigs, false, vctx->mctx))
|
||||
{
|
||||
if (active_keys[dnskey->algorithm] != DNS_KEYALG_MAX) {
|
||||
active_keys[dnskey->algorithm]++;
|
||||
if (active_keys[algorithm] != DNS_KEYALG_MAX) {
|
||||
active_keys[algorithm]++;
|
||||
}
|
||||
} else {
|
||||
if (standby_keys[dnskey->algorithm] != DNS_KEYALG_MAX) {
|
||||
standby_keys[dnskey->algorithm]++;
|
||||
if (standby_keys[algorithm] != DNS_KEYALG_MAX) {
|
||||
standby_keys[algorithm]++;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (active_keys[dnskey->algorithm] != DNS_KEYALG_MAX) {
|
||||
active_keys[dnskey->algorithm]++;
|
||||
if (active_keys[algorithm] != DNS_KEYALG_MAX) {
|
||||
active_keys[algorithm]++;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1503,14 +1513,15 @@ check_dnskey_sigs(vctx_t *vctx, const dns_rdata_dnskey_t *dnskey,
|
|||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
|
||||
if (ds.key_tag != dst_key_id(key) ||
|
||||
ds.algorithm != dst_key_alg(key))
|
||||
ds.algorithm !=
|
||||
dst_algorithm_tosecalg(dst_key_alg(key)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
result = dns_ds_buildrdata(vctx->origin, keyrdata,
|
||||
ds.digest_type, buf,
|
||||
&newdsrdata);
|
||||
sizeof(buf), &newdsrdata);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -1558,6 +1569,7 @@ check_dnskey(vctx_t *vctx) {
|
|||
if ((dnskey.flags & DNS_KEYOWNER_ZONE) != 0 &&
|
||||
(dnskey.flags & DNS_KEYFLAG_REVOKE) != 0)
|
||||
{
|
||||
dst_algorithm_t algorithm;
|
||||
if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0 &&
|
||||
!dns_dnssec_selfsigns(&rdata, vctx->origin,
|
||||
&vctx->keyset, &vctx->keysigs,
|
||||
|
|
@ -1586,16 +1598,17 @@ check_dnskey(vctx_t *vctx) {
|
|||
buffer);
|
||||
return ISC_R_FAILURE;
|
||||
}
|
||||
algorithm = dst_algorithm_fromdata(
|
||||
dnskey.algorithm, dnskey.data, dnskey.datalen);
|
||||
if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0 &&
|
||||
vctx->revoked_ksk[dnskey.algorithm] !=
|
||||
DNS_KEYALG_MAX)
|
||||
vctx->revoked_ksk[algorithm] != DNS_KEYALG_MAX)
|
||||
{
|
||||
vctx->revoked_ksk[dnskey.algorithm]++;
|
||||
vctx->revoked_ksk[algorithm]++;
|
||||
} else if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0 &&
|
||||
vctx->revoked_zsk[dnskey.algorithm] !=
|
||||
vctx->revoked_zsk[algorithm] !=
|
||||
DNS_KEYALG_MAX)
|
||||
{
|
||||
vctx->revoked_zsk[dnskey.algorithm]++;
|
||||
vctx->revoked_zsk[algorithm]++;
|
||||
}
|
||||
} else {
|
||||
check_dnskey_sigs(vctx, &dnskey, &rdata, is_ksk);
|
||||
|
|
@ -1627,7 +1640,7 @@ determine_active_algorithms(vctx_t *vctx, bool ignore_kskflag,
|
|||
: 0;
|
||||
}
|
||||
if (vctx->act_algorithms[i] != 0) {
|
||||
dns_secalg_format(i, algbuf, sizeof(algbuf));
|
||||
dst_algorithm_format(i, algbuf, sizeof(algbuf));
|
||||
report("- %s", algbuf);
|
||||
}
|
||||
}
|
||||
|
|
@ -1646,7 +1659,7 @@ determine_active_algorithms(vctx_t *vctx, bool ignore_kskflag,
|
|||
{
|
||||
continue;
|
||||
}
|
||||
dns_secalg_format(i, algbuf, sizeof(algbuf));
|
||||
dst_algorithm_format(i, algbuf, sizeof(algbuf));
|
||||
zoneverify_log_error(vctx, "Missing %s for algorithm %s",
|
||||
(vctx->ksk_algorithms[i] != 0) ? "ZSK"
|
||||
: "self-"
|
||||
|
|
@ -1889,7 +1902,7 @@ check_bad_algorithms(const vctx_t *vctx, void (*report)(const char *, ...)) {
|
|||
report("The zone is not fully signed "
|
||||
"for the following algorithms:");
|
||||
}
|
||||
dns_secalg_format(i, algbuf, sizeof(algbuf));
|
||||
dst_algorithm_format(i, algbuf, sizeof(algbuf));
|
||||
report(" %s", algbuf);
|
||||
first = false;
|
||||
}
|
||||
|
|
@ -1916,7 +1929,7 @@ print_summary(const vctx_t *vctx, bool keyset_kskonly,
|
|||
{
|
||||
continue;
|
||||
}
|
||||
dns_secalg_format(i, algbuf, sizeof(algbuf));
|
||||
dst_algorithm_format(i, algbuf, sizeof(algbuf));
|
||||
report("Algorithm: %s: KSKs: "
|
||||
"%u active, %u stand-by, %u revoked",
|
||||
algbuf, vctx->ksk_algorithms[i], vctx->standby_ksk[i],
|
||||
|
|
|
|||
|
|
@ -365,12 +365,12 @@ disabled_algorithms(const cfg_obj_t *disabled) {
|
|||
|
||||
CFG_LIST_FOREACH (obj, element) {
|
||||
isc_textregion_t r;
|
||||
dns_secalg_t alg;
|
||||
dst_algorithm_t alg;
|
||||
|
||||
r.base = UNCONST(cfg_obj_asstring(cfg_listelt_value(element)));
|
||||
r.length = strlen(r.base);
|
||||
|
||||
tresult = dns_secalg_fromtext(&alg, &r);
|
||||
tresult = dst_algorithm_fromtext(&alg, &r);
|
||||
if (tresult != ISC_R_SUCCESS) {
|
||||
cfg_obj_log(cfg_listelt_value(element), ISC_LOG_ERROR,
|
||||
"invalid algorithm '%s'", r.base);
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@
|
|||
#include <dns/secalg.h>
|
||||
#include <dns/ttl.h>
|
||||
|
||||
#include <dst/dst.h>
|
||||
|
||||
#include <isccfg/cfg.h>
|
||||
#include <isccfg/duration.h>
|
||||
#include <isccfg/kaspconf.h>
|
||||
|
|
@ -127,7 +129,7 @@ cfg_kaspkey_fromconfig(const cfg_obj_t *config, dns_kasp_t *kasp,
|
|||
INSIST(!offline_ksk);
|
||||
key->role |= DNS_KASP_KEY_ROLE_KSK | DNS_KASP_KEY_ROLE_ZSK;
|
||||
key->lifetime = 0; /* unlimited */
|
||||
key->algorithm = DNS_KEYALG_ECDSA256;
|
||||
key->algorithm = DST_ALG_ECDSA256;
|
||||
key->length = -1;
|
||||
result = dns_keystorelist_find(keystorelist,
|
||||
DNS_KEYSTORE_KEYDIRECTORY,
|
||||
|
|
@ -217,8 +219,8 @@ cfg_kaspkey_fromconfig(const cfg_obj_t *config, dns_kasp_t *kasp,
|
|||
obj = cfg_tuple_get(config, "algorithm");
|
||||
alg.base = cfg_obj_asstring(obj);
|
||||
alg.length = strlen(alg.base);
|
||||
result = dns_secalg_fromtext(&key->algorithm,
|
||||
(isc_textregion_t *)&alg);
|
||||
result = dst_algorithm_fromtext(&key->algorithm,
|
||||
(isc_textregion_t *)&alg);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
cfg_obj_log(obj, ISC_LOG_ERROR,
|
||||
"dnssec-policy: bad algorithm %s",
|
||||
|
|
@ -226,10 +228,9 @@ cfg_kaspkey_fromconfig(const cfg_obj_t *config, dns_kasp_t *kasp,
|
|||
result = DNS_R_BADALG;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (check_algorithms && isc_crypto_fips_mode() &&
|
||||
(key->algorithm == DNS_KEYALG_RSASHA1 ||
|
||||
key->algorithm == DNS_KEYALG_NSEC3RSASHA1))
|
||||
(key->algorithm == DST_ALG_RSASHA1 ||
|
||||
key->algorithm == DST_ALG_NSEC3RSASHA1))
|
||||
{
|
||||
cfg_obj_log(obj, ISC_LOG_ERROR,
|
||||
"dnssec-policy: algorithm %s not supported "
|
||||
|
|
@ -255,14 +256,16 @@ cfg_kaspkey_fromconfig(const cfg_obj_t *config, dns_kasp_t *kasp,
|
|||
size = cfg_obj_asuint32(obj);
|
||||
|
||||
switch (key->algorithm) {
|
||||
case DNS_KEYALG_RSASHA1:
|
||||
case DNS_KEYALG_NSEC3RSASHA1:
|
||||
case DNS_KEYALG_RSASHA256:
|
||||
case DNS_KEYALG_RSASHA512:
|
||||
case DST_ALG_RSASHA1:
|
||||
case DST_ALG_NSEC3RSASHA1:
|
||||
case DST_ALG_RSASHA256:
|
||||
case DST_ALG_RSASHA512:
|
||||
case DST_ALG_RSASHA256PRIVATEOID:
|
||||
case DST_ALG_RSASHA512PRIVATEOID:
|
||||
if (isc_crypto_fips_mode()) {
|
||||
min = 2048;
|
||||
} else {
|
||||
min = DNS_KEYALG_RSASHA512 ? 1024 : 512;
|
||||
min = DST_ALG_RSASHA512 ? 1024 : 512;
|
||||
}
|
||||
if (size < min || size > 4096) {
|
||||
cfg_obj_log(obj, ISC_LOG_ERROR,
|
||||
|
|
@ -274,10 +277,10 @@ cfg_kaspkey_fromconfig(const cfg_obj_t *config, dns_kasp_t *kasp,
|
|||
goto cleanup;
|
||||
}
|
||||
break;
|
||||
case DNS_KEYALG_ECDSA256:
|
||||
case DNS_KEYALG_ECDSA384:
|
||||
case DNS_KEYALG_ED25519:
|
||||
case DNS_KEYALG_ED448:
|
||||
case DST_ALG_ECDSA256:
|
||||
case DST_ALG_ECDSA384:
|
||||
case DST_ALG_ED25519:
|
||||
case DST_ALG_ED448:
|
||||
cfg_obj_log(obj, ISC_LOG_WARNING,
|
||||
"dnssec-policy: key algorithm %s "
|
||||
"has predefined length; ignoring "
|
||||
|
|
@ -356,8 +359,8 @@ cfg_nsec3param_fromconfig(const cfg_obj_t *config, dns_kasp_t *kasp) {
|
|||
}
|
||||
|
||||
/* NSEC3 cannot be used with certain key algorithms. */
|
||||
if (keyalg == DNS_KEYALG_RSAMD5 || keyalg == DNS_KEYALG_DSA ||
|
||||
keyalg == DNS_KEYALG_RSASHA1)
|
||||
if (keyalg == DST_ALG_RSAMD5 || keyalg == DST_ALG_DSA ||
|
||||
keyalg == DST_ALG_RSASHA1)
|
||||
{
|
||||
badalg = keyalg;
|
||||
}
|
||||
|
|
@ -624,8 +627,8 @@ cfg_kasp_fromconfig(const cfg_obj_t *config, dns_kasp_t *default_kasp,
|
|||
|
||||
(void)confget(maps, "keys", &keys);
|
||||
if (keys != NULL) {
|
||||
char role[256] = { 0 };
|
||||
bool warn[256][2] = { { false } };
|
||||
char role[DST_MAX_ALGS] = { 0 };
|
||||
bool warn[DST_MAX_ALGS][2] = { { false } };
|
||||
|
||||
CFG_LIST_FOREACH (keys, element) {
|
||||
cfg_obj_t *kobj = cfg_listelt_value(element);
|
||||
|
|
|
|||
|
|
@ -2375,6 +2375,7 @@ get_key(ns_client_t *client, dns_db_t *db, dns_rdata_rrsig_t *rrsig,
|
|||
bool secure = false;
|
||||
dns_clientinfomethods_t cm;
|
||||
dns_clientinfo_t ci;
|
||||
dst_algorithm_t sigalg, keyalg;
|
||||
|
||||
dns_clientinfomethods_init(&cm, ns_client_sourceip);
|
||||
dns_clientinfo_init(&ci, client, NULL);
|
||||
|
|
@ -2403,6 +2404,9 @@ get_key(ns_client_t *client, dns_db_t *db, dns_rdata_rrsig_t *rrsig,
|
|||
result = dns_rdataset_next(keyrdataset);
|
||||
}
|
||||
|
||||
sigalg = dst_algorithm_fromdata(rrsig->algorithm, rrsig->signature,
|
||||
rrsig->siglen);
|
||||
|
||||
for (; result == ISC_R_SUCCESS; result = dns_rdataset_next(keyrdataset))
|
||||
{
|
||||
dns_rdata_t rdata = DNS_RDATA_INIT;
|
||||
|
|
@ -2411,10 +2415,10 @@ get_key(ns_client_t *client, dns_db_t *db, dns_rdata_rrsig_t *rrsig,
|
|||
|
||||
dns_rdataset_current(keyrdataset, &rdata);
|
||||
dns_rdata_tostruct(&rdata, &key, NULL); /* can't fail */
|
||||
keyalg = dst_algorithm_fromdata(key.algorithm, key.data,
|
||||
key.datalen);
|
||||
|
||||
if (rrsig->algorithm != key.algorithm ||
|
||||
!dns_dnssec_iszonekey(&key))
|
||||
{
|
||||
if (sigalg != keyalg || !dns_dnssec_iszonekey(&key)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -2476,14 +2480,18 @@ validate(ns_client_t *client, dns_db_t *db, dns_name_t *name,
|
|||
dns_rdataset_current(sigrdataset, &rdata);
|
||||
result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
if (!dns_resolver_algorithm_supported(client->view->resolver,
|
||||
name, rrsig.algorithm))
|
||||
if (!dns_resolver_algorithm_supported(
|
||||
client->view->resolver, name, rrsig.algorithm,
|
||||
rrsig.signature, rrsig.siglen))
|
||||
{
|
||||
char txt[DNS_NAME_FORMATSIZE + 32];
|
||||
isc_buffer_t buffer;
|
||||
dst_algorithm_t alg;
|
||||
alg = dst_algorithm_fromdata(
|
||||
rrsig.algorithm, rrsig.signature, rrsig.siglen);
|
||||
|
||||
isc_buffer_init(&buffer, txt, sizeof(txt));
|
||||
dns_secalg_totext(rrsig.algorithm, &buffer);
|
||||
dst_algorithm_totext(alg, &buffer);
|
||||
isc_buffer_putstr(&buffer, " ");
|
||||
dns_name_totext(name, DNS_NAME_OMITFINALDOT, &buffer);
|
||||
isc_buffer_putstr(&buffer, " (cached)");
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ create_keystruct(uint16_t flags, uint8_t proto, uint8_t alg, const char *keystr,
|
|||
|
||||
static void
|
||||
create_dsstruct(dns_name_t *name, uint16_t flags, uint8_t proto, uint8_t alg,
|
||||
const char *keystr, unsigned char *digest,
|
||||
const char *keystr, unsigned char *digest, size_t digest_len,
|
||||
dns_rdata_ds_t *dsstruct) {
|
||||
isc_result_t result;
|
||||
unsigned char rrdata[4096];
|
||||
|
|
@ -156,7 +156,7 @@ create_dsstruct(dns_name_t *name, uint16_t flags, uint8_t proto, uint8_t alg,
|
|||
* Build DS rdata struct.
|
||||
*/
|
||||
result = dns_ds_fromkeyrdata(name, &rdata, DNS_DSDIGEST_SHA256, digest,
|
||||
dsstruct);
|
||||
digest_len, dsstruct);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
dns_rdata_freestruct(&dnskey);
|
||||
|
|
@ -165,7 +165,7 @@ create_dsstruct(dns_name_t *name, uint16_t flags, uint8_t proto, uint8_t alg,
|
|||
/* Common setup: create a keytable and ntatable to test with a few keys */
|
||||
static void
|
||||
create_tables(void) {
|
||||
unsigned char digest[ISC_MAX_MD_SIZE];
|
||||
unsigned char digest[DNS_DS_BUFFERSIZE];
|
||||
dns_rdata_ds_t ds;
|
||||
dns_fixedname_t fn;
|
||||
dns_name_t *keyname = dns_fixedname_name(&fn);
|
||||
|
|
@ -179,14 +179,16 @@ create_tables(void) {
|
|||
|
||||
/* Add a normal key */
|
||||
dns_test_namefromstring("example.com.", &fn);
|
||||
create_dsstruct(keyname, 257, 3, 5, keystr1, digest, &ds);
|
||||
create_dsstruct(keyname, 257, 3, 5, keystr1, digest, sizeof(digest),
|
||||
&ds);
|
||||
assert_int_equal(dns_keytable_add(keytable, false, false, keyname, &ds,
|
||||
NULL, NULL),
|
||||
ISC_R_SUCCESS);
|
||||
|
||||
/* Add an initializing managed key */
|
||||
dns_test_namefromstring("managed.com.", &fn);
|
||||
create_dsstruct(keyname, 257, 3, 5, keystr1, digest, &ds);
|
||||
create_dsstruct(keyname, 257, 3, 5, keystr1, digest, sizeof(digest),
|
||||
&ds);
|
||||
assert_int_equal(dns_keytable_add(keytable, true, true, keyname, &ds,
|
||||
NULL, NULL),
|
||||
ISC_R_SUCCESS);
|
||||
|
|
@ -220,7 +222,7 @@ destroy_tables(void) {
|
|||
ISC_LOOP_TEST_IMPL(add) {
|
||||
dns_keynode_t *keynode = NULL;
|
||||
dns_keynode_t *null_keynode = NULL;
|
||||
unsigned char digest[ISC_MAX_MD_SIZE];
|
||||
unsigned char digest[DNS_DS_BUFFERSIZE];
|
||||
dns_rdata_ds_t ds;
|
||||
dns_fixedname_t fn;
|
||||
dns_name_t *keyname = dns_fixedname_name(&fn);
|
||||
|
|
@ -241,7 +243,8 @@ ISC_LOOP_TEST_IMPL(add) {
|
|||
* report success.
|
||||
*/
|
||||
dns_test_namefromstring("example.com.", &fn);
|
||||
create_dsstruct(keyname, 257, 3, 5, keystr1, digest, &ds);
|
||||
create_dsstruct(keyname, 257, 3, 5, keystr1, digest, sizeof(digest),
|
||||
&ds);
|
||||
assert_int_equal(dns_keytable_add(keytable, false, false, keyname, &ds,
|
||||
NULL, NULL),
|
||||
ISC_R_SUCCESS);
|
||||
|
|
@ -252,7 +255,8 @@ ISC_LOOP_TEST_IMPL(add) {
|
|||
|
||||
/* Add another key (different keydata) */
|
||||
dns_keynode_detach(&keynode);
|
||||
create_dsstruct(keyname, 257, 3, 5, keystr2, digest, &ds);
|
||||
create_dsstruct(keyname, 257, 3, 5, keystr2, digest, sizeof(digest),
|
||||
&ds);
|
||||
assert_int_equal(dns_keytable_add(keytable, false, false, keyname, &ds,
|
||||
NULL, NULL),
|
||||
ISC_R_SUCCESS);
|
||||
|
|
@ -280,7 +284,8 @@ ISC_LOOP_TEST_IMPL(add) {
|
|||
* node, the node should *not* be marked as initializing.
|
||||
*/
|
||||
dns_test_namefromstring("managed.com.", &fn);
|
||||
create_dsstruct(keyname, 257, 3, 5, keystr2, digest, &ds);
|
||||
create_dsstruct(keyname, 257, 3, 5, keystr2, digest, sizeof(digest),
|
||||
&ds);
|
||||
assert_int_equal(dns_keytable_add(keytable, true, true, keyname, &ds,
|
||||
NULL, NULL),
|
||||
ISC_R_SUCCESS);
|
||||
|
|
@ -310,7 +315,8 @@ ISC_LOOP_TEST_IMPL(add) {
|
|||
* initializing key.
|
||||
*/
|
||||
dns_test_namefromstring("two.com.", &fn);
|
||||
create_dsstruct(keyname, 257, 3, 5, keystr1, digest, &ds);
|
||||
create_dsstruct(keyname, 257, 3, 5, keystr1, digest, sizeof(digest),
|
||||
&ds);
|
||||
assert_int_equal(dns_keytable_add(keytable, true, true, keyname, &ds,
|
||||
NULL, NULL),
|
||||
ISC_R_SUCCESS);
|
||||
|
|
@ -326,7 +332,8 @@ ISC_LOOP_TEST_IMPL(add) {
|
|||
* trust anchor for two.com and we haven't run dns_keynode_trust(),
|
||||
* the initialization status should not change.
|
||||
*/
|
||||
create_dsstruct(keyname, 257, 3, 5, keystr2, digest, &ds);
|
||||
create_dsstruct(keyname, 257, 3, 5, keystr2, digest, sizeof(digest),
|
||||
&ds);
|
||||
assert_int_equal(dns_keytable_add(keytable, true, false, keyname, &ds,
|
||||
NULL, NULL),
|
||||
ISC_R_SUCCESS);
|
||||
|
|
@ -344,7 +351,8 @@ ISC_LOOP_TEST_IMPL(add) {
|
|||
&null_keynode),
|
||||
ISC_R_SUCCESS);
|
||||
dns_test_namefromstring("null.example.", &fn);
|
||||
create_dsstruct(keyname, 257, 3, 5, keystr2, digest, &ds);
|
||||
create_dsstruct(keyname, 257, 3, 5, keystr2, digest, sizeof(digest),
|
||||
&ds);
|
||||
assert_int_equal(dns_keytable_add(keytable, false, false, keyname, &ds,
|
||||
NULL, NULL),
|
||||
ISC_R_SUCCESS);
|
||||
|
|
@ -598,7 +606,7 @@ ISC_LOOP_TEST_IMPL(nta) {
|
|||
bool issecure, covered;
|
||||
dns_fixedname_t fn;
|
||||
dns_name_t *keyname = dns_fixedname_name(&fn);
|
||||
unsigned char digest[ISC_MAX_MD_SIZE];
|
||||
unsigned char digest[DNS_DS_BUFFERSIZE];
|
||||
dns_rdata_ds_t ds;
|
||||
dns_view_t *myview = NULL;
|
||||
isc_stdtime_t now = isc_stdtime_now();
|
||||
|
|
@ -616,7 +624,8 @@ ISC_LOOP_TEST_IMPL(nta) {
|
|||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
dns_test_namefromstring("example.", &fn);
|
||||
create_dsstruct(keyname, 257, 3, 5, keystr1, digest, &ds);
|
||||
create_dsstruct(keyname, 257, 3, 5, keystr1, digest, sizeof(digest),
|
||||
&ds);
|
||||
result = dns_keytable_add(keytable, false, false, keyname, &ds, NULL,
|
||||
NULL),
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
|
|
|||
Loading…
Reference in a new issue