dst_api.c revision 1.1 1 /* $NetBSD: dst_api.c,v 1.1 2018/08/12 12:08:14 christos Exp $ */
2
3 /*
4 * Portions Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5 *
6 * This Source Code Form is subject to the terms of the Mozilla Public
7 * License, v. 2.0. If a copy of the MPL was not distributed with this
8 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 *
10 * See the COPYRIGHT file distributed with this work for additional
11 * information regarding copyright ownership.
12 *
13 * Portions Copyright (C) Network Associates, Inc.
14 *
15 * Permission to use, copy, modify, and/or distribute this software for any
16 * purpose with or without fee is hereby granted, provided that the above
17 * copyright notice and this permission notice appear in all copies.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
20 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
22 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
23 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
24 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
25 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
26 */
27
28 /*! \file */
29
30 #include <config.h>
31
32 #include <stdlib.h>
33 #include <time.h>
34
35 #include <isc/buffer.h>
36 #include <isc/dir.h>
37 #include <isc/entropy.h>
38 #include <isc/fsaccess.h>
39 #include <isc/hmacsha.h>
40 #include <isc/lex.h>
41 #include <isc/mem.h>
42 #include <isc/once.h>
43 #include <isc/platform.h>
44 #include <isc/print.h>
45 #include <isc/refcount.h>
46 #include <isc/random.h>
47 #include <isc/safe.h>
48 #include <isc/string.h>
49 #include <isc/time.h>
50 #include <isc/util.h>
51 #include <isc/file.h>
52
53 #include <pk11/site.h>
54
55 #define DST_KEY_INTERNAL
56
57 #include <dns/fixedname.h>
58 #include <dns/keyvalues.h>
59 #include <dns/name.h>
60 #include <dns/rdata.h>
61 #include <dns/rdataclass.h>
62 #include <dns/ttl.h>
63 #include <dns/types.h>
64
65 #include <dst/result.h>
66
67 #include "dst_internal.h"
68
69 #define DST_AS_STR(t) ((t).value.as_textregion.base)
70
71 static dst_func_t *dst_t_func[DST_MAX_ALGS];
72 static isc_entropy_t *dst_entropy_pool = NULL;
73 static unsigned int dst_entropy_flags = 0;
74
75 static isc_boolean_t dst_initialized = ISC_FALSE;
76
77 void gss_log(int level, const char *fmt, ...) ISC_FORMAT_PRINTF(2, 3);
78
79 LIBDNS_EXTERNAL_DATA isc_mem_t *dst__memory_pool = NULL;
80
81 /*
82 * Static functions.
83 */
84 static dst_key_t * get_key_struct(const dns_name_t *name,
85 unsigned int alg,
86 unsigned int flags,
87 unsigned int protocol,
88 unsigned int bits,
89 dns_rdataclass_t rdclass,
90 dns_ttl_t ttl,
91 isc_mem_t *mctx);
92 static isc_result_t write_public_key(const dst_key_t *key, int type,
93 const char *directory);
94 static isc_result_t buildfilename(dns_name_t *name,
95 dns_keytag_t id,
96 unsigned int alg,
97 unsigned int type,
98 const char *directory,
99 isc_buffer_t *out);
100 static isc_result_t computeid(dst_key_t *key);
101 static isc_result_t frombuffer(const dns_name_t *name,
102 unsigned int alg,
103 unsigned int flags,
104 unsigned int protocol,
105 dns_rdataclass_t rdclass,
106 isc_buffer_t *source,
107 isc_mem_t *mctx,
108 dst_key_t **keyp);
109
110 static isc_result_t algorithm_status(unsigned int alg);
111
112 static isc_result_t addsuffix(char *filename, int len,
113 const char *dirname, const char *ofilename,
114 const char *suffix);
115
116 #define RETERR(x) \
117 do { \
118 result = (x); \
119 if (result != ISC_R_SUCCESS) \
120 goto out; \
121 } while (0)
122
123 #define CHECKALG(alg) \
124 do { \
125 isc_result_t _r; \
126 _r = algorithm_status(alg); \
127 if (_r != ISC_R_SUCCESS) \
128 return (_r); \
129 } while (0); \
130
131 #if defined(OPENSSL)
132 static void *
133 default_memalloc(void *arg, size_t size) {
134 UNUSED(arg);
135 if (size == 0U)
136 size = 1;
137 return (malloc(size));
138 }
139
140 static void
141 default_memfree(void *arg, void *ptr) {
142 UNUSED(arg);
143 free(ptr);
144 }
145 #endif
146
147 isc_result_t
148 dst_lib_init(isc_mem_t *mctx, isc_entropy_t *ectx, unsigned int eflags) {
149 return (dst_lib_init2(mctx, ectx, NULL, eflags));
150 }
151
152 isc_result_t
153 dst_lib_init2(isc_mem_t *mctx, isc_entropy_t *ectx,
154 const char *engine, unsigned int eflags) {
155 isc_result_t result;
156
157 REQUIRE(mctx != NULL);
158 REQUIRE(dst_initialized == ISC_FALSE);
159
160 #if !defined(OPENSSL) && !defined(PKCS11CRYPTO)
161 UNUSED(engine);
162 #endif
163
164 dst__memory_pool = NULL;
165
166 #if defined(OPENSSL)
167 UNUSED(mctx);
168 /*
169 * When using --with-openssl, there seems to be no good way of not
170 * leaking memory due to the openssl error handling mechanism.
171 * Avoid assertions by using a local memory context and not checking
172 * for leaks on exit. Note: as there are leaks we cannot use
173 * ISC_MEMFLAG_INTERNAL as it will free up memory still being used
174 * by libcrypto.
175 */
176 result = isc_mem_createx2(0, 0, default_memalloc, default_memfree,
177 NULL, &dst__memory_pool, 0);
178 if (result != ISC_R_SUCCESS)
179 return (result);
180 isc_mem_setname(dst__memory_pool, "dst", NULL);
181 #ifndef OPENSSL_LEAKS
182 isc_mem_setdestroycheck(dst__memory_pool, ISC_FALSE);
183 #endif
184 #else /* OPENSSL */
185 isc_mem_attach(mctx, &dst__memory_pool);
186 #endif /* OPENSSL */
187 if (ectx != NULL) {
188 isc_entropy_attach(ectx, &dst_entropy_pool);
189 dst_entropy_flags = eflags;
190 }
191
192 dst_result_register();
193
194 memset(dst_t_func, 0, sizeof(dst_t_func));
195 #ifndef PK11_MD5_DISABLE
196 RETERR(dst__hmacmd5_init(&dst_t_func[DST_ALG_HMACMD5]));
197 #endif
198 RETERR(dst__hmacsha1_init(&dst_t_func[DST_ALG_HMACSHA1]));
199 RETERR(dst__hmacsha224_init(&dst_t_func[DST_ALG_HMACSHA224]));
200 RETERR(dst__hmacsha256_init(&dst_t_func[DST_ALG_HMACSHA256]));
201 RETERR(dst__hmacsha384_init(&dst_t_func[DST_ALG_HMACSHA384]));
202 RETERR(dst__hmacsha512_init(&dst_t_func[DST_ALG_HMACSHA512]));
203 #ifdef OPENSSL
204 RETERR(dst__openssl_init(engine));
205 #ifndef PK11_MD5_DISABLE
206 RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSAMD5],
207 DST_ALG_RSAMD5));
208 #endif
209 RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSASHA1],
210 DST_ALG_RSASHA1));
211 RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_NSEC3RSASHA1],
212 DST_ALG_NSEC3RSASHA1));
213 RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSASHA256],
214 DST_ALG_RSASHA256));
215 RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSASHA512],
216 DST_ALG_RSASHA512));
217 #if defined(HAVE_OPENSSL_DSA) && !defined(PK11_DSA_DISABLE)
218 RETERR(dst__openssldsa_init(&dst_t_func[DST_ALG_DSA]));
219 RETERR(dst__openssldsa_init(&dst_t_func[DST_ALG_NSEC3DSA]));
220 #endif
221 #ifndef PK11_DH_DISABLE
222 RETERR(dst__openssldh_init(&dst_t_func[DST_ALG_DH]));
223 #endif
224 #ifdef HAVE_OPENSSL_GOST
225 RETERR(dst__opensslgost_init(&dst_t_func[DST_ALG_ECCGOST]));
226 #endif
227 #ifdef HAVE_OPENSSL_ECDSA
228 RETERR(dst__opensslecdsa_init(&dst_t_func[DST_ALG_ECDSA256]));
229 RETERR(dst__opensslecdsa_init(&dst_t_func[DST_ALG_ECDSA384]));
230 #endif
231 #ifdef HAVE_OPENSSL_ED25519
232 RETERR(dst__openssleddsa_init(&dst_t_func[DST_ALG_ED25519]));
233 #endif
234 #ifdef HAVE_OPENSSL_ED448
235 RETERR(dst__openssleddsa_init(&dst_t_func[DST_ALG_ED448]));
236 #endif
237 #elif PKCS11CRYPTO
238 RETERR(dst__pkcs11_init(mctx, engine));
239 #ifndef PK11_MD5_DISABLE
240 RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSAMD5]));
241 #endif
242 RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSASHA1]));
243 RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_NSEC3RSASHA1]));
244 RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSASHA256]));
245 RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSASHA512]));
246 #ifndef PK11_DSA_DISABLE
247 RETERR(dst__pkcs11dsa_init(&dst_t_func[DST_ALG_DSA]));
248 RETERR(dst__pkcs11dsa_init(&dst_t_func[DST_ALG_NSEC3DSA]));
249 #endif
250 #ifndef PK11_DH_DISABLE
251 RETERR(dst__pkcs11dh_init(&dst_t_func[DST_ALG_DH]));
252 #endif
253 #ifdef HAVE_PKCS11_ECDSA
254 RETERR(dst__pkcs11ecdsa_init(&dst_t_func[DST_ALG_ECDSA256]));
255 RETERR(dst__pkcs11ecdsa_init(&dst_t_func[DST_ALG_ECDSA384]));
256 #endif
257 #ifdef HAVE_PKCS11_ED25519
258 RETERR(dst__pkcs11eddsa_init(&dst_t_func[DST_ALG_ED25519]));
259 #endif
260 #ifdef HAVE_PKCS11_ED448
261 RETERR(dst__pkcs11eddsa_init(&dst_t_func[DST_ALG_ED448]));
262 #endif
263 #ifdef HAVE_PKCS11_GOST
264 RETERR(dst__pkcs11gost_init(&dst_t_func[DST_ALG_ECCGOST]));
265 #endif
266 #endif /* if OPENSSL, elif PKCS11CRYPTO */
267 #ifdef GSSAPI
268 RETERR(dst__gssapi_init(&dst_t_func[DST_ALG_GSSAPI]));
269 #endif
270 #if defined(OPENSSL) || defined(PKCS11CRYPTO)
271 #ifdef ISC_PLATFORM_CRYPTORANDOM
272 if (dst_entropy_pool != NULL) {
273 isc_entropy_sethook(dst_random_getdata);
274 }
275 #endif
276 #endif /* defined(OPENSSL) || defined(PKCS11CRYPTO) */
277 dst_initialized = ISC_TRUE;
278 return (ISC_R_SUCCESS);
279
280 out:
281 /* avoid immediate crash! */
282 dst_initialized = ISC_TRUE;
283 dst_lib_destroy();
284 return (result);
285 }
286
287 void
288 dst_lib_destroy(void) {
289 int i;
290 RUNTIME_CHECK(dst_initialized == ISC_TRUE);
291 dst_initialized = ISC_FALSE;
292
293 for (i = 0; i < DST_MAX_ALGS; i++)
294 if (dst_t_func[i] != NULL && dst_t_func[i]->cleanup != NULL)
295 dst_t_func[i]->cleanup();
296 #if defined(OPENSSL) || defined(PKCS11CRYPTO)
297 #ifdef ISC_PLATFORM_CRYPTORANDOM
298 if (dst_entropy_pool != NULL) {
299 isc_entropy_usehook(dst_entropy_pool, ISC_FALSE);
300 isc_entropy_sethook(NULL);
301 }
302 #endif
303 #ifdef OPENSSL
304 dst__openssl_destroy();
305 #elif PKCS11CRYPTO
306 (void) dst__pkcs11_destroy();
307 #endif /* if OPENSSL, elif PKCS11CRYPTO */
308 #endif /* defined(OPENSSL) || defined(PKCS11CRYPTO) */
309 if (dst__memory_pool != NULL)
310 isc_mem_detach(&dst__memory_pool);
311 if (dst_entropy_pool != NULL)
312 isc_entropy_detach(&dst_entropy_pool);
313 }
314
315 isc_boolean_t
316 dst_algorithm_supported(unsigned int alg) {
317 REQUIRE(dst_initialized == ISC_TRUE);
318
319 if (alg >= DST_MAX_ALGS || dst_t_func[alg] == NULL)
320 return (ISC_FALSE);
321 return (ISC_TRUE);
322 }
323
324 isc_boolean_t
325 dst_ds_digest_supported(unsigned int digest_type) {
326 #if defined(HAVE_OPENSSL_GOST) || defined(HAVE_PKCS11_GOST)
327 return (ISC_TF(digest_type == DNS_DSDIGEST_SHA1 ||
328 digest_type == DNS_DSDIGEST_SHA256 ||
329 digest_type == DNS_DSDIGEST_GOST ||
330 digest_type == DNS_DSDIGEST_SHA384));
331 #else
332 return (ISC_TF(digest_type == DNS_DSDIGEST_SHA1 ||
333 digest_type == DNS_DSDIGEST_SHA256 ||
334 digest_type == DNS_DSDIGEST_SHA384));
335 #endif
336 }
337
338 isc_result_t
339 dst_context_create(dst_key_t *key, isc_mem_t *mctx, dst_context_t **dctxp) {
340 return (dst_context_create4(key, mctx, DNS_LOGCATEGORY_GENERAL,
341 ISC_TRUE, 0, dctxp));
342 }
343
344 isc_result_t
345 dst_context_create2(dst_key_t *key, isc_mem_t *mctx,
346 isc_logcategory_t *category, dst_context_t **dctxp)
347 {
348 return (dst_context_create4(key, mctx, category, ISC_TRUE, 0, dctxp));
349 }
350
351 isc_result_t
352 dst_context_create3(dst_key_t *key, isc_mem_t *mctx,
353 isc_logcategory_t *category, isc_boolean_t useforsigning,
354 dst_context_t **dctxp)
355 {
356 return (dst_context_create4(key, mctx, category,
357 useforsigning, 0, dctxp));
358 }
359
360 isc_result_t
361 dst_context_create4(dst_key_t *key, isc_mem_t *mctx,
362 isc_logcategory_t *category, isc_boolean_t useforsigning,
363 int maxbits, dst_context_t **dctxp)
364 {
365 dst_context_t *dctx;
366 isc_result_t result;
367
368 REQUIRE(dst_initialized == ISC_TRUE);
369 REQUIRE(VALID_KEY(key));
370 REQUIRE(mctx != NULL);
371 REQUIRE(dctxp != NULL && *dctxp == NULL);
372
373 if (key->func->createctx == NULL &&
374 key->func->createctx2 == NULL)
375 return (DST_R_UNSUPPORTEDALG);
376 if (key->keydata.generic == NULL)
377 return (DST_R_NULLKEY);
378
379 dctx = isc_mem_get(mctx, sizeof(dst_context_t));
380 if (dctx == NULL)
381 return (ISC_R_NOMEMORY);
382 memset(dctx, 0, sizeof(*dctx));
383 dst_key_attach(key, &dctx->key);
384 isc_mem_attach(mctx, &dctx->mctx);
385 dctx->category = category;
386 if (useforsigning)
387 dctx->use = DO_SIGN;
388 else
389 dctx->use = DO_VERIFY;
390 if (key->func->createctx2 != NULL)
391 result = key->func->createctx2(key, maxbits, dctx);
392 else
393 result = key->func->createctx(key, dctx);
394 if (result != ISC_R_SUCCESS) {
395 if (dctx->key != NULL)
396 dst_key_free(&dctx->key);
397 isc_mem_putanddetach(&dctx->mctx, dctx, sizeof(dst_context_t));
398 return (result);
399 }
400 dctx->magic = CTX_MAGIC;
401 *dctxp = dctx;
402 return (ISC_R_SUCCESS);
403 }
404
405 void
406 dst_context_destroy(dst_context_t **dctxp) {
407 dst_context_t *dctx;
408
409 REQUIRE(dctxp != NULL && VALID_CTX(*dctxp));
410
411 dctx = *dctxp;
412 INSIST(dctx->key->func->destroyctx != NULL);
413 dctx->key->func->destroyctx(dctx);
414 if (dctx->key != NULL)
415 dst_key_free(&dctx->key);
416 dctx->magic = 0;
417 isc_mem_putanddetach(&dctx->mctx, dctx, sizeof(dst_context_t));
418 *dctxp = NULL;
419 }
420
421 isc_result_t
422 dst_context_adddata(dst_context_t *dctx, const isc_region_t *data) {
423 REQUIRE(VALID_CTX(dctx));
424 REQUIRE(data != NULL);
425 INSIST(dctx->key->func->adddata != NULL);
426
427 return (dctx->key->func->adddata(dctx, data));
428 }
429
430 isc_result_t
431 dst_context_sign(dst_context_t *dctx, isc_buffer_t *sig) {
432 dst_key_t *key;
433
434 REQUIRE(VALID_CTX(dctx));
435 REQUIRE(sig != NULL);
436
437 key = dctx->key;
438 CHECKALG(key->key_alg);
439 if (key->keydata.generic == NULL)
440 return (DST_R_NULLKEY);
441
442 if (key->func->sign == NULL)
443 return (DST_R_NOTPRIVATEKEY);
444 if (key->func->isprivate == NULL ||
445 key->func->isprivate(key) == ISC_FALSE)
446 return (DST_R_NOTPRIVATEKEY);
447
448 return (key->func->sign(dctx, sig));
449 }
450
451 isc_result_t
452 dst_context_verify(dst_context_t *dctx, isc_region_t *sig) {
453 REQUIRE(VALID_CTX(dctx));
454 REQUIRE(sig != NULL);
455
456 CHECKALG(dctx->key->key_alg);
457 if (dctx->key->keydata.generic == NULL)
458 return (DST_R_NULLKEY);
459 if (dctx->key->func->verify == NULL)
460 return (DST_R_NOTPUBLICKEY);
461
462 return (dctx->key->func->verify(dctx, sig));
463 }
464
465 isc_result_t
466 dst_context_verify2(dst_context_t *dctx, unsigned int maxbits,
467 isc_region_t *sig)
468 {
469 REQUIRE(VALID_CTX(dctx));
470 REQUIRE(sig != NULL);
471
472 CHECKALG(dctx->key->key_alg);
473 if (dctx->key->keydata.generic == NULL)
474 return (DST_R_NULLKEY);
475 if (dctx->key->func->verify == NULL &&
476 dctx->key->func->verify2 == NULL)
477 return (DST_R_NOTPUBLICKEY);
478
479 return (dctx->key->func->verify2 != NULL ?
480 dctx->key->func->verify2(dctx, maxbits, sig) :
481 dctx->key->func->verify(dctx, sig));
482 }
483
484 isc_result_t
485 dst_key_computesecret(const dst_key_t *pub, const dst_key_t *priv,
486 isc_buffer_t *secret)
487 {
488 REQUIRE(dst_initialized == ISC_TRUE);
489 REQUIRE(VALID_KEY(pub) && VALID_KEY(priv));
490 REQUIRE(secret != NULL);
491
492 CHECKALG(pub->key_alg);
493 CHECKALG(priv->key_alg);
494
495 if (pub->keydata.generic == NULL || priv->keydata.generic == NULL)
496 return (DST_R_NULLKEY);
497
498 if (pub->key_alg != priv->key_alg ||
499 pub->func->computesecret == NULL ||
500 priv->func->computesecret == NULL)
501 return (DST_R_KEYCANNOTCOMPUTESECRET);
502
503 if (dst_key_isprivate(priv) == ISC_FALSE)
504 return (DST_R_NOTPRIVATEKEY);
505
506 return (pub->func->computesecret(pub, priv, secret));
507 }
508
509 isc_result_t
510 dst_key_tofile(const dst_key_t *key, int type, const char *directory) {
511 isc_result_t ret = ISC_R_SUCCESS;
512
513 REQUIRE(dst_initialized == ISC_TRUE);
514 REQUIRE(VALID_KEY(key));
515 REQUIRE((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) != 0);
516
517 CHECKALG(key->key_alg);
518
519 if (key->func->tofile == NULL)
520 return (DST_R_UNSUPPORTEDALG);
521
522 if (type & DST_TYPE_PUBLIC) {
523 ret = write_public_key(key, type, directory);
524 if (ret != ISC_R_SUCCESS)
525 return (ret);
526 }
527
528 if ((type & DST_TYPE_PRIVATE) &&
529 (key->key_flags & DNS_KEYFLAG_TYPEMASK) != DNS_KEYTYPE_NOKEY)
530 return (key->func->tofile(key, directory));
531 else
532 return (ISC_R_SUCCESS);
533 }
534
535 void
536 dst_key_setexternal(dst_key_t *key, isc_boolean_t value) {
537 key->external = value;
538 }
539
540 isc_boolean_t
541 dst_key_isexternal(dst_key_t *key) {
542 return (key->external);
543 }
544
545 isc_result_t
546 dst_key_getfilename(dns_name_t *name, dns_keytag_t id,
547 unsigned int alg, int type, const char *directory,
548 isc_mem_t *mctx, isc_buffer_t *buf)
549 {
550 isc_result_t result;
551
552 REQUIRE(dst_initialized == ISC_TRUE);
553 REQUIRE(dns_name_isabsolute(name));
554 REQUIRE((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) != 0);
555 REQUIRE(mctx != NULL);
556 REQUIRE(buf != NULL);
557
558 CHECKALG(alg);
559
560 result = buildfilename(name, id, alg, type, directory, buf);
561 if (result == ISC_R_SUCCESS) {
562 if (isc_buffer_availablelength(buf) > 0)
563 isc_buffer_putuint8(buf, 0);
564 else
565 result = ISC_R_NOSPACE;
566 }
567
568 return (result);
569 }
570
571 isc_result_t
572 dst_key_fromfile(dns_name_t *name, dns_keytag_t id,
573 unsigned int alg, int type, const char *directory,
574 isc_mem_t *mctx, dst_key_t **keyp)
575 {
576 isc_result_t result;
577 char filename[ISC_DIR_NAMEMAX];
578 isc_buffer_t buf;
579 dst_key_t *key;
580
581 REQUIRE(dst_initialized == ISC_TRUE);
582 REQUIRE(dns_name_isabsolute(name));
583 REQUIRE((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) != 0);
584 REQUIRE(mctx != NULL);
585 REQUIRE(keyp != NULL && *keyp == NULL);
586
587 CHECKALG(alg);
588
589 key = NULL;
590
591 isc_buffer_init(&buf, filename, ISC_DIR_NAMEMAX);
592 result = dst_key_getfilename(name, id, alg, type, NULL, mctx, &buf);
593 if (result != ISC_R_SUCCESS)
594 goto out;
595
596 result = dst_key_fromnamedfile(filename, directory, type, mctx, &key);
597 if (result != ISC_R_SUCCESS)
598 goto out;
599
600 result = computeid(key);
601 if (result != ISC_R_SUCCESS)
602 goto out;
603
604 if (!dns_name_equal(name, key->key_name) || id != key->key_id ||
605 alg != key->key_alg) {
606 result = DST_R_INVALIDPRIVATEKEY;
607 goto out;
608 }
609
610 *keyp = key;
611 result = ISC_R_SUCCESS;
612
613 out:
614 if ((key != NULL) && (result != ISC_R_SUCCESS))
615 dst_key_free(&key);
616
617 return (result);
618 }
619
620 isc_result_t
621 dst_key_fromnamedfile(const char *filename, const char *dirname,
622 int type, isc_mem_t *mctx, dst_key_t **keyp)
623 {
624 isc_result_t result;
625 dst_key_t *pubkey = NULL, *key = NULL;
626 char *newfilename = NULL;
627 int newfilenamelen = 0;
628 isc_lex_t *lex = NULL;
629
630 REQUIRE(dst_initialized == ISC_TRUE);
631 REQUIRE(filename != NULL);
632 REQUIRE((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) != 0);
633 REQUIRE(mctx != NULL);
634 REQUIRE(keyp != NULL && *keyp == NULL);
635
636 /* If an absolute path is specified, don't use the key directory */
637 #ifndef WIN32
638 if (filename[0] == '/')
639 dirname = NULL;
640 #else /* WIN32 */
641 if (filename[0] == '/' || filename[0] == '\\')
642 dirname = NULL;
643 #endif
644
645 newfilenamelen = strlen(filename) + 5;
646 if (dirname != NULL)
647 newfilenamelen += strlen(dirname) + 1;
648 newfilename = isc_mem_get(mctx, newfilenamelen);
649 if (newfilename == NULL)
650 return (ISC_R_NOMEMORY);
651 result = addsuffix(newfilename, newfilenamelen,
652 dirname, filename, ".key");
653 INSIST(result == ISC_R_SUCCESS);
654
655 result = dst_key_read_public(newfilename, type, mctx, &pubkey);
656 isc_mem_put(mctx, newfilename, newfilenamelen);
657 newfilename = NULL;
658 RETERR(result);
659
660 if ((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) == DST_TYPE_PUBLIC ||
661 (pubkey->key_flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY) {
662 result = computeid(pubkey);
663 if (result != ISC_R_SUCCESS) {
664 dst_key_free(&pubkey);
665 return (result);
666 }
667
668 *keyp = pubkey;
669 return (ISC_R_SUCCESS);
670 }
671
672 result = algorithm_status(pubkey->key_alg);
673 if (result != ISC_R_SUCCESS) {
674 dst_key_free(&pubkey);
675 return (result);
676 }
677
678 key = get_key_struct(pubkey->key_name, pubkey->key_alg,
679 pubkey->key_flags, pubkey->key_proto, 0,
680 pubkey->key_class, pubkey->key_ttl, mctx);
681 if (key == NULL) {
682 dst_key_free(&pubkey);
683 return (ISC_R_NOMEMORY);
684 }
685
686 if (key->func->parse == NULL)
687 RETERR(DST_R_UNSUPPORTEDALG);
688
689 newfilenamelen = strlen(filename) + 9;
690 if (dirname != NULL)
691 newfilenamelen += strlen(dirname) + 1;
692 newfilename = isc_mem_get(mctx, newfilenamelen);
693 if (newfilename == NULL)
694 RETERR(ISC_R_NOMEMORY);
695 result = addsuffix(newfilename, newfilenamelen,
696 dirname, filename, ".private");
697 INSIST(result == ISC_R_SUCCESS);
698
699 RETERR(isc_lex_create(mctx, 1500, &lex));
700 RETERR(isc_lex_openfile(lex, newfilename));
701 isc_mem_put(mctx, newfilename, newfilenamelen);
702
703 RETERR(key->func->parse(key, lex, pubkey));
704 isc_lex_destroy(&lex);
705
706 RETERR(computeid(key));
707
708 if (pubkey->key_id != key->key_id)
709 RETERR(DST_R_INVALIDPRIVATEKEY);
710 dst_key_free(&pubkey);
711
712 *keyp = key;
713 return (ISC_R_SUCCESS);
714
715 out:
716 if (pubkey != NULL)
717 dst_key_free(&pubkey);
718 if (newfilename != NULL)
719 isc_mem_put(mctx, newfilename, newfilenamelen);
720 if (lex != NULL)
721 isc_lex_destroy(&lex);
722 if (key != NULL)
723 dst_key_free(&key);
724 return (result);
725 }
726
727 isc_result_t
728 dst_key_todns(const dst_key_t *key, isc_buffer_t *target) {
729 REQUIRE(dst_initialized == ISC_TRUE);
730 REQUIRE(VALID_KEY(key));
731 REQUIRE(target != NULL);
732
733 CHECKALG(key->key_alg);
734
735 if (key->func->todns == NULL)
736 return (DST_R_UNSUPPORTEDALG);
737
738 if (isc_buffer_availablelength(target) < 4)
739 return (ISC_R_NOSPACE);
740 isc_buffer_putuint16(target, (isc_uint16_t)(key->key_flags & 0xffff));
741 isc_buffer_putuint8(target, (isc_uint8_t)key->key_proto);
742 isc_buffer_putuint8(target, (isc_uint8_t)key->key_alg);
743
744 if (key->key_flags & DNS_KEYFLAG_EXTENDED) {
745 if (isc_buffer_availablelength(target) < 2)
746 return (ISC_R_NOSPACE);
747 isc_buffer_putuint16(target,
748 (isc_uint16_t)((key->key_flags >> 16)
749 & 0xffff));
750 }
751
752 if (key->keydata.generic == NULL) /*%< NULL KEY */
753 return (ISC_R_SUCCESS);
754
755 return (key->func->todns(key, target));
756 }
757
758 isc_result_t
759 dst_key_fromdns(const dns_name_t *name, dns_rdataclass_t rdclass,
760 isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp)
761 {
762 isc_uint8_t alg, proto;
763 isc_uint32_t flags, extflags;
764 dst_key_t *key = NULL;
765 dns_keytag_t id, rid;
766 isc_region_t r;
767 isc_result_t result;
768
769 REQUIRE(dst_initialized);
770
771 isc_buffer_remainingregion(source, &r);
772
773 if (isc_buffer_remaininglength(source) < 4)
774 return (DST_R_INVALIDPUBLICKEY);
775 flags = isc_buffer_getuint16(source);
776 proto = isc_buffer_getuint8(source);
777 alg = isc_buffer_getuint8(source);
778
779 id = dst_region_computeid(&r, alg);
780 rid = dst_region_computerid(&r, alg);
781
782 if (flags & DNS_KEYFLAG_EXTENDED) {
783 if (isc_buffer_remaininglength(source) < 2)
784 return (DST_R_INVALIDPUBLICKEY);
785 extflags = isc_buffer_getuint16(source);
786 flags |= (extflags << 16);
787 }
788
789 result = frombuffer(name, alg, flags, proto, rdclass, source,
790 mctx, &key);
791 if (result != ISC_R_SUCCESS)
792 return (result);
793 key->key_id = id;
794 key->key_rid = rid;
795
796 *keyp = key;
797 return (ISC_R_SUCCESS);
798 }
799
800 isc_result_t
801 dst_key_frombuffer(const dns_name_t *name, unsigned int alg,
802 unsigned int flags, unsigned int protocol,
803 dns_rdataclass_t rdclass,
804 isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp)
805 {
806 dst_key_t *key = NULL;
807 isc_result_t result;
808
809 REQUIRE(dst_initialized);
810
811 result = frombuffer(name, alg, flags, protocol, rdclass, source,
812 mctx, &key);
813 if (result != ISC_R_SUCCESS)
814 return (result);
815
816 result = computeid(key);
817 if (result != ISC_R_SUCCESS) {
818 dst_key_free(&key);
819 return (result);
820 }
821
822 *keyp = key;
823 return (ISC_R_SUCCESS);
824 }
825
826 isc_result_t
827 dst_key_tobuffer(const dst_key_t *key, isc_buffer_t *target) {
828 REQUIRE(dst_initialized == ISC_TRUE);
829 REQUIRE(VALID_KEY(key));
830 REQUIRE(target != NULL);
831
832 CHECKALG(key->key_alg);
833
834 if (key->func->todns == NULL)
835 return (DST_R_UNSUPPORTEDALG);
836
837 return (key->func->todns(key, target));
838 }
839
840 isc_result_t
841 dst_key_privatefrombuffer(dst_key_t *key, isc_buffer_t *buffer) {
842 isc_lex_t *lex = NULL;
843 isc_result_t result = ISC_R_SUCCESS;
844
845 REQUIRE(dst_initialized == ISC_TRUE);
846 REQUIRE(VALID_KEY(key));
847 REQUIRE(!dst_key_isprivate(key));
848 REQUIRE(buffer != NULL);
849
850 if (key->func->parse == NULL)
851 RETERR(DST_R_UNSUPPORTEDALG);
852
853 RETERR(isc_lex_create(key->mctx, 1500, &lex));
854 RETERR(isc_lex_openbuffer(lex, buffer));
855 RETERR(key->func->parse(key, lex, NULL));
856 out:
857 if (lex != NULL)
858 isc_lex_destroy(&lex);
859 return (result);
860 }
861
862 gss_ctx_id_t
863 dst_key_getgssctx(const dst_key_t *key)
864 {
865 REQUIRE(key != NULL);
866
867 return (key->keydata.gssctx);
868 }
869
870 isc_result_t
871 dst_key_fromgssapi(const dns_name_t *name, gss_ctx_id_t gssctx,
872 isc_mem_t *mctx, dst_key_t **keyp, isc_region_t *intoken)
873 {
874 dst_key_t *key;
875 isc_result_t result;
876
877 REQUIRE(gssctx != NULL);
878 REQUIRE(keyp != NULL && *keyp == NULL);
879
880 key = get_key_struct(name, DST_ALG_GSSAPI, 0, DNS_KEYPROTO_DNSSEC,
881 0, dns_rdataclass_in, 0, mctx);
882 if (key == NULL)
883 return (ISC_R_NOMEMORY);
884
885 if (intoken != NULL) {
886 /*
887 * Keep the token for use by external ssu rules. They may need
888 * to examine the PAC in the kerberos ticket.
889 */
890 RETERR(isc_buffer_allocate(key->mctx, &key->key_tkeytoken,
891 intoken->length));
892 RETERR(isc_buffer_copyregion(key->key_tkeytoken, intoken));
893 }
894
895 key->keydata.gssctx = gssctx;
896 *keyp = key;
897 result = ISC_R_SUCCESS;
898 out:
899 return result;
900 }
901
902 isc_result_t
903 dst_key_buildinternal(const dns_name_t *name, unsigned int alg,
904 unsigned int bits, unsigned int flags,
905 unsigned int protocol, dns_rdataclass_t rdclass,
906 void *data, isc_mem_t *mctx, dst_key_t **keyp)
907 {
908 dst_key_t *key;
909 isc_result_t result;
910
911 REQUIRE(dst_initialized == ISC_TRUE);
912 REQUIRE(dns_name_isabsolute(name));
913 REQUIRE(mctx != NULL);
914 REQUIRE(keyp != NULL && *keyp == NULL);
915 REQUIRE(data != NULL);
916
917 CHECKALG(alg);
918
919 key = get_key_struct(name, alg, flags, protocol, bits, rdclass,
920 0, mctx);
921 if (key == NULL)
922 return (ISC_R_NOMEMORY);
923
924 key->keydata.generic = data;
925
926 result = computeid(key);
927 if (result != ISC_R_SUCCESS) {
928 dst_key_free(&key);
929 return (result);
930 }
931
932 *keyp = key;
933 return (ISC_R_SUCCESS);
934 }
935
936 isc_result_t
937 dst_key_fromlabel(const dns_name_t *name, int alg, unsigned int flags,
938 unsigned int protocol, dns_rdataclass_t rdclass,
939 const char *engine, const char *label, const char *pin,
940 isc_mem_t *mctx, dst_key_t **keyp)
941 {
942 dst_key_t *key;
943 isc_result_t result;
944
945 REQUIRE(dst_initialized == ISC_TRUE);
946 REQUIRE(dns_name_isabsolute(name));
947 REQUIRE(mctx != NULL);
948 REQUIRE(keyp != NULL && *keyp == NULL);
949 REQUIRE(label != NULL);
950
951 CHECKALG(alg);
952
953 key = get_key_struct(name, alg, flags, protocol, 0, rdclass, 0, mctx);
954 if (key == NULL)
955 return (ISC_R_NOMEMORY);
956
957 if (key->func->fromlabel == NULL) {
958 dst_key_free(&key);
959 return (DST_R_UNSUPPORTEDALG);
960 }
961
962 result = key->func->fromlabel(key, engine, label, pin);
963 if (result != ISC_R_SUCCESS) {
964 dst_key_free(&key);
965 return (result);
966 }
967
968 result = computeid(key);
969 if (result != ISC_R_SUCCESS) {
970 dst_key_free(&key);
971 return (result);
972 }
973
974 *keyp = key;
975 return (ISC_R_SUCCESS);
976 }
977
978 isc_result_t
979 dst_key_generate(const dns_name_t *name, unsigned int alg,
980 unsigned int bits, unsigned int param,
981 unsigned int flags, unsigned int protocol,
982 dns_rdataclass_t rdclass,
983 isc_mem_t *mctx, dst_key_t **keyp)
984 {
985 return (dst_key_generate2(name, alg, bits, param, flags, protocol,
986 rdclass, mctx, keyp, NULL));
987 }
988
989 isc_result_t
990 dst_key_generate2(const dns_name_t *name, unsigned int alg,
991 unsigned int bits, unsigned int param,
992 unsigned int flags, unsigned int protocol,
993 dns_rdataclass_t rdclass,
994 isc_mem_t *mctx, dst_key_t **keyp,
995 void (*callback)(int))
996 {
997 dst_key_t *key;
998 isc_result_t ret;
999
1000 REQUIRE(dst_initialized == ISC_TRUE);
1001 REQUIRE(dns_name_isabsolute(name));
1002 REQUIRE(mctx != NULL);
1003 REQUIRE(keyp != NULL && *keyp == NULL);
1004
1005 CHECKALG(alg);
1006
1007 key = get_key_struct(name, alg, flags, protocol, bits,
1008 rdclass, 0, mctx);
1009 if (key == NULL)
1010 return (ISC_R_NOMEMORY);
1011
1012 if (bits == 0) { /*%< NULL KEY */
1013 key->key_flags |= DNS_KEYTYPE_NOKEY;
1014 *keyp = key;
1015 return (ISC_R_SUCCESS);
1016 }
1017
1018 if (key->func->generate == NULL) {
1019 dst_key_free(&key);
1020 return (DST_R_UNSUPPORTEDALG);
1021 }
1022
1023 ret = key->func->generate(key, param, callback);
1024 if (ret != ISC_R_SUCCESS) {
1025 dst_key_free(&key);
1026 return (ret);
1027 }
1028
1029 ret = computeid(key);
1030 if (ret != ISC_R_SUCCESS) {
1031 dst_key_free(&key);
1032 return (ret);
1033 }
1034
1035 *keyp = key;
1036 return (ISC_R_SUCCESS);
1037 }
1038
1039 isc_result_t
1040 dst_key_getnum(const dst_key_t *key, int type, isc_uint32_t *valuep)
1041 {
1042 REQUIRE(VALID_KEY(key));
1043 REQUIRE(valuep != NULL);
1044 REQUIRE(type <= DST_MAX_NUMERIC);
1045 if (!key->numset[type])
1046 return (ISC_R_NOTFOUND);
1047 *valuep = key->nums[type];
1048 return (ISC_R_SUCCESS);
1049 }
1050
1051 void
1052 dst_key_setnum(dst_key_t *key, int type, isc_uint32_t value)
1053 {
1054 REQUIRE(VALID_KEY(key));
1055 REQUIRE(type <= DST_MAX_NUMERIC);
1056 key->nums[type] = value;
1057 key->numset[type] = ISC_TRUE;
1058 }
1059
1060 void
1061 dst_key_unsetnum(dst_key_t *key, int type)
1062 {
1063 REQUIRE(VALID_KEY(key));
1064 REQUIRE(type <= DST_MAX_NUMERIC);
1065 key->numset[type] = ISC_FALSE;
1066 }
1067
1068 isc_result_t
1069 dst_key_gettime(const dst_key_t *key, int type, isc_stdtime_t *timep) {
1070 REQUIRE(VALID_KEY(key));
1071 REQUIRE(timep != NULL);
1072 REQUIRE(type <= DST_MAX_TIMES);
1073 if (!key->timeset[type])
1074 return (ISC_R_NOTFOUND);
1075 *timep = key->times[type];
1076 return (ISC_R_SUCCESS);
1077 }
1078
1079 void
1080 dst_key_settime(dst_key_t *key, int type, isc_stdtime_t when) {
1081 REQUIRE(VALID_KEY(key));
1082 REQUIRE(type <= DST_MAX_TIMES);
1083 key->times[type] = when;
1084 key->timeset[type] = ISC_TRUE;
1085 }
1086
1087 void
1088 dst_key_unsettime(dst_key_t *key, int type) {
1089 REQUIRE(VALID_KEY(key));
1090 REQUIRE(type <= DST_MAX_TIMES);
1091 key->timeset[type] = ISC_FALSE;
1092 }
1093
1094 isc_result_t
1095 dst_key_getprivateformat(const dst_key_t *key, int *majorp, int *minorp) {
1096 REQUIRE(VALID_KEY(key));
1097 REQUIRE(majorp != NULL);
1098 REQUIRE(minorp != NULL);
1099 *majorp = key->fmt_major;
1100 *minorp = key->fmt_minor;
1101 return (ISC_R_SUCCESS);
1102 }
1103
1104 void
1105 dst_key_setprivateformat(dst_key_t *key, int major, int minor) {
1106 REQUIRE(VALID_KEY(key));
1107 key->fmt_major = major;
1108 key->fmt_minor = minor;
1109 }
1110
1111 static isc_boolean_t
1112 comparekeys(const dst_key_t *key1, const dst_key_t *key2,
1113 isc_boolean_t match_revoked_key,
1114 isc_boolean_t (*compare)(const dst_key_t *key1,
1115 const dst_key_t *key2))
1116 {
1117 REQUIRE(dst_initialized == ISC_TRUE);
1118 REQUIRE(VALID_KEY(key1));
1119 REQUIRE(VALID_KEY(key2));
1120
1121 if (key1 == key2)
1122 return (ISC_TRUE);
1123
1124 if (key1->key_alg != key2->key_alg)
1125 return (ISC_FALSE);
1126
1127 if (key1->key_id != key2->key_id) {
1128 if (!match_revoked_key)
1129 return (ISC_FALSE);
1130 #ifndef PK11_MD5_DISABLE
1131 if (key1->key_alg == DST_ALG_RSAMD5)
1132 return (ISC_FALSE);
1133 #endif
1134 if ((key1->key_flags & DNS_KEYFLAG_REVOKE) ==
1135 (key2->key_flags & DNS_KEYFLAG_REVOKE))
1136 return (ISC_FALSE);
1137 if (key1->key_id != key2->key_rid &&
1138 key1->key_rid != key2->key_id)
1139 return (ISC_FALSE);
1140 }
1141
1142 if (compare != NULL)
1143 return (compare(key1, key2));
1144 else
1145 return (ISC_FALSE);
1146 }
1147
1148
1149 /*
1150 * Compares only the public portion of two keys, by converting them
1151 * both to wire format and comparing the results.
1152 */
1153 static isc_boolean_t
1154 pub_compare(const dst_key_t *key1, const dst_key_t *key2) {
1155 isc_result_t result;
1156 unsigned char buf1[DST_KEY_MAXSIZE], buf2[DST_KEY_MAXSIZE];
1157 isc_buffer_t b1, b2;
1158 isc_region_t r1, r2;
1159
1160 isc_buffer_init(&b1, buf1, sizeof(buf1));
1161 result = dst_key_todns(key1, &b1);
1162 if (result != ISC_R_SUCCESS)
1163 return (ISC_FALSE);
1164 /* Zero out flags. */
1165 buf1[0] = buf1[1] = 0;
1166 if ((key1->key_flags & DNS_KEYFLAG_EXTENDED) != 0)
1167 isc_buffer_subtract(&b1, 2);
1168
1169 isc_buffer_init(&b2, buf2, sizeof(buf2));
1170 result = dst_key_todns(key2, &b2);
1171 if (result != ISC_R_SUCCESS)
1172 return (ISC_FALSE);
1173 /* Zero out flags. */
1174 buf2[0] = buf2[1] = 0;
1175 if ((key2->key_flags & DNS_KEYFLAG_EXTENDED) != 0)
1176 isc_buffer_subtract(&b2, 2);
1177
1178 isc_buffer_usedregion(&b1, &r1);
1179 /* Remove extended flags. */
1180 if ((key1->key_flags & DNS_KEYFLAG_EXTENDED) != 0) {
1181 memmove(&buf1[4], &buf1[6], r1.length - 6);
1182 r1.length -= 2;
1183 }
1184
1185 isc_buffer_usedregion(&b2, &r2);
1186 /* Remove extended flags. */
1187 if ((key2->key_flags & DNS_KEYFLAG_EXTENDED) != 0) {
1188 memmove(&buf2[4], &buf2[6], r2.length - 6);
1189 r2.length -= 2;
1190 }
1191 return (ISC_TF(isc_region_compare(&r1, &r2) == 0));
1192 }
1193
1194 isc_boolean_t
1195 dst_key_compare(const dst_key_t *key1, const dst_key_t *key2) {
1196 return (comparekeys(key1, key2, ISC_FALSE, key1->func->compare));
1197 }
1198
1199 isc_boolean_t
1200 dst_key_pubcompare(const dst_key_t *key1, const dst_key_t *key2,
1201 isc_boolean_t match_revoked_key)
1202 {
1203 return (comparekeys(key1, key2, match_revoked_key, pub_compare));
1204 }
1205
1206
1207 isc_boolean_t
1208 dst_key_paramcompare(const dst_key_t *key1, const dst_key_t *key2) {
1209 REQUIRE(dst_initialized == ISC_TRUE);
1210 REQUIRE(VALID_KEY(key1));
1211 REQUIRE(VALID_KEY(key2));
1212
1213 if (key1 == key2)
1214 return (ISC_TRUE);
1215 if (key1->key_alg == key2->key_alg &&
1216 key1->func->paramcompare != NULL &&
1217 key1->func->paramcompare(key1, key2) == ISC_TRUE)
1218 return (ISC_TRUE);
1219 else
1220 return (ISC_FALSE);
1221 }
1222
1223 void
1224 dst_key_attach(dst_key_t *source, dst_key_t **target) {
1225
1226 REQUIRE(dst_initialized == ISC_TRUE);
1227 REQUIRE(target != NULL && *target == NULL);
1228 REQUIRE(VALID_KEY(source));
1229
1230 isc_refcount_increment(&source->refs, NULL);
1231 *target = source;
1232 }
1233
1234 void
1235 dst_key_free(dst_key_t **keyp) {
1236 isc_mem_t *mctx;
1237 dst_key_t *key;
1238 unsigned int refs;
1239
1240 REQUIRE(dst_initialized == ISC_TRUE);
1241 REQUIRE(keyp != NULL && VALID_KEY(*keyp));
1242
1243 key = *keyp;
1244 mctx = key->mctx;
1245
1246 isc_refcount_decrement(&key->refs, &refs);
1247 if (refs != 0)
1248 return;
1249
1250 isc_refcount_destroy(&key->refs);
1251 if (key->keydata.generic != NULL) {
1252 INSIST(key->func->destroy != NULL);
1253 key->func->destroy(key);
1254 }
1255 if (key->engine != NULL)
1256 isc_mem_free(mctx, key->engine);
1257 if (key->label != NULL)
1258 isc_mem_free(mctx, key->label);
1259 dns_name_free(key->key_name, mctx);
1260 isc_mem_put(mctx, key->key_name, sizeof(dns_name_t));
1261 if (key->key_tkeytoken) {
1262 isc_buffer_free(&key->key_tkeytoken);
1263 }
1264 isc_safe_memwipe(key, sizeof(*key));
1265 isc_mem_putanddetach(&mctx, key, sizeof(*key));
1266 *keyp = NULL;
1267 }
1268
1269 isc_boolean_t
1270 dst_key_isprivate(const dst_key_t *key) {
1271 REQUIRE(VALID_KEY(key));
1272 INSIST(key->func->isprivate != NULL);
1273 return (key->func->isprivate(key));
1274 }
1275
1276 isc_result_t
1277 dst_key_buildfilename(const dst_key_t *key, int type,
1278 const char *directory, isc_buffer_t *out) {
1279
1280 REQUIRE(VALID_KEY(key));
1281 REQUIRE(type == DST_TYPE_PRIVATE || type == DST_TYPE_PUBLIC ||
1282 type == 0);
1283
1284 return (buildfilename(key->key_name, key->key_id, key->key_alg,
1285 type, directory, out));
1286 }
1287
1288 isc_result_t
1289 dst_key_sigsize(const dst_key_t *key, unsigned int *n) {
1290 REQUIRE(dst_initialized == ISC_TRUE);
1291 REQUIRE(VALID_KEY(key));
1292 REQUIRE(n != NULL);
1293
1294 /* XXXVIX this switch statement is too sparse to gen a jump table. */
1295 switch (key->key_alg) {
1296 #ifndef PK11_MD5_DISABLE
1297 case DST_ALG_RSAMD5:
1298 #endif
1299 case DST_ALG_RSASHA1:
1300 case DST_ALG_NSEC3RSASHA1:
1301 case DST_ALG_RSASHA256:
1302 case DST_ALG_RSASHA512:
1303 *n = (key->key_size + 7) / 8;
1304 break;
1305 #ifndef PK11_DSA_DISABLE
1306 case DST_ALG_DSA:
1307 case DST_ALG_NSEC3DSA:
1308 *n = DNS_SIG_DSASIGSIZE;
1309 break;
1310 #endif
1311 case DST_ALG_ECCGOST:
1312 *n = DNS_SIG_GOSTSIGSIZE;
1313 break;
1314 case DST_ALG_ECDSA256:
1315 *n = DNS_SIG_ECDSA256SIZE;
1316 break;
1317 case DST_ALG_ECDSA384:
1318 *n = DNS_SIG_ECDSA384SIZE;
1319 break;
1320 case DST_ALG_ED25519:
1321 *n = DNS_SIG_ED25519SIZE;
1322 break;
1323 case DST_ALG_ED448:
1324 *n = DNS_SIG_ED448SIZE;
1325 break;
1326 #ifndef PK11_MD5_DISABLE
1327 case DST_ALG_HMACMD5:
1328 *n = 16;
1329 break;
1330 #endif
1331 case DST_ALG_HMACSHA1:
1332 *n = ISC_SHA1_DIGESTLENGTH;
1333 break;
1334 case DST_ALG_HMACSHA224:
1335 *n = ISC_SHA224_DIGESTLENGTH;
1336 break;
1337 case DST_ALG_HMACSHA256:
1338 *n = ISC_SHA256_DIGESTLENGTH;
1339 break;
1340 case DST_ALG_HMACSHA384:
1341 *n = ISC_SHA384_DIGESTLENGTH;
1342 break;
1343 case DST_ALG_HMACSHA512:
1344 *n = ISC_SHA512_DIGESTLENGTH;
1345 break;
1346 case DST_ALG_GSSAPI:
1347 *n = 128; /*%< XXX */
1348 break;
1349 #ifndef PK11_DH_DISABLE
1350 case DST_ALG_DH:
1351 #endif
1352 default:
1353 return (DST_R_UNSUPPORTEDALG);
1354 }
1355 return (ISC_R_SUCCESS);
1356 }
1357
1358 isc_result_t
1359 dst_key_secretsize(const dst_key_t *key, unsigned int *n) {
1360 REQUIRE(dst_initialized == ISC_TRUE);
1361 REQUIRE(VALID_KEY(key));
1362 REQUIRE(n != NULL);
1363
1364 #ifndef PK11_DH_DISABLE
1365 if (key->key_alg == DST_ALG_DH)
1366 *n = (key->key_size + 7) / 8;
1367 else
1368 #endif
1369 return (DST_R_UNSUPPORTEDALG);
1370 #ifndef PK11_DH_DISABLE
1371 return (ISC_R_SUCCESS);
1372 #endif
1373 }
1374
1375 /*%
1376 * Set the flags on a key, then recompute the key ID
1377 */
1378 isc_result_t
1379 dst_key_setflags(dst_key_t *key, isc_uint32_t flags) {
1380 REQUIRE(VALID_KEY(key));
1381 key->key_flags = flags;
1382 return (computeid(key));
1383 }
1384
1385 void
1386 dst_key_format(const dst_key_t *key, char *cp, unsigned int size) {
1387 char namestr[DNS_NAME_FORMATSIZE];
1388 char algstr[DNS_NAME_FORMATSIZE];
1389
1390 dns_name_format(dst_key_name(key), namestr, sizeof(namestr));
1391 dns_secalg_format((dns_secalg_t) dst_key_alg(key), algstr,
1392 sizeof(algstr));
1393 snprintf(cp, size, "%s/%s/%d", namestr, algstr, dst_key_id(key));
1394 }
1395
1396 isc_result_t
1397 dst_key_dump(dst_key_t *key, isc_mem_t *mctx, char **buffer, int *length) {
1398
1399 REQUIRE(buffer != NULL && *buffer == NULL);
1400 REQUIRE(length != NULL && *length == 0);
1401 REQUIRE(VALID_KEY(key));
1402
1403 if (key->func->dump == NULL)
1404 return (ISC_R_NOTIMPLEMENTED);
1405 return (key->func->dump(key, mctx, buffer, length));
1406 }
1407
1408 isc_result_t
1409 dst_key_restore(dns_name_t *name, unsigned int alg, unsigned int flags,
1410 unsigned int protocol, dns_rdataclass_t rdclass,
1411 isc_mem_t *mctx, const char *keystr, dst_key_t **keyp)
1412 {
1413 isc_result_t result;
1414 dst_key_t *key;
1415
1416 REQUIRE(dst_initialized == ISC_TRUE);
1417 REQUIRE(keyp != NULL && *keyp == NULL);
1418
1419 if (alg >= DST_MAX_ALGS || dst_t_func[alg] == NULL)
1420 return (DST_R_UNSUPPORTEDALG);
1421
1422 if (dst_t_func[alg]->restore == NULL)
1423 return (ISC_R_NOTIMPLEMENTED);
1424
1425 key = get_key_struct(name, alg, flags, protocol, 0, rdclass, 0, mctx);
1426 if (key == NULL)
1427 return (ISC_R_NOMEMORY);
1428
1429 result = (dst_t_func[alg]->restore)(key, keystr);
1430 if (result == ISC_R_SUCCESS)
1431 *keyp = key;
1432 else
1433 dst_key_free(&key);
1434
1435 return (result);
1436 }
1437
1438 /***
1439 *** Static methods
1440 ***/
1441
1442 /*%
1443 * Allocates a key structure and fills in some of the fields.
1444 */
1445 static dst_key_t *
1446 get_key_struct(const dns_name_t *name, unsigned int alg,
1447 unsigned int flags, unsigned int protocol,
1448 unsigned int bits, dns_rdataclass_t rdclass,
1449 dns_ttl_t ttl, isc_mem_t *mctx)
1450 {
1451 dst_key_t *key;
1452 isc_result_t result;
1453 int i;
1454
1455 key = (dst_key_t *) isc_mem_get(mctx, sizeof(dst_key_t));
1456 if (key == NULL)
1457 return (NULL);
1458
1459 memset(key, 0, sizeof(dst_key_t));
1460
1461 key->key_name = isc_mem_get(mctx, sizeof(dns_name_t));
1462 if (key->key_name == NULL) {
1463 isc_mem_put(mctx, key, sizeof(dst_key_t));
1464 return (NULL);
1465 }
1466
1467 dns_name_init(key->key_name, NULL);
1468 result = dns_name_dup(name, mctx, key->key_name);
1469 if (result != ISC_R_SUCCESS) {
1470 isc_mem_put(mctx, key->key_name, sizeof(dns_name_t));
1471 isc_mem_put(mctx, key, sizeof(dst_key_t));
1472 return (NULL);
1473 }
1474
1475 result = isc_refcount_init(&key->refs, 1);
1476 if (result != ISC_R_SUCCESS) {
1477 dns_name_free(key->key_name, mctx);
1478 isc_mem_put(mctx, key->key_name, sizeof(dns_name_t));
1479 isc_mem_put(mctx, key, sizeof(dst_key_t));
1480 return (NULL);
1481 }
1482 isc_mem_attach(mctx, &key->mctx);
1483 key->key_alg = alg;
1484 key->key_flags = flags;
1485 key->key_proto = protocol;
1486 key->keydata.generic = NULL;
1487 key->key_size = bits;
1488 key->key_class = rdclass;
1489 key->key_ttl = ttl;
1490 key->func = dst_t_func[alg];
1491 key->fmt_major = 0;
1492 key->fmt_minor = 0;
1493 for (i = 0; i < (DST_MAX_TIMES + 1); i++) {
1494 key->times[i] = 0;
1495 key->timeset[i] = ISC_FALSE;
1496 }
1497 key->inactive = ISC_FALSE;
1498 key->magic = KEY_MAGIC;
1499 return (key);
1500 }
1501
1502 isc_boolean_t
1503 dst_key_inactive(const dst_key_t *key) {
1504
1505 REQUIRE(VALID_KEY(key));
1506
1507 return (key->inactive);
1508 }
1509
1510 void
1511 dst_key_setinactive(dst_key_t *key, isc_boolean_t inactive) {
1512
1513 REQUIRE(VALID_KEY(key));
1514
1515 key->inactive = inactive;
1516 }
1517
1518 /*%
1519 * Reads a public key from disk
1520 */
1521 isc_result_t
1522 dst_key_read_public(const char *filename, int type,
1523 isc_mem_t *mctx, dst_key_t **keyp)
1524 {
1525 u_char rdatabuf[DST_KEY_MAXSIZE];
1526 isc_buffer_t b;
1527 dns_fixedname_t name;
1528 isc_lex_t *lex = NULL;
1529 isc_token_t token;
1530 isc_result_t ret;
1531 dns_rdata_t rdata = DNS_RDATA_INIT;
1532 unsigned int opt = ISC_LEXOPT_DNSMULTILINE;
1533 dns_rdataclass_t rdclass = dns_rdataclass_in;
1534 isc_lexspecials_t specials;
1535 isc_uint32_t ttl = 0;
1536 isc_result_t result;
1537 dns_rdatatype_t keytype;
1538
1539 /*
1540 * Open the file and read its formatted contents
1541 * File format:
1542 * domain.name [ttl] [class] [KEY|DNSKEY] <flags> <protocol> <algorithm> <key>
1543 */
1544
1545 /* 1500 should be large enough for any key */
1546 ret = isc_lex_create(mctx, 1500, &lex);
1547 if (ret != ISC_R_SUCCESS)
1548 goto cleanup;
1549
1550 memset(specials, 0, sizeof(specials));
1551 specials['('] = 1;
1552 specials[')'] = 1;
1553 specials['"'] = 1;
1554 isc_lex_setspecials(lex, specials);
1555 isc_lex_setcomments(lex, ISC_LEXCOMMENT_DNSMASTERFILE);
1556
1557 ret = isc_lex_openfile(lex, filename);
1558 if (ret != ISC_R_SUCCESS)
1559 goto cleanup;
1560
1561 #define NEXTTOKEN(lex, opt, token) { \
1562 ret = isc_lex_gettoken(lex, opt, token); \
1563 if (ret != ISC_R_SUCCESS) \
1564 goto cleanup; \
1565 }
1566
1567 #define BADTOKEN() { \
1568 ret = ISC_R_UNEXPECTEDTOKEN; \
1569 goto cleanup; \
1570 }
1571
1572 /* Read the domain name */
1573 NEXTTOKEN(lex, opt, &token);
1574 if (token.type != isc_tokentype_string)
1575 BADTOKEN();
1576
1577 /*
1578 * We don't support "@" in .key files.
1579 */
1580 if (!strcmp(DST_AS_STR(token), "@"))
1581 BADTOKEN();
1582
1583 dns_fixedname_init(&name);
1584 isc_buffer_init(&b, DST_AS_STR(token), strlen(DST_AS_STR(token)));
1585 isc_buffer_add(&b, strlen(DST_AS_STR(token)));
1586 ret = dns_name_fromtext(dns_fixedname_name(&name), &b, dns_rootname,
1587 0, NULL);
1588 if (ret != ISC_R_SUCCESS)
1589 goto cleanup;
1590
1591 /* Read the next word: either TTL, class, or 'KEY' */
1592 NEXTTOKEN(lex, opt, &token);
1593
1594 if (token.type != isc_tokentype_string)
1595 BADTOKEN();
1596
1597 /* If it's a TTL, read the next one */
1598 result = dns_ttl_fromtext(&token.value.as_textregion, &ttl);
1599 if (result == ISC_R_SUCCESS)
1600 NEXTTOKEN(lex, opt, &token);
1601
1602 if (token.type != isc_tokentype_string)
1603 BADTOKEN();
1604
1605 ret = dns_rdataclass_fromtext(&rdclass, &token.value.as_textregion);
1606 if (ret == ISC_R_SUCCESS)
1607 NEXTTOKEN(lex, opt, &token);
1608
1609 if (token.type != isc_tokentype_string)
1610 BADTOKEN();
1611
1612 if (strcasecmp(DST_AS_STR(token), "DNSKEY") == 0)
1613 keytype = dns_rdatatype_dnskey;
1614 else if (strcasecmp(DST_AS_STR(token), "KEY") == 0)
1615 keytype = dns_rdatatype_key; /*%< SIG(0), TKEY */
1616 else
1617 BADTOKEN();
1618
1619 if (((type & DST_TYPE_KEY) != 0 && keytype != dns_rdatatype_key) ||
1620 ((type & DST_TYPE_KEY) == 0 && keytype != dns_rdatatype_dnskey)) {
1621 ret = DST_R_BADKEYTYPE;
1622 goto cleanup;
1623 }
1624
1625 isc_buffer_init(&b, rdatabuf, sizeof(rdatabuf));
1626 ret = dns_rdata_fromtext(&rdata, rdclass, keytype, lex, NULL,
1627 ISC_FALSE, mctx, &b, NULL);
1628 if (ret != ISC_R_SUCCESS)
1629 goto cleanup;
1630
1631 ret = dst_key_fromdns(dns_fixedname_name(&name), rdclass, &b, mctx,
1632 keyp);
1633 if (ret != ISC_R_SUCCESS)
1634 goto cleanup;
1635
1636 dst_key_setttl(*keyp, ttl);
1637
1638 cleanup:
1639 if (lex != NULL)
1640 isc_lex_destroy(&lex);
1641 return (ret);
1642 }
1643
1644 static isc_boolean_t
1645 issymmetric(const dst_key_t *key) {
1646 REQUIRE(dst_initialized == ISC_TRUE);
1647 REQUIRE(VALID_KEY(key));
1648
1649 /* XXXVIX this switch statement is too sparse to gen a jump table. */
1650 switch (key->key_alg) {
1651 #ifndef PK11_MD5_DISABLE
1652 case DST_ALG_RSAMD5:
1653 #endif
1654 case DST_ALG_RSASHA1:
1655 case DST_ALG_NSEC3RSASHA1:
1656 case DST_ALG_RSASHA256:
1657 case DST_ALG_RSASHA512:
1658 #ifndef PK11_DSA_DISABLE
1659 case DST_ALG_DSA:
1660 case DST_ALG_NSEC3DSA:
1661 #endif
1662 #ifndef PK11_DH_DISABLE
1663 case DST_ALG_DH:
1664 #endif
1665 case DST_ALG_ECCGOST:
1666 case DST_ALG_ECDSA256:
1667 case DST_ALG_ECDSA384:
1668 case DST_ALG_ED25519:
1669 case DST_ALG_ED448:
1670 return (ISC_FALSE);
1671 #ifndef PK11_MD5_DISABLE
1672 case DST_ALG_HMACMD5:
1673 #endif
1674 case DST_ALG_HMACSHA1:
1675 case DST_ALG_HMACSHA224:
1676 case DST_ALG_HMACSHA256:
1677 case DST_ALG_HMACSHA384:
1678 case DST_ALG_HMACSHA512:
1679 case DST_ALG_GSSAPI:
1680 return (ISC_TRUE);
1681 default:
1682 return (ISC_FALSE);
1683 }
1684 }
1685
1686 /*%
1687 * Write key timing metadata to a file pointer, preceded by 'tag'
1688 */
1689 static void
1690 printtime(const dst_key_t *key, int type, const char *tag, FILE *stream) {
1691 isc_result_t result;
1692 #ifdef ISC_PLATFORM_USETHREADS
1693 char output[26]; /* Minimum buffer as per ctime_r() specification. */
1694 #else
1695 const char *output;
1696 #endif
1697 isc_stdtime_t when;
1698 time_t t;
1699 char utc[sizeof("YYYYMMDDHHSSMM")];
1700 isc_buffer_t b;
1701 isc_region_t r;
1702
1703 result = dst_key_gettime(key, type, &when);
1704 if (result == ISC_R_NOTFOUND)
1705 return;
1706
1707 /* time_t and isc_stdtime_t might be different sizes */
1708 t = when;
1709 #ifdef ISC_PLATFORM_USETHREADS
1710 #ifdef WIN32
1711 if (ctime_s(output, sizeof(output), &t) != 0)
1712 goto error;
1713 #else
1714 if (ctime_r(&t, output) == NULL)
1715 goto error;
1716 #endif
1717 #else
1718 output = ctime(&t);
1719 #endif
1720
1721 isc_buffer_init(&b, utc, sizeof(utc));
1722 result = dns_time32_totext(when, &b);
1723 if (result != ISC_R_SUCCESS)
1724 goto error;
1725
1726 isc_buffer_usedregion(&b, &r);
1727 fprintf(stream, "%s: %.*s (%.*s)\n", tag, (int)r.length, r.base,
1728 (int)strlen(output) - 1, output);
1729 return;
1730
1731 error:
1732 fprintf(stream, "%s: (set, unable to display)\n", tag);
1733 }
1734
1735 /*%
1736 * Writes a public key to disk in DNS format.
1737 */
1738 static isc_result_t
1739 write_public_key(const dst_key_t *key, int type, const char *directory) {
1740 FILE *fp;
1741 isc_buffer_t keyb, textb, fileb, classb;
1742 isc_region_t r;
1743 char filename[ISC_DIR_NAMEMAX];
1744 unsigned char key_array[DST_KEY_MAXSIZE];
1745 char text_array[DST_KEY_MAXTEXTSIZE];
1746 char class_array[10];
1747 isc_result_t ret;
1748 dns_rdata_t rdata = DNS_RDATA_INIT;
1749 isc_fsaccess_t access;
1750
1751 REQUIRE(VALID_KEY(key));
1752
1753 isc_buffer_init(&keyb, key_array, sizeof(key_array));
1754 isc_buffer_init(&textb, text_array, sizeof(text_array));
1755 isc_buffer_init(&classb, class_array, sizeof(class_array));
1756
1757 ret = dst_key_todns(key, &keyb);
1758 if (ret != ISC_R_SUCCESS)
1759 return (ret);
1760
1761 isc_buffer_usedregion(&keyb, &r);
1762 dns_rdata_fromregion(&rdata, key->key_class, dns_rdatatype_dnskey, &r);
1763
1764 ret = dns_rdata_totext(&rdata, (dns_name_t *) NULL, &textb);
1765 if (ret != ISC_R_SUCCESS)
1766 return (DST_R_INVALIDPUBLICKEY);
1767
1768 ret = dns_rdataclass_totext(key->key_class, &classb);
1769 if (ret != ISC_R_SUCCESS)
1770 return (DST_R_INVALIDPUBLICKEY);
1771
1772 /*
1773 * Make the filename.
1774 */
1775 isc_buffer_init(&fileb, filename, sizeof(filename));
1776 ret = dst_key_buildfilename(key, DST_TYPE_PUBLIC, directory, &fileb);
1777 if (ret != ISC_R_SUCCESS)
1778 return (ret);
1779
1780 /*
1781 * Create public key file.
1782 */
1783 if ((fp = fopen(filename, "w")) == NULL)
1784 return (DST_R_WRITEERROR);
1785
1786 if (issymmetric(key)) {
1787 access = 0;
1788 isc_fsaccess_add(ISC_FSACCESS_OWNER,
1789 ISC_FSACCESS_READ | ISC_FSACCESS_WRITE,
1790 &access);
1791 (void)isc_fsaccess_set(filename, access);
1792 }
1793
1794 /* Write key information in comments */
1795 if ((type & DST_TYPE_KEY) == 0) {
1796 fprintf(fp, "; This is a %s%s-signing key, keyid %d, for ",
1797 (key->key_flags & DNS_KEYFLAG_REVOKE) != 0 ?
1798 "revoked " :
1799 "",
1800 (key->key_flags & DNS_KEYFLAG_KSK) != 0 ?
1801 "key" :
1802 "zone",
1803 key->key_id);
1804 ret = dns_name_print(key->key_name, fp);
1805 if (ret != ISC_R_SUCCESS) {
1806 fclose(fp);
1807 return (ret);
1808 }
1809 fputc('\n', fp);
1810
1811 printtime(key, DST_TIME_CREATED, "; Created", fp);
1812 printtime(key, DST_TIME_PUBLISH, "; Publish", fp);
1813 printtime(key, DST_TIME_ACTIVATE, "; Activate", fp);
1814 printtime(key, DST_TIME_REVOKE, "; Revoke", fp);
1815 printtime(key, DST_TIME_INACTIVE, "; Inactive", fp);
1816 printtime(key, DST_TIME_DELETE, "; Delete", fp);
1817 printtime(key, DST_TIME_SYNCPUBLISH , "; SyncPublish", fp);
1818 printtime(key, DST_TIME_SYNCDELETE , "; SyncDelete", fp);
1819 }
1820
1821 /* Now print the actual key */
1822 ret = dns_name_print(key->key_name, fp);
1823 fprintf(fp, " ");
1824
1825 if (key->key_ttl != 0)
1826 fprintf(fp, "%u ", key->key_ttl);
1827
1828 isc_buffer_usedregion(&classb, &r);
1829 if ((unsigned) fwrite(r.base, 1, r.length, fp) != r.length)
1830 ret = DST_R_WRITEERROR;
1831
1832 if ((type & DST_TYPE_KEY) != 0)
1833 fprintf(fp, " KEY ");
1834 else
1835 fprintf(fp, " DNSKEY ");
1836
1837 isc_buffer_usedregion(&textb, &r);
1838 if ((unsigned) fwrite(r.base, 1, r.length, fp) != r.length)
1839 ret = DST_R_WRITEERROR;
1840
1841 fputc('\n', fp);
1842 fflush(fp);
1843 if (ferror(fp))
1844 ret = DST_R_WRITEERROR;
1845 fclose(fp);
1846
1847 return (ret);
1848 }
1849
1850 static isc_result_t
1851 buildfilename(dns_name_t *name, dns_keytag_t id,
1852 unsigned int alg, unsigned int type,
1853 const char *directory, isc_buffer_t *out)
1854 {
1855 const char *suffix = "";
1856 isc_result_t result;
1857
1858 REQUIRE(out != NULL);
1859 if ((type & DST_TYPE_PRIVATE) != 0)
1860 suffix = ".private";
1861 else if (type == DST_TYPE_PUBLIC)
1862 suffix = ".key";
1863 if (directory != NULL) {
1864 if (isc_buffer_availablelength(out) < strlen(directory))
1865 return (ISC_R_NOSPACE);
1866 isc_buffer_putstr(out, directory);
1867 if (strlen(directory) > 0U &&
1868 directory[strlen(directory) - 1] != '/')
1869 isc_buffer_putstr(out, "/");
1870 }
1871 if (isc_buffer_availablelength(out) < 1)
1872 return (ISC_R_NOSPACE);
1873 isc_buffer_putstr(out, "K");
1874 result = dns_name_tofilenametext(name, ISC_FALSE, out);
1875 if (result != ISC_R_SUCCESS)
1876 return (result);
1877
1878 return (isc_buffer_printf(out, "+%03d+%05d%s", alg, id, suffix));
1879 }
1880
1881 static isc_result_t
1882 computeid(dst_key_t *key) {
1883 isc_buffer_t dnsbuf;
1884 unsigned char dns_array[DST_KEY_MAXSIZE];
1885 isc_region_t r;
1886 isc_result_t ret;
1887
1888 isc_buffer_init(&dnsbuf, dns_array, sizeof(dns_array));
1889 ret = dst_key_todns(key, &dnsbuf);
1890 if (ret != ISC_R_SUCCESS)
1891 return (ret);
1892
1893 isc_buffer_usedregion(&dnsbuf, &r);
1894 key->key_id = dst_region_computeid(&r, key->key_alg);
1895 key->key_rid = dst_region_computerid(&r, key->key_alg);
1896 return (ISC_R_SUCCESS);
1897 }
1898
1899 static isc_result_t
1900 frombuffer(const dns_name_t *name, unsigned int alg, unsigned int flags,
1901 unsigned int protocol, dns_rdataclass_t rdclass,
1902 isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp)
1903 {
1904 dst_key_t *key;
1905 isc_result_t ret;
1906
1907 REQUIRE(dns_name_isabsolute(name));
1908 REQUIRE(source != NULL);
1909 REQUIRE(mctx != NULL);
1910 REQUIRE(keyp != NULL && *keyp == NULL);
1911
1912 key = get_key_struct(name, alg, flags, protocol, 0, rdclass, 0, mctx);
1913 if (key == NULL)
1914 return (ISC_R_NOMEMORY);
1915
1916 if (isc_buffer_remaininglength(source) > 0) {
1917 ret = algorithm_status(alg);
1918 if (ret != ISC_R_SUCCESS) {
1919 dst_key_free(&key);
1920 return (ret);
1921 }
1922 if (key->func->fromdns == NULL) {
1923 dst_key_free(&key);
1924 return (DST_R_UNSUPPORTEDALG);
1925 }
1926
1927 ret = key->func->fromdns(key, source);
1928 if (ret != ISC_R_SUCCESS) {
1929 dst_key_free(&key);
1930 return (ret);
1931 }
1932 }
1933
1934 *keyp = key;
1935 return (ISC_R_SUCCESS);
1936 }
1937
1938 static isc_result_t
1939 algorithm_status(unsigned int alg) {
1940 REQUIRE(dst_initialized == ISC_TRUE);
1941
1942 if (dst_algorithm_supported(alg))
1943 return (ISC_R_SUCCESS);
1944 #if !defined(OPENSSL) && !defined(PKCS11CRYPTO)
1945 if (alg == DST_ALG_RSAMD5 || alg == DST_ALG_RSASHA1 ||
1946 alg == DST_ALG_DSA || alg == DST_ALG_DH ||
1947 alg == DST_ALG_HMACMD5 || alg == DST_ALG_NSEC3DSA ||
1948 alg == DST_ALG_NSEC3RSASHA1 ||
1949 alg == DST_ALG_RSASHA256 || alg == DST_ALG_RSASHA512 ||
1950 alg == DST_ALG_ECCGOST ||
1951 alg == DST_ALG_ECDSA256 || alg == DST_ALG_ECDSA384 ||
1952 alg == DST_ALG_ED25519 || alg == DST_ALG_ED448)
1953 return (DST_R_NOCRYPTO);
1954 #endif
1955 return (DST_R_UNSUPPORTEDALG);
1956 }
1957
1958 static isc_result_t
1959 addsuffix(char *filename, int len, const char *odirname,
1960 const char *ofilename, const char *suffix)
1961 {
1962 int olen = strlen(ofilename);
1963 int n;
1964
1965 if (olen > 1 && ofilename[olen - 1] == '.')
1966 olen -= 1;
1967 else if (olen > 8 && strcmp(ofilename + olen - 8, ".private") == 0)
1968 olen -= 8;
1969 else if (olen > 4 && strcmp(ofilename + olen - 4, ".key") == 0)
1970 olen -= 4;
1971
1972 if (odirname == NULL)
1973 n = snprintf(filename, len, "%.*s%s", olen, ofilename, suffix);
1974 else
1975 n = snprintf(filename, len, "%s/%.*s%s",
1976 odirname, olen, ofilename, suffix);
1977 if (n < 0)
1978 return (ISC_R_FAILURE);
1979 if (n >= len)
1980 return (ISC_R_NOSPACE);
1981 return (ISC_R_SUCCESS);
1982 }
1983
1984 isc_result_t
1985 dst__entropy_getdata(void *buf, unsigned int len, isc_boolean_t pseudo) {
1986 unsigned int flags = dst_entropy_flags;
1987
1988 if (dst_entropy_pool == NULL)
1989 return (ISC_R_FAILURE);
1990
1991 if (len == 0)
1992 return (ISC_R_SUCCESS);
1993
1994 #ifdef PKCS11CRYPTO
1995 UNUSED(pseudo);
1996 UNUSED(flags);
1997 return (pk11_rand_bytes(buf, len));
1998 #else /* PKCS11CRYPTO */
1999 if (pseudo)
2000 flags &= ~ISC_ENTROPY_GOODONLY;
2001 else
2002 flags |= ISC_ENTROPY_BLOCKING;
2003 #ifdef ISC_PLATFORM_CRYPTORANDOM
2004 /* get entropy directly from crypto provider */
2005 return (dst_random_getdata(buf, len, NULL, flags));
2006 #else
2007 /* get entropy from entropy source or hook function */
2008 return (isc_entropy_getdata(dst_entropy_pool, buf, len, NULL, flags));
2009 #endif /* ISC_PLATFORM_CRYPTORANDOM */
2010 #endif /* PKCS11CRYPTO */
2011 }
2012
2013 unsigned int
2014 dst__entropy_status(void) {
2015 #if !defined(PKCS11CRYPTO) && !defined(ISC_PLATFORM_CRYPTORANDOM)
2016 #ifdef GSSAPI
2017 unsigned int flags = dst_entropy_flags;
2018 isc_result_t ret;
2019 unsigned char buf[32];
2020 static isc_boolean_t first = ISC_TRUE;
2021
2022 if (dst_entropy_pool == NULL)
2023 return (0);
2024
2025 if (first) {
2026 /* Someone believes RAND_status() initializes the PRNG */
2027 flags &= ~ISC_ENTROPY_GOODONLY;
2028 ret = isc_entropy_getdata(dst_entropy_pool, buf,
2029 sizeof(buf), NULL, flags);
2030 INSIST(ret == ISC_R_SUCCESS);
2031 isc_entropy_putdata(dst_entropy_pool, buf,
2032 sizeof(buf), 2 * sizeof(buf));
2033 first = ISC_FALSE;
2034 }
2035 #endif
2036 return (isc_entropy_status(dst_entropy_pool));
2037 #else
2038 /* Doesn't matter as it is not used in this case. */
2039 return (0);
2040 #endif
2041 }
2042
2043 isc_buffer_t *
2044 dst_key_tkeytoken(const dst_key_t *key) {
2045 REQUIRE(VALID_KEY(key));
2046 return (key->key_tkeytoken);
2047 }
2048