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