diff options
Diffstat (limited to 'usr.sbin/nsd/tsig-openssl.c')
-rw-r--r-- | usr.sbin/nsd/tsig-openssl.c | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/usr.sbin/nsd/tsig-openssl.c b/usr.sbin/nsd/tsig-openssl.c new file mode 100644 index 00000000000..5773fd2a674 --- /dev/null +++ b/usr.sbin/nsd/tsig-openssl.c @@ -0,0 +1,127 @@ +/* + * tsig-openssl.h -- Interface to OpenSSL for TSIG support. + * + * Copyright (c) 2001-2006, NLnet Labs. All rights reserved. + * + * See LICENSE for the license. + * + */ + +#include <config.h> + +#if defined(TSIG) && defined(HAVE_SSL) + +#include "tsig-openssl.h" +#include "tsig.h" +#include "util.h" + +static void *create_context(region_type *region); +static void init_context(void *context, + tsig_algorithm_type *algorithm, + tsig_key_type *key); +static void update(void *context, const void *data, size_t size); +static void final(void *context, uint8_t *digest, size_t *size); + +static int +tsig_openssl_init_algorithm(region_type* region, + const char* digest, const char* name, const char* wireformat) +{ + tsig_algorithm_type* algorithm; + const EVP_MD *hmac_algorithm; + + hmac_algorithm = EVP_get_digestbyname(digest); + if (!hmac_algorithm) { + log_msg(LOG_ERR, "%s digest not available", digest); + return 0; + } + + algorithm = (tsig_algorithm_type *) region_alloc( + region, sizeof(tsig_algorithm_type)); + algorithm->short_name = name; + algorithm->wireformat_name + = dname_parse(region, wireformat); + if (!algorithm->wireformat_name) { + log_msg(LOG_ERR, "cannot parse %s algorithm", wireformat); + return 0; + } + algorithm->maximum_digest_size = EVP_MAX_MD_SIZE; + algorithm->data = hmac_algorithm; + algorithm->hmac_create_context = create_context; + algorithm->hmac_init_context = init_context; + algorithm->hmac_update = update; + algorithm->hmac_final = final; + tsig_add_algorithm(algorithm); + + return 1; +} + +int +tsig_openssl_init(region_type *region) +{ + OpenSSL_add_all_digests(); + + /* TODO: walk lookup supported algorithms table */ + if (!tsig_openssl_init_algorithm(region, "md5", "hmac-md5","hmac-md5.sig-alg.reg.int.")) + return 0; +#ifdef HAVE_EVP_SHA1 + if (!tsig_openssl_init_algorithm(region, "sha1", "hmac-sha1", "hmac-sha1.")) + return 0; +#endif /* HAVE_EVP_SHA1 */ + +#ifdef HAVE_EVP_SHA256 + if (!tsig_openssl_init_algorithm(region, "sha256", "hmac-sha256", "hmac-sha256.")) + return 0; +#endif /* HAVE_EVP_SHA256 */ + return 1; +} + +static void +cleanup_context(void *data) +{ + HMAC_CTX *context = (HMAC_CTX *) data; + HMAC_CTX_cleanup(context); +} + +static void * +create_context(region_type *region) +{ + HMAC_CTX *context + = (HMAC_CTX *) region_alloc(region, sizeof(HMAC_CTX)); + region_add_cleanup(region, cleanup_context, context); + HMAC_CTX_init(context); + return context; +} + +static void +init_context(void *context, + tsig_algorithm_type *algorithm, + tsig_key_type *key) +{ + HMAC_CTX *ctx = (HMAC_CTX *) context; + const EVP_MD *md = (const EVP_MD *) algorithm->data; + HMAC_Init_ex(ctx, key->data, key->size, md, NULL); +} + +static void +update(void *context, const void *data, size_t size) +{ + HMAC_CTX *ctx = (HMAC_CTX *) context; + HMAC_Update(ctx, (unsigned char *) data, (int) size); +} + +static void +final(void *context, uint8_t *digest, size_t *size) +{ + HMAC_CTX *ctx = (HMAC_CTX *) context; + unsigned len = (unsigned) *size; + HMAC_Final(ctx, digest, &len); + *size = (size_t) len; +} + +void +tsig_openssl_finalize() +{ + EVP_cleanup(); +} + +#endif /* defined(TSIG) && defined(HAVE_SSL) */ |