summaryrefslogtreecommitdiffstats
path: root/bin/confgen/keygen.c
diff options
context:
space:
mode:
Diffstat (limited to 'bin/confgen/keygen.c')
-rw-r--r--bin/confgen/keygen.c204
1 files changed, 204 insertions, 0 deletions
diff --git a/bin/confgen/keygen.c b/bin/confgen/keygen.c
new file mode 100644
index 0000000..73f976c
--- /dev/null
+++ b/bin/confgen/keygen.c
@@ -0,0 +1,204 @@
+/*
+ * 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 "keygen.h"
+#include <stdarg.h>
+#include <stdlib.h>
+
+#include <isc/base64.h>
+#include <isc/buffer.h>
+#include <isc/file.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/string.h>
+
+#include <pk11/site.h>
+
+#include <dns/keyvalues.h>
+#include <dns/name.h>
+
+#include <dst/dst.h>
+
+#include <confgen/os.h>
+
+#include "util.h"
+
+/*%
+ * Convert algorithm type to string.
+ */
+const char *
+alg_totext(dns_secalg_t alg) {
+ switch (alg) {
+ case DST_ALG_HMACMD5:
+ return ("hmac-md5");
+ case DST_ALG_HMACSHA1:
+ return ("hmac-sha1");
+ case DST_ALG_HMACSHA224:
+ return ("hmac-sha224");
+ case DST_ALG_HMACSHA256:
+ return ("hmac-sha256");
+ case DST_ALG_HMACSHA384:
+ return ("hmac-sha384");
+ case DST_ALG_HMACSHA512:
+ return ("hmac-sha512");
+ default:
+ return ("(unknown)");
+ }
+}
+
+/*%
+ * Convert string to algorithm type.
+ */
+dns_secalg_t
+alg_fromtext(const char *name) {
+ const char *p = name;
+ if (strncasecmp(p, "hmac-", 5) == 0) {
+ p = &name[5];
+ }
+
+ if (strcasecmp(p, "md5") == 0) {
+ return (DST_ALG_HMACMD5);
+ }
+ if (strcasecmp(p, "sha1") == 0) {
+ return (DST_ALG_HMACSHA1);
+ }
+ if (strcasecmp(p, "sha224") == 0) {
+ return (DST_ALG_HMACSHA224);
+ }
+ if (strcasecmp(p, "sha256") == 0) {
+ return (DST_ALG_HMACSHA256);
+ }
+ if (strcasecmp(p, "sha384") == 0) {
+ return (DST_ALG_HMACSHA384);
+ }
+ if (strcasecmp(p, "sha512") == 0) {
+ return (DST_ALG_HMACSHA512);
+ }
+ return (DST_ALG_UNKNOWN);
+}
+
+/*%
+ * Return default keysize for a given algorithm type.
+ */
+int
+alg_bits(dns_secalg_t alg) {
+ switch (alg) {
+ case DST_ALG_HMACMD5:
+ return (128);
+ case DST_ALG_HMACSHA1:
+ return (160);
+ case DST_ALG_HMACSHA224:
+ return (224);
+ case DST_ALG_HMACSHA256:
+ return (256);
+ case DST_ALG_HMACSHA384:
+ return (384);
+ case DST_ALG_HMACSHA512:
+ return (512);
+ default:
+ return (0);
+ }
+}
+
+/*%
+ * Generate a key of size 'keysize' and place it in 'key_txtbuffer'
+ */
+void
+generate_key(isc_mem_t *mctx, dns_secalg_t alg, int keysize,
+ isc_buffer_t *key_txtbuffer) {
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_buffer_t key_rawbuffer;
+ isc_region_t key_rawregion;
+ char key_rawsecret[64];
+ dst_key_t *key = NULL;
+
+ switch (alg) {
+ case DST_ALG_HMACMD5:
+ case DST_ALG_HMACSHA1:
+ case DST_ALG_HMACSHA224:
+ case DST_ALG_HMACSHA256:
+ if (keysize < 1 || keysize > 512) {
+ fatal("keysize %d out of range (must be 1-512)\n",
+ keysize);
+ }
+ break;
+ case DST_ALG_HMACSHA384:
+ case DST_ALG_HMACSHA512:
+ if (keysize < 1 || keysize > 1024) {
+ fatal("keysize %d out of range (must be 1-1024)\n",
+ keysize);
+ }
+ break;
+ default:
+ fatal("unsupported algorithm %d\n", alg);
+ }
+
+ DO("initialize dst library", dst_lib_init(mctx, NULL));
+
+ DO("generate key",
+ dst_key_generate(dns_rootname, alg, keysize, 0, 0, DNS_KEYPROTO_ANY,
+ dns_rdataclass_in, mctx, &key, NULL));
+
+ isc_buffer_init(&key_rawbuffer, &key_rawsecret, sizeof(key_rawsecret));
+
+ DO("dump key to buffer", dst_key_tobuffer(key, &key_rawbuffer));
+
+ isc_buffer_usedregion(&key_rawbuffer, &key_rawregion);
+
+ DO("bsse64 encode secret",
+ isc_base64_totext(&key_rawregion, -1, "", key_txtbuffer));
+
+ if (key != NULL) {
+ dst_key_free(&key);
+ }
+
+ dst_lib_destroy();
+}
+
+/*%
+ * Write a key file to 'keyfile'. If 'user' is non-NULL,
+ * make that user the owner of the file. The key will have
+ * the name 'keyname' and the secret in the buffer 'secret'.
+ */
+void
+write_key_file(const char *keyfile, const char *user, const char *keyname,
+ isc_buffer_t *secret, dns_secalg_t alg) {
+ isc_result_t result;
+ const char *algname = alg_totext(alg);
+ FILE *fd = NULL;
+
+ DO("create keyfile", isc_file_safecreate(keyfile, &fd));
+
+ if (user != NULL) {
+ if (set_user(fd, user) == -1) {
+ fatal("unable to set file owner\n");
+ }
+ }
+
+ fprintf(fd,
+ "key \"%s\" {\n\talgorithm %s;\n"
+ "\tsecret \"%.*s\";\n};\n",
+ keyname, algname, (int)isc_buffer_usedlength(secret),
+ (char *)isc_buffer_base(secret));
+ fflush(fd);
+ if (ferror(fd)) {
+ fatal("write to %s failed\n", keyfile);
+ }
+ if (fclose(fd)) {
+ fatal("fclose(%s) failed\n", keyfile);
+ }
+ fprintf(stderr, "wrote key file \"%s\"\n", keyfile);
+}