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