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