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