File: [local] / src / usr.sbin / nsd / tsig-openssl.c (download)
Revision 1.6, Sun Oct 24 12:14:19 2021 UTC (2 years, 7 months ago) by florian
Branch: MAIN
CVS Tags: OPENBSD_7_5_BASE, OPENBSD_7_5, OPENBSD_7_4_BASE, OPENBSD_7_4, OPENBSD_7_3_BASE, OPENBSD_7_3, OPENBSD_7_2_BASE, OPENBSD_7_2, OPENBSD_7_1_BASE, OPENBSD_7_1, HEAD Changes since 1.5: +3 -1 lines
Update to 4.3.8.
OK sthen
|
/*
* 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(HAVE_SSL)
#ifdef HAVE_OPENSSL_CORE_NAMES_H
#include <openssl/core_names.h>
#endif
#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);
#ifdef HAVE_EVP_MAC_CTX_NEW
struct tsig_openssl_data {
/* the MAC for the algorithm, 'hmac' */
EVP_MAC* mac;
/* the digest name for creating the EVP_MAC_CTX with, 'sha256' */
const char* digest;
};
struct tsig_openssl_context {
/* the evp mac context, if notNULL it has algo and key set. */
EVP_MAC_CTX* hmac_ctx;
/* the size of destination buffers */
size_t outsize;
};
static void
cleanup_tsig_openssl_data(void *data)
{
struct tsig_openssl_data* d = (struct tsig_openssl_data*)data;
EVP_MAC_free(d->mac);
d->mac = NULL;
}
#endif
static int
tsig_openssl_init_algorithm(region_type* region,
const char* digest, const char* name, const char* wireformat)
{
tsig_algorithm_type* algorithm;
#ifndef HAVE_EVP_MAC_CTX_NEW
const EVP_MD *hmac_algorithm;
hmac_algorithm = EVP_get_digestbyname(digest);
if (!hmac_algorithm) {
/* skip but don't error */
return 0;
}
#else
struct tsig_openssl_data* data;
EVP_MAC_CTX* hmac_ctx;
OSSL_PARAM params[3];
data = region_alloc(region, sizeof(*data));
data->digest = digest;
data->mac = EVP_MAC_fetch(NULL, "hmac", NULL);
if(!data->mac) {
log_msg(LOG_ERR, "could not fetch MAC implementation 'hmac' with EVP_MAC_fetch");
return 0;
}
/* this context is created to see what size the output is */
hmac_ctx = EVP_MAC_CTX_new(data->mac);
if(!hmac_ctx) {
EVP_MAC_free(data->mac);
return 0;
}
params[0] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST,
(char*)digest, 0);
params[1] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,
"", 1);
params[2] = OSSL_PARAM_construct_end();
#ifdef HAVE_EVP_MAC_CTX_SET_PARAMS
if(EVP_MAC_CTX_set_params(hmac_ctx, params) <= 0) {
log_msg(LOG_ERR, "could not EVP_MAC_CTX_set_params");
EVP_MAC_CTX_free(hmac_ctx);
EVP_MAC_free(data->mac);
return 0;
}
#else
if(EVP_MAC_set_ctx_params(hmac_ctx, params) <= 0) {
log_msg(LOG_ERR, "could not EVP_MAC_set_ctx_params");
EVP_MAC_CTX_free(hmac_ctx);
EVP_MAC_free(data->mac);
return 0;
}
#endif
#endif
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);
#ifdef HAVE_EVP_MAC_CTX_NEW
EVP_MAC_CTX_free(hmac_ctx);
EVP_MAC_free(data->mac);
#endif
return 0;
}
#ifdef HAVE_EVP_MAC_CTX_GET_MAC_SIZE
algorithm->maximum_digest_size = EVP_MAC_CTX_get_mac_size(hmac_ctx);
#elif !defined(HAVE_EVP_MAC_CTX_NEW)
algorithm->maximum_digest_size = EVP_MD_size(hmac_algorithm);
#else
algorithm->maximum_digest_size = EVP_MAC_size(hmac_ctx);
#endif
if(algorithm->maximum_digest_size < 20)
algorithm->maximum_digest_size = EVP_MAX_MD_SIZE;
#ifndef HAVE_EVP_MAC_CTX_NEW
algorithm->data = hmac_algorithm;
#else
algorithm->data = data;
region_add_cleanup(region, cleanup_tsig_openssl_data, data);
#endif
algorithm->hmac_create_context = create_context;
algorithm->hmac_init_context = init_context;
algorithm->hmac_update = update;
algorithm->hmac_final = final;
tsig_add_algorithm(algorithm);
#ifdef HAVE_EVP_MAC_CTX_NEW
EVP_MAC_CTX_free(hmac_ctx);
#endif
return 1;
}
int
tsig_openssl_init(region_type *region)
{
int count = 0;
#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_CRYPTO)
OpenSSL_add_all_digests();
#else
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_DIGESTS, NULL);
#endif
count += tsig_openssl_init_algorithm(region,
"md5", "hmac-md5","hmac-md5.sig-alg.reg.int.");
count += tsig_openssl_init_algorithm(region,
"sha1", "hmac-sha1", "hmac-sha1.");
count += tsig_openssl_init_algorithm(region,
"sha224", "hmac-sha224", "hmac-sha224.");
count += tsig_openssl_init_algorithm(region,
"sha256", "hmac-sha256", "hmac-sha256.");
count += tsig_openssl_init_algorithm(region,
"sha384", "hmac-sha384", "hmac-sha384.");
count += tsig_openssl_init_algorithm(region,
"sha512", "hmac-sha512", "hmac-sha512.");
return count;
}
static void
cleanup_context(void *data)
{
#ifndef HAVE_EVP_MAC_CTX_NEW
HMAC_CTX *context = (HMAC_CTX *) data;
#ifdef HAVE_HMAC_CTX_NEW
HMAC_CTX_free(context);
#else
HMAC_CTX_cleanup(context);
free(context);
#endif
#else
struct tsig_openssl_context* c = (struct tsig_openssl_context*)data;
EVP_MAC_CTX_free(c->hmac_ctx);
c->hmac_ctx = NULL;
#endif
}
static void *
create_context(region_type *region)
{
#ifndef HAVE_EVP_MAC_CTX_NEW
#ifdef HAVE_HMAC_CTX_NEW
HMAC_CTX *context = HMAC_CTX_new();
#else
HMAC_CTX *context = (HMAC_CTX *) malloc(sizeof(HMAC_CTX));
#endif
region_add_cleanup(region, cleanup_context, context);
#ifdef HAVE_HMAC_CTX_RESET
HMAC_CTX_reset(context);
#else
HMAC_CTX_init(context);
#endif
#else
struct tsig_openssl_context* context = region_alloc(region,
sizeof(*context));
memset(context, 0, sizeof(*context));
region_add_cleanup(region, cleanup_context, context);
#endif
return context;
}
static void
init_context(void *context,
tsig_algorithm_type *algorithm,
tsig_key_type *key)
{
#ifndef HAVE_EVP_MAC_CTX_NEW
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);
#else
OSSL_PARAM params[3];
struct tsig_openssl_data* algo_data = (struct tsig_openssl_data*)
algorithm->data;
struct tsig_openssl_context* c = (struct tsig_openssl_context*)context;
if(c->hmac_ctx) {
EVP_MAC_CTX_free(c->hmac_ctx);
}
c->hmac_ctx = EVP_MAC_CTX_new(algo_data->mac);
if(!c->hmac_ctx) {
log_msg(LOG_ERR, "could not EVP_MAC_CTX_new");
return;
}
params[0] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST,
(char*)algo_data->digest, 0);
params[1] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,
key->data, key->size);
params[2] = OSSL_PARAM_construct_end();
#ifdef HAVE_EVP_MAC_CTX_SET_PARAMS
if(EVP_MAC_CTX_set_params(c->hmac_ctx, params) <= 0) {
log_msg(LOG_ERR, "could not EVP_MAC_CTX_set_params");
EVP_MAC_CTX_free(c->hmac_ctx);
c->hmac_ctx = NULL;
return;
}
#else
if(EVP_MAC_set_ctx_params(hmac_ctx, params) <= 0) {
log_msg(LOG_ERR, "could not EVP_MAC_set_ctx_params");
EVP_MAC_CTX_free(c->hmac_ctx);
c->hmac_ctx = NULL;
return;
}
#endif
c->outsize = algorithm->maximum_digest_size;
#endif
}
static void
update(void *context, const void *data, size_t size)
{
#ifndef HAVE_EVP_MAC_CTX_NEW
HMAC_CTX *ctx = (HMAC_CTX *) context;
HMAC_Update(ctx, (unsigned char *) data, (int) size);
#else
struct tsig_openssl_context* c = (struct tsig_openssl_context*)context;
if(EVP_MAC_update(c->hmac_ctx, data, size) <= 0) {
log_msg(LOG_ERR, "could not EVP_MAC_update");
}
#endif
}
static void
final(void *context, uint8_t *digest, size_t *size)
{
#ifndef HAVE_EVP_MAC_CTX_NEW
HMAC_CTX *ctx = (HMAC_CTX *) context;
unsigned len = (unsigned) *size;
HMAC_Final(ctx, digest, &len);
*size = (size_t) len;
#else
struct tsig_openssl_context* c = (struct tsig_openssl_context*)context;
if(EVP_MAC_final(c->hmac_ctx, digest, size, c->outsize) <= 0) {
log_msg(LOG_ERR, "could not EVP_MAC_final");
}
#endif
}
void
tsig_openssl_finalize()
{
#ifdef HAVE_EVP_CLEANUP
EVP_cleanup();
#endif
}
#endif /* defined(HAVE_SSL) */