351b62535d4c4f89883bfdba025999dd32490266Evan Hunt/*
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * Copyright (C) 2009, 2012-2016 Internet Systems Consortium, Inc. ("ISC")
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt *
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * This Source Code Form is subject to the terms of the Mozilla Public
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * License, v. 2.0. If a copy of the MPL was not distributed with this
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * file, You can obtain one at http://mozilla.org/MPL/2.0/.
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt */
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt
adb42115869b8258cd38bc7fd044766f662bdd78Mark Andrews/* $Id: keygen.c,v 1.4 2009/11/12 14:02:38 marka Exp $ */
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt/*! \file */
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt#include <config.h>
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt#include <stdlib.h>
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt#include <stdarg.h>
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt#include <isc/base64.h>
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt#include <isc/buffer.h>
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt#include <isc/entropy.h>
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt#include <isc/file.h>
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt#include <isc/keyboard.h>
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt#include <isc/mem.h>
3759f10fc543747668b1ca4b4671f35b0dea8445Francis Dupont#include <isc/print.h>
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt#include <isc/result.h>
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt#include <isc/string.h>
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews#include <pk11/site.h>
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt#include <dns/keyvalues.h>
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt#include <dns/name.h>
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt#include <dst/dst.h>
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt#include <confgen/os.h>
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt#include "util.h"
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt#include "keygen.h"
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt/*%
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt * Convert algorithm type to string.
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt */
351b62535d4c4f89883bfdba025999dd32490266Evan Huntconst char *
351b62535d4c4f89883bfdba025999dd32490266Evan Huntalg_totext(dns_secalg_t alg) {
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt switch (alg) {
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews#ifndef PK11_MD5_DISABLE
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt case DST_ALG_HMACMD5:
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt return "hmac-md5";
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews#endif
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt case DST_ALG_HMACSHA1:
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt return "hmac-sha1";
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt case DST_ALG_HMACSHA224:
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt return "hmac-sha224";
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt case DST_ALG_HMACSHA256:
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt return "hmac-sha256";
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt case DST_ALG_HMACSHA384:
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt return "hmac-sha384";
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt case DST_ALG_HMACSHA512:
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt return "hmac-sha512";
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt default:
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt return "(unknown)";
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt }
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt}
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt/*%
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt * Convert string to algorithm type.
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt */
351b62535d4c4f89883bfdba025999dd32490266Evan Huntdns_secalg_t
351b62535d4c4f89883bfdba025999dd32490266Evan Huntalg_fromtext(const char *name) {
46bc64f4b1a0e84ab0397943453fe83a17baf2c4Evan Hunt const char *p = name;
46bc64f4b1a0e84ab0397943453fe83a17baf2c4Evan Hunt if (strncasecmp(p, "hmac-", 5) == 0)
46bc64f4b1a0e84ab0397943453fe83a17baf2c4Evan Hunt p = &name[5];
46bc64f4b1a0e84ab0397943453fe83a17baf2c4Evan Hunt
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews#ifndef PK11_MD5_DISABLE
46bc64f4b1a0e84ab0397943453fe83a17baf2c4Evan Hunt if (strcasecmp(p, "md5") == 0)
754cb8a2b33fa6cfaa15d6470f66e5fb0eab4764Automatic Updater return DST_ALG_HMACMD5;
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews#endif
46bc64f4b1a0e84ab0397943453fe83a17baf2c4Evan Hunt if (strcasecmp(p, "sha1") == 0)
754cb8a2b33fa6cfaa15d6470f66e5fb0eab4764Automatic Updater return DST_ALG_HMACSHA1;
46bc64f4b1a0e84ab0397943453fe83a17baf2c4Evan Hunt if (strcasecmp(p, "sha224") == 0)
754cb8a2b33fa6cfaa15d6470f66e5fb0eab4764Automatic Updater return DST_ALG_HMACSHA224;
46bc64f4b1a0e84ab0397943453fe83a17baf2c4Evan Hunt if (strcasecmp(p, "sha256") == 0)
754cb8a2b33fa6cfaa15d6470f66e5fb0eab4764Automatic Updater return DST_ALG_HMACSHA256;
46bc64f4b1a0e84ab0397943453fe83a17baf2c4Evan Hunt if (strcasecmp(p, "sha384") == 0)
754cb8a2b33fa6cfaa15d6470f66e5fb0eab4764Automatic Updater return DST_ALG_HMACSHA384;
46bc64f4b1a0e84ab0397943453fe83a17baf2c4Evan Hunt if (strcasecmp(p, "sha512") == 0)
754cb8a2b33fa6cfaa15d6470f66e5fb0eab4764Automatic Updater return DST_ALG_HMACSHA512;
754cb8a2b33fa6cfaa15d6470f66e5fb0eab4764Automatic Updater return DST_ALG_UNKNOWN;
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt}
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt/*%
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt * Return default keysize for a given algorithm type.
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt */
351b62535d4c4f89883bfdba025999dd32490266Evan Huntint
351b62535d4c4f89883bfdba025999dd32490266Evan Huntalg_bits(dns_secalg_t alg) {
754cb8a2b33fa6cfaa15d6470f66e5fb0eab4764Automatic Updater switch (alg) {
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt case DST_ALG_HMACMD5:
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt return 128;
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt case DST_ALG_HMACSHA1:
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt return 160;
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt case DST_ALG_HMACSHA224:
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt return 224;
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt case DST_ALG_HMACSHA256:
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt return 256;
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt case DST_ALG_HMACSHA384:
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt return 384;
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt case DST_ALG_HMACSHA512:
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt return 512;
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt default:
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt return 0;
754cb8a2b33fa6cfaa15d6470f66e5fb0eab4764Automatic Updater }
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt}
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt/*%
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt * Generate a key of size 'keysize' using entropy source 'randomfile',
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt * and place it in 'key_txtbuffer'
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt */
351b62535d4c4f89883bfdba025999dd32490266Evan Huntvoid
351b62535d4c4f89883bfdba025999dd32490266Evan Huntgenerate_key(isc_mem_t *mctx, const char *randomfile, dns_secalg_t alg,
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt int keysize, isc_buffer_t *key_txtbuffer) {
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt isc_result_t result = ISC_R_SUCCESS;
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt isc_entropysource_t *entropy_source = NULL;
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt int open_keyboard = ISC_ENTROPY_KEYBOARDMAYBE;
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt int entropy_flags = 0;
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt isc_entropy_t *ectx = NULL;
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt isc_buffer_t key_rawbuffer;
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt isc_region_t key_rawregion;
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt char key_rawsecret[64];
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt dst_key_t *key = NULL;
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt switch (alg) {
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews#ifndef PK11_MD5_DISABLE
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt case DST_ALG_HMACMD5:
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews#endif
de5890da9b87cb4b91aca033db0e25b1fdb68c77Evan Hunt case DST_ALG_HMACSHA1:
de5890da9b87cb4b91aca033db0e25b1fdb68c77Evan Hunt case DST_ALG_HMACSHA224:
33b8db1bb3f0aa3a39db459e6a32a1082b8dce13Evan Hunt case DST_ALG_HMACSHA256:
33b8db1bb3f0aa3a39db459e6a32a1082b8dce13Evan Hunt if (keysize < 1 || keysize > 512)
33b8db1bb3f0aa3a39db459e6a32a1082b8dce13Evan Hunt fatal("keysize %d out of range (must be 1-512)\n",
de5890da9b87cb4b91aca033db0e25b1fdb68c77Evan Hunt keysize);
de5890da9b87cb4b91aca033db0e25b1fdb68c77Evan Hunt break;
de5890da9b87cb4b91aca033db0e25b1fdb68c77Evan Hunt case DST_ALG_HMACSHA384:
33b8db1bb3f0aa3a39db459e6a32a1082b8dce13Evan Hunt case DST_ALG_HMACSHA512:
33b8db1bb3f0aa3a39db459e6a32a1082b8dce13Evan Hunt if (keysize < 1 || keysize > 1024)
33b8db1bb3f0aa3a39db459e6a32a1082b8dce13Evan Hunt fatal("keysize %d out of range (must be 1-1024)\n",
de5890da9b87cb4b91aca033db0e25b1fdb68c77Evan Hunt keysize);
de5890da9b87cb4b91aca033db0e25b1fdb68c77Evan Hunt break;
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt default:
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt fatal("unsupported algorithm %d\n", alg);
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt }
754cb8a2b33fa6cfaa15d6470f66e5fb0eab4764Automatic Updater
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt DO("create entropy context", isc_entropy_create(mctx, &ectx));
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt if (randomfile != NULL && strcmp(randomfile, "keyboard") == 0) {
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt randomfile = NULL;
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt open_keyboard = ISC_ENTROPY_KEYBOARDYES;
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt }
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt DO("start entropy source", isc_entropy_usebestsource(ectx,
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt &entropy_source,
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt randomfile,
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt open_keyboard));
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt entropy_flags = ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY;
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt DO("initialize dst library", dst_lib_init(mctx, ectx, entropy_flags));
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt DO("generate key", dst_key_generate(dns_rootname, alg,
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt keysize, 0, 0,
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt DNS_KEYPROTO_ANY,
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt dns_rdataclass_in, mctx, &key));
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt isc_buffer_init(&key_rawbuffer, &key_rawsecret, sizeof(key_rawsecret));
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt DO("dump key to buffer", dst_key_tobuffer(key, &key_rawbuffer));
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt isc_buffer_usedregion(&key_rawbuffer, &key_rawregion);
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt DO("bsse64 encode secret", isc_base64_totext(&key_rawregion, -1, "",
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt key_txtbuffer));
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt /*
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt * Shut down the entropy source now so the "stop typing" message
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt * does not muck with the output.
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt */
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt if (entropy_source != NULL)
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt isc_entropy_destroysource(&entropy_source);
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt if (key != NULL)
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt dst_key_free(&key);
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt isc_entropy_detach(&ectx);
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt dst_lib_destroy();
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt}
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt/*%
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt * Write a key file to 'keyfile'. If 'user' is non-NULL,
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt * make that user the owner of the file. The key will have
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt * the name 'keyname' and the secret in the buffer 'secret'.
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt */
351b62535d4c4f89883bfdba025999dd32490266Evan Huntvoid
351b62535d4c4f89883bfdba025999dd32490266Evan Huntwrite_key_file(const char *keyfile, const char *user,
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt const char *keyname, isc_buffer_t *secret,
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt dns_secalg_t alg) {
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt isc_result_t result;
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt const char *algname = alg_totext(alg);
adb42115869b8258cd38bc7fd044766f662bdd78Mark Andrews FILE *fd = NULL;
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt DO("create keyfile", isc_file_safecreate(keyfile, &fd));
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt if (user != NULL) {
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt if (set_user(fd, user) == -1)
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt fatal("unable to set file owner\n");
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt }
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt fprintf(fd, "key \"%s\" {\n\talgorithm %s;\n"
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt "\tsecret \"%.*s\";\n};\n",
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt keyname, algname,
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt (int)isc_buffer_usedlength(secret),
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt (char *)isc_buffer_base(secret));
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt fflush(fd);
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt if (ferror(fd))
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt fatal("write to %s failed\n", keyfile);
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt if (fclose(fd))
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt fatal("fclose(%s) failed\n", keyfile);
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt fprintf(stderr, "wrote key file \"%s\"\n", keyfile);
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt}
351b62535d4c4f89883bfdba025999dd32490266Evan Hunt