rem: usr: Remove -C option from dnssec-keygen and dnssec-keyfromlabel

The -C option, introduced in BIND 9.7, caused a backward-compatible
key to be generated, using private key format version 1.2, omitting the
creation date and other timing metadata. This made it possible to
generate keys that could be loaded by older versions of BIND.

Those older versions having reached end of life many years ago, the
option can now be removed, along with the `dnssec-settime -f` option,
which caused old-style keys to be upgraded.

Merge branch 'each-remove-keygen-compat' into 'main'

See merge request isc-projects/bind9!11446
This commit is contained in:
Evan Hunt 2026-03-24 20:24:58 +00:00
commit 864932a15e
13 changed files with 100 additions and 247 deletions

View file

@ -1093,6 +1093,7 @@ cross-version-config-tests:
untracked: true
expire_in: "1 day"
when: always
allow_failure: true # GL!11446
# Jobs for regular GCC builds on Alpine Linux 3.23 (amd64)

View file

@ -114,7 +114,6 @@ main(int argc, char **argv) {
dns_name_t *name;
uint16_t flags = 0, kskflag = 0, revflag = 0;
dst_algorithm_t alg;
bool oldstyle = false;
int ch;
isc_result_t result;
isc_textregion_t r;
@ -151,7 +150,7 @@ main(int argc, char **argv) {
isc_commandline_errprint = false;
#define CMDLINE_FLAGS "3A:a:Cc:D:E:Ff:GhI:i:kK:L:l:M:n:P:p:R:S:t:v:Vy"
#define CMDLINE_FLAGS "3A:a:c:D:E:Ff:GhI:i:kK:L:l:M:n:P:p:R:S:t:v:Vy"
while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
switch (ch) {
case '3':
@ -160,9 +159,6 @@ main(int argc, char **argv) {
case 'a':
algname = isc_commandline_argument;
break;
case 'C':
oldstyle = true;
break;
case 'c':
classname = isc_commandline_argument;
break;
@ -407,7 +403,7 @@ main(int argc, char **argv) {
}
}
if (!oldstyle && prepub > 0) {
if (prepub > 0) {
if (setpub && setact && (activate - prepub) < publish) {
fatal("Activation and publication dates "
"are closer together than the\n\t"
@ -452,9 +448,6 @@ main(int argc, char **argv) {
if (use_nsec3) {
fatal("-S and -3 cannot be used together");
}
if (oldstyle) {
fatal("-S and -C cannot be used together");
}
if (genonly) {
fatal("-S and -G cannot be used together");
}
@ -572,70 +565,55 @@ main(int argc, char **argv) {
}
/*
* Set key timing metadata (unless using -C)
* Set key timing metadata.
*
* Publish and activation dates are set to "now" by default, but
* can be overridden. Creation date is always set to "now".
*/
if (!oldstyle) {
dst_key_settime(key, DST_TIME_CREATED, now);
dst_key_settime(key, DST_TIME_CREATED, now);
if (genonly && (setpub || setact)) {
fatal("cannot use -G together with -P or -A options");
}
if (genonly && (setpub || setact)) {
fatal("cannot use -G together with -P or -A options");
}
if (setpub) {
dst_key_settime(key, DST_TIME_PUBLISH, publish);
} else if (setact) {
dst_key_settime(key, DST_TIME_PUBLISH, activate);
} else if (!genonly && !unsetpub) {
dst_key_settime(key, DST_TIME_PUBLISH, now);
}
if (setpub) {
dst_key_settime(key, DST_TIME_PUBLISH, publish);
} else if (setact) {
dst_key_settime(key, DST_TIME_PUBLISH, activate);
} else if (!genonly && !unsetpub) {
dst_key_settime(key, DST_TIME_PUBLISH, now);
}
if (setact) {
dst_key_settime(key, DST_TIME_ACTIVATE, activate);
} else if (!genonly && !unsetact) {
dst_key_settime(key, DST_TIME_ACTIVATE, now);
}
if (setact) {
dst_key_settime(key, DST_TIME_ACTIVATE, activate);
} else if (!genonly && !unsetact) {
dst_key_settime(key, DST_TIME_ACTIVATE, now);
}
if (setrev) {
if (kskflag == 0) {
fprintf(stderr,
"%s: warning: Key is "
"not flagged as a KSK, but -R "
"was used. Revoking a ZSK is "
"legal, but undefined.\n",
isc_commandline_progname);
}
dst_key_settime(key, DST_TIME_REVOKE, revoke);
if (setrev) {
if (kskflag == 0) {
fprintf(stderr,
"%s: warning: Key is "
"not flagged as a KSK, but -R "
"was used. Revoking a ZSK is "
"legal, but undefined.\n",
isc_commandline_progname);
}
dst_key_settime(key, DST_TIME_REVOKE, revoke);
}
if (setinact) {
dst_key_settime(key, DST_TIME_INACTIVE, inactive);
}
if (setinact) {
dst_key_settime(key, DST_TIME_INACTIVE, inactive);
}
if (setdel) {
dst_key_settime(key, DST_TIME_DELETE, deltime);
}
if (setsyncadd) {
dst_key_settime(key, DST_TIME_SYNCPUBLISH, syncadd);
}
if (setsyncdel) {
dst_key_settime(key, DST_TIME_SYNCDELETE, syncdel);
}
} else {
if (setpub || setact || setrev || setinact || setdel ||
unsetpub || unsetact || unsetrev || unsetinact ||
unsetdel || genonly || setsyncadd || setsyncdel)
{
fatal("cannot use -C together with "
"-P, -A, -R, -I, -D, or -G options");
}
/*
* Compatibility mode: Private-key-format
* should be set to 1.2.
*/
dst_key_setprivateformat(key, 1, 2);
if (setdel) {
dst_key_settime(key, DST_TIME_DELETE, deltime);
}
if (setsyncadd) {
dst_key_settime(key, DST_TIME_SYNCPUBLISH, syncadd);
}
if (setsyncdel) {
dst_key_settime(key, DST_TIME_SYNCDELETE, syncdel);
}
/* Set default key TTL */

View file

@ -74,15 +74,6 @@ Options
When BIND 9 is built with OpenSSL-based PKCS#11 support, the label is
an arbitrary string that identifies a particular key.
.. option:: -C
This option enables compatibility mode, which generates an old-style key, without any metadata.
By default, :program:`dnssec-keyfromlabel` includes the key's creation
date in the metadata stored with the private key; other dates may
be set there as well, including publication date, activation date, etc. Keys
that include this data may be incompatible with older versions of
BIND; the :option:`-C` option suppresses them.
.. option:: -c class
This option indicates that the DNS record containing the key should have the

View file

@ -118,7 +118,6 @@ struct keygen_ctx {
bool genonly;
bool showprogress;
bool quiet;
bool oldstyle;
/* state */
time_t lifetime;
bool ksk;
@ -192,8 +191,6 @@ usage(int ret) {
"deletion date\n");
fprintf(stderr, " -G: generate key only; do not set -P or -A\n");
fprintf(stderr, " -C: generate a backward-compatible key, omitting "
"all dates\n");
fprintf(stderr, " -S <key>: generate a successor to an existing "
"key\n");
fprintf(stderr, " -i <interval>: prepublication interval for "
@ -334,7 +331,7 @@ keygen(keygen_ctx_t *ctx, int argc, char **argv) {
}
}
if (!ctx->oldstyle && ctx->prepub > 0) {
if (ctx->prepub > 0) {
if (ctx->setpub && ctx->setact &&
(ctx->activate - ctx->prepub) < ctx->publish)
{
@ -384,9 +381,6 @@ keygen(keygen_ctx_t *ctx, int argc, char **argv) {
if (ctx->use_nsec3) {
fatal("-S and -3 cannot be used together");
}
if (ctx->oldstyle) {
fatal("-S and -C cannot be used together");
}
if (ctx->genonly) {
fatal("-S and -G cannot be used together");
}
@ -586,7 +580,7 @@ keygen(keygen_ctx_t *ctx, int argc, char **argv) {
}
/*
* Set key timing metadata (unless using -C)
* Set key timing metadata.
*
* Creation date is always set to "now".
*
@ -601,90 +595,60 @@ keygen(keygen_ctx_t *ctx, int argc, char **argv) {
* an error; the inactivation date of the predecessor key
* must be updated before a successor key can be created.
*/
if (!ctx->oldstyle) {
dst_key_settime(key, DST_TIME_CREATED, ctx->now);
dst_key_settime(key, DST_TIME_CREATED, ctx->now);
if (ctx->genonly && (ctx->setpub || ctx->setact)) {
fatal("cannot use -G together with "
"-P or -A options");
}
if (ctx->genonly && (ctx->setpub || ctx->setact)) {
fatal("cannot use -G together with -P or -A options");
}
if (ctx->setpub) {
dst_key_settime(key, DST_TIME_PUBLISH,
ctx->publish);
} else if (ctx->setact && !ctx->unsetpub) {
dst_key_settime(key, DST_TIME_PUBLISH,
ctx->activate - ctx->prepub);
} else if (!ctx->genonly && !ctx->unsetpub) {
dst_key_settime(key, DST_TIME_PUBLISH,
ctx->now);
}
if (ctx->setpub) {
dst_key_settime(key, DST_TIME_PUBLISH, ctx->publish);
} else if (ctx->setact && !ctx->unsetpub) {
dst_key_settime(key, DST_TIME_PUBLISH,
ctx->activate - ctx->prepub);
} else if (!ctx->genonly && !ctx->unsetpub) {
dst_key_settime(key, DST_TIME_PUBLISH, ctx->now);
}
if (ctx->setact) {
dst_key_settime(key, DST_TIME_ACTIVATE,
ctx->activate);
} else if (!ctx->genonly && !ctx->unsetact) {
dst_key_settime(key, DST_TIME_ACTIVATE,
ctx->now);
}
if (ctx->setact) {
dst_key_settime(key, DST_TIME_ACTIVATE, ctx->activate);
} else if (!ctx->genonly && !ctx->unsetact) {
dst_key_settime(key, DST_TIME_ACTIVATE, ctx->now);
}
if (ctx->setrev) {
if (!ctx->wantksk) {
fprintf(stderr,
"%s: warning: Key is "
"not flagged as a KSK, but -R "
"was used. Revoking a ZSK is "
"legal, but undefined.\n",
isc_commandline_progname);
}
dst_key_settime(key, DST_TIME_REVOKE,
ctx->revokekey);
if (ctx->setrev) {
if (!ctx->wantksk) {
fprintf(stderr,
"%s: warning: Key is not flagged "
"as a KSK, but -R was used. Revoking "
"a ZSK is legal, but undefined.\n",
isc_commandline_progname);
}
dst_key_settime(key, DST_TIME_REVOKE, ctx->revokekey);
}
if (ctx->setinact) {
dst_key_settime(key, DST_TIME_INACTIVE,
ctx->inactive);
}
if (ctx->setinact) {
dst_key_settime(key, DST_TIME_INACTIVE, ctx->inactive);
}
if (ctx->setdel) {
if (ctx->setinact &&
ctx->deltime < ctx->inactive)
{
fprintf(stderr,
"%s: warning: Key is "
"scheduled to be deleted "
"before it is scheduled to be "
"made inactive.\n",
isc_commandline_progname);
}
dst_key_settime(key, DST_TIME_DELETE,
ctx->deltime);
if (ctx->setdel) {
if (ctx->setinact && ctx->deltime < ctx->inactive) {
fprintf(stderr,
"%s: warning: Key is scheduled to be "
"deleted before it is scheduled to be "
"made inactive.\n",
isc_commandline_progname);
}
dst_key_settime(key, DST_TIME_DELETE, ctx->deltime);
}
if (ctx->setsyncadd) {
dst_key_settime(key, DST_TIME_SYNCPUBLISH,
ctx->syncadd);
}
if (ctx->setsyncadd) {
dst_key_settime(key, DST_TIME_SYNCPUBLISH,
ctx->syncadd);
}
if (ctx->setsyncdel) {
dst_key_settime(key, DST_TIME_SYNCDELETE,
ctx->syncdel);
}
} else {
if (ctx->setpub || ctx->setact || ctx->setrev ||
ctx->setinact || ctx->setdel || ctx->unsetpub ||
ctx->unsetact || ctx->unsetrev || ctx->unsetinact ||
ctx->unsetdel || ctx->genonly || ctx->setsyncadd ||
ctx->setsyncdel)
{
fatal("cannot use -C together with "
"-P, -A, -R, -I, -D, or -G options");
}
/*
* Compatibility mode: Private-key-format
* should be set to 1.2.
*/
dst_key_setprivateformat(key, 1, 2);
if (ctx->setsyncdel) {
dst_key_settime(key, DST_TIME_SYNCDELETE, ctx->syncdel);
}
/* Set the default key TTL */
@ -852,7 +816,7 @@ main(int argc, char **argv) {
}
break;
case 'C':
ctx.oldstyle = true;
fatal("The -C option has been deprecated.");
break;
case 'c':
classname = isc_commandline_argument;
@ -1109,9 +1073,6 @@ main(int argc, char **argv) {
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");
}

View file

@ -21,7 +21,7 @@ dnssec-keygen: DNSSEC key generation tool
Synopsis
~~~~~~~~
:program:`dnssec-keygen` [**-3**] [**-A** date/offset] [**-a** algorithm] [**-b** keysize] [**-C**] [**-c** class] [**-D** date/offset] [**-D** sync date/offset] [**-f** flag] [**-F**] [**-G**] [**-h**] [**-I** date/offset] [**-i** interval] [**-K** directory] [**-k** policy] [**-L** ttl] [**-l** file] [**-M** tag_min:tag_max] [**-P** date/offset] [**-P** sync date/offset] [**-p** protocol] [**-q**] [**-R** date/offset] [**-S** key] [**-s** strength] [**-T** rrtype] [**-V**] [**-v** level] {name}
:program:`dnssec-keygen` [**-3**] [**-A** date/offset] [**-a** algorithm] [**-b** keysize] [**-c** class] [**-D** date/offset] [**-D** sync date/offset] [**-f** flag] [**-F**] [**-G**] [**-h**] [**-I** date/offset] [**-i** interval] [**-K** directory] [**-k** policy] [**-L** ttl] [**-l** file] [**-M** tag_min:tag_max] [**-P** date/offset] [**-P** sync date/offset] [**-p** protocol] [**-q**] [**-R** date/offset] [**-S** key] [**-s** strength] [**-T** rrtype] [**-V**] [**-v** level] {name}
Description
~~~~~~~~~~~
@ -76,15 +76,6 @@ Options
have a default size of 1024 bits; RSA keys for use as key-signing
keys (KSKs, generated with :option:`-f KSK <-f>`) default to 2048 bits.
.. option:: -C
This option enables compatibility mode, which generates an old-style key, without any timing
metadata. By default, :program:`dnssec-keygen` includes the key's
creation date in the metadata stored with the private key; other
dates may be set there as well, including publication date, activation date,
etc. Keys that include this data may be incompatible with older
versions of BIND; the :option:`-C` option suppresses them.
.. option:: -c class
This option indicates that the DNS record containing the key should have the

View file

@ -179,11 +179,7 @@ main(int argc, char **argv) {
fprintf(stderr, "%s: %s\n", isc_commandline_progname, keystr);
}
if (force) {
set_keyversion(key);
} else {
check_keyversion(key, keystr);
}
check_keyversion(key, keystr);
flags = dst_key_flags(key);
if ((flags & DNS_KEYFLAG_REVOKE) == 0) {

View file

@ -50,8 +50,6 @@ usage(int ret) {
isc_commandline_progname);
fprintf(stderr, "Version: %s\n", PACKAGE_VERSION);
fprintf(stderr, "General options:\n");
fprintf(stderr, " -f: force update of old-style "
"keys\n");
fprintf(stderr, " -K directory: set key file location\n");
fprintf(stderr, " -L ttl: set default key TTL\n");
fprintf(stderr, " -v level: set level of verbosity\n");
@ -221,7 +219,6 @@ main(int argc, char **argv) {
bool printcreate = false, printpub = false;
bool printact = false, printrev = false;
bool printinact = false, printdel = false;
bool force = false;
bool epoch = false;
bool changed = false;
bool write_state = false;
@ -313,7 +310,7 @@ main(int argc, char **argv) {
fatal("%s", isc_result_totext(DST_R_NOENGINE));
break;
case 'f':
force = true;
fatal("The -f option has been deprecated");
break;
case 'g':
if (setgoal) {
@ -724,11 +721,7 @@ main(int argc, char **argv) {
isc_commandline_progname);
}
if (force) {
set_keyversion(key);
} else {
check_keyversion(key, keystr);
}
check_keyversion(key, keystr);
if (verbose > 2) {
fprintf(stderr, "%s: %s\n", isc_commandline_progname, keystr);
@ -821,16 +814,6 @@ main(int argc, char **argv) {
dst_key_setnum(key, DST_NUM_PREDECESSOR, dst_key_id(prevkey));
}
/*
* No metadata changes were made but we're forcing an upgrade
* to the new format anyway: use "-P now -A now" as the default
*/
if (force && !changed) {
dst_key_settime(key, DST_TIME_PUBLISH, now);
dst_key_settime(key, DST_TIME_ACTIVATE, now);
changed = true;
}
/*
* Make sure the key state goals are written.
*/

View file

@ -21,7 +21,7 @@ dnssec-settime: set the key timing metadata for a DNSSEC key
Synopsis
~~~~~~~~
:program:`dnssec-settime` [**-f**] [**-K** directory] [**-L** ttl] [**-P** date/offset] [**-P** ds date/offset] [**-P** sync date/offset] [**-A** date/offset] [**-R** date/offset] [**-I** date/offset] [**-D** date/offset] [**-D** ds date/offset] [**-D** sync date/offset] [**-S** key] [**-i** interval] [**-h**] [**-V**] [**-v** level] {keyfile} [**-s**] [**-g** state] [**-d** state date/offset] [**-k** state date/offset] [**-r** state date/offset] [**-z** state date/offset]
:program:`dnssec-settime` [**-K** directory] [**-L** ttl] [**-P** date/offset] [**-P** ds date/offset] [**-P** sync date/offset] [**-A** date/offset] [**-R** date/offset] [**-I** date/offset] [**-D** date/offset] [**-D** ds date/offset] [**-D** sync date/offset] [**-S** key] [**-i** interval] [**-h**] [**-V**] [**-v** level] {keyfile} [**-s**] [**-g** state] [**-d** state date/offset] [**-k** state date/offset] [**-r** state date/offset] [**-z** state date/offset]
Description
~~~~~~~~~~~
@ -61,16 +61,6 @@ purposes.
Options
~~~~~~~
.. option:: -f
This option forces an update of an old-format key with no metadata fields. Without
this option, :program:`dnssec-settime` fails when attempting to update a
legacy key. With this option, the key is recreated in the new
format, but with the original key data retained. The key's creation
date is set to the present time. If no other values are
specified, then the key's publication and activation dates are also
set to the present time.
.. option:: -K directory
This option sets the directory in which the key files are to reside.

View file

@ -431,27 +431,6 @@ check_keyversion(dst_key_t *key, char *keystr) {
}
}
void
set_keyversion(dst_key_t *key) {
int major, minor;
dst_key_getprivateformat(key, &major, &minor);
INSIST(major <= DST_MAJOR_VERSION);
if (major != DST_MAJOR_VERSION || minor != DST_MINOR_VERSION) {
dst_key_setprivateformat(key, DST_MAJOR_VERSION,
DST_MINOR_VERSION);
}
/*
* If the key is from a version older than 1.3, set
* set the creation date
*/
if (major < 1 || (major == 1 && minor <= 2)) {
isc_stdtime_t now = isc_stdtime_now();
dst_key_settime(key, DST_TIME_CREATED, now);
}
}
bool
key_collision(dst_key_t *dstkey, dns_name_t *name, const char *dir,
isc_mem_t *mctx, uint16_t min, uint16_t max, bool *exact) {

View file

@ -98,9 +98,6 @@ try_dir(const char *dirname);
void
check_keyversion(dst_key_t *key, char *keystr);
void
set_keyversion(dst_key_t *key);
bool
key_collision(dst_key_t *dstkey, dns_name_t *name, const char *dir,
isc_mem_t *mctx, uint16_t min, uint16_t max, bool *exact);

View file

@ -54,6 +54,3 @@ echo $pzsk >parent.zsk.key
pksk=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -fk $pzone)
echo $pksk >parent.ksk.key
oldstyle=$($KEYGEN -Cq -a ${DEFAULT_ALGORITHM} $pzone)
echo $oldstyle >oldstyle.key

View file

@ -127,24 +127,13 @@ n=$((n + 1))
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
echo_i "checking update of an old-style key ($n)"
ret=0
# printing metadata should not work with an old-style key
$SETTIME -pall $(cat oldstyle.key) >/dev/null 2>&1 && ret=1
$SETTIME -f $(cat oldstyle.key) >/dev/null 2>&1 || ret=1
# but now it should
$SETTIME -pall $(cat oldstyle.key) >/dev/null 2>&1 || ret=1
n=$((n + 1))
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
echo_i "checking warning about permissions change on key with dnssec-settime ($n)"
ret=0
# settime should print a warning about changing the permissions
chmod 644 $(cat oldstyle.key).private
$SETTIME -P none $(cat oldstyle.key) >settime1.test$n 2>&1 || ret=1
chmod 644 $(cat inact.key).private
$SETTIME -P none $(cat inact.key) >settime1.test$n 2>&1 || ret=1
grep "warning: Permissions on the file.*have changed" settime1.test$n >/dev/null 2>&1 || ret=1
$SETTIME -P none $(cat oldstyle.key) >settime2.test$n 2>&1 || ret=1
$SETTIME -P none $(cat inact.key) >settime2.test$n 2>&1 || ret=1
grep "warning: Permissions on the file.*have changed" settime2.test$n >/dev/null 2>&1 && ret=1
n=$((n + 1))
if [ $ret != 0 ]; then echo_i "failed"; fi
@ -153,7 +142,7 @@ status=$((status + ret))
echo_i "checking warning about delete date < inactive date with dnssec-settime ($n)"
ret=0
# settime should print a warning about delete < inactive
$SETTIME -I now+15s -D now $(cat oldstyle.key) >tmp.out 2>&1 || ret=1
$SETTIME -I now+15s -D now $(cat inact.key) >tmp.out 2>&1 || ret=1
grep "warning" tmp.out >/dev/null 2>&1 || ret=1
n=$((n + 1))
if [ $ret != 0 ]; then echo_i "failed"; fi
@ -161,8 +150,8 @@ status=$((status + ret))
echo_i "checking no warning about delete date < inactive date with dnssec-settime when delete date is unset ($n)"
ret=0
$SETTIME -D none $(cat oldstyle.key) >tmp.out 2>&1 || ret=1
$SETTIME -p all $(cat oldstyle.key) >tmp.out 2>&1 || ret=1
$SETTIME -D none $(cat inact.key) >tmp.out 2>&1 || ret=1
$SETTIME -p all $(cat inact.key) >tmp.out 2>&1 || ret=1
grep "warning" tmp.out >/dev/null 2>&1 && ret=1
n=$((n + 1))
if [ $ret != 0 ]; then echo_i "failed"; fi

View file

@ -13,5 +13,5 @@
. ../conf.sh
key=$($KEYGEN -Cq -K ns1 -a $DEFAULT_ALGORITHM -b $DEFAULT_BITS -T KEY key.example.nil.)
key=$($KEYGEN -q -K ns1 -a $DEFAULT_ALGORITHM -b $DEFAULT_BITS -T KEY key.example.nil.)
cat ns1/example.nil.db.in ns1/${key}.key >ns1/example.nil.db