1 /*
2  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3  *
4  * SPDX-License-Identifier: MPL-2.0 AND 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 https://mozilla.org/MPL/2.0/.
9  *
10  * See the COPYRIGHT file distributed with this work for additional
11  * information regarding copyright ownership.
12  */
13 
14 /*
15  * Copyright (C) Network Associates, Inc.
16  *
17  * Permission to use, copy, modify, and/or distribute this software for any
18  * purpose with or without fee is hereby granted, provided that the above
19  * copyright notice and this permission notice appear in all copies.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
22  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
23  * WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE
24  * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
25  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
26  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
27  * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
28  */
29 
30 /*! \file */
31 
32 #include <inttypes.h>
33 #include <stdbool.h>
34 #include <stdlib.h>
35 #include <time.h>
36 
37 #include <isc/buffer.h>
38 #include <isc/dir.h>
39 #include <isc/file.h>
40 #include <isc/fsaccess.h>
41 #include <isc/lex.h>
42 #include <isc/mem.h>
43 #include <isc/once.h>
44 #include <isc/platform.h>
45 #include <isc/print.h>
46 #include <isc/random.h>
47 #include <isc/refcount.h>
48 #include <isc/safe.h>
49 #include <isc/string.h>
50 #include <isc/time.h>
51 #include <isc/util.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 #define NEXTTOKEN(lex, opt, token)                       \
72 	{                                                \
73 		ret = isc_lex_gettoken(lex, opt, token); \
74 		if (ret != ISC_R_SUCCESS)                \
75 			goto cleanup;                    \
76 	}
77 
78 #define NEXTTOKEN_OR_EOF(lex, opt, token)                \
79 	do {                                             \
80 		ret = isc_lex_gettoken(lex, opt, token); \
81 		if (ret == ISC_R_EOF)                    \
82 			break;                           \
83 		if (ret != ISC_R_SUCCESS)                \
84 			goto cleanup;                    \
85 	} while ((*token).type == isc_tokentype_eol);
86 
87 #define READLINE(lex, opt, token)                        \
88 	do {                                             \
89 		ret = isc_lex_gettoken(lex, opt, token); \
90 		if (ret == ISC_R_EOF)                    \
91 			break;                           \
92 		if (ret != ISC_R_SUCCESS)                \
93 			goto cleanup;                    \
94 	} while ((*token).type != isc_tokentype_eol)
95 
96 #define BADTOKEN()                           \
97 	{                                    \
98 		ret = ISC_R_UNEXPECTEDTOKEN; \
99 		goto cleanup;                \
100 	}
101 
102 #define NUMERIC_NTAGS (DST_MAX_NUMERIC + 1)
103 static const char *numerictags[NUMERIC_NTAGS] = {
104 	"Predecessor:", "Successor:",  "MaxTTL:",    "RollPeriod:",
105 	"Lifetime:",	"DSPubCount:", "DSRemCount:"
106 };
107 
108 #define BOOLEAN_NTAGS (DST_MAX_BOOLEAN + 1)
109 static const char *booleantags[BOOLEAN_NTAGS] = { "KSK:", "ZSK:" };
110 
111 #define TIMING_NTAGS (DST_MAX_TIMES + 1)
112 static const char *timingtags[TIMING_NTAGS] = {
113 	"Generated:",	 "Published:",	  "Active:",	   "Revoked:",
114 	"Retired:",	 "Removed:",
115 
116 	"DSPublish:",	 "SyncPublish:",  "SyncDelete:",
117 
118 	"DNSKEYChange:", "ZRRSIGChange:", "KRRSIGChange:", "DSChange:",
119 
120 	"DSRemoved:"
121 };
122 
123 #define KEYSTATES_NTAGS (DST_MAX_KEYSTATES + 1)
124 static const char *keystatestags[KEYSTATES_NTAGS] = {
125 	"DNSKEYState:", "ZRRSIGState:", "KRRSIGState:", "DSState:", "GoalState:"
126 };
127 
128 #define KEYSTATES_NVALUES 4
129 static const char *keystates[KEYSTATES_NVALUES] = {
130 	"hidden",
131 	"rumoured",
132 	"omnipresent",
133 	"unretentive",
134 };
135 
136 #define STATE_ALGORITHM_STR "Algorithm:"
137 #define STATE_LENGTH_STR    "Length:"
138 #define MAX_NTAGS \
139 	(DST_MAX_NUMERIC + DST_MAX_BOOLEAN + DST_MAX_TIMES + DST_MAX_KEYSTATES)
140 
141 static dst_func_t *dst_t_func[DST_MAX_ALGS];
142 
143 static bool dst_initialized = false;
144 
145 void
146 gss_log(int level, const char *fmt, ...) ISC_FORMAT_PRINTF(2, 3);
147 
148 /*
149  * Static functions.
150  */
151 static dst_key_t *
152 get_key_struct(const dns_name_t *name, unsigned int alg, unsigned int flags,
153 	       unsigned int protocol, unsigned int bits,
154 	       dns_rdataclass_t rdclass, dns_ttl_t ttl, isc_mem_t *mctx);
155 static isc_result_t
156 write_public_key(const dst_key_t *key, int type, const char *directory);
157 static isc_result_t
158 write_key_state(const dst_key_t *key, int type, const char *directory);
159 static isc_result_t
160 buildfilename(dns_name_t *name, dns_keytag_t id, unsigned int alg,
161 	      unsigned int type, const char *directory, isc_buffer_t *out);
162 static isc_result_t
163 computeid(dst_key_t *key);
164 static isc_result_t
165 frombuffer(const dns_name_t *name, unsigned int alg, unsigned int flags,
166 	   unsigned int protocol, dns_rdataclass_t rdclass,
167 	   isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp);
168 
169 static isc_result_t
170 algorithm_status(unsigned int alg);
171 
172 static isc_result_t
173 addsuffix(char *filename, int len, const char *dirname, const char *ofilename,
174 	  const char *suffix);
175 
176 #define RETERR(x)                            \
177 	do {                                 \
178 		result = (x);                \
179 		if (result != ISC_R_SUCCESS) \
180 			goto out;            \
181 	} while (0)
182 
183 #define CHECKALG(alg)                       \
184 	do {                                \
185 		isc_result_t _r;            \
186 		_r = algorithm_status(alg); \
187 		if (_r != ISC_R_SUCCESS)    \
188 			return ((_r));      \
189 	} while (0);
190 
191 isc_result_t
dst_lib_init(isc_mem_t * mctx,const char * engine)192 dst_lib_init(isc_mem_t *mctx, const char *engine) {
193 	isc_result_t result;
194 
195 	REQUIRE(mctx != NULL);
196 	REQUIRE(!dst_initialized);
197 
198 	UNUSED(engine);
199 
200 	dst_result_register();
201 
202 	memset(dst_t_func, 0, sizeof(dst_t_func));
203 	RETERR(dst__hmacmd5_init(&dst_t_func[DST_ALG_HMACMD5]));
204 	RETERR(dst__hmacsha1_init(&dst_t_func[DST_ALG_HMACSHA1]));
205 	RETERR(dst__hmacsha224_init(&dst_t_func[DST_ALG_HMACSHA224]));
206 	RETERR(dst__hmacsha256_init(&dst_t_func[DST_ALG_HMACSHA256]));
207 	RETERR(dst__hmacsha384_init(&dst_t_func[DST_ALG_HMACSHA384]));
208 	RETERR(dst__hmacsha512_init(&dst_t_func[DST_ALG_HMACSHA512]));
209 	RETERR(dst__openssl_init(engine));
210 	RETERR(dst__openssldh_init(&dst_t_func[DST_ALG_DH]));
211 #if USE_OPENSSL
212 	RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSASHA1],
213 				    DST_ALG_RSASHA1));
214 	RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_NSEC3RSASHA1],
215 				    DST_ALG_NSEC3RSASHA1));
216 	RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSASHA256],
217 				    DST_ALG_RSASHA256));
218 	RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSASHA512],
219 				    DST_ALG_RSASHA512));
220 	RETERR(dst__opensslecdsa_init(&dst_t_func[DST_ALG_ECDSA256]));
221 	RETERR(dst__opensslecdsa_init(&dst_t_func[DST_ALG_ECDSA384]));
222 #ifdef HAVE_OPENSSL_ED25519
223 	RETERR(dst__openssleddsa_init(&dst_t_func[DST_ALG_ED25519]));
224 #endif /* ifdef HAVE_OPENSSL_ED25519 */
225 #ifdef HAVE_OPENSSL_ED448
226 	RETERR(dst__openssleddsa_init(&dst_t_func[DST_ALG_ED448]));
227 #endif /* ifdef HAVE_OPENSSL_ED448 */
228 #endif /* USE_OPENSSL */
229 
230 #if USE_PKCS11
231 	RETERR(dst__pkcs11_init(mctx, engine));
232 	RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSASHA1]));
233 	RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_NSEC3RSASHA1]));
234 	RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSASHA256]));
235 	RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSASHA512]));
236 	RETERR(dst__pkcs11ecdsa_init(&dst_t_func[DST_ALG_ECDSA256]));
237 	RETERR(dst__pkcs11ecdsa_init(&dst_t_func[DST_ALG_ECDSA384]));
238 	RETERR(dst__pkcs11eddsa_init(&dst_t_func[DST_ALG_ED25519]));
239 	RETERR(dst__pkcs11eddsa_init(&dst_t_func[DST_ALG_ED448]));
240 #endif /* USE_PKCS11 */
241 #ifdef GSSAPI
242 	RETERR(dst__gssapi_init(&dst_t_func[DST_ALG_GSSAPI]));
243 #endif /* ifdef GSSAPI */
244 
245 	dst_initialized = true;
246 	return (ISC_R_SUCCESS);
247 
248 out:
249 	/* avoid immediate crash! */
250 	dst_initialized = true;
251 	dst_lib_destroy();
252 	return (result);
253 }
254 
255 void
dst_lib_destroy(void)256 dst_lib_destroy(void) {
257 	int i;
258 	RUNTIME_CHECK(dst_initialized);
259 	dst_initialized = false;
260 
261 	for (i = 0; i < DST_MAX_ALGS; i++) {
262 		if (dst_t_func[i] != NULL && dst_t_func[i]->cleanup != NULL) {
263 			dst_t_func[i]->cleanup();
264 		}
265 	}
266 	dst__openssl_destroy();
267 #if USE_PKCS11
268 	(void)dst__pkcs11_destroy();
269 #endif /* USE_PKCS11 */
270 }
271 
272 bool
dst_algorithm_supported(unsigned int alg)273 dst_algorithm_supported(unsigned int alg) {
274 	REQUIRE(dst_initialized);
275 
276 	if (alg >= DST_MAX_ALGS || dst_t_func[alg] == NULL) {
277 		return (false);
278 	}
279 	return (true);
280 }
281 
282 bool
dst_ds_digest_supported(unsigned int digest_type)283 dst_ds_digest_supported(unsigned int digest_type) {
284 	return (digest_type == DNS_DSDIGEST_SHA1 ||
285 		digest_type == DNS_DSDIGEST_SHA256 ||
286 		digest_type == DNS_DSDIGEST_SHA384);
287 }
288 
289 isc_result_t
dst_context_create(dst_key_t * key,isc_mem_t * mctx,isc_logcategory_t * category,bool useforsigning,int maxbits,dst_context_t ** dctxp)290 dst_context_create(dst_key_t *key, isc_mem_t *mctx, isc_logcategory_t *category,
291 		   bool useforsigning, int maxbits, dst_context_t **dctxp) {
292 	dst_context_t *dctx;
293 	isc_result_t result;
294 
295 	REQUIRE(dst_initialized);
296 	REQUIRE(VALID_KEY(key));
297 	REQUIRE(mctx != NULL);
298 	REQUIRE(dctxp != NULL && *dctxp == NULL);
299 
300 	if (key->func->createctx == NULL && key->func->createctx2 == NULL) {
301 		return (DST_R_UNSUPPORTEDALG);
302 	}
303 	if (key->keydata.generic == NULL) {
304 		return (DST_R_NULLKEY);
305 	}
306 
307 	dctx = isc_mem_get(mctx, sizeof(dst_context_t));
308 	memset(dctx, 0, sizeof(*dctx));
309 	dst_key_attach(key, &dctx->key);
310 	isc_mem_attach(mctx, &dctx->mctx);
311 	dctx->category = category;
312 	if (useforsigning) {
313 		dctx->use = DO_SIGN;
314 	} else {
315 		dctx->use = DO_VERIFY;
316 	}
317 	if (key->func->createctx2 != NULL) {
318 		result = key->func->createctx2(key, maxbits, dctx);
319 	} else {
320 		result = key->func->createctx(key, dctx);
321 	}
322 	if (result != ISC_R_SUCCESS) {
323 		if (dctx->key != NULL) {
324 			dst_key_free(&dctx->key);
325 		}
326 		isc_mem_putanddetach(&dctx->mctx, dctx, sizeof(dst_context_t));
327 		return (result);
328 	}
329 	dctx->magic = CTX_MAGIC;
330 	*dctxp = dctx;
331 	return (ISC_R_SUCCESS);
332 }
333 
334 void
dst_context_destroy(dst_context_t ** dctxp)335 dst_context_destroy(dst_context_t **dctxp) {
336 	dst_context_t *dctx;
337 
338 	REQUIRE(dctxp != NULL && VALID_CTX(*dctxp));
339 
340 	dctx = *dctxp;
341 	*dctxp = NULL;
342 	INSIST(dctx->key->func->destroyctx != NULL);
343 	dctx->key->func->destroyctx(dctx);
344 	if (dctx->key != NULL) {
345 		dst_key_free(&dctx->key);
346 	}
347 	dctx->magic = 0;
348 	isc_mem_putanddetach(&dctx->mctx, dctx, sizeof(dst_context_t));
349 }
350 
351 isc_result_t
dst_context_adddata(dst_context_t * dctx,const isc_region_t * data)352 dst_context_adddata(dst_context_t *dctx, const isc_region_t *data) {
353 	REQUIRE(VALID_CTX(dctx));
354 	REQUIRE(data != NULL);
355 	INSIST(dctx->key->func->adddata != NULL);
356 
357 	return (dctx->key->func->adddata(dctx, data));
358 }
359 
360 isc_result_t
dst_context_sign(dst_context_t * dctx,isc_buffer_t * sig)361 dst_context_sign(dst_context_t *dctx, isc_buffer_t *sig) {
362 	dst_key_t *key;
363 
364 	REQUIRE(VALID_CTX(dctx));
365 	REQUIRE(sig != NULL);
366 
367 	key = dctx->key;
368 	CHECKALG(key->key_alg);
369 	if (key->keydata.generic == NULL) {
370 		return (DST_R_NULLKEY);
371 	}
372 
373 	if (key->func->sign == NULL) {
374 		return (DST_R_NOTPRIVATEKEY);
375 	}
376 	if (key->func->isprivate == NULL || !key->func->isprivate(key)) {
377 		return (DST_R_NOTPRIVATEKEY);
378 	}
379 
380 	return (key->func->sign(dctx, sig));
381 }
382 
383 isc_result_t
dst_context_verify(dst_context_t * dctx,isc_region_t * sig)384 dst_context_verify(dst_context_t *dctx, isc_region_t *sig) {
385 	REQUIRE(VALID_CTX(dctx));
386 	REQUIRE(sig != NULL);
387 
388 	CHECKALG(dctx->key->key_alg);
389 	if (dctx->key->keydata.generic == NULL) {
390 		return (DST_R_NULLKEY);
391 	}
392 	if (dctx->key->func->verify == NULL) {
393 		return (DST_R_NOTPUBLICKEY);
394 	}
395 
396 	return (dctx->key->func->verify(dctx, sig));
397 }
398 
399 isc_result_t
dst_context_verify2(dst_context_t * dctx,unsigned int maxbits,isc_region_t * sig)400 dst_context_verify2(dst_context_t *dctx, unsigned int maxbits,
401 		    isc_region_t *sig) {
402 	REQUIRE(VALID_CTX(dctx));
403 	REQUIRE(sig != NULL);
404 
405 	CHECKALG(dctx->key->key_alg);
406 	if (dctx->key->keydata.generic == NULL) {
407 		return (DST_R_NULLKEY);
408 	}
409 	if (dctx->key->func->verify == NULL && dctx->key->func->verify2 == NULL)
410 	{
411 		return (DST_R_NOTPUBLICKEY);
412 	}
413 
414 	return (dctx->key->func->verify2 != NULL
415 			? dctx->key->func->verify2(dctx, maxbits, sig)
416 			: dctx->key->func->verify(dctx, sig));
417 }
418 
419 isc_result_t
dst_key_computesecret(const dst_key_t * pub,const dst_key_t * priv,isc_buffer_t * secret)420 dst_key_computesecret(const dst_key_t *pub, const dst_key_t *priv,
421 		      isc_buffer_t *secret) {
422 	REQUIRE(dst_initialized);
423 	REQUIRE(VALID_KEY(pub) && VALID_KEY(priv));
424 	REQUIRE(secret != NULL);
425 
426 	CHECKALG(pub->key_alg);
427 	CHECKALG(priv->key_alg);
428 
429 	if (pub->keydata.generic == NULL || priv->keydata.generic == NULL) {
430 		return (DST_R_NULLKEY);
431 	}
432 
433 	if (pub->key_alg != priv->key_alg || pub->func->computesecret == NULL ||
434 	    priv->func->computesecret == NULL)
435 	{
436 		return (DST_R_KEYCANNOTCOMPUTESECRET);
437 	}
438 
439 	if (!dst_key_isprivate(priv)) {
440 		return (DST_R_NOTPRIVATEKEY);
441 	}
442 
443 	return (pub->func->computesecret(pub, priv, secret));
444 }
445 
446 isc_result_t
dst_key_tofile(const dst_key_t * key,int type,const char * directory)447 dst_key_tofile(const dst_key_t *key, int type, const char *directory) {
448 	isc_result_t ret = ISC_R_SUCCESS;
449 
450 	REQUIRE(dst_initialized);
451 	REQUIRE(VALID_KEY(key));
452 	REQUIRE((type &
453 		 (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC | DST_TYPE_STATE)) != 0);
454 
455 	CHECKALG(key->key_alg);
456 
457 	if (key->func->tofile == NULL) {
458 		return (DST_R_UNSUPPORTEDALG);
459 	}
460 
461 	if ((type & DST_TYPE_PUBLIC) != 0) {
462 		ret = write_public_key(key, type, directory);
463 		if (ret != ISC_R_SUCCESS) {
464 			return (ret);
465 		}
466 	}
467 
468 	if ((type & DST_TYPE_STATE) != 0) {
469 		ret = write_key_state(key, type, directory);
470 		if (ret != ISC_R_SUCCESS) {
471 			return (ret);
472 		}
473 	}
474 
475 	if (((type & DST_TYPE_PRIVATE) != 0) &&
476 	    (key->key_flags & DNS_KEYFLAG_TYPEMASK) != DNS_KEYTYPE_NOKEY)
477 	{
478 		return (key->func->tofile(key, directory));
479 	}
480 	return (ISC_R_SUCCESS);
481 }
482 
483 void
dst_key_setexternal(dst_key_t * key,bool value)484 dst_key_setexternal(dst_key_t *key, bool value) {
485 	key->external = value;
486 }
487 
488 bool
dst_key_isexternal(dst_key_t * key)489 dst_key_isexternal(dst_key_t *key) {
490 	return (key->external);
491 }
492 
493 isc_result_t
dst_key_getfilename(dns_name_t * name,dns_keytag_t id,unsigned int alg,int type,const char * directory,isc_mem_t * mctx,isc_buffer_t * buf)494 dst_key_getfilename(dns_name_t *name, dns_keytag_t id, unsigned int alg,
495 		    int type, const char *directory, isc_mem_t *mctx,
496 		    isc_buffer_t *buf) {
497 	isc_result_t result;
498 
499 	REQUIRE(dst_initialized);
500 	REQUIRE(dns_name_isabsolute(name));
501 	REQUIRE((type &
502 		 (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC | DST_TYPE_STATE)) != 0);
503 	REQUIRE(mctx != NULL);
504 	REQUIRE(buf != NULL);
505 
506 	CHECKALG(alg);
507 
508 	result = buildfilename(name, id, alg, type, directory, buf);
509 	if (result == ISC_R_SUCCESS) {
510 		if (isc_buffer_availablelength(buf) > 0) {
511 			isc_buffer_putuint8(buf, 0);
512 		} else {
513 			result = ISC_R_NOSPACE;
514 		}
515 	}
516 
517 	return (result);
518 }
519 
520 isc_result_t
dst_key_fromfile(dns_name_t * name,dns_keytag_t id,unsigned int alg,int type,const char * directory,isc_mem_t * mctx,dst_key_t ** keyp)521 dst_key_fromfile(dns_name_t *name, dns_keytag_t id, unsigned int alg, int type,
522 		 const char *directory, isc_mem_t *mctx, dst_key_t **keyp) {
523 	isc_result_t result;
524 	char filename[NAME_MAX];
525 	isc_buffer_t buf;
526 	dst_key_t *key;
527 
528 	REQUIRE(dst_initialized);
529 	REQUIRE(dns_name_isabsolute(name));
530 	REQUIRE((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) != 0);
531 	REQUIRE(mctx != NULL);
532 	REQUIRE(keyp != NULL && *keyp == NULL);
533 
534 	CHECKALG(alg);
535 
536 	key = NULL;
537 
538 	isc_buffer_init(&buf, filename, NAME_MAX);
539 	result = dst_key_getfilename(name, id, alg, type, NULL, mctx, &buf);
540 	if (result != ISC_R_SUCCESS) {
541 		goto out;
542 	}
543 
544 	result = dst_key_fromnamedfile(filename, directory, type, mctx, &key);
545 	if (result != ISC_R_SUCCESS) {
546 		goto out;
547 	}
548 
549 	result = computeid(key);
550 	if (result != ISC_R_SUCCESS) {
551 		goto out;
552 	}
553 
554 	if (!dns_name_equal(name, key->key_name) || id != key->key_id ||
555 	    alg != key->key_alg)
556 	{
557 		result = DST_R_INVALIDPRIVATEKEY;
558 		goto out;
559 	}
560 
561 	*keyp = key;
562 	result = ISC_R_SUCCESS;
563 
564 out:
565 	if ((key != NULL) && (result != ISC_R_SUCCESS)) {
566 		dst_key_free(&key);
567 	}
568 
569 	return (result);
570 }
571 
572 isc_result_t
dst_key_fromnamedfile(const char * filename,const char * dirname,int type,isc_mem_t * mctx,dst_key_t ** keyp)573 dst_key_fromnamedfile(const char *filename, const char *dirname, int type,
574 		      isc_mem_t *mctx, dst_key_t **keyp) {
575 	isc_result_t result;
576 	dst_key_t *pubkey = NULL, *key = NULL;
577 	char *newfilename = NULL, *statefilename = NULL;
578 	int newfilenamelen = 0, statefilenamelen = 0;
579 	isc_lex_t *lex = NULL;
580 
581 	REQUIRE(dst_initialized);
582 	REQUIRE(filename != NULL);
583 	REQUIRE((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) != 0);
584 	REQUIRE(mctx != NULL);
585 	REQUIRE(keyp != NULL && *keyp == NULL);
586 
587 	/* If an absolute path is specified, don't use the key directory */
588 #ifndef WIN32
589 	if (filename[0] == '/') {
590 		dirname = NULL;
591 	}
592 #else  /* WIN32 */
593 	if (filename[0] == '/' || filename[0] == '\\') {
594 		dirname = NULL;
595 	}
596 #endif /* ifndef WIN32 */
597 
598 	newfilenamelen = strlen(filename) + 5;
599 	if (dirname != NULL) {
600 		newfilenamelen += strlen(dirname) + 1;
601 	}
602 	newfilename = isc_mem_get(mctx, newfilenamelen);
603 	result = addsuffix(newfilename, newfilenamelen, dirname, filename,
604 			   ".key");
605 	INSIST(result == ISC_R_SUCCESS);
606 
607 	RETERR(dst_key_read_public(newfilename, type, mctx, &pubkey));
608 	isc_mem_put(mctx, newfilename, newfilenamelen);
609 
610 	/*
611 	 * Read the state file, if requested by type.
612 	 */
613 	if ((type & DST_TYPE_STATE) != 0) {
614 		statefilenamelen = strlen(filename) + 7;
615 		if (dirname != NULL) {
616 			statefilenamelen += strlen(dirname) + 1;
617 		}
618 		statefilename = isc_mem_get(mctx, statefilenamelen);
619 		result = addsuffix(statefilename, statefilenamelen, dirname,
620 				   filename, ".state");
621 		INSIST(result == ISC_R_SUCCESS);
622 	}
623 
624 	pubkey->kasp = false;
625 	if ((type & DST_TYPE_STATE) != 0) {
626 		result = dst_key_read_state(statefilename, mctx, &pubkey);
627 		if (result == ISC_R_SUCCESS) {
628 			pubkey->kasp = true;
629 		} else if (result == ISC_R_FILENOTFOUND) {
630 			/* Having no state is valid. */
631 			result = ISC_R_SUCCESS;
632 		}
633 		RETERR(result);
634 	}
635 
636 	if ((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) == DST_TYPE_PUBLIC ||
637 	    (pubkey->key_flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY)
638 	{
639 		RETERR(computeid(pubkey));
640 		*keyp = pubkey;
641 		pubkey = NULL;
642 		goto out;
643 	}
644 
645 	RETERR(algorithm_status(pubkey->key_alg));
646 
647 	key = get_key_struct(pubkey->key_name, pubkey->key_alg,
648 			     pubkey->key_flags, pubkey->key_proto,
649 			     pubkey->key_size, pubkey->key_class,
650 			     pubkey->key_ttl, mctx);
651 	if (key == NULL) {
652 		RETERR(ISC_R_NOMEMORY);
653 	}
654 
655 	if (key->func->parse == NULL) {
656 		RETERR(DST_R_UNSUPPORTEDALG);
657 	}
658 
659 	newfilenamelen = strlen(filename) + 9;
660 	if (dirname != NULL) {
661 		newfilenamelen += strlen(dirname) + 1;
662 	}
663 	newfilename = isc_mem_get(mctx, newfilenamelen);
664 	result = addsuffix(newfilename, newfilenamelen, dirname, filename,
665 			   ".private");
666 	INSIST(result == ISC_R_SUCCESS);
667 
668 	RETERR(isc_lex_create(mctx, 1500, &lex));
669 	RETERR(isc_lex_openfile(lex, newfilename));
670 	isc_mem_put(mctx, newfilename, newfilenamelen);
671 
672 	RETERR(key->func->parse(key, lex, pubkey));
673 	isc_lex_destroy(&lex);
674 
675 	key->kasp = false;
676 	if ((type & DST_TYPE_STATE) != 0) {
677 		result = dst_key_read_state(statefilename, mctx, &key);
678 		if (result == ISC_R_SUCCESS) {
679 			key->kasp = true;
680 		} else if (result == ISC_R_FILENOTFOUND) {
681 			/* Having no state is valid. */
682 			result = ISC_R_SUCCESS;
683 		}
684 		RETERR(result);
685 	}
686 
687 	RETERR(computeid(key));
688 
689 	if (pubkey->key_id != key->key_id) {
690 		RETERR(DST_R_INVALIDPRIVATEKEY);
691 	}
692 
693 	*keyp = key;
694 	key = NULL;
695 
696 out:
697 	if (pubkey != NULL) {
698 		dst_key_free(&pubkey);
699 	}
700 	if (newfilename != NULL) {
701 		isc_mem_put(mctx, newfilename, newfilenamelen);
702 	}
703 	if (statefilename != NULL) {
704 		isc_mem_put(mctx, statefilename, statefilenamelen);
705 	}
706 	if (lex != NULL) {
707 		isc_lex_destroy(&lex);
708 	}
709 	if (key != NULL) {
710 		dst_key_free(&key);
711 	}
712 	return (result);
713 }
714 
715 isc_result_t
dst_key_todns(const dst_key_t * key,isc_buffer_t * target)716 dst_key_todns(const dst_key_t *key, isc_buffer_t *target) {
717 	REQUIRE(dst_initialized);
718 	REQUIRE(VALID_KEY(key));
719 	REQUIRE(target != NULL);
720 
721 	CHECKALG(key->key_alg);
722 
723 	if (key->func->todns == NULL) {
724 		return (DST_R_UNSUPPORTEDALG);
725 	}
726 
727 	if (isc_buffer_availablelength(target) < 4) {
728 		return (ISC_R_NOSPACE);
729 	}
730 	isc_buffer_putuint16(target, (uint16_t)(key->key_flags & 0xffff));
731 	isc_buffer_putuint8(target, (uint8_t)key->key_proto);
732 	isc_buffer_putuint8(target, (uint8_t)key->key_alg);
733 
734 	if ((key->key_flags & DNS_KEYFLAG_EXTENDED) != 0) {
735 		if (isc_buffer_availablelength(target) < 2) {
736 			return (ISC_R_NOSPACE);
737 		}
738 		isc_buffer_putuint16(
739 			target, (uint16_t)((key->key_flags >> 16) & 0xffff));
740 	}
741 
742 	if (key->keydata.generic == NULL) { /*%< NULL KEY */
743 		return (ISC_R_SUCCESS);
744 	}
745 
746 	return (key->func->todns(key, target));
747 }
748 
749 isc_result_t
dst_key_fromdns(const dns_name_t * name,dns_rdataclass_t rdclass,isc_buffer_t * source,isc_mem_t * mctx,dst_key_t ** keyp)750 dst_key_fromdns(const dns_name_t *name, dns_rdataclass_t rdclass,
751 		isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp) {
752 	uint8_t alg, proto;
753 	uint32_t flags, extflags;
754 	dst_key_t *key = NULL;
755 	dns_keytag_t id, rid;
756 	isc_region_t r;
757 	isc_result_t result;
758 
759 	REQUIRE(dst_initialized);
760 
761 	isc_buffer_remainingregion(source, &r);
762 
763 	if (isc_buffer_remaininglength(source) < 4) {
764 		return (DST_R_INVALIDPUBLICKEY);
765 	}
766 	flags = isc_buffer_getuint16(source);
767 	proto = isc_buffer_getuint8(source);
768 	alg = isc_buffer_getuint8(source);
769 
770 	id = dst_region_computeid(&r);
771 	rid = dst_region_computerid(&r);
772 
773 	if ((flags & DNS_KEYFLAG_EXTENDED) != 0) {
774 		if (isc_buffer_remaininglength(source) < 2) {
775 			return (DST_R_INVALIDPUBLICKEY);
776 		}
777 		extflags = isc_buffer_getuint16(source);
778 		flags |= (extflags << 16);
779 	}
780 
781 	result = frombuffer(name, alg, flags, proto, rdclass, source, mctx,
782 			    &key);
783 	if (result != ISC_R_SUCCESS) {
784 		return (result);
785 	}
786 	key->key_id = id;
787 	key->key_rid = rid;
788 
789 	*keyp = key;
790 	return (ISC_R_SUCCESS);
791 }
792 
793 isc_result_t
dst_key_frombuffer(const dns_name_t * name,unsigned int alg,unsigned int flags,unsigned int protocol,dns_rdataclass_t rdclass,isc_buffer_t * source,isc_mem_t * mctx,dst_key_t ** keyp)794 dst_key_frombuffer(const dns_name_t *name, unsigned int alg, unsigned int flags,
795 		   unsigned int protocol, dns_rdataclass_t rdclass,
796 		   isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp) {
797 	dst_key_t *key = NULL;
798 	isc_result_t result;
799 
800 	REQUIRE(dst_initialized);
801 
802 	result = frombuffer(name, alg, flags, protocol, rdclass, source, mctx,
803 			    &key);
804 	if (result != ISC_R_SUCCESS) {
805 		return (result);
806 	}
807 
808 	result = computeid(key);
809 	if (result != ISC_R_SUCCESS) {
810 		dst_key_free(&key);
811 		return (result);
812 	}
813 
814 	*keyp = key;
815 	return (ISC_R_SUCCESS);
816 }
817 
818 isc_result_t
dst_key_tobuffer(const dst_key_t * key,isc_buffer_t * target)819 dst_key_tobuffer(const dst_key_t *key, isc_buffer_t *target) {
820 	REQUIRE(dst_initialized);
821 	REQUIRE(VALID_KEY(key));
822 	REQUIRE(target != NULL);
823 
824 	CHECKALG(key->key_alg);
825 
826 	if (key->func->todns == NULL) {
827 		return (DST_R_UNSUPPORTEDALG);
828 	}
829 
830 	return (key->func->todns(key, target));
831 }
832 
833 isc_result_t
dst_key_privatefrombuffer(dst_key_t * key,isc_buffer_t * buffer)834 dst_key_privatefrombuffer(dst_key_t *key, isc_buffer_t *buffer) {
835 	isc_lex_t *lex = NULL;
836 	isc_result_t result = ISC_R_SUCCESS;
837 
838 	REQUIRE(dst_initialized);
839 	REQUIRE(VALID_KEY(key));
840 	REQUIRE(!dst_key_isprivate(key));
841 	REQUIRE(buffer != NULL);
842 
843 	if (key->func->parse == NULL) {
844 		RETERR(DST_R_UNSUPPORTEDALG);
845 	}
846 
847 	RETERR(isc_lex_create(key->mctx, 1500, &lex));
848 	RETERR(isc_lex_openbuffer(lex, buffer));
849 	RETERR(key->func->parse(key, lex, NULL));
850 out:
851 	if (lex != NULL) {
852 		isc_lex_destroy(&lex);
853 	}
854 	return (result);
855 }
856 
857 dns_gss_ctx_id_t
dst_key_getgssctx(const dst_key_t * key)858 dst_key_getgssctx(const dst_key_t *key) {
859 	REQUIRE(key != NULL);
860 
861 	return (key->keydata.gssctx);
862 }
863 
864 isc_result_t
dst_key_fromgssapi(const dns_name_t * name,dns_gss_ctx_id_t gssctx,isc_mem_t * mctx,dst_key_t ** keyp,isc_region_t * intoken)865 dst_key_fromgssapi(const dns_name_t *name, dns_gss_ctx_id_t gssctx,
866 		   isc_mem_t *mctx, dst_key_t **keyp, isc_region_t *intoken) {
867 	dst_key_t *key;
868 	isc_result_t result;
869 
870 	REQUIRE(gssctx != NULL);
871 	REQUIRE(keyp != NULL && *keyp == NULL);
872 
873 	key = get_key_struct(name, DST_ALG_GSSAPI, 0, DNS_KEYPROTO_DNSSEC, 0,
874 			     dns_rdataclass_in, 0, mctx);
875 	if (key == NULL) {
876 		return (ISC_R_NOMEMORY);
877 	}
878 
879 	if (intoken != NULL) {
880 		/*
881 		 * Keep the token for use by external ssu rules. They may need
882 		 * to examine the PAC in the kerberos ticket.
883 		 */
884 		isc_buffer_allocate(key->mctx, &key->key_tkeytoken,
885 				    intoken->length);
886 		RETERR(isc_buffer_copyregion(key->key_tkeytoken, intoken));
887 	}
888 
889 	key->keydata.gssctx = gssctx;
890 	*keyp = key;
891 	result = ISC_R_SUCCESS;
892 out:
893 	if (result != ISC_R_SUCCESS) {
894 		dst_key_free(&key);
895 	}
896 	return (result);
897 }
898 
899 isc_result_t
dst_key_buildinternal(const dns_name_t * name,unsigned int alg,unsigned int bits,unsigned int flags,unsigned int protocol,dns_rdataclass_t rdclass,void * data,isc_mem_t * mctx,dst_key_t ** keyp)900 dst_key_buildinternal(const dns_name_t *name, unsigned int alg,
901 		      unsigned int bits, unsigned int flags,
902 		      unsigned int protocol, dns_rdataclass_t rdclass,
903 		      void *data, isc_mem_t *mctx, dst_key_t **keyp) {
904 	dst_key_t *key;
905 	isc_result_t result;
906 
907 	REQUIRE(dst_initialized);
908 	REQUIRE(dns_name_isabsolute(name));
909 	REQUIRE(mctx != NULL);
910 	REQUIRE(keyp != NULL && *keyp == NULL);
911 	REQUIRE(data != NULL);
912 
913 	CHECKALG(alg);
914 
915 	key = get_key_struct(name, alg, flags, protocol, bits, rdclass, 0,
916 			     mctx);
917 	if (key == NULL) {
918 		return (ISC_R_NOMEMORY);
919 	}
920 
921 	key->keydata.generic = data;
922 
923 	result = computeid(key);
924 	if (result != ISC_R_SUCCESS) {
925 		dst_key_free(&key);
926 		return (result);
927 	}
928 
929 	*keyp = key;
930 	return (ISC_R_SUCCESS);
931 }
932 
933 isc_result_t
dst_key_fromlabel(const dns_name_t * name,int alg,unsigned int flags,unsigned int protocol,dns_rdataclass_t rdclass,const char * engine,const char * label,const char * pin,isc_mem_t * mctx,dst_key_t ** keyp)934 dst_key_fromlabel(const dns_name_t *name, int alg, unsigned int flags,
935 		  unsigned int protocol, dns_rdataclass_t rdclass,
936 		  const char *engine, const char *label, const char *pin,
937 		  isc_mem_t *mctx, dst_key_t **keyp) {
938 	dst_key_t *key;
939 	isc_result_t result;
940 
941 	REQUIRE(dst_initialized);
942 	REQUIRE(dns_name_isabsolute(name));
943 	REQUIRE(mctx != NULL);
944 	REQUIRE(keyp != NULL && *keyp == NULL);
945 	REQUIRE(label != NULL);
946 
947 	CHECKALG(alg);
948 
949 	key = get_key_struct(name, alg, flags, protocol, 0, rdclass, 0, mctx);
950 	if (key == NULL) {
951 		return (ISC_R_NOMEMORY);
952 	}
953 
954 	if (key->func->fromlabel == NULL) {
955 		dst_key_free(&key);
956 		return (DST_R_UNSUPPORTEDALG);
957 	}
958 
959 	result = key->func->fromlabel(key, engine, label, pin);
960 	if (result != ISC_R_SUCCESS) {
961 		dst_key_free(&key);
962 		return (result);
963 	}
964 
965 	result = computeid(key);
966 	if (result != ISC_R_SUCCESS) {
967 		dst_key_free(&key);
968 		return (result);
969 	}
970 
971 	*keyp = key;
972 	return (ISC_R_SUCCESS);
973 }
974 
975 isc_result_t
dst_key_generate(const dns_name_t * name,unsigned int alg,unsigned int bits,unsigned int param,unsigned int flags,unsigned int protocol,dns_rdataclass_t rdclass,isc_mem_t * mctx,dst_key_t ** keyp,void (* callback)(int))976 dst_key_generate(const dns_name_t *name, unsigned int alg, unsigned int bits,
977 		 unsigned int param, unsigned int flags, unsigned int protocol,
978 		 dns_rdataclass_t rdclass, isc_mem_t *mctx, dst_key_t **keyp,
979 		 void (*callback)(int)) {
980 	dst_key_t *key;
981 	isc_result_t ret;
982 
983 	REQUIRE(dst_initialized);
984 	REQUIRE(dns_name_isabsolute(name));
985 	REQUIRE(mctx != NULL);
986 	REQUIRE(keyp != NULL && *keyp == NULL);
987 
988 	CHECKALG(alg);
989 
990 	key = get_key_struct(name, alg, flags, protocol, bits, rdclass, 0,
991 			     mctx);
992 	if (key == NULL) {
993 		return (ISC_R_NOMEMORY);
994 	}
995 
996 	if (bits == 0) { /*%< NULL KEY */
997 		key->key_flags |= DNS_KEYTYPE_NOKEY;
998 		*keyp = key;
999 		return (ISC_R_SUCCESS);
1000 	}
1001 
1002 	if (key->func->generate == NULL) {
1003 		dst_key_free(&key);
1004 		return (DST_R_UNSUPPORTEDALG);
1005 	}
1006 
1007 	ret = key->func->generate(key, param, callback);
1008 	if (ret != ISC_R_SUCCESS) {
1009 		dst_key_free(&key);
1010 		return (ret);
1011 	}
1012 
1013 	ret = computeid(key);
1014 	if (ret != ISC_R_SUCCESS) {
1015 		dst_key_free(&key);
1016 		return (ret);
1017 	}
1018 
1019 	*keyp = key;
1020 	return (ISC_R_SUCCESS);
1021 }
1022 
1023 isc_result_t
dst_key_getbool(const dst_key_t * key,int type,bool * valuep)1024 dst_key_getbool(const dst_key_t *key, int type, bool *valuep) {
1025 	dst_key_t *k;
1026 
1027 	REQUIRE(VALID_KEY(key));
1028 	REQUIRE(valuep != NULL);
1029 	REQUIRE(type <= DST_MAX_BOOLEAN);
1030 
1031 	DE_CONST(key, k);
1032 
1033 	isc_mutex_lock(&k->mdlock);
1034 	if (!key->boolset[type]) {
1035 		isc_mutex_unlock(&k->mdlock);
1036 		return (ISC_R_NOTFOUND);
1037 	}
1038 	*valuep = key->bools[type];
1039 	isc_mutex_unlock(&k->mdlock);
1040 
1041 	return (ISC_R_SUCCESS);
1042 }
1043 
1044 void
dst_key_setbool(dst_key_t * key,int type,bool value)1045 dst_key_setbool(dst_key_t *key, int type, bool value) {
1046 	REQUIRE(VALID_KEY(key));
1047 	REQUIRE(type <= DST_MAX_BOOLEAN);
1048 
1049 	isc_mutex_lock(&key->mdlock);
1050 	key->bools[type] = value;
1051 	key->boolset[type] = true;
1052 	isc_mutex_unlock(&key->mdlock);
1053 }
1054 
1055 void
dst_key_unsetbool(dst_key_t * key,int type)1056 dst_key_unsetbool(dst_key_t *key, int type) {
1057 	REQUIRE(VALID_KEY(key));
1058 	REQUIRE(type <= DST_MAX_BOOLEAN);
1059 
1060 	isc_mutex_lock(&key->mdlock);
1061 	key->boolset[type] = false;
1062 	isc_mutex_unlock(&key->mdlock);
1063 }
1064 
1065 isc_result_t
dst_key_getnum(const dst_key_t * key,int type,uint32_t * valuep)1066 dst_key_getnum(const dst_key_t *key, int type, uint32_t *valuep) {
1067 	dst_key_t *k;
1068 
1069 	REQUIRE(VALID_KEY(key));
1070 	REQUIRE(valuep != NULL);
1071 	REQUIRE(type <= DST_MAX_NUMERIC);
1072 
1073 	DE_CONST(key, k);
1074 
1075 	isc_mutex_lock(&k->mdlock);
1076 	if (!key->numset[type]) {
1077 		isc_mutex_unlock(&k->mdlock);
1078 		return (ISC_R_NOTFOUND);
1079 	}
1080 	*valuep = key->nums[type];
1081 	isc_mutex_unlock(&k->mdlock);
1082 
1083 	return (ISC_R_SUCCESS);
1084 }
1085 
1086 void
dst_key_setnum(dst_key_t * key,int type,uint32_t value)1087 dst_key_setnum(dst_key_t *key, int type, uint32_t value) {
1088 	REQUIRE(VALID_KEY(key));
1089 	REQUIRE(type <= DST_MAX_NUMERIC);
1090 
1091 	isc_mutex_lock(&key->mdlock);
1092 	key->nums[type] = value;
1093 	key->numset[type] = true;
1094 	isc_mutex_unlock(&key->mdlock);
1095 }
1096 
1097 void
dst_key_unsetnum(dst_key_t * key,int type)1098 dst_key_unsetnum(dst_key_t *key, int type) {
1099 	REQUIRE(VALID_KEY(key));
1100 	REQUIRE(type <= DST_MAX_NUMERIC);
1101 
1102 	isc_mutex_lock(&key->mdlock);
1103 	key->numset[type] = false;
1104 	isc_mutex_unlock(&key->mdlock);
1105 }
1106 
1107 isc_result_t
dst_key_gettime(const dst_key_t * key,int type,isc_stdtime_t * timep)1108 dst_key_gettime(const dst_key_t *key, int type, isc_stdtime_t *timep) {
1109 	dst_key_t *k;
1110 
1111 	REQUIRE(VALID_KEY(key));
1112 	REQUIRE(timep != NULL);
1113 	REQUIRE(type <= DST_MAX_TIMES);
1114 
1115 	DE_CONST(key, k);
1116 
1117 	isc_mutex_lock(&k->mdlock);
1118 	if (!key->timeset[type]) {
1119 		isc_mutex_unlock(&k->mdlock);
1120 		return (ISC_R_NOTFOUND);
1121 	}
1122 	*timep = key->times[type];
1123 	isc_mutex_unlock(&k->mdlock);
1124 	return (ISC_R_SUCCESS);
1125 }
1126 
1127 void
dst_key_settime(dst_key_t * key,int type,isc_stdtime_t when)1128 dst_key_settime(dst_key_t *key, int type, isc_stdtime_t when) {
1129 	REQUIRE(VALID_KEY(key));
1130 	REQUIRE(type <= DST_MAX_TIMES);
1131 
1132 	isc_mutex_lock(&key->mdlock);
1133 	key->times[type] = when;
1134 	key->timeset[type] = true;
1135 	isc_mutex_unlock(&key->mdlock);
1136 }
1137 
1138 void
dst_key_unsettime(dst_key_t * key,int type)1139 dst_key_unsettime(dst_key_t *key, int type) {
1140 	REQUIRE(VALID_KEY(key));
1141 	REQUIRE(type <= DST_MAX_TIMES);
1142 
1143 	isc_mutex_lock(&key->mdlock);
1144 	key->timeset[type] = false;
1145 	isc_mutex_unlock(&key->mdlock);
1146 }
1147 
1148 isc_result_t
dst_key_getstate(const dst_key_t * key,int type,dst_key_state_t * statep)1149 dst_key_getstate(const dst_key_t *key, int type, dst_key_state_t *statep) {
1150 	dst_key_t *k;
1151 
1152 	REQUIRE(VALID_KEY(key));
1153 	REQUIRE(statep != NULL);
1154 	REQUIRE(type <= DST_MAX_KEYSTATES);
1155 
1156 	DE_CONST(key, k);
1157 
1158 	isc_mutex_lock(&k->mdlock);
1159 	if (!key->keystateset[type]) {
1160 		isc_mutex_unlock(&k->mdlock);
1161 		return (ISC_R_NOTFOUND);
1162 	}
1163 	*statep = key->keystates[type];
1164 	isc_mutex_unlock(&k->mdlock);
1165 
1166 	return (ISC_R_SUCCESS);
1167 }
1168 
1169 void
dst_key_setstate(dst_key_t * key,int type,dst_key_state_t state)1170 dst_key_setstate(dst_key_t *key, int type, dst_key_state_t state) {
1171 	REQUIRE(VALID_KEY(key));
1172 	REQUIRE(type <= DST_MAX_KEYSTATES);
1173 
1174 	isc_mutex_lock(&key->mdlock);
1175 	key->keystates[type] = state;
1176 	key->keystateset[type] = true;
1177 	isc_mutex_unlock(&key->mdlock);
1178 }
1179 
1180 void
dst_key_unsetstate(dst_key_t * key,int type)1181 dst_key_unsetstate(dst_key_t *key, int type) {
1182 	REQUIRE(VALID_KEY(key));
1183 	REQUIRE(type <= DST_MAX_KEYSTATES);
1184 
1185 	isc_mutex_lock(&key->mdlock);
1186 	key->keystateset[type] = false;
1187 	isc_mutex_unlock(&key->mdlock);
1188 }
1189 
1190 isc_result_t
dst_key_getprivateformat(const dst_key_t * key,int * majorp,int * minorp)1191 dst_key_getprivateformat(const dst_key_t *key, int *majorp, int *minorp) {
1192 	REQUIRE(VALID_KEY(key));
1193 	REQUIRE(majorp != NULL);
1194 	REQUIRE(minorp != NULL);
1195 	*majorp = key->fmt_major;
1196 	*minorp = key->fmt_minor;
1197 	return (ISC_R_SUCCESS);
1198 }
1199 
1200 void
dst_key_setprivateformat(dst_key_t * key,int major,int minor)1201 dst_key_setprivateformat(dst_key_t *key, int major, int minor) {
1202 	REQUIRE(VALID_KEY(key));
1203 	key->fmt_major = major;
1204 	key->fmt_minor = minor;
1205 }
1206 
1207 static bool
comparekeys(const dst_key_t * key1,const dst_key_t * key2,bool match_revoked_key,bool (* compare)(const dst_key_t * key1,const dst_key_t * key2))1208 comparekeys(const dst_key_t *key1, const dst_key_t *key2,
1209 	    bool match_revoked_key,
1210 	    bool (*compare)(const dst_key_t *key1, const dst_key_t *key2)) {
1211 	REQUIRE(dst_initialized);
1212 	REQUIRE(VALID_KEY(key1));
1213 	REQUIRE(VALID_KEY(key2));
1214 
1215 	if (key1 == key2) {
1216 		return (true);
1217 	}
1218 
1219 	if (key1->key_alg != key2->key_alg) {
1220 		return (false);
1221 	}
1222 
1223 	if (key1->key_id != key2->key_id) {
1224 		if (!match_revoked_key) {
1225 			return (false);
1226 		}
1227 		if ((key1->key_flags & DNS_KEYFLAG_REVOKE) ==
1228 		    (key2->key_flags & DNS_KEYFLAG_REVOKE))
1229 		{
1230 			return (false);
1231 		}
1232 		if (key1->key_id != key2->key_rid &&
1233 		    key1->key_rid != key2->key_id) {
1234 			return (false);
1235 		}
1236 	}
1237 
1238 	if (compare != NULL) {
1239 		return (compare(key1, key2));
1240 	} else {
1241 		return (false);
1242 	}
1243 }
1244 
1245 /*
1246  * Compares only the public portion of two keys, by converting them
1247  * both to wire format and comparing the results.
1248  */
1249 static bool
pub_compare(const dst_key_t * key1,const dst_key_t * key2)1250 pub_compare(const dst_key_t *key1, const dst_key_t *key2) {
1251 	isc_result_t result;
1252 	unsigned char buf1[DST_KEY_MAXSIZE], buf2[DST_KEY_MAXSIZE];
1253 	isc_buffer_t b1, b2;
1254 	isc_region_t r1, r2;
1255 
1256 	isc_buffer_init(&b1, buf1, sizeof(buf1));
1257 	result = dst_key_todns(key1, &b1);
1258 	if (result != ISC_R_SUCCESS) {
1259 		return (false);
1260 	}
1261 	/* Zero out flags. */
1262 	buf1[0] = buf1[1] = 0;
1263 	if ((key1->key_flags & DNS_KEYFLAG_EXTENDED) != 0) {
1264 		isc_buffer_subtract(&b1, 2);
1265 	}
1266 
1267 	isc_buffer_init(&b2, buf2, sizeof(buf2));
1268 	result = dst_key_todns(key2, &b2);
1269 	if (result != ISC_R_SUCCESS) {
1270 		return (false);
1271 	}
1272 	/* Zero out flags. */
1273 	buf2[0] = buf2[1] = 0;
1274 	if ((key2->key_flags & DNS_KEYFLAG_EXTENDED) != 0) {
1275 		isc_buffer_subtract(&b2, 2);
1276 	}
1277 
1278 	isc_buffer_usedregion(&b1, &r1);
1279 	/* Remove extended flags. */
1280 	if ((key1->key_flags & DNS_KEYFLAG_EXTENDED) != 0) {
1281 		memmove(&buf1[4], &buf1[6], r1.length - 6);
1282 		r1.length -= 2;
1283 	}
1284 
1285 	isc_buffer_usedregion(&b2, &r2);
1286 	/* Remove extended flags. */
1287 	if ((key2->key_flags & DNS_KEYFLAG_EXTENDED) != 0) {
1288 		memmove(&buf2[4], &buf2[6], r2.length - 6);
1289 		r2.length -= 2;
1290 	}
1291 	return (isc_region_compare(&r1, &r2) == 0);
1292 }
1293 
1294 bool
dst_key_compare(const dst_key_t * key1,const dst_key_t * key2)1295 dst_key_compare(const dst_key_t *key1, const dst_key_t *key2) {
1296 	return (comparekeys(key1, key2, false, key1->func->compare));
1297 }
1298 
1299 bool
dst_key_pubcompare(const dst_key_t * key1,const dst_key_t * key2,bool match_revoked_key)1300 dst_key_pubcompare(const dst_key_t *key1, const dst_key_t *key2,
1301 		   bool match_revoked_key) {
1302 	return (comparekeys(key1, key2, match_revoked_key, pub_compare));
1303 }
1304 
1305 bool
dst_key_paramcompare(const dst_key_t * key1,const dst_key_t * key2)1306 dst_key_paramcompare(const dst_key_t *key1, const dst_key_t *key2) {
1307 	REQUIRE(dst_initialized);
1308 	REQUIRE(VALID_KEY(key1));
1309 	REQUIRE(VALID_KEY(key2));
1310 
1311 	if (key1 == key2) {
1312 		return (true);
1313 	}
1314 	if (key1->key_alg == key2->key_alg &&
1315 	    key1->func->paramcompare != NULL &&
1316 	    key1->func->paramcompare(key1, key2))
1317 	{
1318 		return (true);
1319 	} else {
1320 		return (false);
1321 	}
1322 }
1323 
1324 void
dst_key_attach(dst_key_t * source,dst_key_t ** target)1325 dst_key_attach(dst_key_t *source, dst_key_t **target) {
1326 	REQUIRE(dst_initialized);
1327 	REQUIRE(target != NULL && *target == NULL);
1328 	REQUIRE(VALID_KEY(source));
1329 
1330 	isc_refcount_increment(&source->refs);
1331 	*target = source;
1332 }
1333 
1334 void
dst_key_free(dst_key_t ** keyp)1335 dst_key_free(dst_key_t **keyp) {
1336 	REQUIRE(dst_initialized);
1337 	REQUIRE(keyp != NULL && VALID_KEY(*keyp));
1338 	dst_key_t *key = *keyp;
1339 	*keyp = NULL;
1340 
1341 	if (isc_refcount_decrement(&key->refs) == 1) {
1342 		isc_refcount_destroy(&key->refs);
1343 		isc_mem_t *mctx = key->mctx;
1344 		if (key->keydata.generic != NULL) {
1345 			INSIST(key->func->destroy != NULL);
1346 			key->func->destroy(key);
1347 		}
1348 		if (key->engine != NULL) {
1349 			isc_mem_free(mctx, key->engine);
1350 		}
1351 		if (key->label != NULL) {
1352 			isc_mem_free(mctx, key->label);
1353 		}
1354 		dns_name_free(key->key_name, mctx);
1355 		isc_mem_put(mctx, key->key_name, sizeof(dns_name_t));
1356 		if (key->key_tkeytoken) {
1357 			isc_buffer_free(&key->key_tkeytoken);
1358 		}
1359 		isc_mutex_destroy(&key->mdlock);
1360 		isc_safe_memwipe(key, sizeof(*key));
1361 		isc_mem_putanddetach(&mctx, key, sizeof(*key));
1362 	}
1363 }
1364 
1365 bool
dst_key_isprivate(const dst_key_t * key)1366 dst_key_isprivate(const dst_key_t *key) {
1367 	REQUIRE(VALID_KEY(key));
1368 	INSIST(key->func->isprivate != NULL);
1369 	return (key->func->isprivate(key));
1370 }
1371 
1372 isc_result_t
dst_key_buildfilename(const dst_key_t * key,int type,const char * directory,isc_buffer_t * out)1373 dst_key_buildfilename(const dst_key_t *key, int type, const char *directory,
1374 		      isc_buffer_t *out) {
1375 	REQUIRE(VALID_KEY(key));
1376 	REQUIRE(type == DST_TYPE_PRIVATE || type == DST_TYPE_PUBLIC ||
1377 		type == DST_TYPE_STATE || type == 0);
1378 
1379 	return (buildfilename(key->key_name, key->key_id, key->key_alg, type,
1380 			      directory, out));
1381 }
1382 
1383 isc_result_t
dst_key_sigsize(const dst_key_t * key,unsigned int * n)1384 dst_key_sigsize(const dst_key_t *key, unsigned int *n) {
1385 	REQUIRE(dst_initialized);
1386 	REQUIRE(VALID_KEY(key));
1387 	REQUIRE(n != NULL);
1388 
1389 	/* XXXVIX this switch statement is too sparse to gen a jump table. */
1390 	switch (key->key_alg) {
1391 	case DST_ALG_RSASHA1:
1392 	case DST_ALG_NSEC3RSASHA1:
1393 	case DST_ALG_RSASHA256:
1394 	case DST_ALG_RSASHA512:
1395 		*n = (key->key_size + 7) / 8;
1396 		break;
1397 	case DST_ALG_ECDSA256:
1398 		*n = DNS_SIG_ECDSA256SIZE;
1399 		break;
1400 	case DST_ALG_ECDSA384:
1401 		*n = DNS_SIG_ECDSA384SIZE;
1402 		break;
1403 	case DST_ALG_ED25519:
1404 		*n = DNS_SIG_ED25519SIZE;
1405 		break;
1406 	case DST_ALG_ED448:
1407 		*n = DNS_SIG_ED448SIZE;
1408 		break;
1409 	case DST_ALG_HMACMD5:
1410 		*n = isc_md_type_get_size(ISC_MD_MD5);
1411 		break;
1412 	case DST_ALG_HMACSHA1:
1413 		*n = isc_md_type_get_size(ISC_MD_SHA1);
1414 		break;
1415 	case DST_ALG_HMACSHA224:
1416 		*n = isc_md_type_get_size(ISC_MD_SHA224);
1417 		break;
1418 	case DST_ALG_HMACSHA256:
1419 		*n = isc_md_type_get_size(ISC_MD_SHA256);
1420 		break;
1421 	case DST_ALG_HMACSHA384:
1422 		*n = isc_md_type_get_size(ISC_MD_SHA384);
1423 		break;
1424 	case DST_ALG_HMACSHA512:
1425 		*n = isc_md_type_get_size(ISC_MD_SHA512);
1426 		break;
1427 	case DST_ALG_GSSAPI:
1428 		*n = 128; /*%< XXX */
1429 		break;
1430 	case DST_ALG_DH:
1431 	default:
1432 		return (DST_R_UNSUPPORTEDALG);
1433 	}
1434 	return (ISC_R_SUCCESS);
1435 }
1436 
1437 isc_result_t
dst_key_secretsize(const dst_key_t * key,unsigned int * n)1438 dst_key_secretsize(const dst_key_t *key, unsigned int *n) {
1439 	REQUIRE(dst_initialized);
1440 	REQUIRE(VALID_KEY(key));
1441 	REQUIRE(n != NULL);
1442 
1443 	if (key->key_alg == DST_ALG_DH) {
1444 		*n = (key->key_size + 7) / 8;
1445 		return (ISC_R_SUCCESS);
1446 	}
1447 	return (DST_R_UNSUPPORTEDALG);
1448 }
1449 
1450 /*%
1451  * Set the flags on a key, then recompute the key ID
1452  */
1453 isc_result_t
dst_key_setflags(dst_key_t * key,uint32_t flags)1454 dst_key_setflags(dst_key_t *key, uint32_t flags) {
1455 	REQUIRE(VALID_KEY(key));
1456 	key->key_flags = flags;
1457 	return (computeid(key));
1458 }
1459 
1460 void
dst_key_format(const dst_key_t * key,char * cp,unsigned int size)1461 dst_key_format(const dst_key_t *key, char *cp, unsigned int size) {
1462 	char namestr[DNS_NAME_FORMATSIZE];
1463 	char algstr[DNS_NAME_FORMATSIZE];
1464 
1465 	dns_name_format(dst_key_name(key), namestr, sizeof(namestr));
1466 	dns_secalg_format((dns_secalg_t)dst_key_alg(key), algstr,
1467 			  sizeof(algstr));
1468 	snprintf(cp, size, "%s/%s/%d", namestr, algstr, dst_key_id(key));
1469 }
1470 
1471 isc_result_t
dst_key_dump(dst_key_t * key,isc_mem_t * mctx,char ** buffer,int * length)1472 dst_key_dump(dst_key_t *key, isc_mem_t *mctx, char **buffer, int *length) {
1473 	REQUIRE(buffer != NULL && *buffer == NULL);
1474 	REQUIRE(length != NULL && *length == 0);
1475 	REQUIRE(VALID_KEY(key));
1476 
1477 	if (key->func->dump == NULL) {
1478 		return (ISC_R_NOTIMPLEMENTED);
1479 	}
1480 	return (key->func->dump(key, mctx, buffer, length));
1481 }
1482 
1483 isc_result_t
dst_key_restore(dns_name_t * name,unsigned int alg,unsigned int flags,unsigned int protocol,dns_rdataclass_t rdclass,isc_mem_t * mctx,const char * keystr,dst_key_t ** keyp)1484 dst_key_restore(dns_name_t *name, unsigned int alg, unsigned int flags,
1485 		unsigned int protocol, dns_rdataclass_t rdclass,
1486 		isc_mem_t *mctx, const char *keystr, dst_key_t **keyp) {
1487 	isc_result_t result;
1488 	dst_key_t *key;
1489 
1490 	REQUIRE(dst_initialized);
1491 	REQUIRE(keyp != NULL && *keyp == NULL);
1492 
1493 	if (alg >= DST_MAX_ALGS || dst_t_func[alg] == NULL) {
1494 		return (DST_R_UNSUPPORTEDALG);
1495 	}
1496 
1497 	if (dst_t_func[alg]->restore == NULL) {
1498 		return (ISC_R_NOTIMPLEMENTED);
1499 	}
1500 
1501 	key = get_key_struct(name, alg, flags, protocol, 0, rdclass, 0, mctx);
1502 	if (key == NULL) {
1503 		return (ISC_R_NOMEMORY);
1504 	}
1505 
1506 	result = (dst_t_func[alg]->restore)(key, keystr);
1507 	if (result == ISC_R_SUCCESS) {
1508 		*keyp = key;
1509 	} else {
1510 		dst_key_free(&key);
1511 	}
1512 
1513 	return (result);
1514 }
1515 
1516 /***
1517  *** Static methods
1518  ***/
1519 
1520 /*%
1521  * Allocates a key structure and fills in some of the fields.
1522  */
1523 static dst_key_t *
get_key_struct(const dns_name_t * name,unsigned int alg,unsigned int flags,unsigned int protocol,unsigned int bits,dns_rdataclass_t rdclass,dns_ttl_t ttl,isc_mem_t * mctx)1524 get_key_struct(const dns_name_t *name, unsigned int alg, unsigned int flags,
1525 	       unsigned int protocol, unsigned int bits,
1526 	       dns_rdataclass_t rdclass, dns_ttl_t ttl, isc_mem_t *mctx) {
1527 	dst_key_t *key;
1528 	int i;
1529 
1530 	key = isc_mem_get(mctx, sizeof(dst_key_t));
1531 
1532 	memset(key, 0, sizeof(dst_key_t));
1533 
1534 	key->key_name = isc_mem_get(mctx, sizeof(dns_name_t));
1535 
1536 	dns_name_init(key->key_name, NULL);
1537 	dns_name_dup(name, mctx, key->key_name);
1538 
1539 	isc_refcount_init(&key->refs, 1);
1540 	isc_mem_attach(mctx, &key->mctx);
1541 	key->key_alg = alg;
1542 	key->key_flags = flags;
1543 	key->key_proto = protocol;
1544 	key->keydata.generic = NULL;
1545 	key->key_size = bits;
1546 	key->key_class = rdclass;
1547 	key->key_ttl = ttl;
1548 	key->func = dst_t_func[alg];
1549 	key->fmt_major = 0;
1550 	key->fmt_minor = 0;
1551 	for (i = 0; i < (DST_MAX_TIMES + 1); i++) {
1552 		key->times[i] = 0;
1553 		key->timeset[i] = false;
1554 	}
1555 	isc_mutex_init(&key->mdlock);
1556 	key->inactive = false;
1557 	key->magic = KEY_MAGIC;
1558 	return (key);
1559 }
1560 
1561 bool
dst_key_inactive(const dst_key_t * key)1562 dst_key_inactive(const dst_key_t *key) {
1563 	REQUIRE(VALID_KEY(key));
1564 
1565 	return (key->inactive);
1566 }
1567 
1568 void
dst_key_setinactive(dst_key_t * key,bool inactive)1569 dst_key_setinactive(dst_key_t *key, bool inactive) {
1570 	REQUIRE(VALID_KEY(key));
1571 
1572 	key->inactive = inactive;
1573 }
1574 
1575 /*%
1576  * Reads a public key from disk.
1577  */
1578 isc_result_t
dst_key_read_public(const char * filename,int type,isc_mem_t * mctx,dst_key_t ** keyp)1579 dst_key_read_public(const char *filename, int type, isc_mem_t *mctx,
1580 		    dst_key_t **keyp) {
1581 	u_char rdatabuf[DST_KEY_MAXSIZE];
1582 	isc_buffer_t b;
1583 	dns_fixedname_t name;
1584 	isc_lex_t *lex = NULL;
1585 	isc_token_t token;
1586 	isc_result_t ret;
1587 	dns_rdata_t rdata = DNS_RDATA_INIT;
1588 	unsigned int opt = ISC_LEXOPT_DNSMULTILINE;
1589 	dns_rdataclass_t rdclass = dns_rdataclass_in;
1590 	isc_lexspecials_t specials;
1591 	uint32_t ttl = 0;
1592 	isc_result_t result;
1593 	dns_rdatatype_t keytype;
1594 
1595 	/*
1596 	 * Open the file and read its formatted contents
1597 	 * File format:
1598 	 *    domain.name [ttl] [class] [KEY|DNSKEY] <flags> <protocol>
1599 	 * <algorithm> <key>
1600 	 */
1601 
1602 	/* 1500 should be large enough for any key */
1603 	ret = isc_lex_create(mctx, 1500, &lex);
1604 	if (ret != ISC_R_SUCCESS) {
1605 		goto cleanup;
1606 	}
1607 
1608 	memset(specials, 0, sizeof(specials));
1609 	specials['('] = 1;
1610 	specials[')'] = 1;
1611 	specials['"'] = 1;
1612 	isc_lex_setspecials(lex, specials);
1613 	isc_lex_setcomments(lex, ISC_LEXCOMMENT_DNSMASTERFILE);
1614 
1615 	ret = isc_lex_openfile(lex, filename);
1616 	if (ret != ISC_R_SUCCESS) {
1617 		goto cleanup;
1618 	}
1619 
1620 	/* Read the domain name */
1621 	NEXTTOKEN(lex, opt, &token);
1622 	if (token.type != isc_tokentype_string) {
1623 		BADTOKEN();
1624 	}
1625 
1626 	/*
1627 	 * We don't support "@" in .key files.
1628 	 */
1629 	if (!strcmp(DST_AS_STR(token), "@")) {
1630 		BADTOKEN();
1631 	}
1632 
1633 	dns_fixedname_init(&name);
1634 	isc_buffer_init(&b, DST_AS_STR(token), strlen(DST_AS_STR(token)));
1635 	isc_buffer_add(&b, strlen(DST_AS_STR(token)));
1636 	ret = dns_name_fromtext(dns_fixedname_name(&name), &b, dns_rootname, 0,
1637 				NULL);
1638 	if (ret != ISC_R_SUCCESS) {
1639 		goto cleanup;
1640 	}
1641 
1642 	/* Read the next word: either TTL, class, or 'KEY' */
1643 	NEXTTOKEN(lex, opt, &token);
1644 
1645 	if (token.type != isc_tokentype_string) {
1646 		BADTOKEN();
1647 	}
1648 
1649 	/* If it's a TTL, read the next one */
1650 	result = dns_ttl_fromtext(&token.value.as_textregion, &ttl);
1651 	if (result == ISC_R_SUCCESS) {
1652 		NEXTTOKEN(lex, opt, &token);
1653 	}
1654 
1655 	if (token.type != isc_tokentype_string) {
1656 		BADTOKEN();
1657 	}
1658 
1659 	ret = dns_rdataclass_fromtext(&rdclass, &token.value.as_textregion);
1660 	if (ret == ISC_R_SUCCESS) {
1661 		NEXTTOKEN(lex, opt, &token);
1662 	}
1663 
1664 	if (token.type != isc_tokentype_string) {
1665 		BADTOKEN();
1666 	}
1667 
1668 	if (strcasecmp(DST_AS_STR(token), "DNSKEY") == 0) {
1669 		keytype = dns_rdatatype_dnskey;
1670 	} else if (strcasecmp(DST_AS_STR(token), "KEY") == 0) {
1671 		keytype = dns_rdatatype_key; /*%< SIG(0), TKEY */
1672 	} else {
1673 		BADTOKEN();
1674 	}
1675 
1676 	if (((type & DST_TYPE_KEY) != 0 && keytype != dns_rdatatype_key) ||
1677 	    ((type & DST_TYPE_KEY) == 0 && keytype != dns_rdatatype_dnskey))
1678 	{
1679 		ret = DST_R_BADKEYTYPE;
1680 		goto cleanup;
1681 	}
1682 
1683 	isc_buffer_init(&b, rdatabuf, sizeof(rdatabuf));
1684 	ret = dns_rdata_fromtext(&rdata, rdclass, keytype, lex, NULL, false,
1685 				 mctx, &b, NULL);
1686 	if (ret != ISC_R_SUCCESS) {
1687 		goto cleanup;
1688 	}
1689 
1690 	ret = dst_key_fromdns(dns_fixedname_name(&name), rdclass, &b, mctx,
1691 			      keyp);
1692 	if (ret != ISC_R_SUCCESS) {
1693 		goto cleanup;
1694 	}
1695 
1696 	dst_key_setttl(*keyp, ttl);
1697 
1698 cleanup:
1699 	if (lex != NULL) {
1700 		isc_lex_destroy(&lex);
1701 	}
1702 	return (ret);
1703 }
1704 
1705 static int
find_metadata(const char * s,const char * tags[],int ntags)1706 find_metadata(const char *s, const char *tags[], int ntags) {
1707 	for (int i = 0; i < ntags; i++) {
1708 		if (tags[i] != NULL && strcasecmp(s, tags[i]) == 0) {
1709 			return (i);
1710 		}
1711 	}
1712 	return (-1);
1713 }
1714 
1715 static int
find_numericdata(const char * s)1716 find_numericdata(const char *s) {
1717 	return (find_metadata(s, numerictags, NUMERIC_NTAGS));
1718 }
1719 
1720 static int
find_booleandata(const char * s)1721 find_booleandata(const char *s) {
1722 	return (find_metadata(s, booleantags, BOOLEAN_NTAGS));
1723 }
1724 
1725 static int
find_timingdata(const char * s)1726 find_timingdata(const char *s) {
1727 	return (find_metadata(s, timingtags, TIMING_NTAGS));
1728 }
1729 
1730 static int
find_keystatedata(const char * s)1731 find_keystatedata(const char *s) {
1732 	return (find_metadata(s, keystatestags, KEYSTATES_NTAGS));
1733 }
1734 
1735 static isc_result_t
keystate_fromtext(const char * s,dst_key_state_t * state)1736 keystate_fromtext(const char *s, dst_key_state_t *state) {
1737 	for (int i = 0; i < KEYSTATES_NVALUES; i++) {
1738 		if (keystates[i] != NULL && strcasecmp(s, keystates[i]) == 0) {
1739 			*state = (dst_key_state_t)i;
1740 			return (ISC_R_SUCCESS);
1741 		}
1742 	}
1743 	return (ISC_R_NOTFOUND);
1744 }
1745 
1746 /*%
1747  * Reads a key state from disk.
1748  */
1749 isc_result_t
dst_key_read_state(const char * filename,isc_mem_t * mctx,dst_key_t ** keyp)1750 dst_key_read_state(const char *filename, isc_mem_t *mctx, dst_key_t **keyp) {
1751 	isc_lex_t *lex = NULL;
1752 	isc_token_t token;
1753 	isc_result_t ret;
1754 	unsigned int opt = ISC_LEXOPT_EOL;
1755 
1756 	ret = isc_lex_create(mctx, 1500, &lex);
1757 	if (ret != ISC_R_SUCCESS) {
1758 		goto cleanup;
1759 	}
1760 	isc_lex_setcomments(lex, ISC_LEXCOMMENT_DNSMASTERFILE);
1761 
1762 	ret = isc_lex_openfile(lex, filename);
1763 	if (ret != ISC_R_SUCCESS) {
1764 		goto cleanup;
1765 	}
1766 
1767 	/*
1768 	 * Read the comment line.
1769 	 */
1770 	READLINE(lex, opt, &token);
1771 
1772 	/*
1773 	 * Read the algorithm line.
1774 	 */
1775 	NEXTTOKEN(lex, opt, &token);
1776 	if (token.type != isc_tokentype_string ||
1777 	    strcmp(DST_AS_STR(token), STATE_ALGORITHM_STR) != 0)
1778 	{
1779 		BADTOKEN();
1780 	}
1781 
1782 	NEXTTOKEN(lex, opt | ISC_LEXOPT_NUMBER, &token);
1783 	if (token.type != isc_tokentype_number ||
1784 	    token.value.as_ulong != (unsigned long)dst_key_alg(*keyp))
1785 	{
1786 		BADTOKEN();
1787 	}
1788 
1789 	READLINE(lex, opt, &token);
1790 
1791 	/*
1792 	 * Read the length line.
1793 	 */
1794 	NEXTTOKEN(lex, opt, &token);
1795 	if (token.type != isc_tokentype_string ||
1796 	    strcmp(DST_AS_STR(token), STATE_LENGTH_STR) != 0)
1797 	{
1798 		BADTOKEN();
1799 	}
1800 
1801 	NEXTTOKEN(lex, opt | ISC_LEXOPT_NUMBER, &token);
1802 	if (token.type != isc_tokentype_number ||
1803 	    token.value.as_ulong != (unsigned long)dst_key_size(*keyp))
1804 	{
1805 		BADTOKEN();
1806 	}
1807 
1808 	READLINE(lex, opt, &token);
1809 
1810 	/*
1811 	 * Read the metadata.
1812 	 */
1813 	for (int n = 0; n < MAX_NTAGS; n++) {
1814 		int tag;
1815 
1816 		NEXTTOKEN_OR_EOF(lex, opt, &token);
1817 		if (ret == ISC_R_EOF) {
1818 			break;
1819 		}
1820 		if (token.type != isc_tokentype_string) {
1821 			BADTOKEN();
1822 		}
1823 
1824 		/* Numeric metadata */
1825 		tag = find_numericdata(DST_AS_STR(token));
1826 		if (tag >= 0) {
1827 			INSIST(tag < NUMERIC_NTAGS);
1828 
1829 			NEXTTOKEN(lex, opt | ISC_LEXOPT_NUMBER, &token);
1830 			if (token.type != isc_tokentype_number) {
1831 				BADTOKEN();
1832 			}
1833 
1834 			dst_key_setnum(*keyp, tag, token.value.as_ulong);
1835 			goto next;
1836 		}
1837 
1838 		/* Boolean metadata */
1839 		tag = find_booleandata(DST_AS_STR(token));
1840 		if (tag >= 0) {
1841 			INSIST(tag < BOOLEAN_NTAGS);
1842 
1843 			NEXTTOKEN(lex, opt, &token);
1844 			if (token.type != isc_tokentype_string) {
1845 				BADTOKEN();
1846 			}
1847 
1848 			if (strcmp(DST_AS_STR(token), "yes") == 0) {
1849 				dst_key_setbool(*keyp, tag, true);
1850 			} else if (strcmp(DST_AS_STR(token), "no") == 0) {
1851 				dst_key_setbool(*keyp, tag, false);
1852 			} else {
1853 				BADTOKEN();
1854 			}
1855 			goto next;
1856 		}
1857 
1858 		/* Timing metadata */
1859 		tag = find_timingdata(DST_AS_STR(token));
1860 		if (tag >= 0) {
1861 			uint32_t when;
1862 
1863 			INSIST(tag < TIMING_NTAGS);
1864 
1865 			NEXTTOKEN(lex, opt, &token);
1866 			if (token.type != isc_tokentype_string) {
1867 				BADTOKEN();
1868 			}
1869 
1870 			ret = dns_time32_fromtext(DST_AS_STR(token), &when);
1871 			if (ret != ISC_R_SUCCESS) {
1872 				goto cleanup;
1873 			}
1874 
1875 			dst_key_settime(*keyp, tag, when);
1876 			goto next;
1877 		}
1878 
1879 		/* Keystate metadata */
1880 		tag = find_keystatedata(DST_AS_STR(token));
1881 		if (tag >= 0) {
1882 			dst_key_state_t state;
1883 
1884 			INSIST(tag < KEYSTATES_NTAGS);
1885 
1886 			NEXTTOKEN(lex, opt, &token);
1887 			if (token.type != isc_tokentype_string) {
1888 				BADTOKEN();
1889 			}
1890 
1891 			ret = keystate_fromtext(DST_AS_STR(token), &state);
1892 			if (ret != ISC_R_SUCCESS) {
1893 				goto cleanup;
1894 			}
1895 
1896 			dst_key_setstate(*keyp, tag, state);
1897 			goto next;
1898 		}
1899 
1900 	next:
1901 		READLINE(lex, opt, &token);
1902 	}
1903 
1904 	/* Done, successfully parsed the whole file. */
1905 	ret = ISC_R_SUCCESS;
1906 
1907 cleanup:
1908 	if (lex != NULL) {
1909 		isc_lex_destroy(&lex);
1910 	}
1911 	return (ret);
1912 }
1913 
1914 static bool
issymmetric(const dst_key_t * key)1915 issymmetric(const dst_key_t *key) {
1916 	REQUIRE(dst_initialized);
1917 	REQUIRE(VALID_KEY(key));
1918 
1919 	/* XXXVIX this switch statement is too sparse to gen a jump table. */
1920 	switch (key->key_alg) {
1921 	case DST_ALG_RSASHA1:
1922 	case DST_ALG_NSEC3RSASHA1:
1923 	case DST_ALG_RSASHA256:
1924 	case DST_ALG_RSASHA512:
1925 	case DST_ALG_DH:
1926 	case DST_ALG_ECDSA256:
1927 	case DST_ALG_ECDSA384:
1928 	case DST_ALG_ED25519:
1929 	case DST_ALG_ED448:
1930 		return (false);
1931 	case DST_ALG_HMACMD5:
1932 	case DST_ALG_HMACSHA1:
1933 	case DST_ALG_HMACSHA224:
1934 	case DST_ALG_HMACSHA256:
1935 	case DST_ALG_HMACSHA384:
1936 	case DST_ALG_HMACSHA512:
1937 	case DST_ALG_GSSAPI:
1938 		return (true);
1939 	default:
1940 		return (false);
1941 	}
1942 }
1943 
1944 /*%
1945  * Write key boolean metadata to a file pointer, preceded by 'tag'
1946  */
1947 static void
printbool(const dst_key_t * key,int type,const char * tag,FILE * stream)1948 printbool(const dst_key_t *key, int type, const char *tag, FILE *stream) {
1949 	isc_result_t result;
1950 	bool value = 0;
1951 
1952 	result = dst_key_getbool(key, type, &value);
1953 	if (result != ISC_R_SUCCESS) {
1954 		return;
1955 	}
1956 	fprintf(stream, "%s: %s\n", tag, value ? "yes" : "no");
1957 }
1958 
1959 /*%
1960  * Write key numeric metadata to a file pointer, preceded by 'tag'
1961  */
1962 static void
printnum(const dst_key_t * key,int type,const char * tag,FILE * stream)1963 printnum(const dst_key_t *key, int type, const char *tag, FILE *stream) {
1964 	isc_result_t result;
1965 	uint32_t value = 0;
1966 
1967 	result = dst_key_getnum(key, type, &value);
1968 	if (result != ISC_R_SUCCESS) {
1969 		return;
1970 	}
1971 	fprintf(stream, "%s: %u\n", tag, value);
1972 }
1973 
1974 /*%
1975  * Write key timing metadata to a file pointer, preceded by 'tag'
1976  */
1977 static void
printtime(const dst_key_t * key,int type,const char * tag,FILE * stream)1978 printtime(const dst_key_t *key, int type, const char *tag, FILE *stream) {
1979 	isc_result_t result;
1980 	char output[26]; /* Minimum buffer as per ctime_r() specification. */
1981 	isc_stdtime_t when;
1982 	char utc[sizeof("YYYYMMDDHHSSMM")];
1983 	isc_buffer_t b;
1984 	isc_region_t r;
1985 
1986 	result = dst_key_gettime(key, type, &when);
1987 	if (result == ISC_R_NOTFOUND) {
1988 		return;
1989 	}
1990 
1991 	isc_stdtime_tostring(when, output, sizeof(output));
1992 	isc_buffer_init(&b, utc, sizeof(utc));
1993 	result = dns_time32_totext(when, &b);
1994 	if (result != ISC_R_SUCCESS) {
1995 		goto error;
1996 	}
1997 
1998 	isc_buffer_usedregion(&b, &r);
1999 	fprintf(stream, "%s: %.*s (%s)\n", tag, (int)r.length, r.base, output);
2000 	return;
2001 
2002 error:
2003 	fprintf(stream, "%s: (set, unable to display)\n", tag);
2004 }
2005 
2006 /*%
2007  * Write key state metadata to a file pointer, preceded by 'tag'
2008  */
2009 static void
printstate(const dst_key_t * key,int type,const char * tag,FILE * stream)2010 printstate(const dst_key_t *key, int type, const char *tag, FILE *stream) {
2011 	isc_result_t result;
2012 	dst_key_state_t value = 0;
2013 
2014 	result = dst_key_getstate(key, type, &value);
2015 	if (result != ISC_R_SUCCESS) {
2016 		return;
2017 	}
2018 	fprintf(stream, "%s: %s\n", tag, keystates[value]);
2019 }
2020 
2021 /*%
2022  * Writes a key state to disk.
2023  */
2024 static isc_result_t
write_key_state(const dst_key_t * key,int type,const char * directory)2025 write_key_state(const dst_key_t *key, int type, const char *directory) {
2026 	FILE *fp;
2027 	isc_buffer_t fileb;
2028 	char filename[NAME_MAX];
2029 	isc_result_t ret;
2030 	isc_fsaccess_t access;
2031 
2032 	REQUIRE(VALID_KEY(key));
2033 
2034 	/*
2035 	 * Make the filename.
2036 	 */
2037 	isc_buffer_init(&fileb, filename, sizeof(filename));
2038 	ret = dst_key_buildfilename(key, DST_TYPE_STATE, directory, &fileb);
2039 	if (ret != ISC_R_SUCCESS) {
2040 		return (ret);
2041 	}
2042 
2043 	/*
2044 	 * Create public key file.
2045 	 */
2046 	if ((fp = fopen(filename, "w")) == NULL) {
2047 		return (DST_R_WRITEERROR);
2048 	}
2049 
2050 	if (issymmetric(key)) {
2051 		access = 0;
2052 		isc_fsaccess_add(ISC_FSACCESS_OWNER,
2053 				 ISC_FSACCESS_READ | ISC_FSACCESS_WRITE,
2054 				 &access);
2055 		(void)isc_fsaccess_set(filename, access);
2056 	}
2057 
2058 	/* Write key state */
2059 	if ((type & DST_TYPE_KEY) == 0) {
2060 		fprintf(fp, "; This is the state of key %d, for ", key->key_id);
2061 		ret = dns_name_print(key->key_name, fp);
2062 		if (ret != ISC_R_SUCCESS) {
2063 			fclose(fp);
2064 			return (ret);
2065 		}
2066 		fputc('\n', fp);
2067 
2068 		fprintf(fp, "Algorithm: %u\n", key->key_alg);
2069 		fprintf(fp, "Length: %u\n", key->key_size);
2070 
2071 		printnum(key, DST_NUM_LIFETIME, "Lifetime", fp);
2072 		printnum(key, DST_NUM_PREDECESSOR, "Predecessor", fp);
2073 		printnum(key, DST_NUM_SUCCESSOR, "Successor", fp);
2074 
2075 		printbool(key, DST_BOOL_KSK, "KSK", fp);
2076 		printbool(key, DST_BOOL_ZSK, "ZSK", fp);
2077 
2078 		printtime(key, DST_TIME_CREATED, "Generated", fp);
2079 		printtime(key, DST_TIME_PUBLISH, "Published", fp);
2080 		printtime(key, DST_TIME_ACTIVATE, "Active", fp);
2081 		printtime(key, DST_TIME_INACTIVE, "Retired", fp);
2082 		printtime(key, DST_TIME_REVOKE, "Revoked", fp);
2083 		printtime(key, DST_TIME_DELETE, "Removed", fp);
2084 		printtime(key, DST_TIME_DSPUBLISH, "DSPublish", fp);
2085 		printtime(key, DST_TIME_DSDELETE, "DSRemoved", fp);
2086 		printtime(key, DST_TIME_SYNCPUBLISH, "PublishCDS", fp);
2087 		printtime(key, DST_TIME_SYNCDELETE, "DeleteCDS", fp);
2088 
2089 		printnum(key, DST_NUM_DSPUBCOUNT, "DSPubCount", fp);
2090 		printnum(key, DST_NUM_DSDELCOUNT, "DSDelCount", fp);
2091 
2092 		printtime(key, DST_TIME_DNSKEY, "DNSKEYChange", fp);
2093 		printtime(key, DST_TIME_ZRRSIG, "ZRRSIGChange", fp);
2094 		printtime(key, DST_TIME_KRRSIG, "KRRSIGChange", fp);
2095 		printtime(key, DST_TIME_DS, "DSChange", fp);
2096 
2097 		printstate(key, DST_KEY_DNSKEY, "DNSKEYState", fp);
2098 		printstate(key, DST_KEY_ZRRSIG, "ZRRSIGState", fp);
2099 		printstate(key, DST_KEY_KRRSIG, "KRRSIGState", fp);
2100 		printstate(key, DST_KEY_DS, "DSState", fp);
2101 		printstate(key, DST_KEY_GOAL, "GoalState", fp);
2102 	}
2103 
2104 	fflush(fp);
2105 	if (ferror(fp)) {
2106 		ret = DST_R_WRITEERROR;
2107 	}
2108 	fclose(fp);
2109 
2110 	return (ret);
2111 }
2112 
2113 /*%
2114  * Writes a public key to disk in DNS format.
2115  */
2116 static isc_result_t
write_public_key(const dst_key_t * key,int type,const char * directory)2117 write_public_key(const dst_key_t *key, int type, const char *directory) {
2118 	FILE *fp;
2119 	isc_buffer_t keyb, textb, fileb, classb;
2120 	isc_region_t r;
2121 	char filename[NAME_MAX];
2122 	unsigned char key_array[DST_KEY_MAXSIZE];
2123 	char text_array[DST_KEY_MAXTEXTSIZE];
2124 	char class_array[10];
2125 	isc_result_t ret;
2126 	dns_rdata_t rdata = DNS_RDATA_INIT;
2127 	isc_fsaccess_t access;
2128 
2129 	REQUIRE(VALID_KEY(key));
2130 
2131 	isc_buffer_init(&keyb, key_array, sizeof(key_array));
2132 	isc_buffer_init(&textb, text_array, sizeof(text_array));
2133 	isc_buffer_init(&classb, class_array, sizeof(class_array));
2134 
2135 	ret = dst_key_todns(key, &keyb);
2136 	if (ret != ISC_R_SUCCESS) {
2137 		return (ret);
2138 	}
2139 
2140 	isc_buffer_usedregion(&keyb, &r);
2141 	dns_rdata_fromregion(&rdata, key->key_class, dns_rdatatype_dnskey, &r);
2142 
2143 	ret = dns_rdata_totext(&rdata, (dns_name_t *)NULL, &textb);
2144 	if (ret != ISC_R_SUCCESS) {
2145 		return (DST_R_INVALIDPUBLICKEY);
2146 	}
2147 
2148 	ret = dns_rdataclass_totext(key->key_class, &classb);
2149 	if (ret != ISC_R_SUCCESS) {
2150 		return (DST_R_INVALIDPUBLICKEY);
2151 	}
2152 
2153 	/*
2154 	 * Make the filename.
2155 	 */
2156 	isc_buffer_init(&fileb, filename, sizeof(filename));
2157 	ret = dst_key_buildfilename(key, DST_TYPE_PUBLIC, directory, &fileb);
2158 	if (ret != ISC_R_SUCCESS) {
2159 		return (ret);
2160 	}
2161 
2162 	/*
2163 	 * Create public key file.
2164 	 */
2165 	if ((fp = fopen(filename, "w")) == NULL) {
2166 		return (DST_R_WRITEERROR);
2167 	}
2168 
2169 	if (issymmetric(key)) {
2170 		access = 0;
2171 		isc_fsaccess_add(ISC_FSACCESS_OWNER,
2172 				 ISC_FSACCESS_READ | ISC_FSACCESS_WRITE,
2173 				 &access);
2174 		(void)isc_fsaccess_set(filename, access);
2175 	}
2176 
2177 	/* Write key information in comments */
2178 	if ((type & DST_TYPE_KEY) == 0) {
2179 		fprintf(fp, "; This is a %s%s-signing key, keyid %d, for ",
2180 			(key->key_flags & DNS_KEYFLAG_REVOKE) != 0 ? "revoked "
2181 								   : "",
2182 			(key->key_flags & DNS_KEYFLAG_KSK) != 0 ? "key"
2183 								: "zone",
2184 			key->key_id);
2185 		ret = dns_name_print(key->key_name, fp);
2186 		if (ret != ISC_R_SUCCESS) {
2187 			fclose(fp);
2188 			return (ret);
2189 		}
2190 		fputc('\n', fp);
2191 
2192 		printtime(key, DST_TIME_CREATED, "; Created", fp);
2193 		printtime(key, DST_TIME_PUBLISH, "; Publish", fp);
2194 		printtime(key, DST_TIME_ACTIVATE, "; Activate", fp);
2195 		printtime(key, DST_TIME_REVOKE, "; Revoke", fp);
2196 		printtime(key, DST_TIME_INACTIVE, "; Inactive", fp);
2197 		printtime(key, DST_TIME_DELETE, "; Delete", fp);
2198 		printtime(key, DST_TIME_SYNCPUBLISH, "; SyncPublish", fp);
2199 		printtime(key, DST_TIME_SYNCDELETE, "; SyncDelete", fp);
2200 	}
2201 
2202 	/* Now print the actual key */
2203 	ret = dns_name_print(key->key_name, fp);
2204 	fprintf(fp, " ");
2205 
2206 	if (key->key_ttl != 0) {
2207 		fprintf(fp, "%u ", key->key_ttl);
2208 	}
2209 
2210 	isc_buffer_usedregion(&classb, &r);
2211 	if ((unsigned)fwrite(r.base, 1, r.length, fp) != r.length) {
2212 		ret = DST_R_WRITEERROR;
2213 	}
2214 
2215 	if ((type & DST_TYPE_KEY) != 0) {
2216 		fprintf(fp, " KEY ");
2217 	} else {
2218 		fprintf(fp, " DNSKEY ");
2219 	}
2220 
2221 	isc_buffer_usedregion(&textb, &r);
2222 	if ((unsigned)fwrite(r.base, 1, r.length, fp) != r.length) {
2223 		ret = DST_R_WRITEERROR;
2224 	}
2225 
2226 	fputc('\n', fp);
2227 	fflush(fp);
2228 	if (ferror(fp)) {
2229 		ret = DST_R_WRITEERROR;
2230 	}
2231 	fclose(fp);
2232 
2233 	return (ret);
2234 }
2235 
2236 static isc_result_t
buildfilename(dns_name_t * name,dns_keytag_t id,unsigned int alg,unsigned int type,const char * directory,isc_buffer_t * out)2237 buildfilename(dns_name_t *name, dns_keytag_t id, unsigned int alg,
2238 	      unsigned int type, const char *directory, isc_buffer_t *out) {
2239 	const char *suffix = "";
2240 	isc_result_t result;
2241 
2242 	REQUIRE(out != NULL);
2243 	if ((type & DST_TYPE_PRIVATE) != 0) {
2244 		suffix = ".private";
2245 	} else if ((type & DST_TYPE_PUBLIC) != 0) {
2246 		suffix = ".key";
2247 	} else if ((type & DST_TYPE_STATE) != 0) {
2248 		suffix = ".state";
2249 	}
2250 
2251 	if (directory != NULL) {
2252 		if (isc_buffer_availablelength(out) < strlen(directory)) {
2253 			return (ISC_R_NOSPACE);
2254 		}
2255 		isc_buffer_putstr(out, directory);
2256 		if (strlen(directory) > 0U &&
2257 		    directory[strlen(directory) - 1] != '/') {
2258 			isc_buffer_putstr(out, "/");
2259 		}
2260 	}
2261 	if (isc_buffer_availablelength(out) < 1) {
2262 		return (ISC_R_NOSPACE);
2263 	}
2264 	isc_buffer_putstr(out, "K");
2265 	result = dns_name_tofilenametext(name, false, out);
2266 	if (result != ISC_R_SUCCESS) {
2267 		return (result);
2268 	}
2269 
2270 	return (isc_buffer_printf(out, "+%03d+%05d%s", alg, id, suffix));
2271 }
2272 
2273 static isc_result_t
computeid(dst_key_t * key)2274 computeid(dst_key_t *key) {
2275 	isc_buffer_t dnsbuf;
2276 	unsigned char dns_array[DST_KEY_MAXSIZE];
2277 	isc_region_t r;
2278 	isc_result_t ret;
2279 
2280 	isc_buffer_init(&dnsbuf, dns_array, sizeof(dns_array));
2281 	ret = dst_key_todns(key, &dnsbuf);
2282 	if (ret != ISC_R_SUCCESS) {
2283 		return (ret);
2284 	}
2285 
2286 	isc_buffer_usedregion(&dnsbuf, &r);
2287 	key->key_id = dst_region_computeid(&r);
2288 	key->key_rid = dst_region_computerid(&r);
2289 	return (ISC_R_SUCCESS);
2290 }
2291 
2292 static isc_result_t
frombuffer(const dns_name_t * name,unsigned int alg,unsigned int flags,unsigned int protocol,dns_rdataclass_t rdclass,isc_buffer_t * source,isc_mem_t * mctx,dst_key_t ** keyp)2293 frombuffer(const dns_name_t *name, unsigned int alg, unsigned int flags,
2294 	   unsigned int protocol, dns_rdataclass_t rdclass,
2295 	   isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp) {
2296 	dst_key_t *key;
2297 	isc_result_t ret;
2298 
2299 	REQUIRE(dns_name_isabsolute(name));
2300 	REQUIRE(source != NULL);
2301 	REQUIRE(mctx != NULL);
2302 	REQUIRE(keyp != NULL && *keyp == NULL);
2303 
2304 	key = get_key_struct(name, alg, flags, protocol, 0, rdclass, 0, mctx);
2305 	if (key == NULL) {
2306 		return (ISC_R_NOMEMORY);
2307 	}
2308 
2309 	if (isc_buffer_remaininglength(source) > 0) {
2310 		ret = algorithm_status(alg);
2311 		if (ret != ISC_R_SUCCESS) {
2312 			dst_key_free(&key);
2313 			return (ret);
2314 		}
2315 		if (key->func->fromdns == NULL) {
2316 			dst_key_free(&key);
2317 			return (DST_R_UNSUPPORTEDALG);
2318 		}
2319 
2320 		ret = key->func->fromdns(key, source);
2321 		if (ret != ISC_R_SUCCESS) {
2322 			dst_key_free(&key);
2323 			return (ret);
2324 		}
2325 	}
2326 
2327 	*keyp = key;
2328 	return (ISC_R_SUCCESS);
2329 }
2330 
2331 static isc_result_t
algorithm_status(unsigned int alg)2332 algorithm_status(unsigned int alg) {
2333 	REQUIRE(dst_initialized);
2334 
2335 	if (dst_algorithm_supported(alg)) {
2336 		return (ISC_R_SUCCESS);
2337 	}
2338 	return (DST_R_UNSUPPORTEDALG);
2339 }
2340 
2341 static isc_result_t
addsuffix(char * filename,int len,const char * odirname,const char * ofilename,const char * suffix)2342 addsuffix(char *filename, int len, const char *odirname, const char *ofilename,
2343 	  const char *suffix) {
2344 	int olen = strlen(ofilename);
2345 	int n;
2346 
2347 	if (olen > 1 && ofilename[olen - 1] == '.') {
2348 		olen -= 1;
2349 	} else if (olen > 8 && strcmp(ofilename + olen - 8, ".private") == 0) {
2350 		olen -= 8;
2351 	} else if (olen > 4 && strcmp(ofilename + olen - 4, ".key") == 0) {
2352 		olen -= 4;
2353 	}
2354 
2355 	if (odirname == NULL) {
2356 		n = snprintf(filename, len, "%.*s%s", olen, ofilename, suffix);
2357 	} else {
2358 		n = snprintf(filename, len, "%s/%.*s%s", odirname, olen,
2359 			     ofilename, suffix);
2360 	}
2361 	if (n < 0) {
2362 		return (ISC_R_FAILURE);
2363 	}
2364 	if (n >= len) {
2365 		return (ISC_R_NOSPACE);
2366 	}
2367 	return (ISC_R_SUCCESS);
2368 }
2369 
2370 isc_buffer_t *
dst_key_tkeytoken(const dst_key_t * key)2371 dst_key_tkeytoken(const dst_key_t *key) {
2372 	REQUIRE(VALID_KEY(key));
2373 	return (key->key_tkeytoken);
2374 }
2375 
2376 /*
2377  * A key is considered unused if it does not have any timing metadata set
2378  * other than "Created".
2379  *
2380  */
2381 bool
dst_key_is_unused(dst_key_t * key)2382 dst_key_is_unused(dst_key_t *key) {
2383 	isc_stdtime_t val;
2384 	dst_key_state_t st;
2385 	int state_type;
2386 	bool state_type_set;
2387 
2388 	REQUIRE(VALID_KEY(key));
2389 
2390 	/*
2391 	 * None of the key timing metadata, except Created, may be set.  Key
2392 	 * state times may be set only if their respective state is HIDDEN.
2393 	 */
2394 	for (int i = 0; i < DST_MAX_TIMES + 1; i++) {
2395 		state_type_set = false;
2396 
2397 		switch (i) {
2398 		case DST_TIME_CREATED:
2399 			break;
2400 		case DST_TIME_DNSKEY:
2401 			state_type = DST_KEY_DNSKEY;
2402 			state_type_set = true;
2403 			break;
2404 		case DST_TIME_ZRRSIG:
2405 			state_type = DST_KEY_ZRRSIG;
2406 			state_type_set = true;
2407 			break;
2408 		case DST_TIME_KRRSIG:
2409 			state_type = DST_KEY_KRRSIG;
2410 			state_type_set = true;
2411 			break;
2412 		case DST_TIME_DS:
2413 			state_type = DST_KEY_DS;
2414 			state_type_set = true;
2415 			break;
2416 		default:
2417 			break;
2418 		}
2419 
2420 		/* Created is fine. */
2421 		if (i == DST_TIME_CREATED) {
2422 			continue;
2423 		}
2424 		/* No such timing metadata found, that is fine too. */
2425 		if (dst_key_gettime(key, i, &val) == ISC_R_NOTFOUND) {
2426 			continue;
2427 		}
2428 		/*
2429 		 * Found timing metadata and it is not related to key states.
2430 		 * This key is used.
2431 		 */
2432 		if (!state_type_set) {
2433 			return (false);
2434 		}
2435 		/*
2436 		 * If the state is not HIDDEN, the key is in use.
2437 		 * If the state is not set, this is odd and we default to NA.
2438 		 */
2439 		if (dst_key_getstate(key, state_type, &st) != ISC_R_SUCCESS) {
2440 			st = DST_KEY_STATE_NA;
2441 		}
2442 		if (st != DST_KEY_STATE_HIDDEN) {
2443 			return (false);
2444 		}
2445 	}
2446 	/* This key is unused. */
2447 	return (true);
2448 }
2449 
2450 isc_result_t
dst_key_role(dst_key_t * key,bool * ksk,bool * zsk)2451 dst_key_role(dst_key_t *key, bool *ksk, bool *zsk) {
2452 	bool k = false, z = false;
2453 	isc_result_t result, ret = ISC_R_SUCCESS;
2454 
2455 	if (ksk != NULL) {
2456 		result = dst_key_getbool(key, DST_BOOL_KSK, &k);
2457 		if (result == ISC_R_SUCCESS) {
2458 			*ksk = k;
2459 		} else {
2460 			*ksk = ((dst_key_flags(key) & DNS_KEYFLAG_KSK) != 0);
2461 			ret = result;
2462 		}
2463 	}
2464 
2465 	if (zsk != NULL) {
2466 		result = dst_key_getbool(key, DST_BOOL_ZSK, &z);
2467 		if (result == ISC_R_SUCCESS) {
2468 			*zsk = z;
2469 		} else {
2470 			*zsk = ((dst_key_flags(key) & DNS_KEYFLAG_KSK) == 0);
2471 			ret = result;
2472 		}
2473 	}
2474 	return (ret);
2475 }
2476 
2477 /* Hints on key whether it can be published and/or used for signing. */
2478 
2479 bool
dst_key_is_published(dst_key_t * key,isc_stdtime_t now,isc_stdtime_t * publish)2480 dst_key_is_published(dst_key_t *key, isc_stdtime_t now,
2481 		     isc_stdtime_t *publish) {
2482 	dst_key_state_t state;
2483 	isc_result_t result;
2484 	isc_stdtime_t when;
2485 	bool state_ok = true, time_ok = false;
2486 
2487 	REQUIRE(VALID_KEY(key));
2488 
2489 	result = dst_key_gettime(key, DST_TIME_PUBLISH, &when);
2490 	if (result == ISC_R_SUCCESS) {
2491 		*publish = when;
2492 		time_ok = (when <= now);
2493 	}
2494 
2495 	/* Check key states:
2496 	 * If the DNSKEY state is RUMOURED or OMNIPRESENT, it means it
2497 	 * should be published.
2498 	 */
2499 	result = dst_key_getstate(key, DST_KEY_DNSKEY, &state);
2500 	if (result == ISC_R_SUCCESS) {
2501 		state_ok = ((state == DST_KEY_STATE_RUMOURED) ||
2502 			    (state == DST_KEY_STATE_OMNIPRESENT));
2503 		/*
2504 		 * Key states trump timing metadata.
2505 		 * Ignore inactive time.
2506 		 */
2507 		time_ok = true;
2508 	}
2509 
2510 	return (state_ok && time_ok);
2511 }
2512 
2513 bool
dst_key_is_active(dst_key_t * key,isc_stdtime_t now)2514 dst_key_is_active(dst_key_t *key, isc_stdtime_t now) {
2515 	dst_key_state_t state;
2516 	isc_result_t result;
2517 	isc_stdtime_t when = 0;
2518 	bool ksk = false, zsk = false, inactive = false;
2519 	bool ds_ok = true, zrrsig_ok = true, time_ok = false;
2520 
2521 	REQUIRE(VALID_KEY(key));
2522 
2523 	result = dst_key_gettime(key, DST_TIME_INACTIVE, &when);
2524 	if (result == ISC_R_SUCCESS) {
2525 		inactive = (when <= now);
2526 	}
2527 
2528 	result = dst_key_gettime(key, DST_TIME_ACTIVATE, &when);
2529 	if (result == ISC_R_SUCCESS) {
2530 		time_ok = (when <= now);
2531 	}
2532 
2533 	(void)dst_key_role(key, &ksk, &zsk);
2534 
2535 	/* Check key states:
2536 	 * KSK: If the DS is RUMOURED or OMNIPRESENT the key is considered
2537 	 * active.
2538 	 */
2539 	if (ksk) {
2540 		result = dst_key_getstate(key, DST_KEY_DS, &state);
2541 		if (result == ISC_R_SUCCESS) {
2542 			ds_ok = ((state == DST_KEY_STATE_RUMOURED) ||
2543 				 (state == DST_KEY_STATE_OMNIPRESENT));
2544 			/*
2545 			 * Key states trump timing metadata.
2546 			 * Ignore inactive time.
2547 			 */
2548 			time_ok = true;
2549 			inactive = false;
2550 		}
2551 	}
2552 	/*
2553 	 * ZSK: If the ZRRSIG state is RUMOURED or OMNIPRESENT, it means the
2554 	 * key is active.
2555 	 */
2556 	if (zsk) {
2557 		result = dst_key_getstate(key, DST_KEY_ZRRSIG, &state);
2558 		if (result == ISC_R_SUCCESS) {
2559 			zrrsig_ok = ((state == DST_KEY_STATE_RUMOURED) ||
2560 				     (state == DST_KEY_STATE_OMNIPRESENT));
2561 			/*
2562 			 * Key states trump timing metadata.
2563 			 * Ignore inactive time.
2564 			 */
2565 			time_ok = true;
2566 			inactive = false;
2567 		}
2568 	}
2569 	return (ds_ok && zrrsig_ok && time_ok && !inactive);
2570 }
2571 
2572 bool
dst_key_is_signing(dst_key_t * key,int role,isc_stdtime_t now,isc_stdtime_t * active)2573 dst_key_is_signing(dst_key_t *key, int role, isc_stdtime_t now,
2574 		   isc_stdtime_t *active) {
2575 	dst_key_state_t state;
2576 	isc_result_t result;
2577 	isc_stdtime_t when = 0;
2578 	bool ksk = false, zsk = false, inactive = false;
2579 	bool krrsig_ok = true, zrrsig_ok = true, time_ok = false;
2580 
2581 	REQUIRE(VALID_KEY(key));
2582 
2583 	result = dst_key_gettime(key, DST_TIME_INACTIVE, &when);
2584 	if (result == ISC_R_SUCCESS) {
2585 		inactive = (when <= now);
2586 	}
2587 
2588 	result = dst_key_gettime(key, DST_TIME_ACTIVATE, &when);
2589 	if (result == ISC_R_SUCCESS) {
2590 		*active = when;
2591 		time_ok = (when <= now);
2592 	}
2593 
2594 	(void)dst_key_role(key, &ksk, &zsk);
2595 
2596 	/* Check key states:
2597 	 * If the RRSIG state is RUMOURED or OMNIPRESENT, it means the key
2598 	 * is active.
2599 	 */
2600 	if (ksk && role == DST_BOOL_KSK) {
2601 		result = dst_key_getstate(key, DST_KEY_KRRSIG, &state);
2602 		if (result == ISC_R_SUCCESS) {
2603 			krrsig_ok = ((state == DST_KEY_STATE_RUMOURED) ||
2604 				     (state == DST_KEY_STATE_OMNIPRESENT));
2605 			/*
2606 			 * Key states trump timing metadata.
2607 			 * Ignore inactive time.
2608 			 */
2609 			time_ok = true;
2610 			inactive = false;
2611 		}
2612 	} else if (zsk && role == DST_BOOL_ZSK) {
2613 		result = dst_key_getstate(key, DST_KEY_ZRRSIG, &state);
2614 		if (result == ISC_R_SUCCESS) {
2615 			zrrsig_ok = ((state == DST_KEY_STATE_RUMOURED) ||
2616 				     (state == DST_KEY_STATE_OMNIPRESENT));
2617 			/*
2618 			 * Key states trump timing metadata.
2619 			 * Ignore inactive time.
2620 			 */
2621 			time_ok = true;
2622 			inactive = false;
2623 		}
2624 	}
2625 	return (krrsig_ok && zrrsig_ok && time_ok && !inactive);
2626 }
2627 
2628 bool
dst_key_is_revoked(dst_key_t * key,isc_stdtime_t now,isc_stdtime_t * revoke)2629 dst_key_is_revoked(dst_key_t *key, isc_stdtime_t now, isc_stdtime_t *revoke) {
2630 	isc_result_t result;
2631 	isc_stdtime_t when = 0;
2632 	bool time_ok = false;
2633 
2634 	REQUIRE(VALID_KEY(key));
2635 
2636 	result = dst_key_gettime(key, DST_TIME_REVOKE, &when);
2637 	if (result == ISC_R_SUCCESS) {
2638 		*revoke = when;
2639 		time_ok = (when <= now);
2640 	}
2641 
2642 	return (time_ok);
2643 }
2644 
2645 bool
dst_key_is_removed(dst_key_t * key,isc_stdtime_t now,isc_stdtime_t * remove)2646 dst_key_is_removed(dst_key_t *key, isc_stdtime_t now, isc_stdtime_t *remove) {
2647 	dst_key_state_t state;
2648 	isc_result_t result;
2649 	isc_stdtime_t when = 0;
2650 	bool state_ok = true, time_ok = false;
2651 
2652 	REQUIRE(VALID_KEY(key));
2653 
2654 	if (dst_key_is_unused(key)) {
2655 		/* This key was never used. */
2656 		return (false);
2657 	}
2658 
2659 	result = dst_key_gettime(key, DST_TIME_DELETE, &when);
2660 	if (result == ISC_R_SUCCESS) {
2661 		*remove = when;
2662 		time_ok = (when <= now);
2663 	}
2664 
2665 	/* Check key states:
2666 	 * If the DNSKEY state is UNRETENTIVE or HIDDEN, it means the key
2667 	 * should not be published.
2668 	 */
2669 	result = dst_key_getstate(key, DST_KEY_DNSKEY, &state);
2670 	if (result == ISC_R_SUCCESS) {
2671 		state_ok = ((state == DST_KEY_STATE_UNRETENTIVE) ||
2672 			    (state == DST_KEY_STATE_HIDDEN));
2673 		/*
2674 		 * Key states trump timing metadata.
2675 		 * Ignore delete time.
2676 		 */
2677 		time_ok = true;
2678 	}
2679 
2680 	return (state_ok && time_ok);
2681 }
2682 
2683 dst_key_state_t
dst_key_goal(dst_key_t * key)2684 dst_key_goal(dst_key_t *key) {
2685 	dst_key_state_t state;
2686 	isc_result_t result;
2687 
2688 	REQUIRE(VALID_KEY(key));
2689 
2690 	result = dst_key_getstate(key, DST_KEY_GOAL, &state);
2691 	if (result == ISC_R_SUCCESS) {
2692 		return (state);
2693 	}
2694 	return (DST_KEY_STATE_HIDDEN);
2695 }
2696 
2697 bool
dst_key_haskasp(dst_key_t * key)2698 dst_key_haskasp(dst_key_t *key) {
2699 	REQUIRE(VALID_KEY(key));
2700 
2701 	return (key->kasp);
2702 }
2703 
2704 void
dst_key_copy_metadata(dst_key_t * to,dst_key_t * from)2705 dst_key_copy_metadata(dst_key_t *to, dst_key_t *from) {
2706 	dst_key_state_t state;
2707 	isc_stdtime_t when;
2708 	uint32_t num;
2709 	bool yesno;
2710 	isc_result_t result;
2711 
2712 	REQUIRE(VALID_KEY(to));
2713 	REQUIRE(VALID_KEY(from));
2714 
2715 	for (int i = 0; i < DST_MAX_TIMES + 1; i++) {
2716 		result = dst_key_gettime(from, i, &when);
2717 		if (result == ISC_R_SUCCESS) {
2718 			dst_key_settime(to, i, when);
2719 		} else {
2720 			dst_key_unsettime(to, i);
2721 		}
2722 	}
2723 
2724 	for (int i = 0; i < DST_MAX_NUMERIC + 1; i++) {
2725 		result = dst_key_getnum(from, i, &num);
2726 		if (result == ISC_R_SUCCESS) {
2727 			dst_key_setnum(to, i, num);
2728 		} else {
2729 			dst_key_unsetnum(to, i);
2730 		}
2731 	}
2732 
2733 	for (int i = 0; i < DST_MAX_BOOLEAN + 1; i++) {
2734 		result = dst_key_getbool(from, i, &yesno);
2735 		if (result == ISC_R_SUCCESS) {
2736 			dst_key_setbool(to, i, yesno);
2737 		} else {
2738 			dst_key_unsetbool(to, i);
2739 		}
2740 	}
2741 
2742 	for (int i = 0; i < DST_MAX_KEYSTATES + 1; i++) {
2743 		result = dst_key_getstate(from, i, &state);
2744 		if (result == ISC_R_SUCCESS) {
2745 			dst_key_setstate(to, i, state);
2746 		} else {
2747 			dst_key_unsetstate(to, i);
2748 		}
2749 	}
2750 }
2751