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 */
28 #include <isc/base64.h>
29 #include <isc/buffer.h>
30 #include <isc/entropy.h>
32 #include <isc/keyboard.h>
34 #include <isc/result.h>
35 #include <isc/string.h>
37 #include <dns/keyvalues.h>
41 #include <confgen/os.h>
47 * Convert algorithm type to string.
50 alg_totext(dns_secalg_t alg
) {
54 case DST_ALG_HMACSHA1
:
56 case DST_ALG_HMACSHA224
:
58 case DST_ALG_HMACSHA256
:
60 case DST_ALG_HMACSHA384
:
62 case DST_ALG_HMACSHA512
:
70 * Convert string to algorithm type.
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
;
90 * Return default keysize for a given algorithm type.
93 alg_bits(dns_secalg_t alg
) {
97 case DST_ALG_HMACSHA1
:
99 case DST_ALG_HMACSHA224
:
101 case DST_ALG_HMACSHA256
:
103 case DST_ALG_HMACSHA384
:
105 case DST_ALG_HMACSHA512
:
113 * Generate a key of size 'keysize' using entropy source 'randomfile',
114 * and place it in 'key_txtbuffer'
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
;
130 case DST_ALG_HMACMD5
:
131 if (keysize
< 1 || keysize
> 512)
132 fatal("keysize %d out of range (must be 1-512)\n",
135 case DST_ALG_HMACSHA256
:
136 if (keysize
< 1 || keysize
> 256)
137 fatal("keysize %d out of range (must be 1-256)\n",
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) {
149 open_keyboard
= ISC_ENTROPY_KEYBOARDYES
;
151 DO("start entropy source", isc_entropy_usebestsource(ectx
,
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
,
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, "",
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
);
184 isc_entropy_detach(&ectx
);
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'.
194 write_key_file(const char *keyfile
, const char *user
,
195 const char *keyname
, isc_buffer_t
*secret
,
198 const char *algname
= alg_totext(alg
);
201 DO("create keyfile", isc_file_safecreate(keyfile
, &fd
));
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",
211 (int)isc_buffer_usedlength(secret
),
212 (char *)isc_buffer_base(secret
));
215 fatal("write to %s failed\n", keyfile
);
217 fatal("fclose(%s) failed\n", keyfile
);
218 fprintf(stderr
, "wrote key file \"%s\"\n", keyfile
);