2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-22 01:59:26 +00:00
bind/lib/dns/keystore.c
Ondřej Surý ef7aba7072
Remove OpenSSL Engine support
The OpenSSL 1.x Engines support has been deprecated in the OpenSSL 3.x
and is going to be removed.  Remove the OpenSSL Engine support in favor
of OpenSSL Providers.
2024-08-06 15:17:48 +02:00

283 lines
7.5 KiB
C

/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* SPDX-License-Identifier: MPL-2.0
*
* 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 https://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
/*! \file */
#include <string.h>
#include <isc/assertions.h>
#include <isc/buffer.h>
#include <isc/mem.h>
#include <isc/time.h>
#include <isc/util.h>
#include <dns/fixedname.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_t *keystore;
REQUIRE(name != NULL);
REQUIRE(kspp != NULL && *kspp == NULL);
keystore = isc_mem_get(mctx, sizeof(*keystore));
keystore->mctx = NULL;
isc_mem_attach(mctx, &keystore->mctx);
keystore->name = isc_mem_strdup(mctx, name);
isc_mutex_init(&keystore->lock);
isc_refcount_init(&keystore->references, 1);
ISC_LINK_INIT(keystore, link);
keystore->directory = NULL;
keystore->pkcs11uri = NULL;
keystore->magic = DNS_KEYSTORE_MAGIC;
*kspp = keystore;
return (ISC_R_SUCCESS);
}
static inline void
dns__keystore_destroy(dns_keystore_t *keystore) {
char *name;
REQUIRE(!ISC_LINK_LINKED(keystore, link));
isc_mutex_destroy(&keystore->lock);
name = UNCONST(keystore->name);
isc_mem_free(keystore->mctx, name);
if (keystore->directory != NULL) {
isc_mem_free(keystore->mctx, keystore->directory);
}
if (keystore->pkcs11uri != NULL) {
isc_mem_free(keystore->mctx, keystore->pkcs11uri);
}
isc_mem_putanddetach(&keystore->mctx, keystore, sizeof(*keystore));
}
#ifdef DNS_KEYSTORE_TRACE
ISC_REFCOUNT_TRACE_IMPL(dns_keystore, dns__keystore_destroy);
#else
ISC_REFCOUNT_IMPL(dns_keystore, dns__keystore_destroy);
#endif
const char *
dns_keystore_name(dns_keystore_t *keystore) {
REQUIRE(DNS_KEYSTORE_VALID(keystore));
return (keystore->name);
}
const char *
dns_keystore_directory(dns_keystore_t *keystore, const char *keydir) {
if (keystore == NULL) {
return (keydir);
}
INSIST(DNS_KEYSTORE_VALID(keystore));
if (keystore->directory == NULL) {
return (keydir);
}
return (keystore->directory);
}
void
dns_keystore_setdirectory(dns_keystore_t *keystore, const char *dir) {
REQUIRE(DNS_KEYSTORE_VALID(keystore));
if (keystore->directory != NULL) {
isc_mem_free(keystore->mctx, keystore->directory);
}
keystore->directory = (dir == NULL)
? NULL
: isc_mem_strdup(keystore->mctx, dir);
}
const char *
dns_keystore_pkcs11uri(dns_keystore_t *keystore) {
REQUIRE(DNS_KEYSTORE_VALID(keystore));
return (keystore->pkcs11uri);
}
void
dns_keystore_setpkcs11uri(dns_keystore_t *keystore, const char *uri) {
REQUIRE(DNS_KEYSTORE_VALID(keystore));
if (keystore->pkcs11uri != NULL) {
isc_mem_free(keystore->mctx, keystore->pkcs11uri);
}
keystore->pkcs11uri = (uri == NULL)
? NULL
: isc_mem_strdup(keystore->mctx, uri);
}
static isc_result_t
buildpkcs11label(const char *uri, const dns_name_t *zname, const char *policy,
int flags, isc_buffer_t *buf) {
bool ksk = ((flags & DNS_KEYFLAG_KSK) != 0);
char timebuf[18];
isc_time_t now = isc_time_now();
isc_result_t result;
dns_fixedname_t fname;
dns_name_t *pname = dns_fixedname_initname(&fname);
/* uri + object */
if (isc_buffer_availablelength(buf) < strlen(uri) + strlen(";object="))
{
return (ISC_R_NOSPACE);
}
isc_buffer_putstr(buf, uri);
isc_buffer_putstr(buf, ";object=");
/* zone name */
result = dns_name_tofilenametext(zname, false, buf);
if (result != ISC_R_SUCCESS) {
return (result);
}
/*
* policy name
*
* Note that strlen(policy) is not the actual length, but if this
* already does not fit, the escaped version returned from
* dns_name_tofilenametext() certainly won't fit.
*/
if (isc_buffer_availablelength(buf) < (strlen(policy) + 1)) {
return (ISC_R_NOSPACE);
}
isc_buffer_putstr(buf, "-");
result = dns_name_fromstring(pname, policy, dns_rootname, 0, NULL);
if (result != ISC_R_SUCCESS) {
return (result);
}
result = dns_name_tofilenametext(pname, false, buf);
if (result != ISC_R_SUCCESS) {
return (result);
}
/* key type + current time */
isc_time_formatshorttimestamp(&now, timebuf, sizeof(timebuf));
return isc_buffer_printf(buf, "-%s-%s", ksk ? "ksk" : "zsk", timebuf);
}
isc_result_t
dns_keystore_keygen(dns_keystore_t *keystore, const dns_name_t *origin,
const char *policy, 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(policy != NULL);
REQUIRE(mctx != NULL);
REQUIRE(dstkey != NULL && *dstkey == NULL);
uri = dns_keystore_pkcs11uri(keystore);
if (uri != NULL) {
/*
* Create the PKCS#11 label.
* The label consists of the configured URI, and the object
* parameter. The object parameter needs to be unique. We
* know that for a given point in time, there will be at most
* one key per type created for each zone in a given DNSSEC
* policy. Hence the object is constructed out of the following
* parts: the zone name, policy name, key type, and the
* current time.
*
* The object may not contain any characters that conflict with
* special characters in the PKCS#11 URI scheme syntax (see
* RFC 7512, Section 2.3). Therefore, we mangle the zone name
* and policy name through 'dns_name_tofilenametext()'. We
* could create a new function to convert a name to PKCS#11
* text, but this existing function will suffice.
*/
char label[NAME_MAX];
isc_buffer_t buf;
isc_buffer_init(&buf, label, sizeof(label));
result = buildpkcs11label(uri, origin, policy, flags, &buf);
if (result != ISC_R_SUCCESS) {
char namebuf[DNS_NAME_FORMATSIZE];
dns_name_format(origin, namebuf, sizeof(namebuf));
isc_log_write(
dns_lctx, DNS_LOGCATEGORY_DNSSEC,
DNS_LOGMODULE_DNSSEC, ISC_LOG_ERROR,
"keystore: failed to create PKCS#11 object "
"for zone %s, policy %s: %s",
namebuf, policy, isc_result_totext(result));
return (result);
}
/* Generate the key */
result = dst_key_generate(origin, alg, size, 0, flags,
DNS_KEYPROTO_DNSSEC, rdclass, label,
mctx, &newkey, NULL);
if (result != ISC_R_SUCCESS) {
isc_log_write(
dns_lctx, DNS_LOGCATEGORY_DNSSEC,
DNS_LOGMODULE_DNSSEC, ISC_LOG_ERROR,
"keystore: failed to generate PKCS#11 object "
"%s: %s",
label, isc_result_totext(result));
return (result);
}
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC,
DNS_LOGMODULE_DNSSEC, ISC_LOG_ERROR,
"keystore: generated PKCS#11 object %s", label);
} 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) {
dns_keystore_t *keystore = NULL;
REQUIRE(kspp != NULL && *kspp == NULL);
if (list == NULL) {
return (ISC_R_NOTFOUND);
}
for (keystore = ISC_LIST_HEAD(*list); keystore != NULL;
keystore = ISC_LIST_NEXT(keystore, link))
{
if (strcmp(keystore->name, name) == 0) {
break;
}
}
if (keystore == NULL) {
return (ISC_R_NOTFOUND);
}
dns_keystore_attach(keystore, kspp);
return (ISC_R_SUCCESS);
}