diff options
Diffstat (limited to '')
-rw-r--r-- | lib/dns/include/dst/dst.h | 1245 | ||||
-rw-r--r-- | lib/dns/include/dst/gssapi.h | 192 |
2 files changed, 1437 insertions, 0 deletions
diff --git a/lib/dns/include/dst/dst.h b/lib/dns/include/dst/dst.h new file mode 100644 index 0000000..ca292b0 --- /dev/null +++ b/lib/dns/include/dst/dst.h @@ -0,0 +1,1245 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#pragma once + +/*! \file dst/dst.h */ + +#include <inttypes.h> +#include <stdbool.h> + +#include <isc/lang.h> +#include <isc/stdtime.h> + +#include <dns/ds.h> +#include <dns/dsdigest.h> +#include <dns/log.h> +#include <dns/name.h> +#include <dns/secalg.h> +#include <dns/types.h> + +#include <dst/gssapi.h> + +ISC_LANG_BEGINDECLS + +/*** + *** Types + ***/ + +/*% + * The dst_key structure is opaque. Applications should use the accessor + * functions provided to retrieve key attributes. If an application needs + * to set attributes, new accessor functions will be written. + */ + +typedef struct dst_key dst_key_t; +typedef struct dst_context dst_context_t; + +/*% + * Key states for the DNSSEC records related to a key: DNSKEY, RRSIG (ksk), + * RRSIG (zsk), and DS. + * + * DST_KEY_STATE_HIDDEN: Records of this type are not published in zone. + * This may be because the key parts were never + * introduced in the zone, or because the key has + * retired and has no records of this type left in + * the zone. + * DST_KEY_STATE_RUMOURED: Records of this type are published in zone, but + * not long enough to ensure all resolvers know + * about it. + * DST_KEY_STATE_OMNIPRESENT: Records of this type are published in zone long + * enough so that all resolvers that know about + * these records, no longer have outdated data. + * DST_KEY_STATE_UNRETENTIVE: Records of this type have been removed from the + * zone, but there may be resolvers that still have + * have predecessor records cached. Note that RRSIG + * records in this state may actually still be in the + * zone because they are reused, but retired RRSIG + * records will never be refreshed: A successor key + * is used to create signatures. + * DST_KEY_STATE_NA: The state is not applicable for this record type. + */ +typedef enum dst_key_state { + DST_KEY_STATE_HIDDEN = 0, + DST_KEY_STATE_RUMOURED = 1, + DST_KEY_STATE_OMNIPRESENT = 2, + DST_KEY_STATE_UNRETENTIVE = 3, + DST_KEY_STATE_NA = 4 +} dst_key_state_t; + +/* DST algorithm codes */ +typedef enum dst_algorithm { + DST_ALG_UNKNOWN = 0, + DST_ALG_RSA = 1, /* Used for parsing RSASHA1, RSASHA256 and RSASHA512 */ + DST_ALG_RSAMD5 = 1, + DST_ALG_DH = 2, + DST_ALG_DSA = 3, + DST_ALG_ECC = 4, + DST_ALG_RSASHA1 = 5, + DST_ALG_NSEC3DSA = 6, + DST_ALG_NSEC3RSASHA1 = 7, + DST_ALG_RSASHA256 = 8, + DST_ALG_RSASHA512 = 10, + DST_ALG_ECCGOST = 12, + DST_ALG_ECDSA256 = 13, + DST_ALG_ECDSA384 = 14, + DST_ALG_ED25519 = 15, + DST_ALG_ED448 = 16, + + /* + * Do not renumber HMAC algorithms as they are used externally to named + * in legacy K* key pair files. + * Do not add non HMAC between DST_ALG_HMACMD5 and DST_ALG_HMACSHA512. + */ + DST_ALG_HMACMD5 = 157, + DST_ALG_HMAC_FIRST = DST_ALG_HMACMD5, + DST_ALG_GSSAPI = 160, /* Internal use only. Exception. */ + DST_ALG_HMACSHA1 = 161, /* XXXMPA */ + DST_ALG_HMACSHA224 = 162, /* XXXMPA */ + DST_ALG_HMACSHA256 = 163, /* XXXMPA */ + DST_ALG_HMACSHA384 = 164, /* XXXMPA */ + DST_ALG_HMACSHA512 = 165, /* XXXMPA */ + DST_ALG_HMAC_LAST = DST_ALG_HMACSHA512, + + DST_ALG_INDIRECT = 252, + DST_ALG_PRIVATE = 254, + DST_MAX_ALGS = 256, +} dst_algorithm_t; + +/*% A buffer of this size is large enough to hold any key */ +#define DST_KEY_MAXSIZE 1280 + +/*% + * A buffer of this size is large enough to hold the textual representation + * of any key + */ +#define DST_KEY_MAXTEXTSIZE 2048 + +/*% 'Type' for dst_read_key() */ +#define DST_TYPE_KEY 0x1000000 /* KEY key */ +#define DST_TYPE_PRIVATE 0x2000000 +#define DST_TYPE_PUBLIC 0x4000000 +#define DST_TYPE_STATE 0x8000000 +#define DST_TYPE_TEMPLATE 0x10000000 + +/* Key timing metadata definitions */ +#define DST_TIME_CREATED 0 +#define DST_TIME_PUBLISH 1 +#define DST_TIME_ACTIVATE 2 +#define DST_TIME_REVOKE 3 +#define DST_TIME_INACTIVE 4 +#define DST_TIME_DELETE 5 +#define DST_TIME_DSPUBLISH 6 +#define DST_TIME_SYNCPUBLISH 7 +#define DST_TIME_SYNCDELETE 8 +#define DST_TIME_DNSKEY 9 +#define DST_TIME_ZRRSIG 10 +#define DST_TIME_KRRSIG 11 +#define DST_TIME_DS 12 +#define DST_TIME_DSDELETE 13 +#define DST_MAX_TIMES 13 + +/* Numeric metadata definitions */ +#define DST_NUM_PREDECESSOR 0 +#define DST_NUM_SUCCESSOR 1 +#define DST_NUM_MAXTTL 2 +#define DST_NUM_ROLLPERIOD 3 +#define DST_NUM_LIFETIME 4 +#define DST_NUM_DSPUBCOUNT 5 +#define DST_NUM_DSDELCOUNT 6 +#define DST_MAX_NUMERIC 6 + +/* Boolean metadata definitions */ +#define DST_BOOL_KSK 0 +#define DST_BOOL_ZSK 1 +#define DST_MAX_BOOLEAN 1 + +/* Key state metadata definitions */ +#define DST_KEY_DNSKEY 0 +#define DST_KEY_ZRRSIG 1 +#define DST_KEY_KRRSIG 2 +#define DST_KEY_DS 3 +#define DST_KEY_GOAL 4 +#define DST_MAX_KEYSTATES 4 + +/* + * Current format version number of the private key parser. + * + * When parsing a key file with the same major number but a higher minor + * number, the key parser will ignore any fields it does not recognize. + * Thus, DST_MINOR_VERSION should be incremented whenever new + * fields are added to the private key file (such as new metadata). + * + * When rewriting these keys, those fields will be dropped, and the + * format version set back to the current one.. + * + * When a key is seen with a higher major number, the key parser will + * reject it as invalid. Thus, DST_MAJOR_VERSION should be incremented + * and DST_MINOR_VERSION set to zero whenever there is a format change + * which is not backward compatible to previous versions of the dst_key + * parser, such as change in the syntax of an existing field, the removal + * of a currently mandatory field, or a new field added which would + * alter the functioning of the key if it were absent. + */ +#define DST_MAJOR_VERSION 1 +#define DST_MINOR_VERSION 3 + +/*** + *** Functions + ***/ +isc_result_t +dst_lib_init(isc_mem_t *mctx, const char *engine); +/*%< + * Initializes the DST subsystem. + * + * Requires: + * \li "mctx" is a valid memory context + * + * Returns: + * \li ISC_R_SUCCESS + * \li ISC_R_NOMEMORY + * \li DST_R_NOENGINE + * + * Ensures: + * \li DST is properly initialized. + */ + +void +dst_lib_destroy(void); +/*%< + * Releases all resources allocated by DST. + */ + +bool +dst_algorithm_supported(unsigned int alg); +/*%< + * Checks that a given algorithm is supported by DST. + * + * Returns: + * \li true + * \li false + */ + +bool +dst_ds_digest_supported(unsigned int digest_type); +/*%< + * Checks that a given digest algorithm is supported by DST. + * + * Returns: + * \li true + * \li false + */ + +isc_result_t +dst_context_create(dst_key_t *key, isc_mem_t *mctx, isc_logcategory_t *category, + bool useforsigning, int maxbits, dst_context_t **dctxp); +/*%< + * Creates a context to be used for a sign or verify operation. + * + * Requires: + * \li "key" is a valid key. + * \li "mctx" is a valid memory context. + * \li dctxp != NULL && *dctxp == NULL + * + * Returns: + * \li ISC_R_SUCCESS + * \li ISC_R_NOMEMORY + * + * Ensures: + * \li *dctxp will contain a usable context. + */ + +void +dst_context_destroy(dst_context_t **dctxp); +/*%< + * Destroys all memory associated with a context. + * + * Requires: + * \li *dctxp != NULL && *dctxp == NULL + * + * Ensures: + * \li *dctxp == NULL + */ + +isc_result_t +dst_context_adddata(dst_context_t *dctx, const isc_region_t *data); +/*%< + * Incrementally adds data to the context to be used in a sign or verify + * operation. + * + * Requires: + * \li "dctx" is a valid context + * \li "data" is a valid region + * + * Returns: + * \li ISC_R_SUCCESS + * \li DST_R_SIGNFAILURE + * \li all other errors indicate failure + */ + +isc_result_t +dst_context_sign(dst_context_t *dctx, isc_buffer_t *sig); +/*%< + * Computes a signature using the data and key stored in the context. + * + * Requires: + * \li "dctx" is a valid context. + * \li "sig" is a valid buffer. + * + * Returns: + * \li ISC_R_SUCCESS + * \li DST_R_VERIFYFAILURE + * \li all other errors indicate failure + * + * Ensures: + * \li "sig" will contain the signature + */ + +isc_result_t +dst_context_verify(dst_context_t *dctx, isc_region_t *sig); + +isc_result_t +dst_context_verify2(dst_context_t *dctx, unsigned int maxbits, + isc_region_t *sig); +/*%< + * Verifies the signature using the data and key stored in the context. + * + * 'maxbits' specifies the maximum number of bits permitted in the RSA + * exponent. + * + * Requires: + * \li "dctx" is a valid context. + * \li "sig" is a valid region. + * + * Returns: + * \li ISC_R_SUCCESS + * \li all other errors indicate failure + * + * Ensures: + * \li "sig" will contain the signature + */ + +isc_result_t +dst_key_computesecret(const dst_key_t *pub, const dst_key_t *priv, + isc_buffer_t *secret); +/*%< + * Computes a shared secret from two (Diffie-Hellman) keys. + * + * Requires: + * \li "pub" is a valid key that can be used to derive a shared secret + * \li "priv" is a valid private key that can be used to derive a shared secret + * \li "secret" is a valid buffer + * + * Returns: + * \li ISC_R_SUCCESS + * \li any other result indicates failure + * + * Ensures: + * \li If successful, secret will contain the derived shared secret. + */ + +isc_result_t +dst_key_getfilename(dns_name_t *name, dns_keytag_t id, unsigned int alg, + int type, const char *directory, isc_mem_t *mctx, + isc_buffer_t *buf); +/*%< + * Generates a key filename for the name, algorithm, and + * id, and places it in the buffer 'buf'. If directory is NULL, the + * current directory is assumed. + * + * Requires: + * \li "name" is a valid absolute dns name. + * \li "id" is a valid key tag identifier. + * \li "alg" is a supported key algorithm. + * \li "type" is DST_TYPE_PUBLIC, DST_TYPE_PRIVATE, or the bitwise union. + * DST_TYPE_KEY look for a KEY record otherwise DNSKEY + * \li "mctx" is a valid memory context. + * \li "buf" is not NULL. + * + * Returns: + * \li ISC_R_SUCCESS + * \li any other result indicates failure + */ + +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); +/*%< + * Reads a key from permanent storage. The key can either be a public or + * private key, or a key state. It specified by name, algorithm, and id. If + * a private key or key state is specified, the public key must also be + * present. If directory is NULL, the current directory is assumed. + * + * Requires: + * \li "name" is a valid absolute dns name. + * \li "id" is a valid key tag identifier. + * \li "alg" is a supported key algorithm. + * \li "type" is DST_TYPE_PUBLIC, DST_TYPE_PRIVATE or the bitwise union. + * DST_TYPE_KEY look for a KEY record otherwise DNSKEY. + * DST_TYPE_STATE to also read the key state. + * \li "mctx" is a valid memory context. + * \li "keyp" is not NULL and "*keyp" is NULL. + * + * Returns: + * \li ISC_R_SUCCESS + * \li any other result indicates failure + * + * Ensures: + * \li If successful, *keyp will contain a valid key. + */ + +isc_result_t +dst_key_fromnamedfile(const char *filename, const char *dirname, int type, + isc_mem_t *mctx, dst_key_t **keyp); +/*%< + * Reads a key from permanent storage. The key can either be a public or + * private key, or a key state. It is specified by filename. If a private key + * or key state is specified, the public key must also be present. + * + * If 'dirname' is not NULL, and 'filename' is a relative path, + * then the file is looked up relative to the given directory. + * If 'filename' is an absolute path, 'dirname' is ignored. + * + * Requires: + * \li "filename" is not NULL + * \li "type" is DST_TYPE_PUBLIC, DST_TYPE_PRIVATE, or the bitwise union. + * DST_TYPE_KEY look for a KEY record otherwise DNSKEY. + * DST_TYPE_STATE to also read the key state. + * \li "mctx" is a valid memory context + * \li "keyp" is not NULL and "*keyp" is NULL. + * + * Returns: + * \li ISC_R_SUCCESS + * \li any other result indicates failure + * + * Ensures: + * \li If successful, *keyp will contain a valid key. + */ + +isc_result_t +dst_key_read_public(const char *filename, int type, isc_mem_t *mctx, + dst_key_t **keyp); +/*%< + * Reads a public key from permanent storage. The key must be a public key. + * + * Requires: + * \li "filename" is not NULL. + * \li "type" is DST_TYPE_KEY look for a KEY record otherwise DNSKEY. + * \li "mctx" is a valid memory context. + * \li "keyp" is not NULL and "*keyp" is NULL. + * + * Returns: + * \li ISC_R_SUCCESS + * \li DST_R_BADKEYTYPE if the key type is not the expected one + * \li ISC_R_UNEXPECTEDTOKEN if the file can not be parsed as a public key + * \li any other result indicates failure + * + * Ensures: + * \li If successful, *keyp will contain a valid key. + */ + +isc_result_t +dst_key_read_state(const char *filename, isc_mem_t *mctx, dst_key_t **keyp); +/*%< + * Reads a key state from permanent storage. + * + * Requires: + * \li "filename" is not NULL. + * \li "mctx" is a valid memory context. + * \li "keyp" is not NULL and "*keyp" is NULL. + * + * Returns: + * \li ISC_R_SUCCESS + * \li ISC_R_UNEXPECTEDTOKEN if the file can not be parsed as a public key + * \li any other result indicates failure + */ + +isc_result_t +dst_key_tofile(const dst_key_t *key, int type, const char *directory); +/*%< + * Writes a key to permanent storage. The key can either be a public or + * private key. Public keys are written in DNS format and private keys + * are written as a set of base64 encoded values. If directory is NULL, + * the current directory is assumed. + * + * Requires: + * \li "key" is a valid key. + * \li "type" is DST_TYPE_PUBLIC, DST_TYPE_PRIVATE, or the bitwise union + * + * Returns: + * \li ISC_R_SUCCESS + * \li any other result indicates failure + */ + +isc_result_t +dst_key_fromdns(const dns_name_t *name, dns_rdataclass_t rdclass, + isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp); +/*%< + * Converts a DNS KEY record into a DST key. + * + * Requires: + * \li "name" is a valid absolute dns name. + * \li "source" is a valid buffer. There must be at least 4 bytes available. + * \li "mctx" is a valid memory context. + * \li "keyp" is not NULL and "*keyp" is NULL. + * + * Returns: + * \li ISC_R_SUCCESS + * \li any other result indicates failure + * + * Ensures: + * \li If successful, *keyp will contain a valid key, and the consumed + * pointer in data will be advanced. + */ + +isc_result_t +dst_key_todns(const dst_key_t *key, isc_buffer_t *target); +/*%< + * Converts a DST key into a DNS KEY record. + * + * Requires: + * \li "key" is a valid key. + * \li "target" is a valid buffer. There must be at least 4 bytes unused. + * + * Returns: + * \li ISC_R_SUCCESS + * \li any other result indicates failure + * + * Ensures: + * \li If successful, the used pointer in 'target' is advanced by at least 4. + */ + +isc_result_t +dst_key_frombuffer(const 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); +/*%< + * Converts a buffer containing DNS KEY RDATA into a DST key. + * + * Requires: + *\li "name" is a valid absolute dns name. + *\li "alg" is a supported key algorithm. + *\li "source" is a valid buffer. + *\li "mctx" is a valid memory context. + *\li "keyp" is not NULL and "*keyp" is NULL. + * + * Returns: + *\li ISC_R_SUCCESS + * \li any other result indicates failure + * + * Ensures: + *\li If successful, *keyp will contain a valid key, and the consumed + * pointer in source will be advanced. + */ + +isc_result_t +dst_key_tobuffer(const dst_key_t *key, isc_buffer_t *target); +/*%< + * Converts a DST key into DNS KEY RDATA format. + * + * Requires: + *\li "key" is a valid key. + *\li "target" is a valid buffer. + * + * Returns: + *\li ISC_R_SUCCESS + * \li any other result indicates failure + * + * Ensures: + *\li If successful, the used pointer in 'target' is advanced. + */ + +isc_result_t +dst_key_privatefrombuffer(dst_key_t *key, isc_buffer_t *buffer); +/*%< + * Converts a public key into a private key, reading the private key + * information from the buffer. The buffer should contain the same data + * as the .private key file would. + * + * Requires: + *\li "key" is a valid public key. + *\li "buffer" is not NULL. + * + * Returns: + *\li ISC_R_SUCCESS + * \li any other result indicates failure + * + * Ensures: + *\li If successful, key will contain a valid private key. + */ + +dns_gss_ctx_id_t +dst_key_getgssctx(const dst_key_t *key); +/*%< + * Returns the opaque key data. + * Be cautions when using this value unless you know what you are doing. + * + * Requires: + *\li "key" is not NULL. + * + * Returns: + *\li gssctx key data, possibly NULL. + */ + +isc_result_t +dst_key_fromgssapi(const dns_name_t *name, dns_gss_ctx_id_t gssctx, + isc_mem_t *mctx, dst_key_t **keyp, isc_region_t *intoken); +/*%< + * Converts a GSSAPI opaque context id into a DST key. + * + * Requires: + *\li "name" is a valid absolute dns name. + *\li "gssctx" is a GSSAPI context id. + *\li "mctx" is a valid memory context. + *\li "keyp" is not NULL and "*keyp" is NULL. + * + * Returns: + *\li ISC_R_SUCCESS + * \li any other result indicates failure + * + * Ensures: + *\li If successful, *keyp will contain a valid key and be responsible for + * the context id. + */ + +#ifdef DST_KEY_INTERNAL +isc_result_t +dst_key_buildinternal(const 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); +#endif /* ifdef DST_KEY_INTERNAL */ + +isc_result_t +dst_key_fromlabel(const 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); + +isc_result_t +dst_key_generate(const 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)); + +/*%< + * Generate a DST key (or keypair) with the supplied parameters. The + * interpretation of the "param" field depends on the algorithm: + * \code + * RSA: exponent + * 0 use exponent 3 + * !0 use Fermat4 (2^16 + 1) + * DH: generator + * 0 default - use well known prime if bits == 768 or 1024, + * otherwise use 2 as the generator. + * !0 use this value as the generator. + * DSA: unused + * HMACMD5: entropy + * 0 default - require good entropy + * !0 lack of good entropy is ok + *\endcode + * + * Requires: + *\li "name" is a valid absolute dns name. + *\li "keyp" is not NULL and "*keyp" is NULL. + * + * Returns: + *\li ISC_R_SUCCESS + * \li any other result indicates failure + * + * Ensures: + *\li If successful, *keyp will contain a valid key. + */ + +bool +dst_key_compare(const dst_key_t *key1, const dst_key_t *key2); +/*%< + * Compares two DST keys. Returns true if they match, false otherwise. + * + * Keys ARE NOT considered to match if one of them is the revoked version + * of the other. + * + * Requires: + *\li "key1" is a valid key. + *\li "key2" is a valid key. + * + * Returns: + *\li true + * \li false + */ + +bool +dst_key_pubcompare(const dst_key_t *key1, const dst_key_t *key2, + bool match_revoked_key); +/*%< + * Compares only the public portions of two DST keys. Returns true + * if they match, false otherwise. This allows us, for example, to + * determine whether a public key found in a zone matches up with a + * key pair found on disk. + * + * If match_revoked_key is TRUE, then keys ARE considered to match if one + * of them is the revoked version of the other. Otherwise, they are not. + * + * Requires: + *\li "key1" is a valid key. + *\li "key2" is a valid key. + * + * Returns: + *\li true + * \li false + */ + +bool +dst_key_paramcompare(const dst_key_t *key1, const dst_key_t *key2); +/*%< + * Compares the parameters of two DST keys. This is used to determine if + * two (Diffie-Hellman) keys can be used to derive a shared secret. + * + * Requires: + *\li "key1" is a valid key. + *\li "key2" is a valid key. + * + * Returns: + *\li true + * \li false + */ + +void +dst_key_attach(dst_key_t *source, dst_key_t **target); +/* + * Attach to a existing key increasing the reference count. + * + * Requires: + *\li 'source' to be a valid key. + *\li 'target' to be non-NULL and '*target' to be NULL. + */ + +void +dst_key_free(dst_key_t **keyp); +/*%< + * Decrement the key's reference counter and, when it reaches zero, + * release all memory associated with the key. + * + * Requires: + *\li "keyp" is not NULL and "*keyp" is a valid key. + *\li reference counter greater than zero. + * + * Ensures: + *\li All memory associated with "*keyp" will be freed. + *\li *keyp == NULL + */ + +/*%< + * Accessor functions to obtain key fields. + * + * Require: + *\li "key" is a valid key. + */ +dns_name_t * +dst_key_name(const dst_key_t *key); + +unsigned int +dst_key_size(const dst_key_t *key); + +unsigned int +dst_key_proto(const dst_key_t *key); + +unsigned int +dst_key_alg(const dst_key_t *key); + +uint32_t +dst_key_flags(const dst_key_t *key); + +dns_keytag_t +dst_key_id(const dst_key_t *key); + +dns_keytag_t +dst_key_rid(const dst_key_t *key); + +dns_rdataclass_t +dst_key_class(const dst_key_t *key); + +bool +dst_key_isprivate(const dst_key_t *key); + +bool +dst_key_iszonekey(const dst_key_t *key); + +bool +dst_key_isnullkey(const dst_key_t *key); + +isc_result_t +dst_key_buildfilename(const dst_key_t *key, int type, const char *directory, + isc_buffer_t *out); +/*%< + * Generates the filename used by dst to store the specified key. + * If directory is NULL, the current directory is assumed. + * If tmp is not NULL, generates a template for mkstemp(). + * + * Requires: + *\li "key" is a valid key + *\li "type" is either DST_TYPE_PUBLIC, DST_TYPE_PRIVATE, or 0 for no suffix. + *\li "out" is a valid buffer + *\li "tmp" is a valid buffer or NULL + * + * Ensures: + *\li the file name will be written to "out", and the used pointer will + * be advanced. + */ + +isc_result_t +dst_key_sigsize(const dst_key_t *key, unsigned int *n); +/*%< + * Computes the size of a signature generated by the given key. + * + * Requires: + *\li "key" is a valid key. + *\li "n" is not NULL + * + * Returns: + *\li #ISC_R_SUCCESS + *\li DST_R_UNSUPPORTEDALG + * + * Ensures: + *\li "n" stores the size of a generated signature + */ + +isc_result_t +dst_key_secretsize(const dst_key_t *key, unsigned int *n); +/*%< + * Computes the size of a shared secret generated by the given key. + * + * Requires: + *\li "key" is a valid key. + *\li "n" is not NULL + * + * Returns: + *\li #ISC_R_SUCCESS + *\li DST_R_UNSUPPORTEDALG + * + * Ensures: + *\li "n" stores the size of a generated shared secret + */ + +uint16_t +dst_region_computeid(const isc_region_t *source); +uint16_t +dst_region_computerid(const isc_region_t *source); +/*%< + * Computes the (revoked) key id of the key stored in the provided + * region. + * + * Requires: + *\li "source" contains a valid, non-NULL region. + * + * Returns: + *\li the key id + */ + +uint16_t +dst_key_getbits(const dst_key_t *key); +/*%< + * Get the number of digest bits required (0 == MAX). + * + * Requires: + * "key" is a valid key. + */ + +void +dst_key_setbits(dst_key_t *key, uint16_t bits); +/*%< + * Set the number of digest bits required (0 == MAX). + * + * Requires: + * "key" is a valid key. + */ + +void +dst_key_setttl(dst_key_t *key, dns_ttl_t ttl); +/*%< + * Set the default TTL to use when converting the key + * to a KEY or DNSKEY RR. + * + * Requires: + * "key" is a valid key. + */ + +dns_ttl_t +dst_key_getttl(const dst_key_t *key); +/*%< + * Get the default TTL to use when converting the key + * to a KEY or DNSKEY RR. + * + * Requires: + * "key" is a valid key. + */ + +isc_result_t +dst_key_setflags(dst_key_t *key, uint32_t flags); +/* + * Set the key flags, and recompute the key ID. + * + * Requires: + * "key" is a valid key. + */ + +isc_result_t +dst_key_getbool(const dst_key_t *key, int type, bool *valuep); +/*%< + * Get a member of the boolean metadata array and place it in '*valuep'. + * + * Requires: + * "key" is a valid key. + * "type" is no larger than DST_MAX_BOOLEAN + * "valuep" is not null. + */ + +void +dst_key_setbool(dst_key_t *key, int type, bool value); +/*%< + * Set a member of the boolean metadata array. + * + * Requires: + * "key" is a valid key. + * "type" is no larger than DST_MAX_BOOLEAN + */ + +void +dst_key_unsetbool(dst_key_t *key, int type); +/*%< + * Flag a member of the boolean metadata array as "not set". + * + * Requires: + * "key" is a valid key. + * "type" is no larger than DST_MAX_BOOLEAN + */ + +isc_result_t +dst_key_getnum(const dst_key_t *key, int type, uint32_t *valuep); +/*%< + * Get a member of the numeric metadata array and place it in '*valuep'. + * + * Requires: + * "key" is a valid key. + * "type" is no larger than DST_MAX_NUMERIC + * "valuep" is not null. + */ + +void +dst_key_setnum(dst_key_t *key, int type, uint32_t value); +/*%< + * Set a member of the numeric metadata array. + * + * Requires: + * "key" is a valid key. + * "type" is no larger than DST_MAX_NUMERIC + */ + +void +dst_key_unsetnum(dst_key_t *key, int type); +/*%< + * Flag a member of the numeric metadata array as "not set". + * + * Requires: + * "key" is a valid key. + * "type" is no larger than DST_MAX_NUMERIC + */ + +isc_result_t +dst_key_gettime(const dst_key_t *key, int type, isc_stdtime_t *timep); +/*%< + * Get a member of the timing metadata array and place it in '*timep'. + * + * Requires: + * "key" is a valid key. + * "type" is no larger than DST_MAX_TIMES + * "timep" is not null. + */ + +void +dst_key_settime(dst_key_t *key, int type, isc_stdtime_t when); +/*%< + * Set a member of the timing metadata array. + * + * Requires: + * "key" is a valid key. + * "type" is no larger than DST_MAX_TIMES + */ + +void +dst_key_unsettime(dst_key_t *key, int type); +/*%< + * Flag a member of the timing metadata array as "not set". + * + * Requires: + * "key" is a valid key. + * "type" is no larger than DST_MAX_TIMES + */ + +isc_result_t +dst_key_getstate(const dst_key_t *key, int type, dst_key_state_t *statep); +/*%< + * Get a member of the keystate metadata array and place it in '*statep'. + * + * Requires: + * "key" is a valid key. + * "type" is no larger than DST_MAX_KEYSTATES + * "statep" is not null. + */ + +void +dst_key_setstate(dst_key_t *key, int type, dst_key_state_t state); +/*%< + * Set a member of the keystate metadata array. + * + * Requires: + * "key" is a valid key. + * "state" is a valid state. + * "type" is no larger than DST_MAX_KEYSTATES + */ + +void +dst_key_unsetstate(dst_key_t *key, int type); +/*%< + * Flag a member of the keystate metadata array as "not set". + * + * Requires: + * "key" is a valid key. + * "type" is no larger than DST_MAX_KEYSTATES + */ + +isc_result_t +dst_key_getprivateformat(const dst_key_t *key, int *majorp, int *minorp); +/*%< + * Get the private key format version number. (If the key does not have + * a private key associated with it, the version will be 0.0.) The major + * version number is placed in '*majorp', and the minor version number in + * '*minorp'. + * + * Requires: + * "key" is a valid key. + * "majorp" is not NULL. + * "minorp" is not NULL. + */ + +void +dst_key_setprivateformat(dst_key_t *key, int major, int minor); +/*%< + * Set the private key format version number. + * + * Requires: + * "key" is a valid key. + */ + +#define DST_KEY_FORMATSIZE (DNS_NAME_FORMATSIZE + DNS_SECALG_FORMATSIZE + 7) + +void +dst_key_format(const dst_key_t *key, char *cp, unsigned int size); +/*%< + * Write the uniquely identifying information about the key (name, + * algorithm, key ID) into a string 'cp' of size 'size'. + */ + +isc_buffer_t * +dst_key_tkeytoken(const dst_key_t *key); +/*%< + * Return the token from the TKEY request, if any. If this key was + * not negotiated via TKEY, return NULL. + * + * Requires: + * "key" is a valid key. + */ + +isc_result_t +dst_key_dump(dst_key_t *key, isc_mem_t *mctx, char **buffer, int *length); +/*%< + * Allocate 'buffer' and dump the key into it in base64 format. The buffer + * is not NUL terminated. The length of the buffer is returned in *length. + * + * 'buffer' needs to be freed using isc_mem_put(mctx, buffer, length); + * + * Requires: + * 'buffer' to be non NULL and *buffer to be NULL. + * 'length' to be non NULL and *length to be zero. + * + * Returns: + * ISC_R_SUCCESS + * ISC_R_NOMEMORY + * ISC_R_NOTIMPLEMENTED + * others. + */ + +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); + +bool +dst_key_inactive(const dst_key_t *key); +/*%< + * Determines if the private key is missing due the key being deemed inactive. + * + * Requires: + * 'key' to be valid. + */ + +void +dst_key_setinactive(dst_key_t *key, bool inactive); +/*%< + * Set key inactive state. + * + * Requires: + * 'key' to be valid. + */ + +void +dst_key_setexternal(dst_key_t *key, bool value); +/*%< + * Set key external state. + * + * Requires: + * 'key' to be valid. + */ + +bool +dst_key_isexternal(dst_key_t *key); +/*%< + * Check if this is an external key. + * + * Requires: + * 'key' to be valid. + */ + +void +dst_key_setmodified(dst_key_t *key, bool value); +/*%< + * If 'value' is true, this marks the key to indicate that key file metadata + * has been modified. If 'value' is false, this resets the value, for example + * after you have written the key to file. + * + * Requires: + * 'key' to be valid. + */ + +bool +dst_key_ismodified(const dst_key_t *key); +/*%< + * Check if the key file has been modified. + * + * Requires: + * 'key' to be valid. + */ + +bool +dst_key_haskasp(dst_key_t *key); +/*%< + * Check if this key has state (and thus uses KASP). + * + * Requires: + * 'key' to be valid. + */ + +bool +dst_key_is_unused(dst_key_t *key); +/*%< + * Check if this key is unused. + * + * Requires: + * 'key' to be valid. + */ + +bool +dst_key_is_published(dst_key_t *key, isc_stdtime_t now, isc_stdtime_t *publish); +/*%< + * Check if it is safe to publish this key (e.g. put the DNSKEY in the zone). + * + * Requires: + * 'key' to be valid. + */ + +bool +dst_key_is_active(dst_key_t *key, isc_stdtime_t now); +/*%< + * Check if this key is active. This means that it is creating RRSIG records + * (ZSK), or that it is used to create a chain of trust (KSK), or both (CSK). + * + * Requires: + * 'key' to be valid. + */ + +bool +dst_key_is_signing(dst_key_t *key, int role, isc_stdtime_t now, + isc_stdtime_t *active); +/*%< + * Check if it is safe to use this key for signing, given the role. + * + * Requires: + * 'key' to be valid. + */ + +bool +dst_key_is_revoked(dst_key_t *key, isc_stdtime_t now, isc_stdtime_t *revoke); +/*%< + * Check if this key is revoked. + * + * Requires: + * 'key' to be valid. + */ + +bool +dst_key_is_removed(dst_key_t *key, isc_stdtime_t now, isc_stdtime_t *remove); +/*%< + * Check if this key is removed from the zone (e.g. the DNSKEY record should + * no longer be in the zone). + * + * Requires: + * 'key' to be valid. + */ + +dst_key_state_t +dst_key_goal(dst_key_t *key); +/*%< + * Get the key goal. Should be OMNIPRESENT or HIDDEN. + * This can be used to determine if the key is being introduced or + * is on its way out. + * + * Requires: + * 'key' to be valid. + */ + +isc_result_t +dst_key_role(dst_key_t *key, bool *ksk, bool *zsk); +/*%< + * Get the key role. A key can have the KSK or the ZSK role, or both. + * + * Requires: + * 'key' to be valid. + */ + +void +dst_key_copy_metadata(dst_key_t *to, dst_key_t *from); +/*%< + * Copy key metadata from one key to another. + * + * Requires: + * 'to' and 'from' to be valid. + */ + +const char * +dst_hmac_algorithm_totext(dst_algorithm_t alg); +/*$< + * Return the name associtated with the HMAC algorithm 'alg' + * or return "unknown". + */ + +ISC_LANG_ENDDECLS diff --git a/lib/dns/include/dst/gssapi.h b/lib/dns/include/dst/gssapi.h new file mode 100644 index 0000000..494b4b0 --- /dev/null +++ b/lib/dns/include/dst/gssapi.h @@ -0,0 +1,192 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#pragma once + +/*! \file dst/gssapi.h */ + +#include <inttypes.h> +#include <stdbool.h> + +#include <isc/formatcheck.h> +#include <isc/lang.h> +#include <isc/types.h> + +#include <dns/types.h> + +typedef void *dns_gss_cred_id_t; +typedef void *dns_gss_ctx_id_t; + +ISC_LANG_BEGINDECLS + +/*** + *** Types + ***/ + +/*** + *** Functions + ***/ + +isc_result_t +dst_gssapi_acquirecred(const dns_name_t *name, bool initiate, + dns_gss_cred_id_t *cred); +/* + * Acquires GSS credentials. + * + * Requires: + * 'name' is a valid name, preferably one known by the GSS provider + * 'initiate' indicates whether the credentials are for initiating or + * accepting contexts + * 'cred' is a pointer to NULL, which will be allocated with the + * credential handle. Call dst_gssapi_releasecred to free + * the memory. + * + * Returns: + * ISC_R_SUCCESS msg was successfully updated to include the + * query to be sent + * other an error occurred while building the message + */ + +isc_result_t +dst_gssapi_releasecred(dns_gss_cred_id_t *cred); +/* + * Releases GSS credentials. Calling this function does release the + * memory allocated for the credential in dst_gssapi_acquirecred() + * + * Requires: + * 'mctx' is a valid memory context + * 'cred' is a pointer to the credential to be released + * + * Returns: + * ISC_R_SUCCESS credential was released successfully + * other an error occurred while releaseing + * the credential + */ + +isc_result_t +dst_gssapi_initctx(const dns_name_t *name, isc_buffer_t *intoken, + isc_buffer_t *outtoken, dns_gss_ctx_id_t *gssctx, + isc_mem_t *mctx, char **err_message); +/* + * Initiates a GSS context. + * + * Requires: + * 'name' is a valid name, preferably one known by the GSS + * provider + * 'intoken' is a token received from the acceptor, or NULL if + * there isn't one + * 'outtoken' is a buffer to receive the token generated by + * gss_init_sec_context() to be sent to the acceptor + * 'context' is a pointer to a valid dns_gss_ctx_id_t + * (which may have the value DNS_GSS_C_NO_CONTEXT) + * + * Returns: + * ISC_R_SUCCESS msg was successfully updated to include the + * query to be sent + * other an error occurred while building the message + * *err_message optional error message + */ + +isc_result_t +dst_gssapi_acceptctx(dns_gss_cred_id_t cred, const char *gssapi_keytab, + isc_region_t *intoken, isc_buffer_t **outtoken, + dns_gss_ctx_id_t *context, dns_name_t *principal, + isc_mem_t *mctx); +/* + * Accepts a GSS context. + * + * Requires: + * 'mctx' is a valid memory context + * 'cred' is the acceptor's valid GSS credential handle + * 'intoken' is a token received from the initiator + * 'outtoken' is a pointer a buffer pointer used to return the token + * generated by gss_accept_sec_context() to be sent to the + * initiator + * 'context' is a valid pointer to receive the generated context handle. + * On the initial call, it should be a pointer to NULL, which + * will be allocated as a dns_gss_ctx_id_t. Subsequent calls + * should pass in the handle generated on the first call. + * Call dst_gssapi_releasecred to delete the context and free + * the memory. + * + * Requires: + * 'outtoken' to != NULL && *outtoken == NULL. + * + * Returns: + * ISC_R_SUCCESS msg was successfully updated to include the + * query to be sent + * DNS_R_CONTINUE transaction still in progress + * other an error occurred while building the message + */ + +isc_result_t +dst_gssapi_deletectx(isc_mem_t *mctx, dns_gss_ctx_id_t *gssctx); +/* + * Destroys a GSS context. This function deletes the context from the GSS + * provider and then frees the memory used by the context pointer. + * + * Requires: + * 'mctx' is a valid memory context + * 'context' is a valid GSS context + * + * Returns: + * ISC_R_SUCCESS + */ + +void +gss_log(int level, const char *fmt, ...) ISC_FORMAT_PRINTF(2, 3); +/* + * Logging function for GSS. + * + * Requires + * 'level' is the log level to be used, as an integer + * 'fmt' is a printf format specifier + */ + +char * +gss_error_tostring(uint32_t major, uint32_t minor, char *buf, size_t buflen); +/* + * Render a GSS major status/minor status pair into a string + * + * Requires: + * 'major' is a GSS major status code + * 'minor' is a GSS minor status code + * + * Returns: + * A string containing the text representation of the error codes. + * Users should copy the string if they wish to keep it. + */ + +bool +dst_gssapi_identitymatchesrealmkrb5(const dns_name_t *signer, + const dns_name_t *name, + const dns_name_t *realm, bool subdomain); +/* + * Compare a "signer" (in the format of a Kerberos-format Kerberos5 + * principal: host/example.com@EXAMPLE.COM) to the realm name stored + * in "name" (which represents the realm name). + * + */ + +bool +dst_gssapi_identitymatchesrealmms(const dns_name_t *signer, + const dns_name_t *name, + const dns_name_t *realm, bool subdomain); +/* + * Compare a "signer" (in the format of a Kerberos-format Kerberos5 + * principal: host/example.com@EXAMPLE.COM) to the realm name stored + * in "name" (which represents the realm name). + * + */ + +ISC_LANG_ENDDECLS |