* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: dnssec-keyfromlabel.c,v 1.11 2009/09/03 13:43:52 fdupont Exp $ */
+/* $Id: dnssec-keyfromlabel.c,v 1.12 2009/09/07 12:54:59 fdupont Exp $ */
/*! \file */
#include <config.h>
+#include <ctype.h>
#include <stdlib.h>
#include <isc/buffer.h>
fprintf(stderr, "Version: %s\n", VERSION);
fprintf(stderr, "Required options:\n");
fprintf(stderr, " -a algorithm: %s\n", algs);
- fprintf(stderr, " -l label: label of the key\n");
+ fprintf(stderr, " -l label: label of the keys\n");
fprintf(stderr, " name: owner of the key\n");
fprintf(stderr, "Other options:\n");
- fprintf(stderr, " -n nametype: ZONE | HOST | ENTITY | USER | OTHER\n");
- fprintf(stderr, " (DNSKEY generation defaults to ZONE\n");
fprintf(stderr, " -c <class> (default: IN)\n");
- fprintf(stderr, " -f keyflag (KSK or REVOKE)\n");
+ fprintf(stderr, " -f keyflag: KSK | REVOKE\n");
fprintf(stderr, " -K directory: directory in which to place "
"key files\n");
+ fprintf(stderr, " -k : generate a TYPE=KEY key\n");
+ fprintf(stderr, " -n nametype: ZONE | HOST | ENTITY | USER | OTHER\n");
+ fprintf(stderr, " (DNSKEY generation defaults to ZONE\n");
+ fprintf(stderr, " -p <protocol>: default: 3 [dnssec]\n");
fprintf(stderr, " -t <type>: "
"AUTHCONF | NOAUTHCONF | NOAUTH | NOCONF "
"(default: AUTHCONF)\n");
- fprintf(stderr, " -p <protocol>: "
- "default: 3 [dnssec]\n");
fprintf(stderr, " -v <verbose level>\n");
- fprintf(stderr, " -k : generate a TYPE=KEY key\n");
+ fprintf(stderr, "Date options:\n");
+ fprintf(stderr, " -P date/[+-]offset: set key publication date\n");
+ fprintf(stderr, " -A date/[+-]offset: set key activation date\n");
+ fprintf(stderr, " -R date/[+-]offset: set key revocation date\n");
+ fprintf(stderr, " -U date/[+-]offset: set key unpublication date\n");
+ fprintf(stderr, " -D date/[+-]offset: set key deletion date\n");
+ fprintf(stderr, " -C: generate a backward-compatible key, omitting"
+ " dates\n");
fprintf(stderr, "Output:\n");
fprintf(stderr, " K<name>+<alg>+<id>.key, "
- "K<name>+<alg>+<id>.private\n");
+ "K<name>+<alg>+<id>.private\n");
exit (-1);
}
int
main(int argc, char **argv) {
char *algname = NULL, *nametype = NULL, *type = NULL;
- char *directory = NULL;
+ const char *directory = NULL;
char *classname = NULL;
char *endp;
dst_key_t *key = NULL, *oldkey = NULL;
dns_fixedname_t fname;
dns_name_t *name;
- isc_uint16_t flags = 0, ksk = 0, revoke = 0;
+ isc_uint16_t flags = 0, kskflag = 0, revflag = 0;
dns_secalg_t alg;
- isc_boolean_t null_key = ISC_FALSE;
+ isc_boolean_t oldstyle = ISC_FALSE;
isc_mem_t *mctx = NULL;
int ch;
int protocol = -1, signatory = 0;
isc_entropy_t *ectx = NULL;
dns_rdataclass_t rdclass;
int options = DST_TYPE_PRIVATE | DST_TYPE_PUBLIC;
- char *label = NULL;
+ char *label = NULL, *engine = NULL;
+ isc_stdtime_t publish = 0, activate = 0, revoke = 0;
+ isc_stdtime_t unpublish = 0, delete = 0;
+ isc_stdtime_t now;
+ isc_boolean_t setpub = ISC_FALSE, setact = ISC_FALSE;
+ isc_boolean_t setrev = ISC_FALSE, setunpub = ISC_FALSE;
+ isc_boolean_t setdel = ISC_FALSE;
+ isc_boolean_t unsetpub = ISC_FALSE, unsetact = ISC_FALSE;
+ isc_boolean_t unsetrev = ISC_FALSE, unsetunpub = ISC_FALSE;
+ isc_boolean_t unsetdel = ISC_FALSE;
if (argc == 1)
usage();
isc_commandline_errprint = ISC_FALSE;
+ isc_stdtime_get(&now);
+
while ((ch = isc_commandline_parse(argc, argv,
- "a:c:f:K:kl:n:p:t:v:Fh")) != -1)
+ "a:Cc:f:K:kl:n:p:t:v:FhP:A:R:U:D:")) != -1)
{
switch (ch) {
case 'a':
algname = isc_commandline_argument;
break;
+ case 'C':
+ oldstyle = ISC_TRUE;
+ break;
case 'c':
classname = isc_commandline_argument;
break;
case 'f':
- if (strcasecmp(isc_commandline_argument, "KSK") == 0)
- ksk = DNS_KEYFLAG_KSK;
- else if (strcasecmp(isc_commandline_argument,
- "REVOKE") == 0)
- revoke = DNS_KEYFLAG_REVOKE;
+ if (toupper(isc_commandline_argument[0]) == 'K')
+ kskflag = DNS_KEYFLAG_KSK;
+ else if (toupper(isc_commandline_argument[0]) == 'R')
+ revflag = DNS_KEYFLAG_REVOKE;
else
fatal("unknown flag '%s'",
isc_commandline_argument);
if (*endp != '\0')
fatal("-v must be followed by a number");
break;
+ case 'P':
+ if (setpub || unsetpub)
+ fatal("-P specified more than once");
+
+ if (strcasecmp(isc_commandline_argument, "none")) {
+ setpub = ISC_TRUE;
+ publish = strtotime(isc_commandline_argument,
+ now, now);
+ } else {
+ unsetpub = ISC_TRUE;
+ }
+ break;
+ case 'A':
+ if (setact || unsetact)
+ fatal("-A specified more than once");
+
+ if (strcasecmp(isc_commandline_argument, "none")) {
+ setact = ISC_TRUE;
+ activate = strtotime(isc_commandline_argument,
+ now, now);
+ } else {
+ unsetact = ISC_TRUE;
+ }
+ break;
+ case 'R':
+ if (setrev || unsetrev)
+ fatal("-R specified more than once");
+
+ if (strcasecmp(isc_commandline_argument, "none")) {
+ setrev = ISC_TRUE;
+ revoke = strtotime(isc_commandline_argument,
+ now, now);
+ } else {
+ unsetrev = ISC_TRUE;
+ }
+ break;
+ case 'U':
+ if (setunpub || unsetunpub)
+ fatal("-U specified more than once");
+
+ if (strcasecmp(isc_commandline_argument, "none")) {
+ setunpub = ISC_TRUE;
+ unpublish = strtotime(isc_commandline_argument,
+ now, now);
+ } else {
+ unsetunpub = ISC_TRUE;
+ }
+ break;
+ case 'D':
+ if (setdel || unsetdel)
+ fatal("-D specified more than once");
+
+ if (strcasecmp(isc_commandline_argument, "none")) {
+ setdel = ISC_TRUE;
+ delete = strtotime(isc_commandline_argument,
+ now, now);
+ } else {
+ unsetdel = ISC_TRUE;
+ }
+ break;
case 'F':
/* Reserved for FIPS mode */
/* FALLTHROUGH */
rdclass = strtoclass(classname);
+ if (directory == NULL)
+ directory = ".";
+
if ((options & DST_TYPE_KEY) != 0) /* KEY */
flags |= signatory;
else if ((flags & DNS_KEYOWNER_ZONE) != 0) { /* DNSKEY */
- flags |= ksk;
- flags |= revoke;
+ flags |= kskflag;
+ flags |= revflag;
}
if (protocol == -1)
fatal("invalid key name %s: %s", argv[isc_commandline_index],
isc_result_totext(ret));
- if ((flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY)
- null_key = ISC_TRUE;
-
isc_buffer_init(&buf, filename, sizeof(filename) - 1);
/* associate the key */
ret = dst_key_fromlabel(name, alg, flags, protocol,
- rdclass, "", label, NULL, mctx, &key);
+ rdclass, engine, label, NULL, mctx, &key);
isc_entropy_stopcallbacksources(ectx);
if (ret != ISC_R_SUCCESS) {
char algstr[ALG_FORMATSIZE];
dns_name_format(name, namestr, sizeof(namestr));
alg_format(alg, algstr, sizeof(algstr));
- fatal("failed to generate key %s/%s: %s\n",
+ fatal("failed to get key %s/%s: %s\n",
namestr, algstr, isc_result_totext(ret));
exit(-1);
}
+ /*
+ * Set key timing metadata (unless using -C)
+ */
+ if (!oldstyle) {
+ dst_key_settime(key, DST_TIME_CREATED, now);
+
+ if (setpub)
+ dst_key_settime(key, DST_TIME_PUBLISH, publish);
+ if (setact)
+ dst_key_settime(key, DST_TIME_ACTIVATE, activate);
+ if (setrev)
+ dst_key_settime(key, DST_TIME_REVOKE, revoke);
+ if (setunpub)
+ dst_key_settime(key, DST_TIME_UNPUBLISH, unpublish);
+ if (setdel)
+ dst_key_settime(key, DST_TIME_DELETE, delete);
+ } else {
+ if (setpub || setact || setrev || setunpub ||
+ setdel || unsetpub || unsetact ||
+ unsetrev || unsetunpub || unsetdel)
+ fatal("cannot use -C together with "
+ "-P, -A, -R, -U, or -D options");
+ /*
+ * Compatibility mode: Private-key-format
+ * should be set to 1.2.
+ */
+ dst_key_setprivateformat(key, 1, 2);
+ }
+
/*
* Try to read a key with the same name, alg and id from disk.
- * If there is one we must continue generating a new one
- * unless we were asked to generate a null key, in which
- * case we return failure.
+ * If there is one we must return failure.
*/
ret = dst_key_fromfile(name, dst_key_id(key), alg,
DST_TYPE_PRIVATE, directory, mctx, &oldkey);
if (ret == ISC_R_SUCCESS) {
isc_buffer_clear(&buf);
ret = dst_key_buildfilename(key, 0, directory, &buf);
- fprintf(stderr, "%s: %s already exists\n",
- program, filename);
- dst_key_free(&key);
- exit (1);
+ fatal("%s: %s already exists\n", program, filename);
}
ret = dst_key_tofile(key, options, directory);
}
isc_buffer_clear(&buf);
- ret = dst_key_buildfilename(key, 0, directory, &buf);
+ ret = dst_key_buildfilename(key, 0, NULL, &buf);
printf("%s\n", filename);
dst_key_free(&key);
- PERFORMANCE OF THIS SOFTWARE.
-->
-<!-- $Id: dnssec-keyfromlabel.docbook,v 1.8 2009/07/19 23:47:55 tbox Exp $ -->
+<!-- $Id: dnssec-keyfromlabel.docbook,v 1.9 2009/09/07 12:54:59 fdupont Exp $ -->
<refentry id="man.dnssec-keyfromlabel">
<refentryinfo>
<date>February 8, 2008</date>
<command>dnssec-keyfromlabel</command>
<arg choice="req">-a <replaceable class="parameter">algorithm</replaceable></arg>
<arg choice="req">-l <replaceable class="parameter">label</replaceable></arg>
+ <arg><option>-A <replaceable class="parameter">date/offset</replaceable></option></arg>
<arg><option>-c <replaceable class="parameter">class</replaceable></option></arg>
+ <arg><option>-D <replaceable class="parameter">date/offset</replaceable></option></arg>
<arg><option>-f <replaceable class="parameter">flag</replaceable></option></arg>
<arg><option>-k</option></arg>
<arg><option>-K <replaceable class="parameter">directory</replaceable></option></arg>
<arg><option>-n <replaceable class="parameter">nametype</replaceable></option></arg>
+ <arg><option>-P <replaceable class="parameter">date/offset</replaceable></option></arg>
<arg><option>-p <replaceable class="parameter">protocol</replaceable></option></arg>
+ <arg><option>-R <replaceable class="parameter">date/offset</replaceable></option></arg>
<arg><option>-t <replaceable class="parameter">type</replaceable></option></arg>
+ <arg><option>-U <replaceable class="parameter">date/offset</replaceable></option></arg>
<arg><option>-v <replaceable class="parameter">level</replaceable></option></arg>
<arg choice="req">name</arg>
</cmdsynopsis>
key files for DNSSEC (Secure DNS), as defined in RFC 2535
and RFC 4034.
</para>
+ <para>
+ The <option>name</option> of the key is specified on the command
+ line. This must match the name of the zone for which the key is
+ being generated.
+ </para>
</refsect1>
<refsect1>
<listitem>
<para>
Selects the cryptographic algorithm. The value of
- <option>algorithm</option> must be one of RSAMD5 (RSA)
- or RSASHA1, DSA, NSEC3RSASHA1, NSEC3DSA or DH (Diffie Hellman).
+ <option>algorithm</option> must be one of RSAMD5 (RSA),
+ RSASHA1, DSA, NSEC3RSASHA1, NSEC3DSA or DH (Diffie Hellman).
These values are case insensitive.
</para>
<para>
zone key (KEY/DNSKEY)), HOST or ENTITY (for a key associated with
a host (KEY)),
USER (for a key associated with a user(KEY)) or OTHER (DNSKEY).
- These values are
- case insensitive.
+ These values are case insensitive.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-C</term>
+ <listitem>
+ <para>
+ Compatibility mode: generates an old-style key, without
+ any metadata. By default, <command>dnssec-keyfromlabel</command>
+ will include the key's creation date in the metadata stored
+ with the private key, and other dates may be set there as well
+ (publication date, activation date, etc). Keys that include
+ this data may be incompatible with older versions of BIND; the
+ <option>-C</option> option suppresses them.
</para>
</listitem>
</varlistentry>
<listitem>
<para>
Set the specified flag in the flag field of the KEY/DNSKEY record.
- The only recognized flag is KSK (Key Signing Key) DNSKEY.
+ The only recognized flags are KSK (Key Signing Key) and REVOKE.
</para>
</listitem>
</varlistentry>
<listitem>
<para>
Prints a short summary of the options and arguments to
- <command>dnssec-keygen</command>.
+ <command>dnssec-keyfromlabel</command>.
</para>
</listitem>
</varlistentry>
<term>-p <replaceable class="parameter">protocol</replaceable></term>
<listitem>
<para>
- Sets the protocol value for the generated key. The protocol
+ Sets the protocol value for the key. The protocol
is a number between 0 and 255. The default is 3 (DNSSEC).
Other possible values for this argument are listed in
RFC 2535 and its successors.
</variablelist>
</refsect1>
+ <refsect1>
+ <title>TIMING OPTIONS</title>
+
+ <para>
+ Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS.
+ If the argument begins with a '+' or '-', it is interpreted as
+ an offset from the present time. For convenience, if such an offset
+ is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi',
+ then the offset is computed in years (defined as 365 24-hour days,
+ ignoring leap years), months (defined as 30 24-hour days), weeks,
+ days, hours, or minutes, respectively. Without a suffix, the offset
+ is computed in seconds.
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term>-P <replaceable class="parameter">date/offset</replaceable></term>
+ <listitem>
+ <para>
+ Sets the date on which a key is to be published to the zone.
+ After that date, the key will be included in the zone but will
+ not be used to sign it.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-A <replaceable class="parameter">date/offset</replaceable></term>
+ <listitem>
+ <para>
+ Sets the date on which the key is to be activated. After that
+ date, the key will be included and the zone and used to sign
+ it.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-R <replaceable class="parameter">date/offset</replaceable></term>
+ <listitem>
+ <para>
+ Sets the date on which the key is to be revoked. After that
+ date, the key will be flagged as revoked. It will be included
+ in the zone and will be used to sign it.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-U <replaceable class="parameter">date/offset</replaceable></term>
+ <listitem>
+ <para>
+ Sets the date on which the key is to be unpublished. After that
+ date, the key will no longer be included in the zone, but it
+ may remain in the key repository.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-D <replaceable class="parameter">date/offset</replaceable></term>
+ <listitem>
+ <para>
+ Sets the date on which the key is to be deleted. After that
+ date, the key can be removed from the key repository.
+ NOTE: Keys are not currently deleted automatically; this field
+ is included for informational purposes and for future
+ development.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
<refsect1>
<title>GENERATED KEY FILES</title>
<para>
</listitem>
<listitem>
<para><filename>aaa</filename> is the numeric representation
- of the
- algorithm.
+ of the algorithm.
</para>
</listitem>
<listitem>
on the printed string. <filename>Knnnn.+aaa+iiiii.key</filename>
contains the public key, and
<filename>Knnnn.+aaa+iiiii.private</filename> contains the
- private
- key.
+ private key.
</para>
<para>
The <filename>.key</filename> file contains a DNS KEY record
statement).
</para>
<para>
- The <filename>.private</filename> file contains algorithm
- specific
+ The <filename>.private</filename> file contains
+ algorithm-specific
fields. For obvious security reasons, this file does not have
general read permission.
</para>
/*
* Principal Author: Brian Wellington
- * $Id: opensslrsa_link.c,v 1.26 2009/09/03 04:09:58 marka Exp $
+ * $Id: opensslrsa_link.c,v 1.27 2009/09/07 12:54:59 fdupont Exp $
*/
#ifdef OPENSSL
#ifndef USE_EVP
RSA *rsa = NULL, *pubrsa = NULL;
ENGINE *e = NULL;
isc_mem_t *mctx = key->mctx;
- const char *name = NULL, *label = NULL;
+ const char *engine = NULL, *label = NULL;
EVP_PKEY *pkey = NULL;
#if USE_EVP
for (i = 0; i < priv.nelements; i++) {
switch (priv.elements[i].tag) {
case TAG_RSA_ENGINE:
- name = (char *)priv.elements[i].data;
+ engine = (char *)priv.elements[i].data;
break;
case TAG_RSA_LABEL:
label = (char *)priv.elements[i].data;
* Is this key is stored in a HSM?
* See if we can fetch it.
*/
- if (name != NULL || label != NULL) {
- INSIST(name != NULL);
- INSIST(label != NULL);
- e = dst__openssl_getengine(name);
+ if (label != NULL) {
+ if (engine == NULL)
+ DST_RET(DST_R_NOENGINE);
+ e = dst__openssl_getengine(engine);
if (e == NULL)
DST_RET(DST_R_NOENGINE);
pkey = ENGINE_load_private_key(e, label, NULL, NULL);
/* ERR_print_errors_fp(stderr); */
DST_RET(ISC_R_NOTFOUND);
}
- key->engine = isc_mem_strdup(key->mctx, name);
+ key->engine = isc_mem_strdup(key->mctx, engine);
if (key->engine == NULL)
DST_RET(ISC_R_NOMEMORY);
key->label = isc_mem_strdup(key->mctx, label);
DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
if (rsa_check(rsa, pubrsa) != ISC_R_SUCCESS)
DST_RET(DST_R_INVALIDPRIVATEKEY);
+ if (pubrsa != NULL)
+ RSA_free(pubrsa);
key->key_size = EVP_PKEY_bits(pkey);
#if USE_EVP
key->keydata.pkey = pkey;
+ RSA_free(rsa);
#else
key->keydata.rsa = rsa;
EVP_PKEY_free(pkey);
pkey = EVP_PKEY_new();
if (pkey == NULL)
DST_RET(ISC_R_NOMEMORY);
- if (!EVP_PKEY_set1_RSA(pkey, rsa)) {
+ if (!EVP_PKEY_set1_RSA(pkey, rsa))
DST_RET(ISC_R_FAILURE);
- }
key->keydata.pkey = pkey;
#else
key->keydata.rsa = rsa;
ENGINE *e = NULL;
isc_result_t ret;
EVP_PKEY *pkey = NULL;
+ RSA *rsa = NULL, *pubrsa = NULL;
+ char *colon;
UNUSED(pin);
e = dst__openssl_getengine(engine);
if (e == NULL)
DST_RET(DST_R_NOENGINE);
+ pkey = ENGINE_load_public_key(e, label, NULL, NULL);
+ if (pkey != NULL) {
+ pubrsa = EVP_PKEY_get1_RSA(pkey);
+ EVP_PKEY_free(pkey);
+ if (pubrsa == NULL)
+ DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
+ }
pkey = ENGINE_load_private_key(e, label, NULL, NULL);
if (pkey == NULL)
DST_RET(ISC_R_NOTFOUND);
- key->engine = isc_mem_strdup(key->mctx, label);
- if (key->engine == NULL)
- DST_RET(ISC_R_NOMEMORY);
+ if (engine != NULL) {
+ key->engine = isc_mem_strdup(key->mctx, engine);
+ if (key->engine == NULL)
+ DST_RET(ISC_R_NOMEMORY);
+ } else {
+ key->engine = isc_mem_strdup(key->mctx, label);
+ if (key->engine == NULL)
+ DST_RET(ISC_R_NOMEMORY);
+ colon = strchr(key->engine, ':');
+ if (colon != NULL)
+ *colon = '\0';
+ }
key->label = isc_mem_strdup(key->mctx, label);
if (key->label == NULL)
DST_RET(ISC_R_NOMEMORY);
+ rsa = EVP_PKEY_get1_RSA(pkey);
+ if (rsa == NULL)
+ DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
+ if (rsa_check(rsa, pubrsa) != ISC_R_SUCCESS)
+ DST_RET(DST_R_INVALIDPRIVATEKEY);
+ if (pubrsa != NULL)
+ RSA_free(pubrsa);
key->key_size = EVP_PKEY_bits(pkey);
#if USE_EVP
key->keydata.pkey = pkey;
+ RSA_free(rsa);
#else
- key->keydata.rsa = EVP_PKEY_get1_RSA(pkey);
+ key->keydata.rsa = rsa;
EVP_PKEY_free(pkey);
- if (key->keydata.rsa == NULL)
- return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
#endif
return (ISC_R_SUCCESS);
err:
+ if (rsa != NULL)
+ RSA_free(rsa);
+ if (pubrsa != NULL)
+ RSA_free(pubrsa);
if (pkey != NULL)
EVP_PKEY_free(pkey);
return (ret);