1 /* $NetBSD: dst_api.c,v 1.11 2014/12/10 04:37:58 christos Exp $ */
4 * Portions Copyright (C) 2004-2014 Internet Systems Consortium, Inc. ("ISC")
5 * Portions Copyright (C) 1999-2003 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
12 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
13 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
14 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
17 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
21 * Permission to use, copy, modify, and/or distribute this software for any
22 * purpose with or without fee is hereby granted, provided that the above
23 * copyright notice and this permission notice appear in all copies.
25 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
26 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
27 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
28 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
29 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
30 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
31 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
35 * Principal Author: Brian Wellington
36 * Id: dst_api.c,v 1.65 2011/10/20 21:20:02 marka Exp
46 #include <isc/buffer.h>
48 #include <isc/entropy.h>
49 #include <isc/fsaccess.h>
50 #include <isc/hmacsha.h>
54 #include <isc/platform.h>
55 #include <isc/print.h>
56 #include <isc/refcount.h>
57 #include <isc/random.h>
58 #include <isc/string.h>
63 #define DST_KEY_INTERNAL
65 #include <dns/fixedname.h>
66 #include <dns/keyvalues.h>
68 #include <dns/rdata.h>
69 #include <dns/rdataclass.h>
71 #include <dns/types.h>
73 #include <dst/result.h>
75 #include "dst_internal.h"
77 #define DST_AS_STR(t) ((t).value.as_textregion.base)
79 static dst_func_t
*dst_t_func
[DST_MAX_ALGS
];
80 static isc_entropy_t
*dst_entropy_pool
= NULL
;
81 static unsigned int dst_entropy_flags
= 0;
82 static isc_boolean_t dst_initialized
= ISC_FALSE
;
84 void gss_log(int level
, const char *fmt
, ...) ISC_FORMAT_PRINTF(2, 3);
86 isc_mem_t
*dst__memory_pool
= NULL
;
91 static dst_key_t
* get_key_struct(dns_name_t
*name
,
94 unsigned int protocol
,
96 dns_rdataclass_t rdclass
,
99 static isc_result_t
write_public_key(const dst_key_t
*key
, int type
,
100 const char *directory
);
101 static isc_result_t
buildfilename(dns_name_t
*name
,
105 const char *directory
,
107 static isc_result_t
computeid(dst_key_t
*key
);
108 static isc_result_t
frombuffer(dns_name_t
*name
,
111 unsigned int protocol
,
112 dns_rdataclass_t rdclass
,
113 isc_buffer_t
*source
,
117 static isc_result_t
algorithm_status(unsigned int alg
);
119 static isc_result_t
addsuffix(char *filename
, int len
,
120 const char *dirname
, const char *ofilename
,
126 if (result != ISC_R_SUCCESS) \
128 } while (/*CONSTCOND*/0)
130 #define CHECKALG(alg) \
133 _r = algorithm_status(alg); \
134 if (_r != ISC_R_SUCCESS) \
136 } while (/*CONSTCOND*/0); \
140 default_memalloc(void *arg
, size_t size
) {
144 return (malloc(size
));
148 default_memfree(void *arg
, void *ptr
) {
155 dst_lib_init(isc_mem_t
*mctx
, isc_entropy_t
*ectx
, unsigned int eflags
) {
156 return (dst_lib_init2(mctx
, ectx
, NULL
, eflags
));
160 dst_lib_init2(isc_mem_t
*mctx
, isc_entropy_t
*ectx
,
161 const char *engine
, unsigned int eflags
) {
164 REQUIRE(mctx
!= NULL
);
166 REQUIRE(dst_initialized
== ISC_FALSE
);
168 #if !defined(OPENSSL) && !defined(PKCS11CRYPTO)
172 dst__memory_pool
= NULL
;
177 * When using --with-openssl, there seems to be no good way of not
178 * leaking memory due to the openssl error handling mechanism.
179 * Avoid assertions by using a local memory context and not checking
180 * for leaks on exit. Note: as there are leaks we cannot use
181 * ISC_MEMFLAG_INTERNAL as it will free up memory still being used
184 result
= isc_mem_createx2(0, 0, default_memalloc
, default_memfree
,
185 NULL
, &dst__memory_pool
, 0);
186 if (result
!= ISC_R_SUCCESS
)
188 isc_mem_setname(dst__memory_pool
, "dst", NULL
);
189 #ifndef OPENSSL_LEAKS
190 isc_mem_setdestroycheck(dst__memory_pool
, ISC_FALSE
);
193 isc_mem_attach(mctx
, &dst__memory_pool
);
196 isc_entropy_attach(ectx
, &dst_entropy_pool
);
197 dst_entropy_flags
= eflags
;
200 dst_result_register();
202 memset(dst_t_func
, 0, sizeof(dst_t_func
));
203 RETERR(dst__hmacmd5_init(&dst_t_func
[DST_ALG_HMACMD5
]));
204 RETERR(dst__hmacsha1_init(&dst_t_func
[DST_ALG_HMACSHA1
]));
205 RETERR(dst__hmacsha224_init(&dst_t_func
[DST_ALG_HMACSHA224
]));
206 RETERR(dst__hmacsha256_init(&dst_t_func
[DST_ALG_HMACSHA256
]));
207 RETERR(dst__hmacsha384_init(&dst_t_func
[DST_ALG_HMACSHA384
]));
208 RETERR(dst__hmacsha512_init(&dst_t_func
[DST_ALG_HMACSHA512
]));
210 RETERR(dst__openssl_init(engine
));
211 RETERR(dst__opensslrsa_init(&dst_t_func
[DST_ALG_RSAMD5
],
213 RETERR(dst__opensslrsa_init(&dst_t_func
[DST_ALG_RSASHA1
],
215 RETERR(dst__opensslrsa_init(&dst_t_func
[DST_ALG_NSEC3RSASHA1
],
216 DST_ALG_NSEC3RSASHA1
));
217 RETERR(dst__opensslrsa_init(&dst_t_func
[DST_ALG_RSASHA256
],
219 RETERR(dst__opensslrsa_init(&dst_t_func
[DST_ALG_RSASHA512
],
221 #ifdef HAVE_OPENSSL_DSA
222 RETERR(dst__openssldsa_init(&dst_t_func
[DST_ALG_DSA
]));
223 RETERR(dst__openssldsa_init(&dst_t_func
[DST_ALG_NSEC3DSA
]));
225 RETERR(dst__openssldh_init(&dst_t_func
[DST_ALG_DH
]));
226 #ifdef HAVE_OPENSSL_GOST
227 RETERR(dst__opensslgost_init(&dst_t_func
[DST_ALG_ECCGOST
]));
229 #ifdef HAVE_OPENSSL_ECDSA
230 RETERR(dst__opensslecdsa_init(&dst_t_func
[DST_ALG_ECDSA256
]));
231 RETERR(dst__opensslecdsa_init(&dst_t_func
[DST_ALG_ECDSA384
]));
234 RETERR(dst__pkcs11_init(mctx
, engine
));
235 RETERR(dst__pkcs11rsa_init(&dst_t_func
[DST_ALG_RSAMD5
]));
236 RETERR(dst__pkcs11rsa_init(&dst_t_func
[DST_ALG_RSASHA1
]));
237 RETERR(dst__pkcs11rsa_init(&dst_t_func
[DST_ALG_NSEC3RSASHA1
]));
238 RETERR(dst__pkcs11rsa_init(&dst_t_func
[DST_ALG_RSASHA256
]));
239 RETERR(dst__pkcs11rsa_init(&dst_t_func
[DST_ALG_RSASHA512
]));
240 RETERR(dst__pkcs11dsa_init(&dst_t_func
[DST_ALG_DSA
]));
241 RETERR(dst__pkcs11dsa_init(&dst_t_func
[DST_ALG_NSEC3DSA
]));
242 RETERR(dst__pkcs11dh_init(&dst_t_func
[DST_ALG_DH
]));
243 #ifdef HAVE_PKCS11_ECDSA
244 RETERR(dst__pkcs11ecdsa_init(&dst_t_func
[DST_ALG_ECDSA256
]));
245 RETERR(dst__pkcs11ecdsa_init(&dst_t_func
[DST_ALG_ECDSA384
]));
247 #ifdef HAVE_PKCS11_GOST
248 RETERR(dst__pkcs11gost_init(&dst_t_func
[DST_ALG_ECCGOST
]));
250 #endif /* if OPENSSL, elif PKCS11CRYPTO */
252 RETERR(dst__gssapi_init(&dst_t_func
[DST_ALG_GSSAPI
]));
254 dst_initialized
= ISC_TRUE
;
255 return (ISC_R_SUCCESS
);
258 /* avoid immediate crash! */
259 dst_initialized
= ISC_TRUE
;
265 dst_lib_destroy(void) {
267 RUNTIME_CHECK(dst_initialized
== ISC_TRUE
);
268 dst_initialized
= ISC_FALSE
;
270 for (i
= 0; i
< DST_MAX_ALGS
; i
++)
271 if (dst_t_func
[i
] != NULL
&& dst_t_func
[i
]->cleanup
!= NULL
)
272 dst_t_func
[i
]->cleanup();
274 dst__openssl_destroy();
276 (void) dst__pkcs11_destroy();
277 #endif /* if OPENSSL, elif PKCS11CRYPTO */
278 if (dst__memory_pool
!= NULL
)
279 isc_mem_detach(&dst__memory_pool
);
280 if (dst_entropy_pool
!= NULL
)
281 isc_entropy_detach(&dst_entropy_pool
);
285 dst_algorithm_supported(unsigned int alg
) {
286 REQUIRE(dst_initialized
== ISC_TRUE
);
288 if (alg
>= DST_MAX_ALGS
|| dst_t_func
[alg
] == NULL
)
294 dst_ds_digest_supported(unsigned int digest_type
) {
295 #if defined(HAVE_OPENSSL_GOST) || defined(HAVE_PKCS11_GOST)
296 return (ISC_TF(digest_type
== DNS_DSDIGEST_SHA1
||
297 digest_type
== DNS_DSDIGEST_SHA256
||
298 digest_type
== DNS_DSDIGEST_GOST
||
299 digest_type
== DNS_DSDIGEST_SHA384
));
301 return (ISC_TF(digest_type
== DNS_DSDIGEST_SHA1
||
302 digest_type
== DNS_DSDIGEST_SHA256
||
303 digest_type
== DNS_DSDIGEST_SHA384
));
308 dst_context_create(dst_key_t
*key
, isc_mem_t
*mctx
, dst_context_t
**dctxp
) {
309 return (dst_context_create4(key
, mctx
, DNS_LOGCATEGORY_GENERAL
,
310 ISC_TRUE
, 0, dctxp
));
314 dst_context_create2(dst_key_t
*key
, isc_mem_t
*mctx
,
315 isc_logcategory_t
*category
, dst_context_t
**dctxp
)
317 return (dst_context_create4(key
, mctx
, category
, ISC_TRUE
, 0, dctxp
));
321 dst_context_create3(dst_key_t
*key
, isc_mem_t
*mctx
,
322 isc_logcategory_t
*category
, isc_boolean_t useforsigning
,
323 dst_context_t
**dctxp
)
325 return (dst_context_create4(key
, mctx
, category
,
326 useforsigning
, 0, dctxp
));
330 dst_context_create4(dst_key_t
*key
, isc_mem_t
*mctx
,
331 isc_logcategory_t
*category
, isc_boolean_t useforsigning
,
332 int maxbits
, dst_context_t
**dctxp
)
337 REQUIRE(dst_initialized
== ISC_TRUE
);
338 REQUIRE(VALID_KEY(key
));
339 REQUIRE(mctx
!= NULL
);
340 REQUIRE(dctxp
!= NULL
&& *dctxp
== NULL
);
342 if (key
->func
->createctx
== NULL
&&
343 key
->func
->createctx2
== NULL
)
344 return (DST_R_UNSUPPORTEDALG
);
345 if (key
->keydata
.generic
== NULL
)
346 return (DST_R_NULLKEY
);
348 dctx
= isc_mem_get(mctx
, sizeof(dst_context_t
));
350 return (ISC_R_NOMEMORY
);
353 dctx
->category
= category
;
357 dctx
->use
= DO_VERIFY
;
358 if (key
->func
->createctx2
!= NULL
)
359 result
= key
->func
->createctx2(key
, maxbits
, dctx
);
361 result
= key
->func
->createctx(key
, dctx
);
362 if (result
!= ISC_R_SUCCESS
) {
363 isc_mem_put(mctx
, dctx
, sizeof(dst_context_t
));
366 dctx
->magic
= CTX_MAGIC
;
368 return (ISC_R_SUCCESS
);
372 dst_context_destroy(dst_context_t
**dctxp
) {
375 REQUIRE(dctxp
!= NULL
&& VALID_CTX(*dctxp
));
378 INSIST(dctx
->key
->func
->destroyctx
!= NULL
);
379 dctx
->key
->func
->destroyctx(dctx
);
381 isc_mem_put(dctx
->mctx
, dctx
, sizeof(dst_context_t
));
386 dst_context_adddata(dst_context_t
*dctx
, const isc_region_t
*data
) {
387 REQUIRE(VALID_CTX(dctx
));
388 REQUIRE(data
!= NULL
);
389 INSIST(dctx
->key
->func
->adddata
!= NULL
);
391 return (dctx
->key
->func
->adddata(dctx
, data
));
395 dst_context_sign(dst_context_t
*dctx
, isc_buffer_t
*sig
) {
398 REQUIRE(VALID_CTX(dctx
));
399 REQUIRE(sig
!= NULL
);
402 CHECKALG(key
->key_alg
);
403 if (key
->keydata
.generic
== NULL
)
404 return (DST_R_NULLKEY
);
406 if (key
->func
->sign
== NULL
)
407 return (DST_R_NOTPRIVATEKEY
);
408 if (key
->func
->isprivate
== NULL
||
409 key
->func
->isprivate(key
) == ISC_FALSE
)
410 return (DST_R_NOTPRIVATEKEY
);
412 return (key
->func
->sign(dctx
, sig
));
416 dst_context_verify(dst_context_t
*dctx
, isc_region_t
*sig
) {
417 REQUIRE(VALID_CTX(dctx
));
418 REQUIRE(sig
!= NULL
);
420 CHECKALG(dctx
->key
->key_alg
);
421 if (dctx
->key
->keydata
.generic
== NULL
)
422 return (DST_R_NULLKEY
);
423 if (dctx
->key
->func
->verify
== NULL
)
424 return (DST_R_NOTPUBLICKEY
);
426 return (dctx
->key
->func
->verify(dctx
, sig
));
430 dst_context_verify2(dst_context_t
*dctx
, unsigned int maxbits
,
433 REQUIRE(VALID_CTX(dctx
));
434 REQUIRE(sig
!= NULL
);
436 CHECKALG(dctx
->key
->key_alg
);
437 if (dctx
->key
->keydata
.generic
== NULL
)
438 return (DST_R_NULLKEY
);
439 if (dctx
->key
->func
->verify
== NULL
&&
440 dctx
->key
->func
->verify2
== NULL
)
441 return (DST_R_NOTPUBLICKEY
);
443 return (dctx
->key
->func
->verify2
!= NULL
?
444 dctx
->key
->func
->verify2(dctx
, maxbits
, sig
) :
445 dctx
->key
->func
->verify(dctx
, sig
));
449 dst_key_computesecret(const dst_key_t
*pub
, const dst_key_t
*priv
,
450 isc_buffer_t
*secret
)
452 REQUIRE(dst_initialized
== ISC_TRUE
);
453 REQUIRE(VALID_KEY(pub
) && VALID_KEY(priv
));
454 REQUIRE(secret
!= NULL
);
456 CHECKALG(pub
->key_alg
);
457 CHECKALG(priv
->key_alg
);
459 if (pub
->keydata
.generic
== NULL
|| priv
->keydata
.generic
== NULL
)
460 return (DST_R_NULLKEY
);
462 if (pub
->key_alg
!= priv
->key_alg
||
463 pub
->func
->computesecret
== NULL
||
464 priv
->func
->computesecret
== NULL
)
465 return (DST_R_KEYCANNOTCOMPUTESECRET
);
467 if (dst_key_isprivate(priv
) == ISC_FALSE
)
468 return (DST_R_NOTPRIVATEKEY
);
470 return (pub
->func
->computesecret(pub
, priv
, secret
));
474 dst_key_tofile(const dst_key_t
*key
, int type
, const char *directory
) {
475 isc_result_t ret
= ISC_R_SUCCESS
;
477 REQUIRE(dst_initialized
== ISC_TRUE
);
478 REQUIRE(VALID_KEY(key
));
479 REQUIRE((type
& (DST_TYPE_PRIVATE
| DST_TYPE_PUBLIC
)) != 0);
481 CHECKALG(key
->key_alg
);
483 if (key
->func
->tofile
== NULL
)
484 return (DST_R_UNSUPPORTEDALG
);
486 if (type
& DST_TYPE_PUBLIC
) {
487 ret
= write_public_key(key
, type
, directory
);
488 if (ret
!= ISC_R_SUCCESS
)
492 if ((type
& DST_TYPE_PRIVATE
) &&
493 (key
->key_flags
& DNS_KEYFLAG_TYPEMASK
) != DNS_KEYTYPE_NOKEY
)
494 return (key
->func
->tofile(key
, directory
));
496 return (ISC_R_SUCCESS
);
500 dst_key_setexternal(dst_key_t
*key
, isc_boolean_t value
) {
501 key
->external
= value
;
505 dst_key_isexternal(dst_key_t
*key
) {
506 return (key
->external
);
510 dst_key_fromfile(dns_name_t
*name
, dns_keytag_t id
,
511 unsigned int alg
, int type
, const char *directory
,
512 isc_mem_t
*mctx
, dst_key_t
**keyp
)
514 char filename
[ISC_DIR_NAMEMAX
];
519 REQUIRE(dst_initialized
== ISC_TRUE
);
520 REQUIRE(dns_name_isabsolute(name
));
521 REQUIRE((type
& (DST_TYPE_PRIVATE
| DST_TYPE_PUBLIC
)) != 0);
522 REQUIRE(mctx
!= NULL
);
523 REQUIRE(keyp
!= NULL
&& *keyp
== NULL
);
527 isc_buffer_init(&b
, filename
, sizeof(filename
));
528 result
= buildfilename(name
, id
, alg
, type
, directory
, &b
);
529 if (result
!= ISC_R_SUCCESS
)
533 result
= dst_key_fromnamedfile(filename
, NULL
, type
, mctx
, &key
);
534 if (result
!= ISC_R_SUCCESS
)
537 result
= computeid(key
);
538 if (result
!= ISC_R_SUCCESS
) {
543 if (!dns_name_equal(name
, key
->key_name
) || id
!= key
->key_id
||
544 alg
!= key
->key_alg
) {
546 return (DST_R_INVALIDPRIVATEKEY
);
550 return (ISC_R_SUCCESS
);
554 dst_key_fromnamedfile(const char *filename
, const char *dirname
,
555 int type
, isc_mem_t
*mctx
, dst_key_t
**keyp
)
558 dst_key_t
*pubkey
= NULL
, *key
= NULL
;
559 char *newfilename
= NULL
;
560 int newfilenamelen
= 0;
561 isc_lex_t
*lex
= NULL
;
563 REQUIRE(dst_initialized
== ISC_TRUE
);
564 REQUIRE(filename
!= NULL
);
565 REQUIRE((type
& (DST_TYPE_PRIVATE
| DST_TYPE_PUBLIC
)) != 0);
566 REQUIRE(mctx
!= NULL
);
567 REQUIRE(keyp
!= NULL
&& *keyp
== NULL
);
569 /* If an absolute path is specified, don't use the key directory */
571 if (filename
[0] == '/')
574 if (filename
[0] == '/' || filename
[0] == '\\')
578 newfilenamelen
= strlen(filename
) + 5;
580 newfilenamelen
+= strlen(dirname
) + 1;
581 newfilename
= isc_mem_get(mctx
, newfilenamelen
);
582 if (newfilename
== NULL
)
583 return (ISC_R_NOMEMORY
);
584 result
= addsuffix(newfilename
, newfilenamelen
,
585 dirname
, filename
, ".key");
586 INSIST(result
== ISC_R_SUCCESS
);
588 result
= dst_key_read_public(newfilename
, type
, mctx
, &pubkey
);
589 isc_mem_put(mctx
, newfilename
, newfilenamelen
);
593 if ((type
& (DST_TYPE_PRIVATE
| DST_TYPE_PUBLIC
)) == DST_TYPE_PUBLIC
||
594 (pubkey
->key_flags
& DNS_KEYFLAG_TYPEMASK
) == DNS_KEYTYPE_NOKEY
) {
595 result
= computeid(pubkey
);
596 if (result
!= ISC_R_SUCCESS
) {
597 dst_key_free(&pubkey
);
602 return (ISC_R_SUCCESS
);
605 result
= algorithm_status(pubkey
->key_alg
);
606 if (result
!= ISC_R_SUCCESS
) {
607 dst_key_free(&pubkey
);
611 key
= get_key_struct(pubkey
->key_name
, pubkey
->key_alg
,
612 pubkey
->key_flags
, pubkey
->key_proto
, 0,
613 pubkey
->key_class
, pubkey
->key_ttl
, mctx
);
615 dst_key_free(&pubkey
);
616 return (ISC_R_NOMEMORY
);
619 if (key
->func
->parse
== NULL
)
620 RETERR(DST_R_UNSUPPORTEDALG
);
622 newfilenamelen
= strlen(filename
) + 9;
624 newfilenamelen
+= strlen(dirname
) + 1;
625 newfilename
= isc_mem_get(mctx
, newfilenamelen
);
626 if (newfilename
== NULL
)
627 RETERR(ISC_R_NOMEMORY
);
628 result
= addsuffix(newfilename
, newfilenamelen
,
629 dirname
, filename
, ".private");
630 INSIST(result
== ISC_R_SUCCESS
);
632 RETERR(isc_lex_create(mctx
, 1500, &lex
));
633 RETERR(isc_lex_openfile(lex
, newfilename
));
634 isc_mem_put(mctx
, newfilename
, newfilenamelen
);
636 RETERR(key
->func
->parse(key
, lex
, pubkey
));
637 isc_lex_destroy(&lex
);
639 RETERR(computeid(key
));
641 if (pubkey
->key_id
!= key
->key_id
)
642 RETERR(DST_R_INVALIDPRIVATEKEY
);
643 dst_key_free(&pubkey
);
646 return (ISC_R_SUCCESS
);
650 dst_key_free(&pubkey
);
651 if (newfilename
!= NULL
)
652 isc_mem_put(mctx
, newfilename
, newfilenamelen
);
654 isc_lex_destroy(&lex
);
661 dst_key_todns(const dst_key_t
*key
, isc_buffer_t
*target
) {
662 REQUIRE(dst_initialized
== ISC_TRUE
);
663 REQUIRE(VALID_KEY(key
));
664 REQUIRE(target
!= NULL
);
666 CHECKALG(key
->key_alg
);
668 if (key
->func
->todns
== NULL
)
669 return (DST_R_UNSUPPORTEDALG
);
671 if (isc_buffer_availablelength(target
) < 4)
672 return (ISC_R_NOSPACE
);
673 isc_buffer_putuint16(target
, (isc_uint16_t
)(key
->key_flags
& 0xffff));
674 isc_buffer_putuint8(target
, (isc_uint8_t
)key
->key_proto
);
675 isc_buffer_putuint8(target
, (isc_uint8_t
)key
->key_alg
);
677 if (key
->key_flags
& DNS_KEYFLAG_EXTENDED
) {
678 if (isc_buffer_availablelength(target
) < 2)
679 return (ISC_R_NOSPACE
);
680 isc_buffer_putuint16(target
,
681 (isc_uint16_t
)((key
->key_flags
>> 16)
685 if (key
->keydata
.generic
== NULL
) /*%< NULL KEY */
686 return (ISC_R_SUCCESS
);
688 return (key
->func
->todns(key
, target
));
692 dst_key_fromdns(dns_name_t
*name
, dns_rdataclass_t rdclass
,
693 isc_buffer_t
*source
, isc_mem_t
*mctx
, dst_key_t
**keyp
)
695 isc_uint8_t alg
, proto
;
696 isc_uint32_t flags
, extflags
;
697 dst_key_t
*key
= NULL
;
698 dns_keytag_t id
, rid
;
702 REQUIRE(dst_initialized
);
704 isc_buffer_remainingregion(source
, &r
);
706 if (isc_buffer_remaininglength(source
) < 4)
707 return (DST_R_INVALIDPUBLICKEY
);
708 flags
= isc_buffer_getuint16(source
);
709 proto
= isc_buffer_getuint8(source
);
710 alg
= isc_buffer_getuint8(source
);
712 id
= dst_region_computeid(&r
, alg
);
713 rid
= dst_region_computerid(&r
, alg
);
715 if (flags
& DNS_KEYFLAG_EXTENDED
) {
716 if (isc_buffer_remaininglength(source
) < 2)
717 return (DST_R_INVALIDPUBLICKEY
);
718 extflags
= isc_buffer_getuint16(source
);
719 flags
|= (extflags
<< 16);
722 result
= frombuffer(name
, alg
, flags
, proto
, rdclass
, source
,
724 if (result
!= ISC_R_SUCCESS
)
730 return (ISC_R_SUCCESS
);
734 dst_key_frombuffer(dns_name_t
*name
, unsigned int alg
,
735 unsigned int flags
, unsigned int protocol
,
736 dns_rdataclass_t rdclass
,
737 isc_buffer_t
*source
, isc_mem_t
*mctx
, dst_key_t
**keyp
)
739 dst_key_t
*key
= NULL
;
742 REQUIRE(dst_initialized
);
744 result
= frombuffer(name
, alg
, flags
, protocol
, rdclass
, source
,
746 if (result
!= ISC_R_SUCCESS
)
749 result
= computeid(key
);
750 if (result
!= ISC_R_SUCCESS
) {
756 return (ISC_R_SUCCESS
);
760 dst_key_tobuffer(const dst_key_t
*key
, isc_buffer_t
*target
) {
761 REQUIRE(dst_initialized
== ISC_TRUE
);
762 REQUIRE(VALID_KEY(key
));
763 REQUIRE(target
!= NULL
);
765 CHECKALG(key
->key_alg
);
767 if (key
->func
->todns
== NULL
)
768 return (DST_R_UNSUPPORTEDALG
);
770 return (key
->func
->todns(key
, target
));
774 dst_key_privatefrombuffer(dst_key_t
*key
, isc_buffer_t
*buffer
) {
775 isc_lex_t
*lex
= NULL
;
776 isc_result_t result
= ISC_R_SUCCESS
;
778 REQUIRE(dst_initialized
== ISC_TRUE
);
779 REQUIRE(VALID_KEY(key
));
780 REQUIRE(!dst_key_isprivate(key
));
781 REQUIRE(buffer
!= NULL
);
783 if (key
->func
->parse
== NULL
)
784 RETERR(DST_R_UNSUPPORTEDALG
);
786 RETERR(isc_lex_create(key
->mctx
, 1500, &lex
));
787 RETERR(isc_lex_openbuffer(lex
, buffer
));
788 RETERR(key
->func
->parse(key
, lex
, NULL
));
791 isc_lex_destroy(&lex
);
796 dst_key_getgssctx(const dst_key_t
*key
)
798 REQUIRE(key
!= NULL
);
800 return (key
->keydata
.gssctx
);
804 dst_key_fromgssapi(dns_name_t
*name
, gss_ctx_id_t gssctx
, isc_mem_t
*mctx
,
805 dst_key_t
**keyp
, isc_region_t
*intoken
)
810 REQUIRE(gssctx
!= NULL
);
811 REQUIRE(keyp
!= NULL
&& *keyp
== NULL
);
813 key
= get_key_struct(name
, DST_ALG_GSSAPI
, 0, DNS_KEYPROTO_DNSSEC
,
814 0, dns_rdataclass_in
, 0, mctx
);
816 return (ISC_R_NOMEMORY
);
818 if (intoken
!= NULL
) {
820 * Keep the token for use by external ssu rules. They may need
821 * to examine the PAC in the kerberos ticket.
823 RETERR(isc_buffer_allocate(key
->mctx
, &key
->key_tkeytoken
,
825 RETERR(isc_buffer_copyregion(key
->key_tkeytoken
, intoken
));
828 key
->keydata
.gssctx
= gssctx
;
830 result
= ISC_R_SUCCESS
;
836 dst_key_buildinternal(dns_name_t
*name
, unsigned int alg
,
837 unsigned int bits
, unsigned int flags
,
838 unsigned int protocol
, dns_rdataclass_t rdclass
,
839 void *data
, isc_mem_t
*mctx
, dst_key_t
**keyp
)
844 REQUIRE(dst_initialized
== ISC_TRUE
);
845 REQUIRE(dns_name_isabsolute(name
));
846 REQUIRE(mctx
!= NULL
);
847 REQUIRE(keyp
!= NULL
&& *keyp
== NULL
);
848 REQUIRE(data
!= NULL
);
852 key
= get_key_struct(name
, alg
, flags
, protocol
, bits
, rdclass
,
855 return (ISC_R_NOMEMORY
);
857 key
->keydata
.generic
= data
;
859 result
= computeid(key
);
860 if (result
!= ISC_R_SUCCESS
) {
866 return (ISC_R_SUCCESS
);
870 dst_key_fromlabel(dns_name_t
*name
, int alg
, unsigned int flags
,
871 unsigned int protocol
, dns_rdataclass_t rdclass
,
872 const char *engine
, const char *label
, const char *pin
,
873 isc_mem_t
*mctx
, dst_key_t
**keyp
)
878 REQUIRE(dst_initialized
== ISC_TRUE
);
879 REQUIRE(dns_name_isabsolute(name
));
880 REQUIRE(mctx
!= NULL
);
881 REQUIRE(keyp
!= NULL
&& *keyp
== NULL
);
882 REQUIRE(label
!= NULL
);
886 key
= get_key_struct(name
, alg
, flags
, protocol
, 0, rdclass
, 0, mctx
);
888 return (ISC_R_NOMEMORY
);
890 if (key
->func
->fromlabel
== NULL
) {
892 return (DST_R_UNSUPPORTEDALG
);
895 result
= key
->func
->fromlabel(key
, engine
, label
, pin
);
896 if (result
!= ISC_R_SUCCESS
) {
901 result
= computeid(key
);
902 if (result
!= ISC_R_SUCCESS
) {
908 return (ISC_R_SUCCESS
);
912 dst_key_generate(dns_name_t
*name
, unsigned int alg
,
913 unsigned int bits
, unsigned int param
,
914 unsigned int flags
, unsigned int protocol
,
915 dns_rdataclass_t rdclass
,
916 isc_mem_t
*mctx
, dst_key_t
**keyp
)
918 return (dst_key_generate2(name
, alg
, bits
, param
, flags
, protocol
,
919 rdclass
, mctx
, keyp
, NULL
));
923 dst_key_generate2(dns_name_t
*name
, unsigned int alg
,
924 unsigned int bits
, unsigned int param
,
925 unsigned int flags
, unsigned int protocol
,
926 dns_rdataclass_t rdclass
,
927 isc_mem_t
*mctx
, dst_key_t
**keyp
,
928 void (*callback
)(int))
933 REQUIRE(dst_initialized
== ISC_TRUE
);
934 REQUIRE(dns_name_isabsolute(name
));
935 REQUIRE(mctx
!= NULL
);
936 REQUIRE(keyp
!= NULL
&& *keyp
== NULL
);
940 key
= get_key_struct(name
, alg
, flags
, protocol
, bits
,
943 return (ISC_R_NOMEMORY
);
945 if (bits
== 0) { /*%< NULL KEY */
946 key
->key_flags
|= DNS_KEYTYPE_NOKEY
;
948 return (ISC_R_SUCCESS
);
951 if (key
->func
->generate
== NULL
) {
953 return (DST_R_UNSUPPORTEDALG
);
956 ret
= key
->func
->generate(key
, param
, callback
);
957 if (ret
!= ISC_R_SUCCESS
) {
962 ret
= computeid(key
);
963 if (ret
!= ISC_R_SUCCESS
) {
969 return (ISC_R_SUCCESS
);
973 dst_key_getnum(const dst_key_t
*key
, int type
, isc_uint32_t
*valuep
)
975 REQUIRE(VALID_KEY(key
));
976 REQUIRE(valuep
!= NULL
);
977 REQUIRE(type
<= DST_MAX_NUMERIC
);
978 if (!key
->numset
[type
])
979 return (ISC_R_NOTFOUND
);
980 *valuep
= key
->nums
[type
];
981 return (ISC_R_SUCCESS
);
985 dst_key_setnum(dst_key_t
*key
, int type
, isc_uint32_t value
)
987 REQUIRE(VALID_KEY(key
));
988 REQUIRE(type
<= DST_MAX_NUMERIC
);
989 key
->nums
[type
] = value
;
990 key
->numset
[type
] = ISC_TRUE
;
994 dst_key_unsetnum(dst_key_t
*key
, int type
)
996 REQUIRE(VALID_KEY(key
));
997 REQUIRE(type
<= DST_MAX_NUMERIC
);
998 key
->numset
[type
] = ISC_FALSE
;
1002 dst_key_gettime(const dst_key_t
*key
, int type
, isc_stdtime_t
*timep
) {
1003 REQUIRE(VALID_KEY(key
));
1004 REQUIRE(timep
!= NULL
);
1005 REQUIRE(type
<= DST_MAX_TIMES
);
1006 if (!key
->timeset
[type
])
1007 return (ISC_R_NOTFOUND
);
1008 *timep
= key
->times
[type
];
1009 return (ISC_R_SUCCESS
);
1013 dst_key_settime(dst_key_t
*key
, int type
, isc_stdtime_t when
) {
1014 REQUIRE(VALID_KEY(key
));
1015 REQUIRE(type
<= DST_MAX_TIMES
);
1016 key
->times
[type
] = when
;
1017 key
->timeset
[type
] = ISC_TRUE
;
1021 dst_key_unsettime(dst_key_t
*key
, int type
) {
1022 REQUIRE(VALID_KEY(key
));
1023 REQUIRE(type
<= DST_MAX_TIMES
);
1024 key
->timeset
[type
] = ISC_FALSE
;
1028 dst_key_getprivateformat(const dst_key_t
*key
, int *majorp
, int *minorp
) {
1029 REQUIRE(VALID_KEY(key
));
1030 REQUIRE(majorp
!= NULL
);
1031 REQUIRE(minorp
!= NULL
);
1032 *majorp
= key
->fmt_major
;
1033 *minorp
= key
->fmt_minor
;
1034 return (ISC_R_SUCCESS
);
1038 dst_key_setprivateformat(dst_key_t
*key
, int major
, int minor
) {
1039 REQUIRE(VALID_KEY(key
));
1040 key
->fmt_major
= major
;
1041 key
->fmt_minor
= minor
;
1044 static isc_boolean_t
1045 comparekeys(const dst_key_t
*key1
, const dst_key_t
*key2
,
1046 isc_boolean_t match_revoked_key
,
1047 isc_boolean_t (*compare
)(const dst_key_t
*key1
,
1048 const dst_key_t
*key2
))
1050 REQUIRE(dst_initialized
== ISC_TRUE
);
1051 REQUIRE(VALID_KEY(key1
));
1052 REQUIRE(VALID_KEY(key2
));
1057 if (key1
== NULL
|| key2
== NULL
)
1060 if (key1
->key_alg
!= key2
->key_alg
)
1063 if (key1
->key_id
!= key2
->key_id
) {
1064 if (!match_revoked_key
)
1066 if (key1
->key_alg
== DST_ALG_RSAMD5
)
1068 if ((key1
->key_flags
& DNS_KEYFLAG_REVOKE
) ==
1069 (key2
->key_flags
& DNS_KEYFLAG_REVOKE
))
1071 if (key1
->key_id
!= key2
->key_rid
&&
1072 key1
->key_rid
!= key2
->key_id
)
1076 if (compare
!= NULL
)
1077 return (compare(key1
, key2
));
1084 * Compares only the public portion of two keys, by converting them
1085 * both to wire format and comparing the results.
1087 static isc_boolean_t
1088 pub_compare(const dst_key_t
*key1
, const dst_key_t
*key2
) {
1089 isc_result_t result
;
1090 unsigned char buf1
[DST_KEY_MAXSIZE
], buf2
[DST_KEY_MAXSIZE
];
1091 isc_buffer_t b1
, b2
;
1092 isc_region_t r1
, r2
;
1094 isc_buffer_init(&b1
, buf1
, sizeof(buf1
));
1095 result
= dst_key_todns(key1
, &b1
);
1096 if (result
!= ISC_R_SUCCESS
)
1098 /* Zero out flags. */
1099 buf1
[0] = buf1
[1] = 0;
1100 if ((key1
->key_flags
& DNS_KEYFLAG_EXTENDED
) != 0)
1101 isc_buffer_subtract(&b1
, 2);
1103 isc_buffer_init(&b2
, buf2
, sizeof(buf2
));
1104 result
= dst_key_todns(key2
, &b2
);
1105 if (result
!= ISC_R_SUCCESS
)
1107 /* Zero out flags. */
1108 buf2
[0] = buf2
[1] = 0;
1109 if ((key2
->key_flags
& DNS_KEYFLAG_EXTENDED
) != 0)
1110 isc_buffer_subtract(&b2
, 2);
1112 isc_buffer_usedregion(&b1
, &r1
);
1113 /* Remove extended flags. */
1114 if ((key1
->key_flags
& DNS_KEYFLAG_EXTENDED
) != 0) {
1115 memmove(&buf1
[4], &buf1
[6], r1
.length
- 6);
1119 isc_buffer_usedregion(&b2
, &r2
);
1120 /* Remove extended flags. */
1121 if ((key2
->key_flags
& DNS_KEYFLAG_EXTENDED
) != 0) {
1122 memmove(&buf2
[4], &buf2
[6], r2
.length
- 6);
1125 return (ISC_TF(isc_region_compare(&r1
, &r2
) == 0));
1129 dst_key_compare(const dst_key_t
*key1
, const dst_key_t
*key2
) {
1130 return (comparekeys(key1
, key2
, ISC_FALSE
, key1
->func
->compare
));
1134 dst_key_pubcompare(const dst_key_t
*key1
, const dst_key_t
*key2
,
1135 isc_boolean_t match_revoked_key
)
1137 return (comparekeys(key1
, key2
, match_revoked_key
, pub_compare
));
1142 dst_key_paramcompare(const dst_key_t
*key1
, const dst_key_t
*key2
) {
1143 REQUIRE(dst_initialized
== ISC_TRUE
);
1144 REQUIRE(VALID_KEY(key1
));
1145 REQUIRE(VALID_KEY(key2
));
1149 if (key1
== NULL
|| key2
== NULL
)
1151 if (key1
->key_alg
== key2
->key_alg
&&
1152 key1
->func
->paramcompare
!= NULL
&&
1153 key1
->func
->paramcompare(key1
, key2
) == ISC_TRUE
)
1160 dst_key_attach(dst_key_t
*source
, dst_key_t
**target
) {
1162 REQUIRE(dst_initialized
== ISC_TRUE
);
1163 REQUIRE(target
!= NULL
&& *target
== NULL
);
1164 REQUIRE(VALID_KEY(source
));
1166 isc_refcount_increment(&source
->refs
, NULL
);
1171 dst_key_free(dst_key_t
**keyp
) {
1176 REQUIRE(dst_initialized
== ISC_TRUE
);
1177 REQUIRE(keyp
!= NULL
&& VALID_KEY(*keyp
));
1182 isc_refcount_decrement(&key
->refs
, &refs
);
1186 isc_refcount_destroy(&key
->refs
);
1187 if (key
->keydata
.generic
!= NULL
) {
1188 INSIST(key
->func
->destroy
!= NULL
);
1189 key
->func
->destroy(key
);
1191 if (key
->engine
!= NULL
)
1192 isc_mem_free(mctx
, key
->engine
);
1193 if (key
->label
!= NULL
)
1194 isc_mem_free(mctx
, key
->label
);
1195 dns_name_free(key
->key_name
, mctx
);
1196 isc_mem_put(mctx
, key
->key_name
, sizeof(dns_name_t
));
1197 if (key
->key_tkeytoken
) {
1198 isc_buffer_free(&key
->key_tkeytoken
);
1200 memset(key
, 0, sizeof(dst_key_t
));
1201 isc_mem_putanddetach(&mctx
, key
, sizeof(dst_key_t
));
1206 dst_key_isprivate(const dst_key_t
*key
) {
1207 REQUIRE(VALID_KEY(key
));
1208 INSIST(key
->func
->isprivate
!= NULL
);
1209 return (key
->func
->isprivate(key
));
1213 dst_key_buildfilename(const dst_key_t
*key
, int type
,
1214 const char *directory
, isc_buffer_t
*out
) {
1216 REQUIRE(VALID_KEY(key
));
1217 REQUIRE(type
== DST_TYPE_PRIVATE
|| type
== DST_TYPE_PUBLIC
||
1220 return (buildfilename(key
->key_name
, key
->key_id
, key
->key_alg
,
1221 type
, directory
, out
));
1225 dst_key_sigsize(const dst_key_t
*key
, unsigned int *n
) {
1226 REQUIRE(dst_initialized
== ISC_TRUE
);
1227 REQUIRE(VALID_KEY(key
));
1230 /* XXXVIX this switch statement is too sparse to gen a jump table. */
1231 switch (key
->key_alg
) {
1232 case DST_ALG_RSAMD5
:
1233 case DST_ALG_RSASHA1
:
1234 case DST_ALG_NSEC3RSASHA1
:
1235 case DST_ALG_RSASHA256
:
1236 case DST_ALG_RSASHA512
:
1237 *n
= (key
->key_size
+ 7) / 8;
1240 case DST_ALG_NSEC3DSA
:
1241 *n
= DNS_SIG_DSASIGSIZE
;
1243 case DST_ALG_ECCGOST
:
1244 *n
= DNS_SIG_GOSTSIGSIZE
;
1246 case DST_ALG_ECDSA256
:
1247 *n
= DNS_SIG_ECDSA256SIZE
;
1249 case DST_ALG_ECDSA384
:
1250 *n
= DNS_SIG_ECDSA384SIZE
;
1252 case DST_ALG_HMACMD5
:
1255 case DST_ALG_HMACSHA1
:
1256 *n
= ISC_SHA1_DIGESTLENGTH
;
1258 case DST_ALG_HMACSHA224
:
1259 *n
= ISC_SHA224_DIGESTLENGTH
;
1261 case DST_ALG_HMACSHA256
:
1262 *n
= ISC_SHA256_DIGESTLENGTH
;
1264 case DST_ALG_HMACSHA384
:
1265 *n
= ISC_SHA384_DIGESTLENGTH
;
1267 case DST_ALG_HMACSHA512
:
1268 *n
= ISC_SHA512_DIGESTLENGTH
;
1270 case DST_ALG_GSSAPI
:
1271 *n
= 128; /*%< XXX */
1275 return (DST_R_UNSUPPORTEDALG
);
1277 return (ISC_R_SUCCESS
);
1281 dst_key_secretsize(const dst_key_t
*key
, unsigned int *n
) {
1282 REQUIRE(dst_initialized
== ISC_TRUE
);
1283 REQUIRE(VALID_KEY(key
));
1286 if (key
->key_alg
== DST_ALG_DH
)
1287 *n
= (key
->key_size
+ 7) / 8;
1289 return (DST_R_UNSUPPORTEDALG
);
1290 return (ISC_R_SUCCESS
);
1294 * Set the flags on a key, then recompute the key ID
1297 dst_key_setflags(dst_key_t
*key
, isc_uint32_t flags
) {
1298 REQUIRE(VALID_KEY(key
));
1299 key
->key_flags
= flags
;
1300 return (computeid(key
));
1304 dst_key_format(const dst_key_t
*key
, char *cp
, unsigned int size
) {
1305 char namestr
[DNS_NAME_FORMATSIZE
];
1306 char algstr
[DNS_NAME_FORMATSIZE
];
1308 dns_name_format(dst_key_name(key
), namestr
, sizeof(namestr
));
1309 dns_secalg_format((dns_secalg_t
) dst_key_alg(key
), algstr
,
1311 snprintf(cp
, size
, "%s/%s/%d", namestr
, algstr
, dst_key_id(key
));
1315 dst_key_dump(dst_key_t
*key
, isc_mem_t
*mctx
, char **buffer
, int *length
) {
1317 REQUIRE(buffer
!= NULL
&& *buffer
== NULL
);
1318 REQUIRE(length
!= NULL
&& *length
== 0);
1319 REQUIRE(VALID_KEY(key
));
1321 if (key
->func
->dump
== NULL
)
1322 return (ISC_R_NOTIMPLEMENTED
);
1323 return (key
->func
->dump(key
, mctx
, buffer
, length
));
1327 dst_key_restore(dns_name_t
*name
, unsigned int alg
, unsigned int flags
,
1328 unsigned int protocol
, dns_rdataclass_t rdclass
,
1329 isc_mem_t
*mctx
, const char *keystr
, dst_key_t
**keyp
)
1331 isc_result_t result
;
1334 REQUIRE(dst_initialized
== ISC_TRUE
);
1335 REQUIRE(keyp
!= NULL
&& *keyp
== NULL
);
1337 if (alg
>= DST_MAX_ALGS
|| dst_t_func
[alg
] == NULL
)
1338 return (DST_R_UNSUPPORTEDALG
);
1340 if (dst_t_func
[alg
]->restore
== NULL
)
1341 return (ISC_R_NOTIMPLEMENTED
);
1343 key
= get_key_struct(name
, alg
, flags
, protocol
, 0, rdclass
, 0, mctx
);
1345 return (ISC_R_NOMEMORY
);
1347 result
= (dst_t_func
[alg
]->restore
)(key
, keystr
);
1348 if (result
== ISC_R_SUCCESS
)
1361 * Allocates a key structure and fills in some of the fields.
1364 get_key_struct(dns_name_t
*name
, unsigned int alg
,
1365 unsigned int flags
, unsigned int protocol
,
1366 unsigned int bits
, dns_rdataclass_t rdclass
,
1367 dns_ttl_t ttl
, isc_mem_t
*mctx
)
1370 isc_result_t result
;
1373 key
= (dst_key_t
*) isc_mem_get(mctx
, sizeof(dst_key_t
));
1377 memset(key
, 0, sizeof(dst_key_t
));
1379 key
->key_name
= isc_mem_get(mctx
, sizeof(dns_name_t
));
1380 if (key
->key_name
== NULL
) {
1381 isc_mem_put(mctx
, key
, sizeof(dst_key_t
));
1385 dns_name_init(key
->key_name
, NULL
);
1386 result
= dns_name_dup(name
, mctx
, key
->key_name
);
1387 if (result
!= ISC_R_SUCCESS
) {
1388 isc_mem_put(mctx
, key
->key_name
, sizeof(dns_name_t
));
1389 isc_mem_put(mctx
, key
, sizeof(dst_key_t
));
1393 result
= isc_refcount_init(&key
->refs
, 1);
1394 if (result
!= ISC_R_SUCCESS
) {
1395 dns_name_free(key
->key_name
, mctx
);
1396 isc_mem_put(mctx
, key
->key_name
, sizeof(dns_name_t
));
1397 isc_mem_put(mctx
, key
, sizeof(dst_key_t
));
1400 isc_mem_attach(mctx
, &key
->mctx
);
1402 key
->key_flags
= flags
;
1403 key
->key_proto
= protocol
;
1404 key
->keydata
.generic
= NULL
;
1405 key
->key_size
= bits
;
1406 key
->key_class
= rdclass
;
1408 key
->func
= dst_t_func
[alg
];
1411 for (i
= 0; i
< (DST_MAX_TIMES
+ 1); i
++) {
1413 key
->timeset
[i
] = ISC_FALSE
;
1415 key
->inactive
= ISC_FALSE
;
1416 key
->magic
= KEY_MAGIC
;
1421 dst_key_inactive(const dst_key_t
*key
) {
1423 REQUIRE(VALID_KEY(key
));
1425 return (key
->inactive
);
1429 dst_key_setinactive(dst_key_t
*key
, isc_boolean_t inactive
) {
1431 REQUIRE(VALID_KEY(key
));
1433 key
->inactive
= inactive
;
1437 * Reads a public key from disk
1440 dst_key_read_public(const char *filename
, int type
,
1441 isc_mem_t
*mctx
, dst_key_t
**keyp
)
1443 u_char rdatabuf
[DST_KEY_MAXSIZE
];
1445 dns_fixedname_t name
;
1446 isc_lex_t
*lex
= NULL
;
1449 dns_rdata_t rdata
= DNS_RDATA_INIT
;
1450 unsigned int opt
= ISC_LEXOPT_DNSMULTILINE
;
1451 dns_rdataclass_t rdclass
= dns_rdataclass_in
;
1452 isc_lexspecials_t specials
;
1453 isc_uint32_t ttl
= 0;
1454 isc_result_t result
;
1455 dns_rdatatype_t keytype
;
1458 * Open the file and read its formatted contents
1460 * domain.name [ttl] [class] [KEY|DNSKEY] <flags> <protocol> <algorithm> <key>
1463 /* 1500 should be large enough for any key */
1464 ret
= isc_lex_create(mctx
, 1500, &lex
);
1465 if (ret
!= ISC_R_SUCCESS
)
1468 memset(specials
, 0, sizeof(specials
));
1472 isc_lex_setspecials(lex
, specials
);
1473 isc_lex_setcomments(lex
, ISC_LEXCOMMENT_DNSMASTERFILE
);
1475 ret
= isc_lex_openfile(lex
, filename
);
1476 if (ret
!= ISC_R_SUCCESS
)
1479 #define NEXTTOKEN(lex, opt, token) { \
1480 ret = isc_lex_gettoken(lex, opt, token); \
1481 if (ret != ISC_R_SUCCESS) \
1485 #define BADTOKEN() { \
1486 ret = ISC_R_UNEXPECTEDTOKEN; \
1490 /* Read the domain name */
1491 NEXTTOKEN(lex
, opt
, &token
);
1492 if (token
.type
!= isc_tokentype_string
)
1496 * We don't support "@" in .key files.
1498 if (!strcmp(DST_AS_STR(token
), "@"))
1501 dns_fixedname_init(&name
);
1502 isc_buffer_init(&b
, DST_AS_STR(token
), strlen(DST_AS_STR(token
)));
1503 isc_buffer_add(&b
, strlen(DST_AS_STR(token
)));
1504 ret
= dns_name_fromtext(dns_fixedname_name(&name
), &b
, dns_rootname
,
1506 if (ret
!= ISC_R_SUCCESS
)
1509 /* Read the next word: either TTL, class, or 'KEY' */
1510 NEXTTOKEN(lex
, opt
, &token
);
1512 if (token
.type
!= isc_tokentype_string
)
1515 /* If it's a TTL, read the next one */
1516 result
= dns_ttl_fromtext(&token
.value
.as_textregion
, &ttl
);
1517 if (result
== ISC_R_SUCCESS
)
1518 NEXTTOKEN(lex
, opt
, &token
);
1520 if (token
.type
!= isc_tokentype_string
)
1523 ret
= dns_rdataclass_fromtext(&rdclass
, &token
.value
.as_textregion
);
1524 if (ret
== ISC_R_SUCCESS
)
1525 NEXTTOKEN(lex
, opt
, &token
);
1527 if (token
.type
!= isc_tokentype_string
)
1530 if (strcasecmp(DST_AS_STR(token
), "DNSKEY") == 0)
1531 keytype
= dns_rdatatype_dnskey
;
1532 else if (strcasecmp(DST_AS_STR(token
), "KEY") == 0)
1533 keytype
= dns_rdatatype_key
; /*%< SIG(0), TKEY */
1537 if (((type
& DST_TYPE_KEY
) != 0 && keytype
!= dns_rdatatype_key
) ||
1538 ((type
& DST_TYPE_KEY
) == 0 && keytype
!= dns_rdatatype_dnskey
)) {
1539 ret
= DST_R_BADKEYTYPE
;
1543 isc_buffer_init(&b
, rdatabuf
, sizeof(rdatabuf
));
1544 ret
= dns_rdata_fromtext(&rdata
, rdclass
, keytype
, lex
, NULL
,
1545 ISC_FALSE
, mctx
, &b
, NULL
);
1546 if (ret
!= ISC_R_SUCCESS
)
1549 ret
= dst_key_fromdns(dns_fixedname_name(&name
), rdclass
, &b
, mctx
,
1551 if (ret
!= ISC_R_SUCCESS
)
1554 dst_key_setttl(*keyp
, ttl
);
1558 isc_lex_destroy(&lex
);
1562 static isc_boolean_t
1563 issymmetric(const dst_key_t
*key
) {
1564 REQUIRE(dst_initialized
== ISC_TRUE
);
1565 REQUIRE(VALID_KEY(key
));
1567 /* XXXVIX this switch statement is too sparse to gen a jump table. */
1568 switch (key
->key_alg
) {
1569 case DST_ALG_RSAMD5
:
1570 case DST_ALG_RSASHA1
:
1571 case DST_ALG_NSEC3RSASHA1
:
1572 case DST_ALG_RSASHA256
:
1573 case DST_ALG_RSASHA512
:
1575 case DST_ALG_NSEC3DSA
:
1577 case DST_ALG_ECCGOST
:
1578 case DST_ALG_ECDSA256
:
1579 case DST_ALG_ECDSA384
:
1581 case DST_ALG_HMACMD5
:
1582 case DST_ALG_GSSAPI
:
1590 * Write key timing metadata to a file pointer, preceded by 'tag'
1593 printtime(const dst_key_t
*key
, int type
, const char *tag
, FILE *stream
) {
1594 isc_result_t result
;
1595 #ifdef ISC_PLATFORM_USETHREADS
1596 char output
[26]; /* Minimum buffer as per ctime_r() specification. */
1602 char utc
[sizeof("YYYYMMDDHHSSMM")];
1606 result
= dst_key_gettime(key
, type
, &when
);
1607 if (result
== ISC_R_NOTFOUND
)
1610 /* time_t and isc_stdtime_t might be different sizes */
1612 #ifdef ISC_PLATFORM_USETHREADS
1614 if (ctime_s(output
, sizeof(output
), &t
) != 0)
1617 if (ctime_r(&t
, output
) == NULL
)
1624 isc_buffer_init(&b
, utc
, sizeof(utc
));
1625 result
= dns_time32_totext(when
, &b
);
1626 if (result
!= ISC_R_SUCCESS
)
1629 isc_buffer_usedregion(&b
, &r
);
1630 fprintf(stream
, "%s: %.*s (%.*s)\n", tag
, (int)r
.length
, r
.base
,
1631 (int)strlen(output
) - 1, output
);
1635 fprintf(stream
, "%s: (set, unable to display)\n", tag
);
1639 * Writes a public key to disk in DNS format.
1642 write_public_key(const dst_key_t
*key
, int type
, const char *directory
) {
1644 isc_buffer_t keyb
, textb
, fileb
, classb
;
1646 char filename
[ISC_DIR_NAMEMAX
];
1647 unsigned char key_array
[DST_KEY_MAXSIZE
];
1648 char text_array
[DST_KEY_MAXTEXTSIZE
];
1649 char class_array
[10];
1651 dns_rdata_t rdata
= DNS_RDATA_INIT
;
1652 isc_fsaccess_t access
;
1654 REQUIRE(VALID_KEY(key
));
1656 isc_buffer_init(&keyb
, key_array
, sizeof(key_array
));
1657 isc_buffer_init(&textb
, text_array
, sizeof(text_array
));
1658 isc_buffer_init(&classb
, class_array
, sizeof(class_array
));
1660 ret
= dst_key_todns(key
, &keyb
);
1661 if (ret
!= ISC_R_SUCCESS
)
1664 isc_buffer_usedregion(&keyb
, &r
);
1665 dns_rdata_fromregion(&rdata
, key
->key_class
, dns_rdatatype_dnskey
, &r
);
1667 ret
= dns_rdata_totext(&rdata
, (dns_name_t
*) NULL
, &textb
);
1668 if (ret
!= ISC_R_SUCCESS
)
1669 return (DST_R_INVALIDPUBLICKEY
);
1671 ret
= dns_rdataclass_totext(key
->key_class
, &classb
);
1672 if (ret
!= ISC_R_SUCCESS
)
1673 return (DST_R_INVALIDPUBLICKEY
);
1676 * Make the filename.
1678 isc_buffer_init(&fileb
, filename
, sizeof(filename
));
1679 ret
= dst_key_buildfilename(key
, DST_TYPE_PUBLIC
, directory
, &fileb
);
1680 if (ret
!= ISC_R_SUCCESS
)
1684 * Create public key file.
1686 if ((fp
= fopen(filename
, "w")) == NULL
)
1687 return (DST_R_WRITEERROR
);
1689 if (issymmetric(key
)) {
1691 isc_fsaccess_add(ISC_FSACCESS_OWNER
,
1692 ISC_FSACCESS_READ
| ISC_FSACCESS_WRITE
,
1694 (void)isc_fsaccess_set(filename
, access
);
1697 /* Write key information in comments */
1698 if ((type
& DST_TYPE_KEY
) == 0) {
1699 fprintf(fp
, "; This is a %s%s-signing key, keyid %d, for ",
1700 (key
->key_flags
& DNS_KEYFLAG_REVOKE
) != 0 ?
1703 (key
->key_flags
& DNS_KEYFLAG_KSK
) != 0 ?
1707 ret
= dns_name_print(key
->key_name
, fp
);
1708 if (ret
!= ISC_R_SUCCESS
) {
1714 printtime(key
, DST_TIME_CREATED
, "; Created", fp
);
1715 printtime(key
, DST_TIME_PUBLISH
, "; Publish", fp
);
1716 printtime(key
, DST_TIME_ACTIVATE
, "; Activate", fp
);
1717 printtime(key
, DST_TIME_REVOKE
, "; Revoke", fp
);
1718 printtime(key
, DST_TIME_INACTIVE
, "; Inactive", fp
);
1719 printtime(key
, DST_TIME_DELETE
, "; Delete", fp
);
1722 /* Now print the actual key */
1723 ret
= dns_name_print(key
->key_name
, fp
);
1726 if (key
->key_ttl
!= 0)
1727 fprintf(fp
, "%d ", key
->key_ttl
);
1729 isc_buffer_usedregion(&classb
, &r
);
1730 if ((unsigned) fwrite(r
.base
, 1, r
.length
, fp
) != r
.length
)
1731 ret
= DST_R_WRITEERROR
;
1733 if ((type
& DST_TYPE_KEY
) != 0)
1734 fprintf(fp
, " KEY ");
1736 fprintf(fp
, " DNSKEY ");
1738 isc_buffer_usedregion(&textb
, &r
);
1739 if ((unsigned) fwrite(r
.base
, 1, r
.length
, fp
) != r
.length
)
1740 ret
= DST_R_WRITEERROR
;
1745 ret
= DST_R_WRITEERROR
;
1752 buildfilename(dns_name_t
*name
, dns_keytag_t id
,
1753 unsigned int alg
, unsigned int type
,
1754 const char *directory
, isc_buffer_t
*out
)
1756 const char *suffix
= "";
1758 isc_result_t result
;
1760 REQUIRE(out
!= NULL
);
1761 if ((type
& DST_TYPE_PRIVATE
) != 0)
1762 suffix
= ".private";
1763 else if (type
== DST_TYPE_PUBLIC
)
1765 if (directory
!= NULL
) {
1766 if (isc_buffer_availablelength(out
) < strlen(directory
))
1767 return (ISC_R_NOSPACE
);
1768 isc_buffer_putstr(out
, directory
);
1769 if (strlen(directory
) > 0U &&
1770 directory
[strlen(directory
) - 1] != '/')
1771 isc_buffer_putstr(out
, "/");
1773 if (isc_buffer_availablelength(out
) < 1)
1774 return (ISC_R_NOSPACE
);
1775 isc_buffer_putstr(out
, "K");
1776 result
= dns_name_tofilenametext(name
, ISC_FALSE
, out
);
1777 if (result
!= ISC_R_SUCCESS
)
1779 len
= 1 + 3 + 1 + 5 + strlen(suffix
) + 1;
1780 if (isc_buffer_availablelength(out
) < len
)
1781 return (ISC_R_NOSPACE
);
1782 sprintf((char *) isc_buffer_used(out
), "+%03d+%05d%s", alg
, id
,
1784 isc_buffer_add(out
, len
);
1786 return (ISC_R_SUCCESS
);
1790 computeid(dst_key_t
*key
) {
1791 isc_buffer_t dnsbuf
;
1792 unsigned char dns_array
[DST_KEY_MAXSIZE
];
1796 isc_buffer_init(&dnsbuf
, dns_array
, sizeof(dns_array
));
1797 ret
= dst_key_todns(key
, &dnsbuf
);
1798 if (ret
!= ISC_R_SUCCESS
)
1801 isc_buffer_usedregion(&dnsbuf
, &r
);
1802 key
->key_id
= dst_region_computeid(&r
, key
->key_alg
);
1803 key
->key_rid
= dst_region_computerid(&r
, key
->key_alg
);
1804 return (ISC_R_SUCCESS
);
1808 frombuffer(dns_name_t
*name
, unsigned int alg
, unsigned int flags
,
1809 unsigned int protocol
, dns_rdataclass_t rdclass
,
1810 isc_buffer_t
*source
, isc_mem_t
*mctx
, dst_key_t
**keyp
)
1815 REQUIRE(dns_name_isabsolute(name
));
1816 REQUIRE(source
!= NULL
);
1817 REQUIRE(mctx
!= NULL
);
1818 REQUIRE(keyp
!= NULL
&& *keyp
== NULL
);
1820 key
= get_key_struct(name
, alg
, flags
, protocol
, 0, rdclass
, 0, mctx
);
1822 return (ISC_R_NOMEMORY
);
1824 if (isc_buffer_remaininglength(source
) > 0) {
1825 ret
= algorithm_status(alg
);
1826 if (ret
!= ISC_R_SUCCESS
) {
1830 if (key
->func
->fromdns
== NULL
) {
1832 return (DST_R_UNSUPPORTEDALG
);
1835 ret
= key
->func
->fromdns(key
, source
);
1836 if (ret
!= ISC_R_SUCCESS
) {
1843 return (ISC_R_SUCCESS
);
1847 algorithm_status(unsigned int alg
) {
1848 REQUIRE(dst_initialized
== ISC_TRUE
);
1850 if (dst_algorithm_supported(alg
))
1851 return (ISC_R_SUCCESS
);
1852 #if !defined(OPENSSL) && !defined(PKCS11CRYPTO)
1853 if (alg
== DST_ALG_RSAMD5
|| alg
== DST_ALG_RSASHA1
||
1854 alg
== DST_ALG_DSA
|| alg
== DST_ALG_DH
||
1855 alg
== DST_ALG_HMACMD5
|| alg
== DST_ALG_NSEC3DSA
||
1856 alg
== DST_ALG_NSEC3RSASHA1
||
1857 alg
== DST_ALG_RSASHA256
|| alg
== DST_ALG_RSASHA512
||
1858 alg
== DST_ALG_ECCGOST
||
1859 alg
== DST_ALG_ECDSA256
|| alg
== DST_ALG_ECDSA384
)
1860 return (DST_R_NOCRYPTO
);
1862 return (DST_R_UNSUPPORTEDALG
);
1866 addsuffix(char *filename
, int len
, const char *odirname
,
1867 const char *ofilename
, const char *suffix
)
1869 int olen
= strlen(ofilename
);
1872 if (olen
> 1 && ofilename
[olen
- 1] == '.')
1874 else if (olen
> 8 && strcmp(ofilename
+ olen
- 8, ".private") == 0)
1876 else if (olen
> 4 && strcmp(ofilename
+ olen
- 4, ".key") == 0)
1879 if (odirname
== NULL
)
1880 n
= snprintf(filename
, len
, "%.*s%s", olen
, ofilename
, suffix
);
1882 n
= snprintf(filename
, len
, "%s/%.*s%s",
1883 odirname
, olen
, ofilename
, suffix
);
1885 return (ISC_R_FAILURE
);
1887 return (ISC_R_NOSPACE
);
1888 return (ISC_R_SUCCESS
);
1892 dst__entropy_getdata(void *buf
, unsigned int len
, isc_boolean_t pseudo
) {
1893 unsigned int flags
= dst_entropy_flags
;
1895 if (dst_entropy_pool
== NULL
)
1896 return (ISC_R_FAILURE
);
1899 return (ISC_R_SUCCESS
);
1904 return (pk11_rand_bytes(buf
, len
));
1905 #else /* PKCS11CRYPTO */
1907 flags
&= ~ISC_ENTROPY_GOODONLY
;
1909 flags
|= ISC_ENTROPY_BLOCKING
;
1910 return (isc_entropy_getdata(dst_entropy_pool
, buf
, len
, NULL
, flags
));
1911 #endif /* PKCS11CRYPTO */
1915 dst__entropy_status(void) {
1916 #ifndef PKCS11CRYPTO
1918 unsigned int flags
= dst_entropy_flags
;
1920 unsigned char buf
[32];
1921 static isc_boolean_t first
= ISC_TRUE
;
1923 if (dst_entropy_pool
== NULL
)
1927 /* Someone believes RAND_status() initializes the PRNG */
1928 flags
&= ~ISC_ENTROPY_GOODONLY
;
1929 ret
= isc_entropy_getdata(dst_entropy_pool
, buf
,
1930 sizeof(buf
), NULL
, flags
);
1931 INSIST(ret
== ISC_R_SUCCESS
);
1932 isc_entropy_putdata(dst_entropy_pool
, buf
,
1933 sizeof(buf
), 2 * sizeof(buf
));
1937 return (isc_entropy_status(dst_entropy_pool
));
1944 dst_key_tkeytoken(const dst_key_t
*key
) {
1945 REQUIRE(VALID_KEY(key
));
1946 return (key
->key_tkeytoken
);