dst_api.c revision 89bbdd1f694c7237c29e2fefc0eaac47c7fe544f
499b34cea04a46823d003d4c0520c8b03e8513cbBrian Wellington * Portions Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC")
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * Portions Copyright (C) 1999-2003 Internet Software Consortium.
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * Permission to use, copy, modify, and/or distribute this software for any
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * purpose with or without fee is hereby granted, provided that the above
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * copyright notice and this permission notice appear in all copies.
15a44745412679c30a6d022733925af70a38b715David Lawrence * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
15a44745412679c30a6d022733925af70a38b715David Lawrence * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
15a44745412679c30a6d022733925af70a38b715David Lawrence * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
15a44745412679c30a6d022733925af70a38b715David Lawrence * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15a44745412679c30a6d022733925af70a38b715David Lawrence * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15a44745412679c30a6d022733925af70a38b715David Lawrence * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15a44745412679c30a6d022733925af70a38b715David Lawrence * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
0c310d16b05ee94743d33f6920907edee6084fc8Michael Graff * Permission to use, copy, modify, and/or distribute this software for any
0c310d16b05ee94743d33f6920907edee6084fc8Michael Graff * purpose with or without fee is hereby granted, provided that the above
de153390f5a1f6d4fa86af91d4cae772d9846ca0Mark Andrews * copyright notice and this permission notice appear in all copies.
822f6cdabb1edd44472c7a758b5cae71376fa9beBrian Wellington * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
25a66b4e41e2b0a2af4840749bac80ae78c678bfMark Andrews * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
973a19342597823f111fce6a8cd5adfd0e2e7c0dMark Andrews * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Principal Author: Brian Wellington
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * $Id: dst_api.c,v 1.65 2011/10/20 21:20:02 marka Exp $
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence#define DST_AS_STR(t) ((t).value.as_textregion.base)
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrencestatic isc_entropy_t *dst_entropy_pool = NULL;
0b056755b2f423ba5f6adac8f7851d78f7d11437David Lawrencestatic unsigned int dst_entropy_flags = 0;
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrencestatic isc_boolean_t dst_initialized = ISC_FALSE;
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrencevoid gss_log(int level, const char *fmt, ...) ISC_FORMAT_PRINTF(2, 3);
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence * Static functions.
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrencestatic dst_key_t * get_key_struct(dns_name_t *name,
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence unsigned int alg,
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafssonstatic isc_result_t write_public_key(const dst_key_t *key, int type,
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafssonstatic isc_result_t buildfilename(dns_name_t *name,
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrencestatic isc_result_t computeid(dst_key_t *key);
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrencestatic isc_result_t frombuffer(dns_name_t *name,
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence unsigned int alg,
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence unsigned int flags,
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrencestatic isc_result_t algorithm_status(unsigned int alg);
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrencestatic isc_result_t addsuffix(char *filename, int len,
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence const char *suffix);
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence } while (0); \
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrencedst_lib_init(isc_mem_t *mctx, isc_entropy_t *ectx, unsigned int eflags) {
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence return (dst_lib_init2(mctx, ectx, NULL, eflags));
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrencedst_lib_init2(isc_mem_t *mctx, isc_entropy_t *ectx,
fd4810861c0c0ccb9aebde94e9d289442b2630dbMark Andrews * When using --with-openssl, there seems to be no good way of not
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence * leaking memory due to the openssl error handling mechanism.
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence * Avoid assertions by using a local memory context and not checking
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence * for leaks on exit. Note: as there are leaks we cannot use
7ab0e69f61e61e81d489c95c7ebd981e74e7ef16Andreas Gustafsson * ISC_MEMFLAG_INTERNAL as it will free up memory still being used
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrews * by libcrypto.
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrews result = isc_mem_createx2(0, 0, default_memalloc, default_memfree,
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrews isc_mem_setname(dst__memory_pool, "dst", NULL);
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrews isc_mem_setdestroycheck(dst__memory_pool, ISC_FALSE);
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrews RETERR(dst__hmacmd5_init(&dst_t_func[DST_ALG_HMACMD5]));
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrews RETERR(dst__hmacsha1_init(&dst_t_func[DST_ALG_HMACSHA1]));
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington RETERR(dst__hmacsha224_init(&dst_t_func[DST_ALG_HMACSHA224]));
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrews RETERR(dst__hmacsha256_init(&dst_t_func[DST_ALG_HMACSHA256]));
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrews RETERR(dst__hmacsha384_init(&dst_t_func[DST_ALG_HMACSHA384]));
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrews RETERR(dst__hmacsha512_init(&dst_t_func[DST_ALG_HMACSHA512]));
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrews RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSAMD5],
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrews RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSASHA1],
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrews RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_NSEC3RSASHA1],
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrews RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSASHA256],
f6407f9a0b890bebbfd5f738d9c4aef3d3315fe9Michael Graff RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSASHA512],
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrews RETERR(dst__openssldsa_init(&dst_t_func[DST_ALG_DSA]));
ffe74cc719aa0f10c38fbc1f2f3ea7db0960cb8fMark Andrews RETERR(dst__openssldsa_init(&dst_t_func[DST_ALG_NSEC3DSA]));
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews RETERR(dst__openssldh_init(&dst_t_func[DST_ALG_DH]));
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews RETERR(dst__opensslgost_init(&dst_t_func[DST_ALG_ECCGOST]));
bed8e84810a80dad3d37870be927d1dfd015f480Mark Andrews RETERR(dst__opensslecdsa_init(&dst_t_func[DST_ALG_ECDSA256]));
8d3e74b1683f714a484bbcf73249e8ee470e36d7Mark Andrews RETERR(dst__opensslecdsa_init(&dst_t_func[DST_ALG_ECDSA384]));
8d3e74b1683f714a484bbcf73249e8ee470e36d7Mark Andrews#endif /* OPENSSL */
8d3e74b1683f714a484bbcf73249e8ee470e36d7Mark Andrews RETERR(dst__gssapi_init(&dst_t_func[DST_ALG_GSSAPI]));
8d3e74b1683f714a484bbcf73249e8ee470e36d7Mark Andrews /* avoid immediate crash! */
5d83b561ad7eb84885a8ec63dee4c51b335f067aBrian Wellington RUNTIME_CHECK(dst_initialized == ISC_TRUE);
5d83b561ad7eb84885a8ec63dee4c51b335f067aBrian Wellington for (i = 0; i < DST_MAX_ALGS; i++)
5d83b561ad7eb84885a8ec63dee4c51b335f067aBrian Wellington if (dst_t_func[i] != NULL && dst_t_func[i]->cleanup != NULL)
bcd7fdf06ca76eb2f6eb157f56b612c503e062a7Mark Andrews if (alg >= DST_MAX_ALGS || dst_t_func[alg] == NULL)
bcd7fdf06ca76eb2f6eb157f56b612c503e062a7Mark Andrewsdst_context_create(dst_key_t *key, isc_mem_t *mctx, dst_context_t **dctxp) {
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson REQUIRE(dctxp != NULL && *dctxp == NULL);
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson dctx = isc_mem_get(mctx, sizeof(dst_context_t));
94a537e6ab3069f8d34e12e5ea722250be2b89c8Michael Graff isc_mem_put(mctx, dctx, sizeof(dst_context_t));
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafssondst_context_destroy(dst_context_t **dctxp) {
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson REQUIRE(dctxp != NULL && VALID_CTX(*dctxp));
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson INSIST(dctx->key->func->destroyctx != NULL);
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson isc_mem_put(dctx->mctx, dctx, sizeof(dst_context_t));
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafssondst_context_adddata(dst_context_t *dctx, const isc_region_t *data) {
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson INSIST(dctx->key->func->adddata != NULL);
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson return (dctx->key->func->adddata(dctx, data));
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafssondst_context_sign(dst_context_t *dctx, isc_buffer_t *sig) {
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsdst_context_verify(dst_context_t *dctx, isc_region_t *sig) {
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrewsdst_key_computesecret(const dst_key_t *pub, const dst_key_t *priv,
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews if (pub->keydata.generic == NULL || priv->keydata.generic == NULL)
389c749a5ee18f1c0d6278ae49f2aae5d5f0d2dcMark Andrews return (pub->func->computesecret(pub, priv, secret));
389c749a5ee18f1c0d6278ae49f2aae5d5f0d2dcMark Andrewsdst_key_tofile(const dst_key_t *key, int type, const char *directory) {
29c818c7d40fc8898b062903ec703851328a4deaMark Andrews REQUIRE((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) != 0);
29c818c7d40fc8898b062903ec703851328a4deaMark Andrews (key->key_flags & DNS_KEYFLAG_TYPEMASK) != DNS_KEYTYPE_NOKEY)
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrencedst_key_fromfile(dns_name_t *name, dns_keytag_t id,
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews unsigned int alg, int type, const char *directory,
d981ca645597116d227a48bf37cc5edc061c854dBob Halley REQUIRE((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) != 0);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews isc_buffer_init(&b, filename, sizeof(filename));
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews result = buildfilename(name, id, alg, type, directory, &b);
44a966dff66061ac3f266c6b451a70733eb78e82Mark Andrews result = dst_key_fromnamedfile(filename, NULL, type, mctx, &key);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if (!dns_name_equal(name, key->key_name) || id != key->key_id ||
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrewsdst_key_fromnamedfile(const char *filename, const char *dirname,
19d365e4448f1782611280b020987988b7ac3210Mark Andrews REQUIRE((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) != 0);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews /* If an absolute path is specified, don't use the key directory */
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff#else /* WIN32 */
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews newfilename = isc_mem_get(mctx, newfilenamelen);
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews result = addsuffix(newfilename, newfilenamelen,
f1cae4bcb7ee3060d893f5ab3ba55c1820bf3e4aBrian Wellington result = dst_key_read_public(newfilename, type, mctx, &pubkey);
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews isc_mem_put(mctx, newfilename, newfilenamelen);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if ((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) == DST_TYPE_PUBLIC ||
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews (pubkey->key_flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY) {
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence key = get_key_struct(pubkey->key_name, pubkey->key_alg,
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews newfilename = isc_mem_get(mctx, newfilenamelen);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews result = addsuffix(newfilename, newfilenamelen,
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff isc_mem_put(mctx, newfilename, newfilenamelen);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews isc_mem_put(mctx, newfilename, newfilenamelen);
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graffdst_key_todns(const dst_key_t *key, isc_buffer_t *target) {
7e4cda9965e2edf2ec43c57967eec8eff7061ab0Andreas Gustafsson if (isc_buffer_availablelength(target) < 4)
7e4cda9965e2edf2ec43c57967eec8eff7061ab0Andreas Gustafsson isc_buffer_putuint16(target, (isc_uint16_t)(key->key_flags & 0xffff));
7e4cda9965e2edf2ec43c57967eec8eff7061ab0Andreas Gustafsson isc_buffer_putuint8(target, (isc_uint8_t)key->key_proto);
7e4cda9965e2edf2ec43c57967eec8eff7061ab0Andreas Gustafsson isc_buffer_putuint8(target, (isc_uint8_t)key->key_alg);
7e4cda9965e2edf2ec43c57967eec8eff7061ab0Andreas Gustafsson if (key->key_flags & DNS_KEYFLAG_EXTENDED) {
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington if (isc_buffer_availablelength(target) < 2)
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington if (key->keydata.generic == NULL) /*%< NULL KEY */
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrewsdst_key_fromdns(dns_name_t *name, dns_rdataclass_t rdclass,
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp)
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington if (isc_buffer_remaininglength(source) < 4)
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington if (isc_buffer_remaininglength(source) < 2)
7e4cda9965e2edf2ec43c57967eec8eff7061ab0Andreas Gustafsson result = frombuffer(name, alg, flags, proto, rdclass, source,
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellingtondst_key_frombuffer(dns_name_t *name, unsigned int alg,
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp)
0e8cf9a887c70f96ac448b06c069d90b830215ccMark Andrews result = frombuffer(name, alg, flags, protocol, rdclass, source,
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrewsdst_key_tobuffer(const dst_key_t *key, isc_buffer_t *target) {
228c679d7a269423019f7c528db92e855f08240bMark Andrewsdst_key_privatefrombuffer(dst_key_t *key, isc_buffer_t *buffer) {
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington RETERR(isc_lex_create(key->mctx, 1500, &lex));
82d05588933a3c765aa8518fe455d6477d640b99Mark Andrewsdst_key_fromgssapi(dns_name_t *name, gss_ctx_id_t gssctx, isc_mem_t *mctx,
82d05588933a3c765aa8518fe455d6477d640b99Mark Andrews key = get_key_struct(name, DST_ALG_GSSAPI, 0, DNS_KEYPROTO_DNSSEC,
fd4810861c0c0ccb9aebde94e9d289442b2630dbMark Andrews * Keep the token for use by external ssu rules. They may need
fd4810861c0c0ccb9aebde94e9d289442b2630dbMark Andrews * to examine the PAC in the kerberos ticket.
fd4810861c0c0ccb9aebde94e9d289442b2630dbMark Andrews RETERR(isc_buffer_allocate(key->mctx, &key->key_tkeytoken,
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews RETERR(isc_buffer_copyregion(key->key_tkeytoken, intoken));
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsdst_key_fromlabel(dns_name_t *name, int alg, unsigned int flags,
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews unsigned int protocol, dns_rdataclass_t rdclass,
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff const char *engine, const char *label, const char *pin,
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence key = get_key_struct(name, alg, flags, protocol, 0, rdclass, 0, mctx);
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews result = key->func->fromlabel(key, engine, label, pin);
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrewsdst_key_generate(dns_name_t *name, unsigned int alg,
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews return (dst_key_generate2(name, alg, bits, param, flags, protocol,
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrewsdst_key_generate2(dns_name_t *name, unsigned int alg,
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafsson key = get_key_struct(name, alg, flags, protocol, bits,
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafsson ret = key->func->generate(key, param, callback);
f1cae4bcb7ee3060d893f5ab3ba55c1820bf3e4aBrian Wellingtondst_key_getnum(const dst_key_t *key, int type, isc_uint32_t *valuep)
7d8cdd869ed2162a5befda7cc1600136110f54d6Mark Andrewsdst_key_setnum(dst_key_t *key, int type, isc_uint32_t value)
19d365e4448f1782611280b020987988b7ac3210Mark Andrewsdst_key_gettime(const dst_key_t *key, int type, isc_stdtime_t *timep) {
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrewsdst_key_settime(dst_key_t *key, int type, isc_stdtime_t when) {
d981ca645597116d227a48bf37cc5edc061c854dBob Halleydst_key_getprivateformat(const dst_key_t *key, int *majorp, int *minorp) {
d981ca645597116d227a48bf37cc5edc061c854dBob Halleydst_key_setprivateformat(dst_key_t *key, int major, int minor) {
0513f89e68f82f9ec54e7af9c979a7c43babbe31Bob Halleycomparekeys(const dst_key_t *key1, const dst_key_t *key2,
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson * Compares only the public portion of two keys, by converting them
88ba491496daf4463a2c898be8a6c47775a6d048Mark Andrews * both to wire format and comparing the results.
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafssonpub_compare(const dst_key_t *key1, const dst_key_t *key2) {
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson unsigned char buf1[DST_KEY_MAXSIZE], buf2[DST_KEY_MAXSIZE];
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson isc_buffer_init(&b1, buf1, sizeof(buf1));
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson /* Zero out flags. */
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson if ((key1->key_flags & DNS_KEYFLAG_EXTENDED) != 0)
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence /* Zero out flags. */
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence if ((key2->key_flags & DNS_KEYFLAG_EXTENDED) != 0)
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson /* Remove extended flags. */
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson if ((key1->key_flags & DNS_KEYFLAG_EXTENDED) != 0) {
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson memmove(&buf1[4], &buf1[6], r1.length - 6);
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson /* Remove extended flags. */
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson if ((key2->key_flags & DNS_KEYFLAG_EXTENDED) != 0) {
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson return (ISC_TF(isc_region_compare(&r1, &r2) == 0));
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafssondst_key_compare(const dst_key_t *key1, const dst_key_t *key2) {
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson return (comparekeys(key1, key2, ISC_FALSE, key1->func->compare));
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafssondst_key_pubcompare(const dst_key_t *key1, const dst_key_t *key2,
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson return (comparekeys(key1, key2, match_revoked_key, pub_compare));
fa460c223a69449eaac67ddb6abafe74f5e1ff02Michael Graffdst_key_paramcompare(const dst_key_t *key1, const dst_key_t *key2) {
fa460c223a69449eaac67ddb6abafe74f5e1ff02Michael Graff key1->func->paramcompare(key1, key2) == ISC_TRUE)
6b0ce7d29fac9df84ed34aa2d4634e754aec750dAndreas Gustafssondst_key_attach(dst_key_t *source, dst_key_t **target) {
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington REQUIRE(target != NULL && *target == NULL);
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington isc_refcount_increment(&source->refs, NULL);
fa460c223a69449eaac67ddb6abafe74f5e1ff02Michael Graff unsigned int refs;
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington isc_mem_put(mctx, key->key_name, sizeof(dns_name_t));
fa460c223a69449eaac67ddb6abafe74f5e1ff02Michael Graffdst_key_buildfilename(const dst_key_t *key, int type,
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson REQUIRE(type == DST_TYPE_PRIVATE || type == DST_TYPE_PUBLIC ||
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson return (buildfilename(key->key_name, key->key_id, key->key_alg,
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafssondst_key_sigsize(const dst_key_t *key, unsigned int *n) {
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson /* XXXVIX this switch statement is too sparse to gen a jump table. */
5cca7753fde4cbfe15d0c0c2cf1fd519f61f2e7fBrian Wellingtondst_key_secretsize(const dst_key_t *key, unsigned int *n) {
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson * Set the flags on a key, then recompute the key ID
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafssondst_key_setflags(dst_key_t *key, isc_uint32_t flags) {
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafssondst_key_format(const dst_key_t *key, char *cp, unsigned int size) {
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson dns_name_format(dst_key_name(key), namestr, sizeof(namestr));
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson dns_secalg_format((dns_secalg_t) dst_key_alg(key), algstr,
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson snprintf(cp, size, "%s/%s/%d", namestr, algstr, dst_key_id(key));
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graffdst_key_dump(dst_key_t *key, isc_mem_t *mctx, char **buffer, int *length) {
5d83b561ad7eb84885a8ec63dee4c51b335f067aBrian Wellington REQUIRE(buffer != NULL && *buffer == NULL);
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff return (key->func->dump(key, mctx, buffer, length));
8d3e74b1683f714a484bbcf73249e8ee470e36d7Mark Andrewsdst_key_restore(dns_name_t *name, unsigned int alg, unsigned int flags,
5d83b561ad7eb84885a8ec63dee4c51b335f067aBrian Wellington unsigned int protocol, dns_rdataclass_t rdclass,
5d83b561ad7eb84885a8ec63dee4c51b335f067aBrian Wellington isc_mem_t *mctx, const char *keystr, dst_key_t **keyp)
5d83b561ad7eb84885a8ec63dee4c51b335f067aBrian Wellington if (alg >= DST_MAX_ALGS || dst_t_func[alg] == NULL)
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson key = get_key_struct(name, alg, flags, protocol, 0, rdclass, 0, mctx);
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence result = (dst_t_func[alg]->restore)(key, keystr);
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson *** Static methods
54c26ab21c61c6d6b1e484bb88dc3ac263845d17Mark Andrews * Allocates a key structure and fills in some of the fields.
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafssonget_key_struct(dns_name_t *name, unsigned int alg,
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson key = (dst_key_t *) isc_mem_get(mctx, sizeof(dst_key_t));
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson isc_mem_put(mctx, key, sizeof(dst_key_t));
88ba491496daf4463a2c898be8a6c47775a6d048Mark Andrews key->key_name = isc_mem_get(mctx, sizeof(dns_name_t));
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson isc_mem_put(mctx, key, sizeof(dst_key_t));
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson result = dns_name_dup(name, mctx, key->key_name);
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson isc_mem_put(mctx, key->key_name, sizeof(dns_name_t));
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson isc_mem_put(mctx, key, sizeof(dst_key_t));
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson for (i = 0; i < (DST_MAX_TIMES + 1); i++) {
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson * Reads a public key from disk
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafssondst_key_read_public(const char *filename, int type,
3ddd92da6651bc72aa79a04195ad389d86fd1a66Andreas Gustafsson dns_rdataclass_t rdclass = dns_rdataclass_in;
54c26ab21c61c6d6b1e484bb88dc3ac263845d17Mark Andrews * Open the file and read its formatted contents
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence * File format:
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence * domain.name [ttl] [class] [KEY|DNSKEY] <flags> <protocol> <algorithm> <key>
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews /* 1500 should be large enough for any key */
fe47f41b13620bfafc4f8cf65d5df24f1e568764Bob Halley isc_lex_setcomments(lex, ISC_LEXCOMMENT_DNSMASTERFILE);
ca2912424b1d7c348186a325dd2078a37bb8d818Andreas Gustafsson /* Read the domain name */
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * We don't support "@" in .key files.
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews isc_buffer_init(&b, DST_AS_STR(token), strlen(DST_AS_STR(token)));
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews ret = dns_name_fromtext(dns_fixedname_name(&name), &b, dns_rootname,
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews /* Read the next word: either TTL, class, or 'KEY' */
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff /* If it's a TTL, read the next one */
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews result = dns_ttl_fromtext(&token.value.as_textregion, &ttl);
7d62ddffbb4d1cc97b8d80b7ee4944554a57523eMark Andrews ret = dns_rdataclass_fromtext(&rdclass, &token.value.as_textregion);
7d62ddffbb4d1cc97b8d80b7ee4944554a57523eMark Andrews if (strcasecmp(DST_AS_STR(token), "DNSKEY") == 0)
f0ff273b530afa730025e1c5ad311950f7ff4328Mark Andrews else if (strcasecmp(DST_AS_STR(token), "KEY") == 0)
7d62ddffbb4d1cc97b8d80b7ee4944554a57523eMark Andrews keytype = dns_rdatatype_key; /*%< SIG(0), TKEY */
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence if (((type & DST_TYPE_KEY) != 0 && keytype != dns_rdatatype_key) ||
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence ((type & DST_TYPE_KEY) == 0 && keytype != dns_rdatatype_dnskey)) {
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence isc_buffer_init(&b, rdatabuf, sizeof(rdatabuf));
7d62ddffbb4d1cc97b8d80b7ee4944554a57523eMark Andrews ret = dns_rdata_fromtext(&rdata, rdclass, keytype, lex, NULL,
7d62ddffbb4d1cc97b8d80b7ee4944554a57523eMark Andrews ret = dst_key_fromdns(dns_fixedname_name(&name), rdclass, &b, mctx,
7d62ddffbb4d1cc97b8d80b7ee4944554a57523eMark Andrews /* XXXVIX this switch statement is too sparse to gen a jump table. */
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews * Write key timing metadata to a file pointer, preceded by 'tag'
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsprinttime(const dst_key_t *key, int type, const char *tag, FILE *stream) {
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence char output[26]; /* Minimum buffer as per ctime_r() specification. */
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews /* time_t and isc_stdtime_t might be different sizes */
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews fprintf(stream, "%s: %.*s (%.*s)\n", tag, (int)r.length, r.base,
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews fprintf(stream, "%s: (set, unable to display)\n", tag);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * Writes a public key to disk in DNS format.
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graffwrite_public_key(const dst_key_t *key, int type, const char *directory) {
330705066b03f6ce0bc08a4bbfc5d2418038c68dBrian Wellington isc_buffer_init(&keyb, key_array, sizeof(key_array));
330705066b03f6ce0bc08a4bbfc5d2418038c68dBrian Wellington isc_buffer_init(&textb, text_array, sizeof(text_array));
330705066b03f6ce0bc08a4bbfc5d2418038c68dBrian Wellington isc_buffer_init(&classb, class_array, sizeof(class_array));
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews dns_rdata_fromregion(&rdata, key->key_class, dns_rdatatype_dnskey, &r);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews ret = dns_rdata_totext(&rdata, (dns_name_t *) NULL, &textb);
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews ret = dns_rdataclass_totext(key->key_class, &classb);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * Make the filename.
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence isc_buffer_init(&fileb, filename, sizeof(filename));
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews ret = dst_key_buildfilename(key, DST_TYPE_PUBLIC, directory, &fileb);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * Create public key file.
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews /* Write key information in comments */
5a219d878f0bd786e86da2c9b92999260dda3f8dAndreas Gustafsson fprintf(fp, "; This is a %s%s-signing key, keyid %d, for ",
5a219d878f0bd786e86da2c9b92999260dda3f8dAndreas Gustafsson (key->key_flags & DNS_KEYFLAG_REVOKE) != 0 ?
5466ce3f279d9fa83ce826bcdc9482bc591152aeAndreas Gustafsson printtime(key, DST_TIME_CREATED, "; Created", fp);
5466ce3f279d9fa83ce826bcdc9482bc591152aeAndreas Gustafsson printtime(key, DST_TIME_PUBLISH, "; Publish", fp);
5466ce3f279d9fa83ce826bcdc9482bc591152aeAndreas Gustafsson printtime(key, DST_TIME_ACTIVATE, "; Activate", fp);
5466ce3f279d9fa83ce826bcdc9482bc591152aeAndreas Gustafsson printtime(key, DST_TIME_REVOKE, "; Revoke", fp);
15330e4fa27c82ac04cc2ce234ec930e4b6b42d3Mark Andrews printtime(key, DST_TIME_INACTIVE, "; Inactive", fp);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews printtime(key, DST_TIME_DELETE, "; Delete", fp);
035504dbd8ca5949e8380b860873b3385a4e61e5Mark Andrews /* Now print the actual key */
15330e4fa27c82ac04cc2ce234ec930e4b6b42d3Mark Andrews if ((unsigned) fwrite(r.base, 1, r.length, fp) != r.length)
5a219d878f0bd786e86da2c9b92999260dda3f8dAndreas Gustafsson if ((unsigned) fwrite(r.base, 1, r.length, fp) != r.length)
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graffbuildfilename(dns_name_t *name, dns_keytag_t id,
44a966dff66061ac3f266c6b451a70733eb78e82Mark Andrews unsigned int len;
44a966dff66061ac3f266c6b451a70733eb78e82Mark Andrews if (isc_buffer_availablelength(out) < strlen(directory))
47b26abe77184f9bedc68e36bdad03332cf67570David Lawrence result = dns_name_tofilenametext(name, ISC_FALSE, out);
47b26abe77184f9bedc68e36bdad03332cf67570David Lawrence sprintf((char *) isc_buffer_used(out), "+%03d+%05d%s", alg, id,
47b26abe77184f9bedc68e36bdad03332cf67570David Lawrence isc_buffer_init(&dnsbuf, dns_array, sizeof(dns_array));
8a17d1e7cdba9fdcf71fb2f821a954a251204105Mark Andrews key->key_id = dst_region_computeid(&r, key->key_alg);
3a4ec3da9fa14511cbc3660f75817cfacb3f4d1eMark Andrews key->key_rid = dst_region_computerid(&r, key->key_alg);
3a4ec3da9fa14511cbc3660f75817cfacb3f4d1eMark Andrewsfrombuffer(dns_name_t *name, unsigned int alg, unsigned int flags,
3a4ec3da9fa14511cbc3660f75817cfacb3f4d1eMark Andrews unsigned int protocol, dns_rdataclass_t rdclass,
3a4ec3da9fa14511cbc3660f75817cfacb3f4d1eMark Andrews isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp)
3a4ec3da9fa14511cbc3660f75817cfacb3f4d1eMark Andrews key = get_key_struct(name, alg, flags, protocol, 0, rdclass, 0, mctx);
3a4ec3da9fa14511cbc3660f75817cfacb3f4d1eMark Andrews if (alg == DST_ALG_RSAMD5 || alg == DST_ALG_RSASHA1 ||
3a4ec3da9fa14511cbc3660f75817cfacb3f4d1eMark Andrews alg == DST_ALG_HMACMD5 || alg == DST_ALG_NSEC3DSA ||
3a4ec3da9fa14511cbc3660f75817cfacb3f4d1eMark Andrews alg == DST_ALG_RSASHA256 || alg == DST_ALG_RSASHA512 ||
3a4ec3da9fa14511cbc3660f75817cfacb3f4d1eMark Andrews alg == DST_ALG_ECDSA256 || alg == DST_ALG_ECDSA384)
3a4ec3da9fa14511cbc3660f75817cfacb3f4d1eMark Andrewsaddsuffix(char *filename, int len, const char *odirname,
3a4ec3da9fa14511cbc3660f75817cfacb3f4d1eMark Andrews else if (olen > 8 && strcmp(ofilename + olen - 8, ".private") == 0)
3a4ec3da9fa14511cbc3660f75817cfacb3f4d1eMark Andrews else if (olen > 4 && strcmp(ofilename + olen - 4, ".key") == 0)
3a4ec3da9fa14511cbc3660f75817cfacb3f4d1eMark Andrews n = snprintf(filename, len, "%.*s%s", olen, ofilename, suffix);
3a4ec3da9fa14511cbc3660f75817cfacb3f4d1eMark Andrewsdst__entropy_getdata(void *buf, unsigned int len, isc_boolean_t pseudo) {
3a4ec3da9fa14511cbc3660f75817cfacb3f4d1eMark Andrews return (isc_entropy_getdata(dst_entropy_pool, buf, len, NULL, flags));
3a4ec3da9fa14511cbc3660f75817cfacb3f4d1eMark Andrews /* Someone believes RAND_status() initializes the PRNG */