static void
kasp_from_conf(cfg_obj_t *config, isc_mem_t *mctx, const char *name,
- dns_kasp_t **kaspp) {
+ const char *engine, dns_kasp_t **kaspp) {
isc_result_t result = ISC_R_NOTFOUND;
const cfg_listelt_t *element;
const cfg_obj_t *kasps = NULL;
{
cfg_obj_t *kconfig = cfg_listelt_value(element);
ks = NULL;
- result = cfg_keystore_fromconfig(kconfig, mctx, lctx, &kslist,
- &ks);
+ result = cfg_keystore_fromconfig(kconfig, mctx, lctx, engine,
+ &kslist, &ks);
if (result != ISC_R_SUCCESS) {
fatal("failed to configure key-store '%s': %s",
cfg_obj_asstring(cfg_tuple_get(kconfig, "name")),
ctx.policy, ctx.configfile);
}
- kasp_from_conf(config, mctx, ctx.policy, &kasp);
+ kasp_from_conf(config, mctx, ctx.policy, engine, &kasp);
if (kasp == NULL) {
fatal("failed to load dnssec-policy '%s'",
ctx.policy);
AM_CONDITIONAL([HAVE_LIBNGHTTP2], [test -n "$LIBNGHTTP2_LIBS"])
-
#
# flockfile is usually provided by pthreads
#
#include <dns/types.h>
+#include <dst/dst.h>
+
ISC_LANG_BEGINDECLS
/* Key store */
#define DNS_KEYSTORE_KEYDIRECTORY "key-directory"
isc_result_t
-dns_keystore_create(isc_mem_t *mctx, const char *name, dns_keystore_t **kspp);
+dns_keystore_create(isc_mem_t *mctx, const char *name, const char *engine,
+ dns_keystore_t **kspp);
/*%<
* Create a key store.
*
*
*\li 'name' is a valid C string.
*
+ *\li 'engine' is the name of the OpenSSL engine to use, may be NULL.
+ *
*\li kspp != NULL && *kspp == NULL
*
* Returns:
*\li name of 'keystore'.
*/
+const char *
+dns_keystore_engine(dns_keystore_t *keystore);
+/*%<
+ * Get keystore engine.
+ *
+ * Requires:
+ *
+ *\li 'keystore' is a valid keystore.
+ *
+ * Returns:
+ *
+ *\li engine of 'keystore'. May be NULL.
+ */
+
const char *
dns_keystore_directory(dns_keystore_t *keystore);
/*%<
*
*/
+isc_result_t
+dns_keystore_keygen(dns_keystore_t *keystore, const dns_name_t *origin,
+ dns_rdataclass_t rdclass, isc_mem_t *mctx, uint32_t alg,
+ int size, int flags, dst_key_t **dstkey);
+/*%<
+ * Create a DNSSEC key pair. Set keystore PKCS#11 URI.
+ *
+ * Requires:
+ *
+ *\li 'keystore' is a valid keystore.
+ *
+ *\li 'origin' is a valid DNS owner name.
+ *
+ *\li 'mctx' is a valid memory context.
+ *
+ *\li 'dstkey' is not NULL and '*dstkey' is NULL.
+ *
+ */
+
isc_result_t
dns_keystorelist_find(dns_keystorelist_t *list, const char *name,
dns_keystore_t **kspp);
#include <isc/mem.h>
#include <isc/result.h>
#include <isc/string.h>
+#include <isc/time.h>
#include <isc/util.h>
#include <dns/dnssec.h>
dns_rdataclass_t rdclass, isc_mem_t *mctx,
dns_dnsseckeylist_t *keylist, dns_dnsseckeylist_t *newkeys,
dst_key_t **dst_key) {
- bool conflict = false;
- int keyflags = DNS_KEYOWNER_ZONE;
isc_result_t result = ISC_R_SUCCESS;
+ bool conflict = false;
+ int flags = DNS_KEYOWNER_ZONE;
dst_key_t *newkey = NULL;
+ uint32_t alg = dns_kasp_key_algorithm(kkey);
+ dns_keystore_t *keystore = dns_kasp_key_keystore(kkey);
+ int size = dns_kasp_key_size(kkey);
- do {
- uint32_t algo = dns_kasp_key_algorithm(kkey);
- int size = dns_kasp_key_size(kkey);
+ if (dns_kasp_key_ksk(kkey)) {
+ flags |= DNS_KEYFLAG_KSK;
+ }
- if (dns_kasp_key_ksk(kkey)) {
- keyflags |= DNS_KEYFLAG_KSK;
+ do {
+ if (keystore == NULL) {
+ RETERR(dst_key_generate(origin, alg, size, 0, flags,
+ DNS_KEYPROTO_DNSSEC, rdclass,
+ NULL, mctx, &newkey, NULL));
+ } else {
+ RETERR(dns_keystore_keygen(keystore, origin, rdclass,
+ mctx, alg, size, flags,
+ &newkey));
}
- RETERR(dst_key_generate(origin, algo, size, 0, keyflags,
- DNS_KEYPROTO_DNSSEC, rdclass, NULL,
- mctx, &newkey, NULL));
/* Key collision? */
conflict = keymgr_keyid_conflict(newkey, keylist);
int options = (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC | DST_TYPE_STATE);
char keystr[DST_KEY_FORMATSIZE];
- REQUIRE(DNS_KASP_VALID(kasp));
+ REQUIRE(dns_name_isvalid(origin));
+ REQUIRE(mctx != NULL);
REQUIRE(keyring != NULL);
+ REQUIRE(DNS_KASP_VALID(kasp));
ISC_LIST_INIT(newkeys);
/*! \file */
-#ifdef HAVE_GNUTLS
-#include <gnutls/crypto.h>
-#include <gnutls/pkcs11.h>
-#endif
-
#include <string.h>
#include <isc/assertions.h>
#include <isc/util.h>
#include <dns/keystore.h>
+#include <dns/keyvalues.h>
isc_result_t
-dns_keystore_create(isc_mem_t *mctx, const char *name, dns_keystore_t **kspp) {
+dns_keystore_create(isc_mem_t *mctx, const char *name, const char *engine,
+ dns_keystore_t **kspp) {
dns_keystore_t *keystore;
REQUIRE(name != NULL);
REQUIRE(kspp != NULL && *kspp == NULL);
keystore = isc_mem_get(mctx, sizeof(*keystore));
+ keystore->engine = engine;
keystore->mctx = NULL;
isc_mem_attach(mctx, &keystore->mctx);
static inline void
destroy(dns_keystore_t *keystore) {
+ char *name;
+
REQUIRE(!ISC_LINK_LINKED(keystore, link));
isc_mutex_destroy(&keystore->lock);
return (keystore->name);
}
+const char *
+dns_keystore_engine(dns_keystore_t *keystore) {
+ REQUIRE(DNS_KEYSTORE_VALID(keystore));
+
+ return (keystore->engine);
+}
+
const char *
dns_keystore_directory(dns_keystore_t *keystore) {
REQUIRE(DNS_KEYSTORE_VALID(keystore));
: isc_mem_strdup(keystore->mctx, uri);
}
+isc_result_t
+dns_keystore_keygen(dns_keystore_t *keystore, const dns_name_t *origin,
+ dns_rdataclass_t rdclass, isc_mem_t *mctx, uint32_t alg,
+ int size, int flags, dst_key_t **dstkey) {
+ isc_result_t result;
+ dst_key_t *newkey = NULL;
+ const char *uri = NULL;
+
+ REQUIRE(DNS_KEYSTORE_VALID(keystore));
+ REQUIRE(dns_name_isvalid(origin));
+ REQUIRE(mctx != NULL);
+ REQUIRE(dstkey != NULL && *dstkey == NULL);
+
+ uri = dns_keystore_pkcs11uri(keystore);
+ if (uri != NULL) {
+ dst_key_t *key = NULL;
+ char *label = NULL;
+ size_t len;
+ char timebuf[18];
+ isc_time_t now = isc_time_now();
+ bool ksk = ((flags & DNS_KEYFLAG_KSK) != 0);
+ char namebuf[DNS_NAME_FORMATSIZE];
+ char object[DNS_NAME_FORMATSIZE + 26];
+
+ /* Generate the key */
+ isc_time_formatshorttimestamp(&now, timebuf, sizeof(timebuf));
+ dns_name_format(origin, namebuf, sizeof(namebuf));
+ snprintf(object, sizeof(object), "%s-%s-%s", namebuf,
+ ksk ? "ksk" : "zsk", timebuf);
+
+ result = dst_key_generate(origin, alg, size, 0, flags,
+ DNS_KEYPROTO_DNSSEC, rdclass, object,
+ mctx, &key, NULL);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC,
+ DNS_LOGMODULE_DNSSEC, ISC_LOG_ERROR,
+ "keystore: failed to generate key "
+ "%s (ret=%d)",
+ object, result);
+ return (result);
+ }
+ dst_key_free(&key);
+
+ /* Retrieve generated key from label */
+ len = strlen(object) + strlen(uri) + 10;
+ label = isc_mem_get(mctx, len);
+ sprintf(label, "%s;object=%s;", uri, object);
+ result = dst_key_fromlabel(
+ origin, alg, flags, DNS_KEYPROTO_DNSSEC,
+ dns_rdataclass_in, dns_keystore_engine(keystore), label,
+ NULL, mctx, &newkey);
+
+ isc_mem_put(mctx, label, len);
+
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC,
+ DNS_LOGMODULE_DNSSEC, ISC_LOG_ERROR,
+ "keystore: failed to access key "
+ "%s (ret=%d)",
+ object, result);
+ return (result);
+ }
+ } else {
+ result = dst_key_generate(origin, alg, size, 0, flags,
+ DNS_KEYPROTO_DNSSEC, rdclass, NULL,
+ mctx, &newkey, NULL);
+ }
+
+ if (result == ISC_R_SUCCESS) {
+ *dstkey = newkey;
+ }
+ return (result);
+}
+
isc_result_t
dns_keystorelist_find(dns_keystorelist_t *list, const char *name,
dns_keystore_t **kspp) {
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
static isc_result_t
-opensslecdsa_generate_pkey(unsigned int key_alg, EVP_PKEY **retkey) {
+opensslecdsa_generate_pkey_with_object(int group_nid, const char *object,
+ EVP_PKEY **retkey) {
+ int status;
+ isc_result_t ret;
+ unsigned char id[16];
+ char *label = UNCONST(object);
+ EVP_PKEY_CTX *ctx = NULL;
+ OSSL_PARAM params[3];
+
+ /* Generate the key's parameters. */
+ status = RAND_bytes(id, 16);
+ if (status != 1) {
+ DST_RET(dst__openssl_toresult2("RAND_bytes",
+ DST_R_OPENSSLFAILURE));
+ }
+
+ params[0] = OSSL_PARAM_construct_utf8_string("pkcs11_key_label", label,
+ 0);
+ params[1] = OSSL_PARAM_construct_octet_string("pkcs11_key_id", id, 16);
+ params[2] = OSSL_PARAM_construct_end();
+
+ ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", "provider=pkcs11");
+ if (ctx == NULL) {
+ DST_RET(dst__openssl_toresult2("EVP_PKEY_CTX_new_from_name",
+ DST_R_OPENSSLFAILURE));
+ }
+
+ status = EVP_PKEY_keygen_init(ctx);
+ if (status != 1) {
+ DST_RET(dst__openssl_toresult2("EVP_PKEY_keygen_init",
+ DST_R_OPENSSLFAILURE));
+ }
+
+ status = EVP_PKEY_CTX_set_params(ctx, params);
+ if (status != 1) {
+ DST_RET(dst__openssl_toresult2("EVP_PKEY_CTX_set_params",
+ DST_R_OPENSSLFAILURE));
+ }
+ /*
+ * Setting the P-384 curve doesn't work correctly when using:
+ * OSSL_PARAM_construct_utf8_string("ec_paramgen_curve", "P-384", 0);
+ *
+ * Instead use the OpenSSL function to set the curve nid param.
+ */
+ status = EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, group_nid);
+ if (status != 1) {
+ DST_RET(dst__openssl_toresult2("EVP_PKEY_CTX_set_ec_paramgen_"
+ "curve_nid",
+ DST_R_OPENSSLFAILURE));
+ }
+
+ /* Generate the key. */
+ status = EVP_PKEY_generate(ctx, retkey);
+ if (status != 1) {
+ DST_RET(dst__openssl_toresult2("EVP_PKEY_generate",
+ DST_R_OPENSSLFAILURE));
+ }
+
+ ret = ISC_R_SUCCESS;
+
+err:
+ EVP_PKEY_CTX_free(ctx);
+ return (ret);
+}
+
+static isc_result_t
+opensslecdsa_generate_pkey(unsigned int key_alg, const char *object,
+ EVP_PKEY **retkey) {
isc_result_t ret;
EVP_PKEY_CTX *ctx = NULL;
EVP_PKEY *params_pkey = NULL;
int group_nid = opensslecdsa_key_alg_to_group_nid(key_alg);
int status;
+ if (object != NULL) {
+ return (opensslecdsa_generate_pkey_with_object(group_nid,
+ object, retkey));
+ }
+
/* Generate the key's parameters. */
ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL);
if (ctx == NULL) {
#else
static isc_result_t
-opensslecdsa_generate_pkey(unsigned int key_alg, EVP_PKEY **retkey) {
+opensslecdsa_generate_pkey(unsigned int key_alg, const char *object,
+ EVP_PKEY **retkey) {
isc_result_t ret;
EC_KEY *eckey = NULL;
EVP_PKEY *pkey = NULL;
- int group_nid = opensslecdsa_key_alg_to_group_nid(key_alg);
+ int group_nid;
+
+ UNUSED(object);
+
+ group_nid = opensslecdsa_key_alg_to_group_nid(key_alg);
eckey = EC_KEY_new_by_curve_name(group_nid);
if (eckey == NULL) {
UNUSED(unused);
UNUSED(callback);
- ret = opensslecdsa_generate_pkey(key->key_alg, &pkey);
+ ret = opensslecdsa_generate_pkey(key->key_alg, key->object, &pkey);
if (ret != ISC_R_SUCCESS) {
return (ret);
}
}
static isc_result_t
-opensslrsa_generate_pkey(unsigned int key_size, BIGNUM *e,
+opensslrsa_generate_pkey(unsigned int key_size, const char *object, BIGNUM *e,
void (*callback)(int), EVP_PKEY **retkey) {
- RSA *rsa = RSA_new();
- EVP_PKEY *pkey = EVP_PKEY_new();
+ RSA *rsa = NULL;
+ EVP_PKEY *pkey = NULL;
BN_GENCB *cb = NULL;
isc_result_t ret;
+ UNUSED(object);
+
+ rsa = RSA_new();
+ pkey = EVP_PKEY_new();
if (rsa == NULL || pkey == NULL) {
DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
}
}
static isc_result_t
-opensslrsa_generate_pkey(unsigned int key_size, BIGNUM *e,
+opensslrsa_generate_pkey_with_object(size_t key_size, const char *object,
+ EVP_PKEY **retkey) {
+ EVP_PKEY_CTX *ctx = NULL;
+ OSSL_PARAM params[4];
+ unsigned char id[16];
+ char *label = UNCONST(object);
+ isc_result_t ret;
+ int status;
+
+ status = RAND_bytes(id, 16);
+ if (status != 1) {
+ DST_RET(dst__openssl_toresult2("RAND_bytes",
+ DST_R_OPENSSLFAILURE));
+ }
+
+ params[0] = OSSL_PARAM_construct_utf8_string("pkcs11_key_label", label,
+ 0);
+ params[1] = OSSL_PARAM_construct_octet_string("pkcs11_key_id", id, 16);
+ params[2] = OSSL_PARAM_construct_size_t("rsa_keygen_bits", &key_size);
+ params[3] = OSSL_PARAM_construct_end();
+
+ ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", "provider=pkcs11");
+ if (ctx == NULL) {
+ DST_RET(dst__openssl_toresult2("EVP_PKEY_CTX_new_from_name",
+ DST_R_OPENSSLFAILURE));
+ }
+
+ status = EVP_PKEY_keygen_init(ctx);
+ if (status != 1) {
+ DST_RET(dst__openssl_toresult2("EVP_PKEY_keygen_init",
+ DST_R_OPENSSLFAILURE));
+ }
+
+ status = EVP_PKEY_CTX_set_params(ctx, params);
+ if (status != 1) {
+ DST_RET(dst__openssl_toresult2("EVP_PKEY_CTX_set_params",
+ DST_R_OPENSSLFAILURE));
+ }
+
+ status = EVP_PKEY_generate(ctx, retkey);
+ if (status != 1) {
+ DST_RET(dst__openssl_toresult2("EVP_PKEY_generate",
+ DST_R_OPENSSLFAILURE));
+ }
+
+ ret = ISC_R_SUCCESS;
+err:
+ EVP_PKEY_CTX_free(ctx);
+ return (ret);
+}
+
+static isc_result_t
+opensslrsa_generate_pkey(unsigned int key_size, const char *object, BIGNUM *e,
void (*callback)(int), EVP_PKEY **retkey) {
- EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL);
+ EVP_PKEY_CTX *ctx;
isc_result_t ret;
+ if (object != NULL) {
+ return (opensslrsa_generate_pkey_with_object(key_size, object,
+ retkey));
+ }
+
+ ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL);
if (ctx == NULL) {
DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
}
BN_set_bit(e, 32);
}
- ret = opensslrsa_generate_pkey(key->key_size, e, callback, &pkey);
+ ret = opensslrsa_generate_pkey(key->key_size, key->object, e, callback,
+ &pkey);
if (ret != ISC_R_SUCCESS) {
goto err;
}
}
}
- ret = cfg_keystore_fromconfig(
- kconfig, mctx, logctx, &kslist, &ks);
+ ret = cfg_keystore_fromconfig(kconfig, mctx,
+ logctx, NULL,
+ &kslist, &ks);
if (ret != ISC_R_SUCCESS) {
if (result == ISC_R_SUCCESS) {
result = ret;
/*
* Add default key-store "key-directory".
*/
- tresult = cfg_keystore_fromconfig(NULL, mctx, logctx, &kslist, &ks);
+ tresult = cfg_keystore_fromconfig(NULL, mctx, logctx, NULL, &kslist,
+ &ks);
if (tresult != ISC_R_SUCCESS) {
if (result == ISC_R_SUCCESS) {
result = tresult;
{
cfg_obj_t *kcfg = cfg_listelt_value(element);
ks = NULL;
- (void)cfg_keystore_fromconfig(kcfg, mctx, logctx, &kslist, &ks);
+ (void)cfg_keystore_fromconfig(kcfg, mctx, logctx, NULL, &kslist,
+ &ks);
INSIST(ks != NULL);
dns_keystore_detach(&ks);
}
ks = NULL;
- (void)cfg_keystore_fromconfig(NULL, mctx, logctx, &kslist, &ks);
+ (void)cfg_keystore_fromconfig(NULL, mctx, logctx, NULL, &kslist, &ks);
INSIST(ks != NULL);
dns_keystore_detach(&ks);
isc_result_t
cfg_keystore_fromconfig(const cfg_obj_t *config, isc_mem_t *mctx,
- isc_log_t *logctx, dns_keystorelist_t *keystorelist,
+ isc_log_t *logctx, const char *engine,
+ dns_keystorelist_t *keystorelist,
dns_keystore_t **kspp);
/*%<
* Create and configure a key store. If a 'keystorelist' is provided, a lookup
isc_result_t
cfg_keystore_fromconfig(const cfg_obj_t *config, isc_mem_t *mctx,
- isc_log_t *logctx, dns_keystorelist_t *keystorelist,
+ isc_log_t *logctx, const char *engine,
+ dns_keystorelist_t *keystorelist,
dns_keystore_t **kspp) {
isc_result_t result;
const cfg_obj_t *maps[2];
* No key-store with configured name was found in list, create new one.
*/
INSIST(keystore == NULL);
- result = dns_keystore_create(mctx, name, &keystore);
+ result = dns_keystore_create(mctx, name, engine, &keystore);
if (result != ISC_R_SUCCESS) {
return (result);
}