No empty .Rs/.Re
[netbsd-mini2440.git] / external / bsd / bind / dist / bin / confgen / keygen.c
blobb863f3db1f876cbd5e21ab9fe5205477563db49e
1 /* $NetBSD$ */
3 /*
4 * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
11 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
13 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
19 /* Id: keygen.c,v 1.4 2009/11/12 14:02:38 marka Exp */
21 /*! \file */
23 #include <config.h>
25 #include <stdlib.h>
26 #include <stdarg.h>
28 #include <isc/base64.h>
29 #include <isc/buffer.h>
30 #include <isc/entropy.h>
31 #include <isc/file.h>
32 #include <isc/keyboard.h>
33 #include <isc/mem.h>
34 #include <isc/result.h>
35 #include <isc/string.h>
37 #include <dns/keyvalues.h>
38 #include <dns/name.h>
40 #include <dst/dst.h>
41 #include <confgen/os.h>
43 #include "util.h"
44 #include "keygen.h"
46 /*%
47 * Convert algorithm type to string.
49 const char *
50 alg_totext(dns_secalg_t alg) {
51 switch (alg) {
52 case DST_ALG_HMACMD5:
53 return "hmac-md5";
54 case DST_ALG_HMACSHA1:
55 return "hmac-sha1";
56 case DST_ALG_HMACSHA224:
57 return "hmac-sha224";
58 case DST_ALG_HMACSHA256:
59 return "hmac-sha256";
60 case DST_ALG_HMACSHA384:
61 return "hmac-sha384";
62 case DST_ALG_HMACSHA512:
63 return "hmac-sha512";
64 default:
65 return "(unknown)";
69 /*%
70 * Convert string to algorithm type.
72 dns_secalg_t
73 alg_fromtext(const char *name) {
74 if (strcmp(name, "hmac-md5") == 0)
75 return DST_ALG_HMACMD5;
76 if (strcmp(name, "hmac-sha1") == 0)
77 return DST_ALG_HMACSHA1;
78 if (strcmp(name, "hmac-sha224") == 0)
79 return DST_ALG_HMACSHA224;
80 if (strcmp(name, "hmac-sha256") == 0)
81 return DST_ALG_HMACSHA256;
82 if (strcmp(name, "hmac-sha384") == 0)
83 return DST_ALG_HMACSHA384;
84 if (strcmp(name, "hmac-sha512") == 0)
85 return DST_ALG_HMACSHA512;
86 return DST_ALG_UNKNOWN;
89 /*%
90 * Return default keysize for a given algorithm type.
92 int
93 alg_bits(dns_secalg_t alg) {
94 switch (alg) {
95 case DST_ALG_HMACMD5:
96 return 128;
97 case DST_ALG_HMACSHA1:
98 return 160;
99 case DST_ALG_HMACSHA224:
100 return 224;
101 case DST_ALG_HMACSHA256:
102 return 256;
103 case DST_ALG_HMACSHA384:
104 return 384;
105 case DST_ALG_HMACSHA512:
106 return 512;
107 default:
108 return 0;
113 * Generate a key of size 'keysize' using entropy source 'randomfile',
114 * and place it in 'key_txtbuffer'
116 void
117 generate_key(isc_mem_t *mctx, const char *randomfile, dns_secalg_t alg,
118 int keysize, isc_buffer_t *key_txtbuffer) {
119 isc_result_t result = ISC_R_SUCCESS;
120 isc_entropysource_t *entropy_source = NULL;
121 int open_keyboard = ISC_ENTROPY_KEYBOARDMAYBE;
122 int entropy_flags = 0;
123 isc_entropy_t *ectx = NULL;
124 isc_buffer_t key_rawbuffer;
125 isc_region_t key_rawregion;
126 char key_rawsecret[64];
127 dst_key_t *key = NULL;
129 switch (alg) {
130 case DST_ALG_HMACMD5:
131 if (keysize < 1 || keysize > 512)
132 fatal("keysize %d out of range (must be 1-512)\n",
133 keysize);
134 break;
135 case DST_ALG_HMACSHA256:
136 if (keysize < 1 || keysize > 256)
137 fatal("keysize %d out of range (must be 1-256)\n",
138 keysize);
139 break;
140 default:
141 fatal("unsupported algorithm %d\n", alg);
145 DO("create entropy context", isc_entropy_create(mctx, &ectx));
147 if (randomfile != NULL && strcmp(randomfile, "keyboard") == 0) {
148 randomfile = NULL;
149 open_keyboard = ISC_ENTROPY_KEYBOARDYES;
151 DO("start entropy source", isc_entropy_usebestsource(ectx,
152 &entropy_source,
153 randomfile,
154 open_keyboard));
156 entropy_flags = ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY;
158 DO("initialize dst library", dst_lib_init(mctx, ectx, entropy_flags));
160 DO("generate key", dst_key_generate(dns_rootname, alg,
161 keysize, 0, 0,
162 DNS_KEYPROTO_ANY,
163 dns_rdataclass_in, mctx, &key));
165 isc_buffer_init(&key_rawbuffer, &key_rawsecret, sizeof(key_rawsecret));
167 DO("dump key to buffer", dst_key_tobuffer(key, &key_rawbuffer));
169 isc_buffer_usedregion(&key_rawbuffer, &key_rawregion);
171 DO("bsse64 encode secret", isc_base64_totext(&key_rawregion, -1, "",
172 key_txtbuffer));
175 * Shut down the entropy source now so the "stop typing" message
176 * does not muck with the output.
178 if (entropy_source != NULL)
179 isc_entropy_destroysource(&entropy_source);
181 if (key != NULL)
182 dst_key_free(&key);
184 isc_entropy_detach(&ectx);
185 dst_lib_destroy();
189 * Write a key file to 'keyfile'. If 'user' is non-NULL,
190 * make that user the owner of the file. The key will have
191 * the name 'keyname' and the secret in the buffer 'secret'.
193 void
194 write_key_file(const char *keyfile, const char *user,
195 const char *keyname, isc_buffer_t *secret,
196 dns_secalg_t alg) {
197 isc_result_t result;
198 const char *algname = alg_totext(alg);
199 FILE *fd = NULL;
201 DO("create keyfile", isc_file_safecreate(keyfile, &fd));
203 if (user != NULL) {
204 if (set_user(fd, user) == -1)
205 fatal("unable to set file owner\n");
208 fprintf(fd, "key \"%s\" {\n\talgorithm %s;\n"
209 "\tsecret \"%.*s\";\n};\n",
210 keyname, algname,
211 (int)isc_buffer_usedlength(secret),
212 (char *)isc_buffer_base(secret));
213 fflush(fd);
214 if (ferror(fd))
215 fatal("write to %s failed\n", keyfile);
216 if (fclose(fd))
217 fatal("fclose(%s) failed\n", keyfile);
218 fprintf(stderr, "wrote key file \"%s\"\n", keyfile);