Commit d44d2b82 authored by Libor Peltan's avatar Libor Peltan Committed by Daniel Salzman

dnssec: refactored KSK flag; refactored zone-keys CSK handling, add CSK flag to KASP

parent 43389b1b
......@@ -233,6 +233,7 @@ static int serialize_key_params(const key_params_t *params, const knot_dname_t *
uint8_t flags = 0x02;
flags |= (params->is_ksk ? 0x01 : 0);
flags |= (params->is_pub_only ? 0x04 : 0);
flags |= (params->is_csk ? 0x08 : 0);
wire_ctx_write_u8(&wire, flags);
wire_ctx_write_u64(&wire, (uint64_t)params->timing.created);
wire_ctx_write_u64(&wire, (uint64_t)params->timing.pre_active);
......@@ -274,6 +275,10 @@ static int deserialize_key_params(key_params_t *params, const knot_db_val_t *key
uint8_t isksk_plus_flags = wire_ctx_read_u8(&wire);
params->is_ksk = ((isksk_plus_flags & (uint8_t)0x01) != (uint8_t)0x00);
params->is_pub_only = ((isksk_plus_flags & (uint8_t)0x04) != (uint8_t)0x00);
params->is_csk = ((isksk_plus_flags & (uint8_t)0x08) != (uint8_t)0x00);
if (params->is_csk && !params->is_ksk) {
return KNOT_EMALF;
}
if ((isksk_plus_flags & (uint8_t)0x02) != (uint8_t)0x00) {
params->timing.created = (knot_time_t)wire_ctx_read_u64(&wire);
params->timing.pre_active = (knot_time_t)wire_ctx_read_u64(&wire);
......
......@@ -98,6 +98,9 @@ static int params2kaspkey(const knot_dname_t *dname, key_params_t *params,
key->timing = params->timing;
key->is_pub_only = params->is_pub_only;
assert(params->is_ksk || !params->is_csk);
key->is_ksk = params->is_ksk;
key->is_zsk = (params->is_csk || !params->is_ksk);
return KNOT_EOK;
}
......@@ -111,6 +114,8 @@ static void kaspkey2params(knot_kasp_key_t *key, key_params_t *params)
dnssec_key_get_pubkey(key->key, &params->public_key);
params->algorithm = dnssec_key_get_algorithm(key->key);
params->is_ksk = dnssec_key_get_flags(key->key) == DNSKEY_FLAGS_KSK;
assert(params->is_ksk == key->is_ksk);
params->is_csk = (key->is_ksk && key->is_zsk);
params->timing = key->timing;
params->is_pub_only = key->is_pub_only;
}
......
......@@ -42,6 +42,7 @@ typedef struct {
typedef struct {
char *id;
bool is_ksk;
bool is_csk;
bool is_pub_only;
uint16_t keytag;
uint8_t algorithm;
......@@ -57,6 +58,8 @@ typedef struct {
dnssec_key_t *key; /*!< Instance of the key. */
knot_kasp_key_timing_t timing; /*!< Key timing information. */
bool is_pub_only;
bool is_ksk;
bool is_zsk;
} knot_kasp_key_t;
/*!
......
......@@ -78,12 +78,12 @@ static knot_kasp_key_t *key_get_by_id(kdnssec_ctx_t *ctx, const char *keyid)
return NULL;
}
static int generate_key(kdnssec_ctx_t *ctx, bool ksk, knot_time_t when_active, bool pre_active)
static int generate_key(kdnssec_ctx_t *ctx, bool ksk, bool zsk, knot_time_t when_active, bool pre_active)
{
assert(!pre_active || when_active == 0);
knot_kasp_key_t *key = NULL;
int ret = kdnssec_generate_key(ctx, ksk, &key);
int ret = kdnssec_generate_key(ctx, ksk, zsk, &key);
if (ret != KNOT_EOK) {
return ret;
}
......@@ -98,7 +98,7 @@ static int generate_key(kdnssec_ctx_t *ctx, bool ksk, knot_time_t when_active, b
return KNOT_EOK;
}
static int share_or_generate_key(kdnssec_ctx_t *ctx, bool ksk, knot_time_t when_active, bool pre_active)
static int share_or_generate_key(kdnssec_ctx_t *ctx, bool ksk, bool zsk, knot_time_t when_active, bool pre_active)
{
assert(!pre_active || when_active == 0);
......@@ -118,7 +118,7 @@ static int share_or_generate_key(kdnssec_ctx_t *ctx, bool ksk, knot_time_t when_
// if we already have the policy-last key, we have to generate new one
if (ret == KNOT_ENOENT || key_id_present(ctx, borrow_key, DNSKEY_FLAGS_KSK)) {
knot_kasp_key_t *key = NULL;
ret = kdnssec_generate_key(ctx, ksk, &key);
ret = kdnssec_generate_key(ctx, ksk, zsk, &key);
if (ret != KNOT_EOK) {
return ret;
}
......@@ -180,7 +180,6 @@ static bool running_rollover(const kdnssec_ctx_t *ctx)
for (size_t i = 0; i < ctx->zone->num_keys; i++) {
knot_kasp_key_t *key = &ctx->zone->keys[i];
bool isksk = (dnssec_key_get_flags(key->key) == DNSKEY_FLAGS_KSK);
switch (get_key_state(key, ctx->now)) {
case DNSSEC_KEY_STATE_PRE_ACTIVE:
res = true;
......@@ -189,10 +188,10 @@ static bool running_rollover(const kdnssec_ctx_t *ctx)
res = (res || !key->is_pub_only);
break;
case DNSSEC_KEY_STATE_READY:
ready_ksk = (ready_ksk || isksk);
ready_ksk = (ready_ksk || key->is_ksk);
break;
case DNSSEC_KEY_STATE_ACTIVE:
active_ksk = (active_ksk || isksk);
active_ksk = (active_ksk || key->is_ksk);
break;
case DNSSEC_KEY_STATE_RETIRE_ACTIVE:
case DNSSEC_KEY_STATE_POST_ACTIVE:
......@@ -337,8 +336,7 @@ static roll_action_t next_action(kdnssec_ctx_t *ctx)
if (key->is_pub_only) {
continue;
}
bool isksk = (dnssec_key_get_flags(key->key) == DNSKEY_FLAGS_KSK);
if (isksk) {
if (key->is_ksk) {
switch (get_key_state(key, ctx->now)) {
case DNSSEC_KEY_STATE_PRE_ACTIVE:
keytime = alg_publish_time(key->timing.pre_active, ctx);
......@@ -419,7 +417,7 @@ static roll_action_t next_action(kdnssec_ctx_t *ctx)
}
if (knot_time_cmp(keytime, res.time) < 0) {
res.key = key;
res.ksk = isksk;
res.ksk = key->is_ksk;
res.time = keytime;
res.type = restype;
}
......@@ -431,13 +429,12 @@ static roll_action_t next_action(kdnssec_ctx_t *ctx)
static int submit_key(kdnssec_ctx_t *ctx, knot_kasp_key_t *newkey)
{
assert(get_key_state(newkey, ctx->now) == DNSSEC_KEY_STATE_PUBLISHED);
assert(dnssec_key_get_flags(newkey->key) == DNSKEY_FLAGS_KSK);
assert(newkey->is_ksk);
// pushing from READY into ACTIVE decreases the other key's cds_priority
for (size_t i = 0; i < ctx->zone->num_keys; i++) {
knot_kasp_key_t *key = &ctx->zone->keys[i];
if (dnssec_key_get_flags(key->key) == DNSKEY_FLAGS_KSK &&
get_key_state(key, ctx->now) == DNSSEC_KEY_STATE_READY) {
if (key->is_ksk && get_key_state(key, ctx->now) == DNSSEC_KEY_STATE_READY) {
key->timing.active = ctx->now;
}
}
......@@ -448,20 +445,17 @@ static int submit_key(kdnssec_ctx_t *ctx, knot_kasp_key_t *newkey)
static int exec_new_signatures(kdnssec_ctx_t *ctx, knot_kasp_key_t *newkey)
{
uint16_t kskflag = dnssec_key_get_flags(newkey->key);
if (kskflag == DNSKEY_FLAGS_KSK) {
if (newkey->is_ksk) {
log_zone_notice(ctx->zone->dname, "DNSSEC, KSK submission, confirmed");
}
for (size_t i = 0; i < ctx->zone->num_keys; i++) {
knot_kasp_key_t *key = &ctx->zone->keys[i];
uint16_t keyflags = dnssec_key_get_flags(key->key);
key_state_t keystate = get_key_state(key, ctx->now);
uint8_t keyalg = dnssec_key_get_algorithm(key->key);
if (keyflags == kskflag && keystate == DNSSEC_KEY_STATE_ACTIVE) {
if (keyflags == DNSKEY_FLAGS_KSK ||
keyalg != dnssec_key_get_algorithm(newkey->key)) {
if (((newkey->is_ksk && key->is_ksk) || (newkey->is_zsk && key->is_zsk))
&& keystate == DNSSEC_KEY_STATE_ACTIVE) {
if (key->is_ksk || keyalg != dnssec_key_get_algorithm(newkey->key)) {
key->timing.retire_active = ctx->now;
} else {
key->timing.retire = ctx->now;
......@@ -469,7 +463,7 @@ static int exec_new_signatures(kdnssec_ctx_t *ctx, knot_kasp_key_t *newkey)
}
}
if (kskflag == DNSKEY_FLAGS_KSK) {
if (newkey->is_ksk) {
assert(get_key_state(newkey, ctx->now) == DNSSEC_KEY_STATE_READY);
} else {
assert(get_key_state(newkey, ctx->now) == DNSSEC_KEY_STATE_PUBLISHED);
......@@ -494,8 +488,7 @@ static int exec_ksk_retire(kdnssec_ctx_t *ctx, knot_kasp_key_t *key)
for (size_t i = 0; i < ctx->zone->num_keys; i++) {
knot_kasp_key_t *key = &ctx->zone->keys[i];
if (dnssec_key_get_flags(key->key) == DNSKEY_FLAGS_ZSK &&
get_key_state(key, ctx->now) == DNSSEC_KEY_STATE_RETIRE_ACTIVE) {
if (key->is_zsk && get_key_state(key, ctx->now) == DNSSEC_KEY_STATE_RETIRE_ACTIVE) {
alg_rollover = true;
alg_rollover_friend = key;
}
......@@ -535,9 +528,9 @@ int knot_dnssec_key_rollover(kdnssec_ctx_t *ctx, zone_sign_reschedule_t *resched
// generate initial keys if missing
if (!key_present(ctx, DNSKEY_FLAGS_KSK)) {
if (ctx->policy->ksk_shared) {
ret = share_or_generate_key(ctx, true, ctx->now, false);
ret = share_or_generate_key(ctx, true, ctx->policy->singe_type_signing, ctx->now, false);
} else {
ret = generate_key(ctx, true, ctx->now, false);
ret = generate_key(ctx, true, ctx->policy->singe_type_signing, ctx->now, false);
}
reschedule->plan_ds_query = true;
if (ret == KNOT_EOK) {
......@@ -546,7 +539,7 @@ int knot_dnssec_key_rollover(kdnssec_ctx_t *ctx, zone_sign_reschedule_t *resched
}
if (!ctx->policy->singe_type_signing && ret == KNOT_EOK &&
!key_present(ctx, DNSKEY_FLAGS_ZSK)) {
ret = generate_key(ctx, false, ctx->now, false);
ret = generate_key(ctx, false, true, ctx->now, false);
if (ret == KNOT_EOK) {
reschedule->keys_changed = true;
}
......@@ -555,12 +548,12 @@ int knot_dnssec_key_rollover(kdnssec_ctx_t *ctx, zone_sign_reschedule_t *resched
if (!algorithm_present(ctx,ctx->policy->algorithm) &&
!running_rollover(ctx) && ret == KNOT_EOK) {
if (ctx->policy->ksk_shared) {
ret = share_or_generate_key(ctx, true, 0, true);
ret = share_or_generate_key(ctx, true, ctx->policy->singe_type_signing, 0, true);
} else {
ret = generate_key(ctx, true, 0, true);
ret = generate_key(ctx, true, ctx->policy->singe_type_signing, 0, true);
}
if (!ctx->policy->singe_type_signing && ret == KNOT_EOK) {
ret = generate_key(ctx, false, 0, true);
ret = generate_key(ctx, false, true, 0, true);
}
log_zone_info(ctx->zone->dname, "DNSSEC, algorithm rollover started");
if (ret == KNOT_EOK) {
......@@ -579,9 +572,9 @@ int knot_dnssec_key_rollover(kdnssec_ctx_t *ctx, zone_sign_reschedule_t *resched
switch (next.type) {
case GENERATE:
if (next.ksk && ctx->policy->ksk_shared) {
ret = share_or_generate_key(ctx, next.ksk, 0, false);
ret = share_or_generate_key(ctx, true, ctx->policy->singe_type_signing, 0, false);
} else {
ret = generate_key(ctx, next.ksk, 0, false);
ret = generate_key(ctx, next.ksk, ctx->policy->singe_type_signing || !next.ksk, 0, false);
}
if (ret == KNOT_EOK) {
log_zone_info(ctx->zone->dname, "DNSSEC, %cSK rollover started",
......@@ -634,8 +627,7 @@ int knot_dnssec_ksk_sbm_confirm(kdnssec_ctx_t *ctx)
{
for (size_t i = 0; i < ctx->zone->num_keys; i++) {
knot_kasp_key_t *key = &ctx->zone->keys[i];
if (dnssec_key_get_flags(key->key) == DNSKEY_FLAGS_KSK &&
get_key_state(key, ctx->now) == DNSSEC_KEY_STATE_READY) {
if (key->is_ksk && get_key_state(key, ctx->now) == DNSSEC_KEY_STATE_READY) {
int ret = exec_new_signatures(ctx, key);
if (ret == KNOT_EOK) {
ret = kdnssec_ctx_commit(ctx);
......@@ -652,7 +644,7 @@ bool zone_has_key_sbm(const kdnssec_ctx_t *ctx)
for (size_t i = 0; i < ctx->zone->num_keys; i++) {
knot_kasp_key_t *key = &ctx->zone->keys[i];
if (dnssec_key_get_flags(key->key) == DNSKEY_FLAGS_KSK &&
if (key->is_ksk &&
(get_key_state(key, ctx->now) == DNSSEC_KEY_STATE_READY ||
get_key_state(key, ctx->now) == DNSSEC_KEY_STATE_ACTIVE)) {
return true;
......
......@@ -161,8 +161,7 @@ int knot_dnssec_zone_sign(zone_update_t *update,
goto done;
}
result = load_zone_keys(ctx.zone, ctx.keystore,
ctx.policy->nsec3_enabled, ctx.now, &keyset, true);
result = load_zone_keys(&ctx, &keyset, true);
if (result != KNOT_EOK) {
log_zone_error(zone_name, "DNSSEC, failed to load keys (%s)",
knot_strerror(result));
......@@ -247,8 +246,7 @@ int knot_dnssec_sign_update(zone_update_t *update, zone_sign_reschedule_t *resch
goto done;
}
result = load_zone_keys(ctx.zone, ctx.keystore,
ctx.policy->nsec3_enabled, ctx.now, &keyset, false);
result = load_zone_keys(&ctx, &keyset, false);
if (result != KNOT_EOK) {
log_zone_error(zone_name, "DNSSEC, failed to load keys (%s)",
knot_strerror(result));
......
......@@ -34,12 +34,13 @@ uint16_t dnskey_flags(bool is_ksk)
return is_ksk ? DNSKEY_FLAGS_KSK : DNSKEY_FLAGS_ZSK;
}
int kdnssec_generate_key(kdnssec_ctx_t *ctx, bool ksk, knot_kasp_key_t **key_ptr)
int kdnssec_generate_key(kdnssec_ctx_t *ctx, bool ksk, bool zsk, knot_kasp_key_t **key_ptr)
{
assert(ctx);
assert(ctx->zone);
assert(ctx->keystore);
assert(ctx->policy);
assert(ksk || zsk);
dnssec_key_algorithm_t algorithm = ctx->policy->algorithm;
unsigned size = ksk ? ctx->policy->ksk_size : ctx->policy->zsk_size;
......@@ -87,6 +88,8 @@ int kdnssec_generate_key(kdnssec_ctx_t *ctx, bool ksk, knot_kasp_key_t **key_ptr
key->id = id;
key->key = dnskey;
key->is_ksk = ksk;
key->is_zsk = zsk;
key->timing.created = ctx->now;
r = kasp_zone_append(ctx->zone, key);
......@@ -207,11 +210,8 @@ static int set_key(knot_kasp_key_t *kasp_key, knot_time_t now, zone_key_t *zone_
zone_key->next_event = next;
// key use flags
uint16_t flags = dnssec_key_get_flags(kasp_key->key);
zone_key->is_ksk = flags & KNOT_RDATA_DNSKEY_FLAG_KSK;
zone_key->is_zsk = !zone_key->is_ksk;
zone_key->is_ksk = kasp_key->is_ksk;
zone_key->is_zsk = kasp_key->is_zsk;
zone_key->is_public = (knot_time_cmp(timing->publish, now) <= 0 &&
knot_time_cmp(timing->post_active, now) > 0 &&
......@@ -246,112 +246,77 @@ static bool is_nsec3_allowed(uint8_t algorithm)
}
}
/*!
* \brief Algorithm usage information.
*/
typedef struct algorithm_usage {
unsigned ksk_count; //!< Available KSK count.
unsigned zsk_count; //!< Available ZSK count.
bool is_public; //!< DNSKEY is published.
bool is_stss; //!< Used to sign all types of records.
bool is_ksk_active; //!< Used to sign DNSKEY records.
bool is_zsk_active; //!< Used to sign non-DNSKEY records.
} algorithm_usage_t;
/*!
* \brief Check correct key usage, enable Single-Type Signing Scheme if needed.
*
* Each record in the zone has to be signed at least by one key for each
* algorithm published in the DNSKEY RR set in the zone apex.
*
* Therefore, publishing a DNSKEY creates a requirement on active keys with
* the same algorithm. At least one KSK key and one ZSK has to be enabled.
* If one key type is unavailable (not just inactive and not-published), the
* algorithm is switched to Single-Type Signing Scheme.
*/
static int prepare_and_check_keys(const knot_dname_t *zone_name, bool nsec3_enabled,
zone_keyset_t *keyset)
static void ksk2csk(kdnssec_ctx_t *ctx, zone_keyset_t *keyset, uint8_t alg)
{
assert(zone_name);
assert(keyset);
for (size_t j = 0; j < keyset->count; j++) {
zone_key_t *key = &keyset->keys[j];
if (dnssec_key_get_algorithm(key->key) == alg) {
assert(key->is_ksk);
key->is_zsk = true;
}
}
const size_t max_algorithms = KNOT_DNSSEC_ALG_ED25519 + 1;
algorithm_usage_t usage[max_algorithms];
memset(usage, 0, max_algorithms * sizeof(algorithm_usage_t));
for (size_t i = 0; i < ctx->zone->num_keys; i++) {
knot_kasp_key_t *key = &ctx->zone->keys[i];
if (dnssec_key_get_algorithm(key->key) == alg) {
assert(key->is_ksk);
key->is_zsk = true;
}
}
// count available keys
log_zone_info(ctx->zone->dname, "DNSSEC, Single-Type Signing "
"Scheme enabled");
}
static int walk_algorithms(kdnssec_ctx_t *ctx, zone_keyset_t *keyset)
{
uint8_t alg_usage[256] = { 0 };
bool keys_changed = false, have_active_alg = false;
for (size_t i = 0; i < keyset->count; i++) {
zone_key_t *key = &keyset->keys[i];
uint8_t algorithm = dnssec_key_get_algorithm(key->key);
uint8_t alg = dnssec_key_get_algorithm(key->key);
assert(algorithm < max_algorithms);
algorithm_usage_t *u = &usage[algorithm];
if (nsec3_enabled && !is_nsec3_allowed(algorithm)) {
log_zone_warning(zone_name, "DNSSEC, key %d "
"cannot be used with NSEC3",
dnssec_key_get_keytag(key->key));
if (ctx->policy->nsec3_enabled && !is_nsec3_allowed(alg)) {
log_zone_warning(ctx->zone->dname, "DNSSEC, key %d "
"cannot be used with NSEC3",
dnssec_key_get_keytag(key->key));
key->is_public = false;
key->is_active = false;
key->cds_priority = 0;
continue;
}
if (key->is_ksk) { u->ksk_count += 1; }
if (key->is_zsk) { u->zsk_count += 1; }
if (key->is_ksk && key->is_public) { alg_usage[alg] |= 1; }
if (key->is_zsk && key->is_public) { alg_usage[alg] |= 2; }
if (key->is_ksk && key->is_active) { alg_usage[alg] |= 4; }
if (key->is_zsk && key->is_active) { alg_usage[alg] |= 8; }
}
// enable Single-Type Signing scheme if applicable
for (int i = 0; i < max_algorithms; i++) {
algorithm_usage_t *u = &usage[i];
// either KSK or ZSK keys are available
if ((u->ksk_count == 0) != (u->zsk_count == 0)) {
u->is_stss = true;
log_zone_info(zone_name, "DNSSEC, Single-Type Signing "
"scheme enabled, algorithm %d", i);
for (size_t i = 0; i < sizeof(alg_usage); i++) {
if (!(alg_usage[i] & 3)) {
continue; // no public keys, ignore
}
}
// update key flags for STSS, collect information about usage
for (size_t i = 0; i < keyset->count; i++) {
zone_key_t *key = &keyset->keys[i];
algorithm_usage_t *u = &usage[dnssec_key_get_algorithm(key->key)];
if (u->is_stss) {
key->is_ksk = true;
key->is_zsk = true;
}
if (key->is_public) { u->is_public = true; }
if (key->is_ksk && key->is_active) {
u->is_ksk_active = true;
}
if (key->is_zsk && key->is_active) {
u->is_zsk_active = true;
switch (alg_usage[i]) {
case 5: // because migrating from older version OR from manual setup
ksk2csk(ctx, keyset, i);
alg_usage[i] |= 10;
keys_changed = true;
// FALLTHROUGH
case 15: // all keys ready for signing
have_active_alg = true;
break;
default:
return KNOT_DNSSEC_EMISSINGKEYTYPE;
}
}
// validate conditions for used algorithms
unsigned public_count = 0;
for (int i = 0; i < max_algorithms; i++) {
algorithm_usage_t *u = &usage[i];
if (u->is_public) {
public_count += 1;
if (!u->is_ksk_active || !u->is_zsk_active) {
return KNOT_DNSSEC_EMISSINGKEYTYPE;
}
}
if (!have_active_alg) {
return KNOT_DNSSEC_ENOKEY;
}
if (public_count == 0) {
return KNOT_DNSSEC_ENOKEY;
if (keys_changed) {
return kdnssec_ctx_commit(ctx);
}
return KNOT_EOK;
......@@ -398,11 +363,11 @@ static void log_key_info(const zone_key_t *key, char *out, size_t out_len)
(void)snprintf(out, out_len, "DNSSEC, key, tag %5d, algorithm %s%s%s%s%s",
dnssec_key_get_keytag(key->key),
(alg != NULL ? alg->name : alg_code_str),
(key->is_ksk ? ", KSK" : ""),
(key->is_public ? ", public" : ""),
(key->cds_priority > 1 ? ", ready" : ""),
(key->is_active ? ", active" : ""));
(alg != NULL ? alg->name : alg_code_str),
(key->is_ksk ? (key->is_zsk ? ", CSK" : ", KSK") : ""),
(key->is_public ? ", public" : ""),
(key->cds_priority > 1 ? ", ready" : ""),
(key->is_active ? ", active" : ""));
}
int log_key_sort(const void *a, const void *b)
......@@ -417,32 +382,30 @@ int log_key_sort(const void *a, const void *b)
/*!
* \brief Load zone keys and init cryptographic context.
*/
int load_zone_keys(knot_kasp_zone_t *zone, dnssec_keystore_t *store,
bool nsec3_enabled, knot_time_t now, zone_keyset_t *keyset_ptr,
bool verbose)
int load_zone_keys(kdnssec_ctx_t *ctx, zone_keyset_t *keyset_ptr, bool verbose)
{
if (!zone || !store || !keyset_ptr) {
if (!ctx || !keyset_ptr) {
return KNOT_EINVAL;
}
zone_keyset_t keyset = { 0 };
if (zone->num_keys < 1) {
log_zone_error(zone->dname, "DNSSEC, no keys are available");
if (ctx->zone->num_keys < 1) {
log_zone_error(ctx->zone->dname, "DNSSEC, no keys are available");
return KNOT_DNSSEC_ENOKEY;
}
keyset.count = zone->num_keys;
keyset.count = ctx->zone->num_keys;
keyset.keys = calloc(keyset.count, sizeof(zone_key_t));
if (!keyset.keys) {
free_zone_keys(&keyset);
return KNOT_ENOMEM;
}
char key_info[zone->num_keys][MAX_KEY_INFO];
for (size_t i = 0; i < zone->num_keys; i++) {
knot_kasp_key_t *kasp_key = &zone->keys[i];
set_key(kasp_key, now, &keyset.keys[i]);
char key_info[ctx->zone->num_keys][MAX_KEY_INFO];
for (size_t i = 0; i < ctx->zone->num_keys; i++) {
knot_kasp_key_t *kasp_key = &ctx->zone->keys[i];
set_key(kasp_key, ctx->now, &keyset.keys[i]);
if (verbose) {
log_key_info(&keyset.keys[i], key_info[i], MAX_KEY_INFO);
}
......@@ -450,27 +413,27 @@ int load_zone_keys(knot_kasp_zone_t *zone, dnssec_keystore_t *store,
// Sort the keys by algorithm name.
if (verbose) {
qsort(key_info, zone->num_keys, MAX_KEY_INFO, log_key_sort);
for (size_t i = 0; i < zone->num_keys; i++) {
log_zone_info(zone->dname, "%s", key_info[i]);
qsort(key_info, ctx->zone->num_keys, MAX_KEY_INFO, log_key_sort);
for (size_t i = 0; i < ctx->zone->num_keys; i++) {
log_zone_info(ctx->zone->dname, "%s", key_info[i]);
}
}
int r = prepare_and_check_keys(zone->dname, nsec3_enabled, &keyset);
if (r != KNOT_EOK) {
log_zone_error(zone->dname, "DNSSEC, keys validation failed (%s)",
knot_strerror(r));
int ret = walk_algorithms(ctx, &keyset);
if (ret != KNOT_EOK) {
log_zone_error(ctx->zone->dname, "DNSSEC, keys validation failed (%s)",
knot_strerror(ret));
free_zone_keys(&keyset);
return r;
return ret;
}
r = load_private_keys(store, &keyset);
r = knot_error_from_libdnssec(r);
if (r != KNOT_EOK) {
log_zone_error(zone->dname, "DNSSEC, failed to load private "
"keys (%s)", knot_strerror(r));
ret = load_private_keys(ctx->keystore, &keyset);
ret = knot_error_from_libdnssec(ret);
if (ret != KNOT_EOK) {
log_zone_error(ctx->zone->dname, "DNSSEC, failed to load private "
"keys (%s)", knot_strerror(ret));
free_zone_keys(&keyset);
return r;
return ret;
}
*keyset_ptr = keyset;
......
......@@ -60,12 +60,13 @@ uint16_t dnskey_flags(bool is_ksk);
* \brief Generate new key, store all details in new kasp key structure.
*
* \param ctx kasp context
* \param ksk true = generate KSK, false = generate ZSK
* \param ksk true = generate KSK or CSK, false = generate ZSK
* \param zsk true = generate ZSK or CSK, false = generate KSK
* \param key_ptr output if KNOT_EOK: new pointer to generated key
*
* \return KNOT_E*
*/
int kdnssec_generate_key(kdnssec_ctx_t *ctx, bool ksk, knot_kasp_key_t **key_ptr);
int kdnssec_generate_key(kdnssec_ctx_t *ctx, bool ksk, bool zsk, knot_kasp_key_t **key_ptr);
/*!
* \brief Take a key from another zone (copying info, sharing privkey).
......@@ -95,17 +96,13 @@ int kdnssec_delete_key(kdnssec_ctx_t *ctx, knot_kasp_key_t *key_ptr);
/*!
* \brief Load zone keys and init cryptographic context.
*
* \param zone KASP zone.
* \param store KASP key store.
* \param nsec3_enabled Zone uses NSEC3 for authenticated denial.
* \param now Current time.
* \param ctx Zone signing context.
* \param keyset_ptr Resulting zone keyset.
* \param verbose Print key summary into log.
*
* \return Error code, KNOT_EOK if successful.
*/
int load_zone_keys(knot_kasp_zone_t *zone, dnssec_keystore_t *store,
bool nsec3_enabled, knot_time_t now, zone_keyset_t *keyset_ptr,
bool verbose);
int load_zone_keys(kdnssec_ctx_t *ctx, zone_keyset_t *keyset_ptr, bool verbose);
/*!
* \brief Get zone keys by a keytag.
......
......@@ -219,7 +219,7 @@ int event_parent_ds_q(conf_t *conf, zone_t *zone)
}
zone_keyset_t keyset = { 0 };
ret = load_zone_keys(ctx.zone, ctx.keystore, false, ctx.now, &keyset, false);
ret = load_zone_keys(&ctx, &keyset, false);
if (ret != KNOT_EOK) {
kdnssec_ctx_deinit(&ctx);
return ret;
......
......@@ -154,7 +154,7 @@ int keymgr_generate_key(kdnssec_ctx_t *ctx, int argc, char *argv[])
}
knot_kasp_key_t *key = NULL;
int ret = kdnssec_generate_key(ctx, isksk, &key);
int ret = kdnssec_generate_key(ctx, isksk, !isksk, &key);
if (ret != KNOT_EOK) {
return ret;
}
......@@ -315,6 +315,8 @@ int keymgr_import_bind(kdnssec_ctx_t *ctx, const char *import_file, bool pub_onl
kkey->key = key;
kkey->timing = timing;
kkey->is_pub_only = pub_only;
kkey->is_ksk = (dnssec_key_get_flags(kkey->key) == DNSKEY_FLAGS_KSK);
kkey->is_zsk = !kkey->is_ksk;
// append to zone
ret = kasp_zone_append(ctx->zone, kkey);
......
......@@ -16,7 +16,7 @@ TEST_CASES = {
"rsa_now_ecdsa_future": True,
"rsa_ecdsa_roll": True,
"stss_ksk": True,
"stss_zsk": True,
# "stss_zsk": True, # No longer supported.
"stss_two_ksk": True,
"stss_rsa256_rsa512": True,
"rsa_split_ecdsa_stss": True,
......@@ -73,8 +73,6 @@ knot.key_gen("rsa_ecdsa_roll", ksk="true", created=GEN, publish=PAST, rea
knot.key_gen("rsa_ecdsa_roll", ksk="false", created=GEN, publish=FUTU, ready=PAST, active=PAST, retire=INF, remove=INF)
# STSS: KSK only
knot.key_gen("stss_ksk", ksk="true", created=GEN, publish=PAST, ready=PAST, active=PAST, retire=INF, remove=INF)
# STSS: ZSK only
knot.key_gen("stss_zsk", ksk="false", created=GEN, publish=PAST, ready=PAST, active=PAST, retire=INF, remove=INF)
# STSS: two KSKs
knot.key_gen("stss_two_ksk", ksk="true", created=GEN, publish=PAST, ready=PAST, active=PAST, retire=INF, remove=INF)
knot.key_gen("stss_two_ksk", ksk="true", created=GEN, publish=PAST, ready=PAST, active=PAST, retire=INF, remove=INF)
......
......@@ -8,24 +8,23 @@ from dnstest.test import Test
t = Test()
knot = t.server("knot")
zones = t.zone_rnd(5, dnssec=False, records=10)
zones = t.zone_rnd(4, dnssec=False, records=10)
t.link(zones, knot)
t.start()
# one KSK
knot.gen_key(zones[0], ksk=True, alg="RSASHA256", key_len="512")
# one ZSK
knot.gen_key(zones[1], ksk=False, alg="RSASHA512", key_len="1024")
# one ZSK no longer supported
# multiple KSKs
knot.gen_key(zones[2], ksk=True, alg="RSASHA512", key_len="1024")
knot.gen_key(zones[2], ksk=True, alg="RSASHA256", key_len="512")
knot.gen_key(zones[1], ksk=True, alg="RSASHA512", key_len="1024")
knot.gen_key(zones[1], ksk=True, alg="RSASHA256", key_len="512")
# different algorithms: KSK+ZSK pair, one ZSK
knot.gen_key(zones[3], ksk=True, alg="RSASHA256", key_len="1024")
knot.gen_key(zones[3], ksk=False, alg="RSASHA256", key_len="1024")
knot.gen_key(zones[3], ksk=False, alg="RSASHA512", key_len="1024")
# different algorithms: KSK+ZSK pair, one KSK
knot.gen_key(zones[2], ksk=True, alg="RSASHA256", key_len="1024")
knot.gen_key(zones[2], ksk=False, alg="RSASHA256", key_len="1024")
knot.gen_key(zones[2], ksk=True, alg="RSASHA512", key_len="1024")
for zone in zones[:-1]:
knot.dnssec(zone).enable = True
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment