2009-06-10 00:27:22 +00:00
|
|
|
/*
|
2017-09-18 23:48:50 +00:00
|
|
|
* Copyright (C) 2009, 2012-2017 Internet Systems Consortium, Inc. ("ISC")
|
2009-06-10 00:27:22 +00:00
|
|
|
*
|
2016-06-27 14:56:38 +10:00
|
|
|
* 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 http://mozilla.org/MPL/2.0/.
|
2009-06-10 00:27:22 +00:00
|
|
|
*/
|
|
|
|
|
2009-11-12 14:02:38 +00:00
|
|
|
/* $Id: keygen.c,v 1.4 2009/11/12 14:02:38 marka Exp $ */
|
2009-06-10 00:27:22 +00:00
|
|
|
|
|
|
|
/*! \file */
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
|
|
|
#include <isc/base64.h>
|
|
|
|
#include <isc/buffer.h>
|
|
|
|
#include <isc/entropy.h>
|
|
|
|
#include <isc/file.h>
|
|
|
|
#include <isc/keyboard.h>
|
|
|
|
#include <isc/mem.h>
|
2015-05-23 14:21:51 +02:00
|
|
|
#include <isc/print.h>
|
2009-06-10 00:27:22 +00:00
|
|
|
#include <isc/result.h>
|
|
|
|
#include <isc/string.h>
|
|
|
|
|
2016-08-19 08:02:51 +10:00
|
|
|
#include <pk11/site.h>
|
|
|
|
|
2009-06-10 00:27:22 +00:00
|
|
|
#include <dns/keyvalues.h>
|
|
|
|
#include <dns/name.h>
|
|
|
|
|
|
|
|
#include <dst/dst.h>
|
|
|
|
#include <confgen/os.h>
|
|
|
|
|
|
|
|
#include "util.h"
|
|
|
|
#include "keygen.h"
|
|
|
|
|
|
|
|
/*%
|
|
|
|
* Convert algorithm type to string.
|
|
|
|
*/
|
|
|
|
const char *
|
|
|
|
alg_totext(dns_secalg_t alg) {
|
|
|
|
switch (alg) {
|
2016-08-19 08:02:51 +10:00
|
|
|
#ifndef PK11_MD5_DISABLE
|
2009-06-10 00:27:22 +00:00
|
|
|
case DST_ALG_HMACMD5:
|
|
|
|
return "hmac-md5";
|
2016-08-19 08:02:51 +10:00
|
|
|
#endif
|
2009-06-10 00:27:22 +00:00
|
|
|
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) {
|
2014-03-12 08:29:15 -07:00
|
|
|
const char *p = name;
|
|
|
|
if (strncasecmp(p, "hmac-", 5) == 0)
|
|
|
|
p = &name[5];
|
|
|
|
|
2016-08-19 08:02:51 +10:00
|
|
|
#ifndef PK11_MD5_DISABLE
|
2014-03-12 08:29:15 -07:00
|
|
|
if (strcasecmp(p, "md5") == 0)
|
2009-06-11 23:47:56 +00:00
|
|
|
return DST_ALG_HMACMD5;
|
2016-08-19 08:02:51 +10:00
|
|
|
#endif
|
2014-03-12 08:29:15 -07:00
|
|
|
if (strcasecmp(p, "sha1") == 0)
|
2009-06-11 23:47:56 +00:00
|
|
|
return DST_ALG_HMACSHA1;
|
2014-03-12 08:29:15 -07:00
|
|
|
if (strcasecmp(p, "sha224") == 0)
|
2009-06-11 23:47:56 +00:00
|
|
|
return DST_ALG_HMACSHA224;
|
2014-03-12 08:29:15 -07:00
|
|
|
if (strcasecmp(p, "sha256") == 0)
|
2009-06-11 23:47:56 +00:00
|
|
|
return DST_ALG_HMACSHA256;
|
2014-03-12 08:29:15 -07:00
|
|
|
if (strcasecmp(p, "sha384") == 0)
|
2009-06-11 23:47:56 +00:00
|
|
|
return DST_ALG_HMACSHA384;
|
2014-03-12 08:29:15 -07:00
|
|
|
if (strcasecmp(p, "sha512") == 0)
|
2009-06-11 23:47:56 +00:00
|
|
|
return DST_ALG_HMACSHA512;
|
|
|
|
return DST_ALG_UNKNOWN;
|
2009-06-10 00:27:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*%
|
|
|
|
* Return default keysize for a given algorithm type.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
alg_bits(dns_secalg_t alg) {
|
2009-06-11 23:47:56 +00:00
|
|
|
switch (alg) {
|
2009-06-10 00:27:22 +00:00
|
|
|
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;
|
2009-06-11 23:47:56 +00:00
|
|
|
}
|
2009-06-10 00:27:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*%
|
|
|
|
* Generate a key of size 'keysize' using entropy source 'randomfile',
|
|
|
|
* and place it in 'key_txtbuffer'
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
generate_key(isc_mem_t *mctx, const char *randomfile, dns_secalg_t alg,
|
|
|
|
int keysize, isc_buffer_t *key_txtbuffer) {
|
|
|
|
isc_result_t result = ISC_R_SUCCESS;
|
|
|
|
isc_entropysource_t *entropy_source = NULL;
|
|
|
|
int open_keyboard = ISC_ENTROPY_KEYBOARDMAYBE;
|
|
|
|
int entropy_flags = 0;
|
|
|
|
isc_entropy_t *ectx = NULL;
|
|
|
|
isc_buffer_t key_rawbuffer;
|
|
|
|
isc_region_t key_rawregion;
|
|
|
|
char key_rawsecret[64];
|
|
|
|
dst_key_t *key = NULL;
|
|
|
|
|
|
|
|
switch (alg) {
|
2016-08-19 08:02:51 +10:00
|
|
|
#ifndef PK11_MD5_DISABLE
|
2009-06-10 00:27:22 +00:00
|
|
|
case DST_ALG_HMACMD5:
|
2016-08-19 08:02:51 +10:00
|
|
|
#endif
|
2012-12-05 16:36:58 -08:00
|
|
|
case DST_ALG_HMACSHA1:
|
|
|
|
case DST_ALG_HMACSHA224:
|
2013-03-04 12:14:01 -08:00
|
|
|
case DST_ALG_HMACSHA256:
|
|
|
|
if (keysize < 1 || keysize > 512)
|
|
|
|
fatal("keysize %d out of range (must be 1-512)\n",
|
2012-12-05 16:36:58 -08:00
|
|
|
keysize);
|
|
|
|
break;
|
|
|
|
case DST_ALG_HMACSHA384:
|
2013-03-04 12:14:01 -08:00
|
|
|
case DST_ALG_HMACSHA512:
|
|
|
|
if (keysize < 1 || keysize > 1024)
|
|
|
|
fatal("keysize %d out of range (must be 1-1024)\n",
|
2012-12-05 16:36:58 -08:00
|
|
|
keysize);
|
|
|
|
break;
|
2009-06-10 00:27:22 +00:00
|
|
|
default:
|
|
|
|
fatal("unsupported algorithm %d\n", alg);
|
|
|
|
}
|
2009-06-11 23:47:56 +00:00
|
|
|
|
2009-06-10 00:27:22 +00:00
|
|
|
|
|
|
|
DO("create entropy context", isc_entropy_create(mctx, &ectx));
|
|
|
|
|
2017-09-12 19:05:46 -07:00
|
|
|
#ifdef ISC_PLATFORM_CRYPTORANDOM
|
2017-09-28 10:09:22 -07:00
|
|
|
if (randomfile == NULL) {
|
2017-09-12 19:05:46 -07:00
|
|
|
isc_entropy_usehook(ectx, ISC_TRUE);
|
|
|
|
}
|
|
|
|
#endif
|
2017-09-28 10:09:22 -07:00
|
|
|
if (randomfile != NULL && strcmp(randomfile, "keyboard") == 0) {
|
|
|
|
randomfile = NULL;
|
|
|
|
open_keyboard = ISC_ENTROPY_KEYBOARDYES;
|
|
|
|
}
|
2009-06-10 00:27:22 +00:00
|
|
|
DO("start entropy source", isc_entropy_usebestsource(ectx,
|
|
|
|
&entropy_source,
|
|
|
|
randomfile,
|
|
|
|
open_keyboard));
|
|
|
|
|
|
|
|
entropy_flags = ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY;
|
|
|
|
|
|
|
|
DO("initialize dst library", dst_lib_init(mctx, ectx, entropy_flags));
|
|
|
|
|
|
|
|
DO("generate key", dst_key_generate(dns_rootname, alg,
|
|
|
|
keysize, 0, 0,
|
|
|
|
DNS_KEYPROTO_ANY,
|
|
|
|
dns_rdataclass_in, mctx, &key));
|
|
|
|
|
|
|
|
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));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Shut down the entropy source now so the "stop typing" message
|
|
|
|
* does not muck with the output.
|
|
|
|
*/
|
|
|
|
if (entropy_source != NULL)
|
|
|
|
isc_entropy_destroysource(&entropy_source);
|
|
|
|
|
|
|
|
if (key != NULL)
|
|
|
|
dst_key_free(&key);
|
|
|
|
|
|
|
|
isc_entropy_detach(&ectx);
|
|
|
|
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);
|
2009-11-12 14:02:38 +00:00
|
|
|
FILE *fd = NULL;
|
2009-06-10 00:27:22 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|