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