@BIND9_MAKE_INCLUDES@
-CINCLUDES = ${DNS_INCLUDES} ${ISC_INCLUDES} \
+CINCLUDES = ${DNS_INCLUDES} ${ISC_INCLUDES} ${ISCCFG_INCLUDES} \
${OPENSSL_CFLAGS}
-CDEFINES = -DVERSION=\"${VERSION}\"
+CDEFINES = -DVERSION=\"${VERSION}\" -DNAMED_CONFFILE=\"${sysconfdir}/named.conf\"
CWARNINGS =
DNSLIBS = ../../lib/dns/libdns.@A@ ${MAXMINDDB_LIBS} @DNS_CRYPTO_LIBS@
+ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@
ISCLIBS = ../../lib/isc/libisc.@A@ ${OPENSSL_LIBS} ${JSON_C_LIBS} ${LIBXML2_LIBS}
ISCNOSYMLIBS = ../../lib/isc/libisc-nosymtbl.@A@ ${OPENSSL_LIBS} ${JSON_C_LIBS} ${LIBXML2_LIBS}
DNSDEPLIBS = ../../lib/dns/libdns.@A@
ISCDEPLIBS = ../../lib/isc/libisc.@A@
+ISCCFGDEPLIBS = ../../lib/isccfg/libisccfg.@A@
-DEPLIBS = ${DNSDEPLIBS} ${ISCDEPLIBS}
+DEPLIBS = ${DNSDEPLIBS} ${ISCCFGDEPLIBS} ${ISCDEPLIBS}
-LIBS = ${DNSLIBS} ${ISCLIBS} @LIBS@
+LIBS = ${DNSLIBS} ${ISCCFGLIBS} ${ISCLIBS} @LIBS@
-NOSYMLIBS = ${DNSLIBS} ${ISCNOSYMLIBS} @LIBS@
+NOSYMLIBS = ${DNSLIBS} ${ISCCFGLIBS} ${ISCNOSYMLIBS} @LIBS@
# Alphabetically
TARGETS = dnssec-cds@EXEEXT@ dnssec-dsfromkey@EXEEXT@ \
dnssec-settime.c dnssec-signzone.c dnssec-verify.c \
dnssectool.c
-MANPAGES = dnssec-cds.8 dnssec-dsfromkey.8 dnssec-importkey.8 \
+MANPAGES = dnssec-cds.8 dnssec-dsfromkey.8 dnssec-importkey.8 \
dnssec-keyfromlabel.8 dnssec-keygen.8 dnssec-revoke.8 \
dnssec-settime.8 dnssec-signzone.8 dnssec-verify.8
#include <isc/string.h>
#include <isc/util.h>
+#include <isccfg/cfg.h>
+#include <isccfg/namedconf.h>
+#include <isccfg/kaspconf.h>
+#include <isccfg/grammar.h>
+
#include <pk11/site.h>
#include <dns/dnssec.h>
#include <dns/fixedname.h>
+#include <dns/kasp.h>
#include <dns/keyvalues.h>
#include <dns/log.h>
#include <dns/name.h>
bool showprogress;
bool quiet;
bool oldstyle;
+ /* state */
+ time_t lifetime;
+ bool ksk;
+ bool zsk;
};
typedef struct keygen_ctx keygen_ctx_t;
fprintf(stderr, " name: owner of the key\n");
fprintf(stderr, "Options:\n");
fprintf(stderr, " -K <directory>: write keys into directory\n");
+ fprintf(stderr, " -k <policy>: generate keys for dnssec-policy\n");
+ fprintf(stderr, " -l <file>: configuration file with dnssec-policy "
+ "statement\n");
fprintf(stderr, " -a <algorithm>:\n");
fprintf(stderr, " RSASHA1 | NSEC3RSASHA1 |\n");
fprintf(stderr, " RSASHA256 | RSASHA512 |\n");
(void) fflush(stderr);
}
+static void
+kasp_from_conf(cfg_obj_t* config, isc_mem_t* mctx, const char* name,
+ dns_kasp_t** kaspp)
+{
+ const cfg_listelt_t *element;
+ const cfg_obj_t *kasps = NULL;
+ dns_kasp_t *kasp = NULL, *kasp_next;
+ isc_result_t result = ISC_R_NOTFOUND;
+ dns_kasplist_t kasplist;
+
+ ISC_LIST_INIT(kasplist);
+
+ (void)cfg_map_get(config, "dnssec-policy", &kasps);
+ for (element = cfg_list_first(kasps); element != NULL;
+ element = cfg_list_next(element))
+ {
+ cfg_obj_t *kconfig = cfg_listelt_value(element);
+ kasp = NULL;
+ if (strcmp(cfg_obj_asstring(cfg_tuple_get(kconfig, "name")),
+ name) != 0)
+ {
+ continue;
+ }
+
+ result = cfg_kasp_fromconfig(kconfig, mctx, &kasplist, &kasp);
+ if (result != ISC_R_SUCCESS) {
+ fatal("failed to configure dnssec-policy '%s': %s",
+ cfg_obj_asstring(cfg_tuple_get(kconfig, "name")),
+ isc_result_totext(result));
+ }
+ INSIST(kasp != NULL);
+ dns_kasp_freeze(kasp);
+ break;
+ }
+
+ *kaspp = kasp;
+
+ /*
+ * Same cleanup for kasp list.
+ */
+ for (kasp = ISC_LIST_HEAD(kasplist); kasp != NULL; kasp = kasp_next) {
+ kasp_next = ISC_LIST_NEXT(kasp, link);
+ ISC_LIST_UNLINK(kasplist, kasp, link);
+ dns_kasp_detach(&kasp);
+ }
+}
+
static void
keygen(keygen_ctx_t *ctx, isc_mem_t *mctx, int argc, char **argv)
{
fatal("-S and -G cannot be used together");
ret = dst_key_fromnamedfile(ctx->predecessor, ctx->directory,
- DST_TYPE_PUBLIC | DST_TYPE_PRIVATE,
+ (DST_TYPE_PUBLIC|
+ DST_TYPE_PRIVATE|DST_TYPE_STATE),
mctx, &prevkey);
if (ret != ISC_R_SUCCESS)
fatal("Invalid keyfile %s: %s",
if (ctx->setttl)
dst_key_setttl(key, ctx->ttl);
+ /* Set dnssec-policy related metadata */
+ if (ctx->policy) {
+ dst_key_setnum(key, DST_NUM_LIFETIME, ctx->lifetime);
+ dst_key_setbool(key, DST_BOOL_KSK, ctx->ksk);
+ dst_key_setbool(key, DST_BOOL_ZSK, ctx->zsk);
+ }
+
/*
* Do not overwrite an existing key, or create a key
* if there is a risk of ID collision due to this key
/*
* Process memory debugging argument first.
*/
-#define CMDLINE_FLAGS "3A:a:b:Cc:D:d:E:eFf:Gg:hI:i:K:L:m:n:P:p:qR:r:S:s:T:t:" \
- "v:V"
+#define CMDLINE_FLAGS "3A:a:b:Cc:D:d:E:eFf:Gg:hI:i:K:k:L:l:m:n:P:p:qR:r:S:s:" \
+ "T:t:v:V"
while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
switch (ch) {
case 'm':
fatal("cannot open directory %s: %s",
ctx.directory, isc_result_totext(ret));
break;
+ case 'k':
+ ctx.policy = isc_commandline_argument;
+ break;
case 'L':
ctx.ttl = strtottl(isc_commandline_argument);
ctx.setttl = true;
break;
+ case 'l':
+ ctx.configfile = isc_commandline_argument;
break;
case 'n':
ctx.nametype = isc_commandline_argument;
ctx.rdclass = strtoclass(classname);
+ if (ctx.configfile == NULL || ctx.configfile[0] == '\0') {
+ ctx.configfile = NAMED_CONFFILE;
+ }
+
if (ctx.predecessor == NULL) {
if (argc < isc_commandline_index + 1)
fatal("the key name was not specified");
if (argc > isc_commandline_index + 1)
fatal("extraneous arguments");
+ }
- if (algname == NULL)
+ if (ctx.predecessor == NULL && ctx.policy == NULL) {
+ if (algname == NULL) {
fatal("no algorithm specified");
-
+ }
r.base = algname;
r.length = strlen(algname);
ret = dns_secalg_fromtext(&ctx.alg, &r);
}
}
- keygen(&ctx, mctx, argc, argv);
+ if (ctx.policy != NULL) {
+ if (ctx.nametype != NULL) {
+ fatal("-k and -n cannot be used together");
+ }
+ if (ctx.predecessor != NULL) {
+ fatal("-k and -S cannot be used together");
+ }
+ if (ctx.oldstyle) {
+ fatal("-k and -C cannot be used together");
+ }
+ if (ctx.setttl) {
+ fatal("-k and -L cannot be used together");
+ }
+ if (ctx.prepub > 0) {
+ fatal("-k and -i cannot be used together");
+ }
+ if (ctx.size != -1) {
+ fatal("-k and -b cannot be used together");
+ }
+ if (ctx.kskflag || ctx.revflag) {
+ fatal("-k and -f cannot be used together");
+ }
+ if (ctx.options & DST_TYPE_KEY) {
+ fatal("-k and -T KEY cannot be used together");
+ }
+ if (ctx.use_nsec3) {
+ fatal("-k and -3 cannot be used together");
+ }
+
+ if (ctx.setpub || ctx.setact || ctx.setrev || ctx.setinact ||
+ ctx.setdel || ctx.unsetpub || ctx.unsetact ||
+ ctx.unsetrev || ctx.unsetinact || ctx.unsetdel ||
+ ctx.setsyncadd || ctx.setsyncdel)
+ {
+ fatal("cannot use -k together with "
+ "-P, -A, -R, -I, or -D options "
+ "(use dnssec-settime on keys afterwards)");
+ }
+
+ ctx.options |= DST_TYPE_STATE;
+ ctx.genonly = true;
+
+ if (strcmp(ctx.policy, "default") == 0) {
+ ctx.use_nsec3 = false;
+ ctx.alg = DST_ALG_ECDSA256;
+ ctx.size = 0;
+ ctx.kskflag = DNS_KEYFLAG_KSK;
+ ctx.ttl = 3600;
+ ctx.setttl = true;
+ ctx.ksk = true;
+ ctx.zsk = true;
+ ctx.lifetime = 0;
+
+ keygen(&ctx, mctx, argc, argv);
+ } else {
+ cfg_parser_t *parser = NULL;
+ cfg_obj_t *config = NULL;
+ dns_kasp_t* kasp = NULL;
+ dns_kasp_key_t* kaspkey = NULL;
+
+ RUNTIME_CHECK(cfg_parser_create(mctx, log, &parser)
+ == ISC_R_SUCCESS);
+ if (cfg_parse_file(parser, ctx.configfile,
+ &cfg_type_namedconf, &config) != ISC_R_SUCCESS)
+ {
+ fatal("unable to load dnssec-policy '%s' from "
+ "'%s'", ctx.policy, ctx.configfile);
+ }
+
+ kasp_from_conf(config, mctx, ctx.policy, &kasp);
+ if (kasp == NULL) {
+ fatal("failed to load dnssec-policy '%s'",
+ ctx.policy);
+ }
+ if (ISC_LIST_EMPTY(kasp->keys)) {
+ fatal("dnssec-policy '%s' has no keys "
+ "configured", ctx.policy);
+ }
+
+ ctx.ttl = dns_kasp_dnskeyttl(kasp);
+ ctx.setttl = true;
+
+ kaspkey = ISC_LIST_HEAD(kasp->keys);
+
+ while (kaspkey != NULL) {
+ ctx.use_nsec3 = false;
+ ctx.alg = dns_kasp_key_algorithm(kaspkey);
+ ctx.size = dns_kasp_key_size(kaspkey);
+ ctx.kskflag = dns_kasp_key_ksk(kaspkey) ?
+ DNS_KEYFLAG_KSK : 0;
+ ctx.ksk = dns_kasp_key_ksk(kaspkey);
+ ctx.zsk = dns_kasp_key_zsk(kaspkey);
+ ctx.lifetime = dns_kasp_key_lifetime(kaspkey);
+
+ keygen(&ctx, mctx, argc, argv);
+
+ kaspkey = ISC_LIST_NEXT(kaspkey, link);
+ }
+
+ dns_kasp_detach(&kasp);
+ cfg_obj_destroy(parser, &config);
+ cfg_parser_destroy(&parser);
+ }
+ } else {
+ keygen(&ctx, mctx, argc, argv);
+ }
cleanup_logging(&log);
dst_lib_destroy();
<arg choice="opt" rep="norepeat"><option>-I <replaceable class="parameter">date/offset</replaceable></option></arg>
<arg choice="opt" rep="norepeat"><option>-i <replaceable class="parameter">interval</replaceable></option></arg>
<arg choice="opt" rep="norepeat"><option>-K <replaceable class="parameter">directory</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-k <replaceable class="parameter">policy</replaceable></option></arg>
<arg choice="opt" rep="norepeat"><option>-L <replaceable class="parameter">ttl</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-l <replaceable class="parameter">file</replaceable></option></arg>
<arg choice="opt" rep="norepeat"><option>-n <replaceable class="parameter">nametype</replaceable></option></arg>
<arg choice="opt" rep="norepeat"><option>-P <replaceable class="parameter">date/offset</replaceable></option></arg>
<arg choice="opt" rep="norepeat"><option>-P sync <replaceable class="parameter">date/offset</replaceable></option></arg>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term>-k <replaceable class="parameter">policy</replaceable></term>
+ <listitem>
+ <para>
+ Create keys for a specific dnssec-policy. If a policy uses
+ multiple keys, <command>dnssec-keygen</command> will generate
+ multiple keys. This will also create a ".state" file to keep
+ track of the key state.
+ </para>
+ <para>
+ This option creates keys according to the dnssec-policy
+ configuration, hence it cannot be used together with many of
+ the other options that <command>dnssec-keygen</command>
+ provides.
+ </para>
+ </listitem>
+ </varlistentry>
+
<varlistentry>
<term>-L <replaceable class="parameter">ttl</replaceable></term>
<listitem>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term>-l <replaceable class="parameter">file</replaceable></term>
+ <listitem>
+ <para>
+ Provide a configuration file that contains a dnssec-policy
+ statement (matching the policy set with <command>-k</command>).
+ </para>
+ </listitem>
+ </varlistentry>
+
<varlistentry>
<term>-n <replaceable class="parameter">nametype</replaceable></term>
<listitem>
<ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
<BrowseInformation>true</BrowseInformation>
<ForcedIncludeFiles>..\..\..\config.h</ForcedIncludeFiles>
- <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\isccfg\win32;..\..\..\lib\isccfg\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<CompileAs>CompileAsC</CompileAs>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
- <AdditionalDependencies>@OPENSSL_LIB@dnssectool.lib;libisc.lib;libdns.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
- <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>@OPENSSL_LIB@dnssectool.lib;libisc.lib;libisccfg.lib;libdns.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
<ObjectFileName>.\$(Configuration)\</ObjectFileName>
<ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
<ForcedIncludeFiles>..\..\..\config.h</ForcedIncludeFiles>
- <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\isccfg\win32;..\..\..\lib\isccfg\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<CompileAs>CompileAsC</CompileAs>
</ClCompile>
<Link>
<OptimizeReferences>true</OptimizeReferences>
<OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
<LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
- <AdditionalDependencies>@OPENSSL_LIB@dnssectool.lib;libisc.lib;libdns.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
- <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>@OPENSSL_LIB@dnssectool.lib;libisc.lib;libisccfg.lib;libdns.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
--- /dev/null
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# 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 http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+set -e
+
+rm -f ./keygen.*
+rm -f ./K*.private ./K*.key ./K*.state ./K*.cmp
+rm -f ./keys/K*
+rmdir ./keys/
--- /dev/null
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * This is just a random selection of configuration options.
+ */
+
+dnssec-policy "kasp" {
+ dnskey-ttl 200;
+
+ keys {
+ csk key-directory P1Y 13;
+ ksk key-directory P1Y 8;
+ zsk key-directory P30D 8 1024;
+ zsk key-directory P6M 8 2000;
+ };
+};
--- /dev/null
+#!/bin/sh -e
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# 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 http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. "$SYSTEMTESTTOP/conf.sh"
+
+set -e
+
+$SHELL clean.sh
+
+mkdir keys
--- /dev/null
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# 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 http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+SYSTEMTESTTOP=..
+. "$SYSTEMTESTTOP/conf.sh"
+
+set -e
+
+status=0
+n=0
+log=1
+
+################################################################################
+# Utilities #
+################################################################################
+
+# Get the key ids from key files for zone $2 in directory $1
+# that matches algorithm $3.
+get_keyids() {
+ dir=$1
+ zone=$2
+ algorithm=$(printf "%03d" $3)
+ start="${dir}/K${zone}.+${algorithm}+"
+ end=".key"
+
+ ls ${start}*${end} | sed "s/$dir\/K${zone}.+${algorithm}+\([0-9]\{5\}\)${end}/\1/"
+}
+
+log_error() {
+ test $log -eq 1 && echo_i "error: $1"
+ ret=$((ret+1))
+}
+
+# Check the created key in directory $1 for zone $2.
+# $3: key role. Must be one of "csk", "ksk", or "zsk".
+# $4: key identifier (zero padded)
+# $5: algorithm number
+# $6: algorithm (string format)
+# $7: algorithm length
+# $8: dnskey ttl
+# $9: key lifetime
+check_created_key() {
+ dir=$1
+ zone=$2
+ role=$3
+ key_idpad=$4
+ key_id=$(echo $key_idpad | sed 's/^0*//')
+ alg_num=$5
+ alg_numpad=$(printf "%03d" $alg_num)
+ alg_string=$6
+ length=$7
+ dnskey_ttl=$8
+ lifetime=$9
+
+ ksk="no"
+ zsk="no"
+ if [ "$role" == "ksk" ]; then
+ role2="key-signing"
+ ksk="yes"
+ flags="257"
+ elif [ "$role" == "zsk" ]; then
+ role2="zone-signing"
+ zsk="yes"
+ flags="256"
+ elif [ "$role" == "csk" ]; then
+ role2="key-signing"
+ zsk="yes"
+ ksk="yes"
+ flags="257"
+ fi
+
+ KEY_FILE="${dir}/K${zone}.+${alg_numpad}+${key_idpad}.key"
+ PRIVATE_FILE="${dir}/K${zone}.+${alg_numpad}+${key_idpad}.private"
+ STATE_FILE="${dir}/K${zone}.+${alg_numpad}+${key_idpad}.state"
+
+ # Check the public key file. We expect three lines: a comment,
+ # a "Created" line, and the DNSKEY record.
+ lines=$(cat $KEY_FILE | wc -l)
+ test "$lines" -eq 3 || log_error "bad public keyfile $KEY_FILE"
+ grep "This is a ${role2} key, keyid ${key_id}, for ${zone}." $KEY_FILE > /dev/null || log_error "mismatch top comment in $KEY_FILE"
+ grep "; Created:" $KEY_FILE > /dev/null || log_error "mismatch created comment in $KEY_FILE"
+ grep "${zone}\. ${dnskey_ttl} IN DNSKEY ${flags} 3 ${alg_num}" $KEY_FILE > /dev/null || log_error "mismatch DNSKEY record in $KEY_FILE"
+ # Now check the private key file.
+ grep "Private-key-format: v1.3" $PRIVATE_FILE > /dev/null || log_error "mismatch private key format in $PRIVATE_FILE"
+ grep "Algorithm: ${alg_num} (${alg_string})" $PRIVATE_FILE > /dev/null || log_error "mismatch algorithm in $PRIVATE_FILE"
+ grep "Created:" $PRIVATE_FILE > /dev/null || log_error "mismatch created in $PRIVATE_FILE"
+ # Now check the key state file. There should be seven lines:
+ # a top comment, "Generated", "Lifetime", "Algorithm", "Length",
+ # "KSK", and "ZSK".
+ lines=$(cat $STATE_FILE | wc -l)
+ test "$lines" -eq 7 || log_error "bad state keyfile $STATE_FILE"
+ grep "This is the state of key ${key_id}, for ${zone}." $STATE_FILE > /dev/null || log_error "mismatch top comment in $STATE_FILE"
+ # XXX: Could check if generated is ~now.
+ grep "Generated: " $STATE_FILE > /dev/null || log_error "mismatch generated in $STATE_FILE"
+ grep "Lifetime: ${lifetime}" $STATE_FILE > /dev/null || log_error "mismatch lifetime in $STATE_FILE"
+ grep "Algorithm: ${alg_num}" $STATE_FILE > /dev/null || log_error "mismatch algorithm in $STATE_FILE"
+ grep "Length: ${length}" $STATE_FILE > /dev/null || log_error "mismatch length in $STATE_FILE"
+ grep "KSK: ${ksk}" $STATE_FILE > /dev/null || log_error "mismatch ksk in $STATE_FILE"
+ grep "ZSK: ${zsk}" $STATE_FILE > /dev/null || log_error "mismatch zsk in $STATE_FILE"
+}
+
+################################################################################
+# Tests #
+################################################################################
+
+#
+# dnssec-keygen
+#
+n=$((n+1))
+echo_i "check that 'dnssec-keygen -k' (default policy) creates valid files ($n)"
+ret=0
+$KEYGEN -k _default kasp > keygen.out._default.test$n 2>/dev/null || ret=1
+lines=$(cat keygen.out._default.test$n | wc -l)
+test "$lines" -eq 1 || log_error "wrong number of keys created for policy _default"
+KEY_ID=$(get_keyids "." "kasp" "13")
+echo_i "check key $KEY_ID..."
+check_created_key "." "kasp" "csk" $KEY_ID "13" "ECDSAP256SHA256" "256" "3600" "0"
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "check that 'dnssec-keygen -k' (configured policy) creates valid files ($n)"
+ret=0
+$KEYGEN -K keys -k kasp -l kasp.conf kasp > keygen.out.kasp.test$n 2>/dev/null || ret=1
+lines=$(cat keygen.out.kasp.test$n | wc -l)
+test "$lines" -eq 4 || log_error "wrong number of keys created for policy kasp"
+# Check one algorithm.
+KEY_ID=$(get_keyids "keys" "kasp" "13")
+echo_i "check key $KEY_ID..."
+check_created_key "keys" "kasp" "csk" $KEY_ID "13" "ECDSAP256SHA256" "256" "200" "31536000"
+# Temporarily don't log errors because we are searching multiple files.
+log=0
+# Check the other algorithm.
+KEY_IDS=$(get_keyids "keys" "kasp" "8")
+for KEY_ID in $KEY_IDS; do
+ echo_i "check key $KEY_ID..."
+ # There are three key files with the same algorithm.
+ # Check them until a match is found.
+ ret=0 && check_created_key "keys" "kasp" "ksk" $KEY_ID "8" "RSASHA256" "2048" "200" "31536000"
+ test "$ret" -gt 0 && ret=0 && check_created_key "keys" "kasp" "zsk" $KEY_ID "8" "RSASHA256" "1024" "200" "2592000"
+ test "$ret" -gt 0 && ret=0 && check_created_key "keys" "kasp" "zsk" $KEY_ID "8" "RSASHA256" "2000" "200" "16070400"
+ # If ret is non-zero, non of the files matched.
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status+ret))
+
+done
+# Turn error logs on again.
+log=1
+
+n=$((n+1))
+echo_i "check that 'dnssec-keygen -k' (default policy) creates valid files ($n)"
+ret=0
+$KEYGEN -k default kasp > keygen.out.default.test$n 2>/dev/null || ret=1
+lines=$(cat keygen.out.default.test$n | wc -l)
+test "$lines" -eq 1 || log_error "wrong number of keys created for policy default"
+KEY_ID=$(get_keyids "." "kasp" "13")
+echo_i "check key $KEY_ID..."
+check_created_key "." "kasp" "csk" $KEY_ID "13" "ECDSAP256SHA256" "256" "3600" "0"
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+#
+# dnssec-settime
+#
+
+#
+# named
+#
+
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
+
./bin/tests/system/ixfr/prereq.sh SH 2001,2004,2007,2012,2014,2016,2018,2019
./bin/tests/system/ixfr/setup.sh SH 2001,2004,2007,2011,2012,2013,2014,2016,2018,2019
./bin/tests/system/ixfr/tests.sh SH 2001,2004,2007,2011,2012,2014,2016,2018,2019
+./bin/tests/system/kasp/clean.sh SH 2019
+./bin/tests/system/kasp/setup.sh SH 2019
+./bin/tests/system/kasp/tests.sh SH 2019
./bin/tests/system/keepalive/clean.sh SH 2017,2018,2019
./bin/tests/system/keepalive/expected X 2017,2018,2019
./bin/tests/system/keepalive/setup.sh SH 2017,2018,2019