From 5fc870ef5c4836b3d49b743f2dcff0c10aadff08 Mon Sep 17 00:00:00 2001 From: Chris Dunlap Date: Fri, 22 Jun 2018 16:05:32 -0700 Subject: [PATCH] Add HKDF key derivation to mungekey Update mungekey to use the HMAC-based Key Derivation Function (HKDF) when creating a key. HKDF is based on the extract-then-expand approach. During extraction, entropy_read() (using the kernel's CSPRNG) is used for the input keying material, while entropy_read_uint() (independent of the kernel's CSPRNG) is used for the optional salt value. During expansion, the use, algorithm, and key length are combined for the optional info value in order to bind the derived key material to context-specific information. Reference: - https://tools.ietf.org/html/rfc5869 - https://eprint.iacr.org/2010/264 - http://webee.technion.ac.il/~hugo/kdf/ Signed-off-by: Chris Dunlap --- src/common/hkdf.c | 486 +++++++++++++++++++++++++++++++++++++++ src/common/hkdf.h | 62 +++++ src/mungekey/Makefile.am | 15 +- src/mungekey/key.c | 139 +++++++++-- src/mungekey/mungekey.c | 5 + 5 files changed, 687 insertions(+), 20 deletions(-) create mode 100644 src/common/hkdf.c create mode 100644 src/common/hkdf.h diff --git a/src/common/hkdf.c b/src/common/hkdf.c new file mode 100644 index 00000000..89ec9293 --- /dev/null +++ b/src/common/hkdf.c @@ -0,0 +1,486 @@ +/***************************************************************************** + * Written by Chris Dunlap . + * Copyright (C) 2007-2018 Lawrence Livermore National Security, LLC. + * Copyright (C) 2002-2007 The Regents of the University of California. + * UCRL-CODE-155910. + * + * This file is part of the MUNGE Uid 'N' Gid Emporium (MUNGE). + * For details, see . + * + * MUNGE is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) + * any later version. Additionally for the MUNGE library (libmunge), you + * can redistribute it and/or modify it under the terms of the GNU Lesser + * General Public License as published by the Free Software Foundation, + * either version 3 of the License, or (at your option) any later version. + * + * MUNGE is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * and GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * and GNU Lesser General Public License along with MUNGE. If not, see + * . + *****************************************************************************/ + + +#if HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include "common.h" +#include "hkdf.h" +#include "log.h" +#include "mac.h" +#include "str.h" + + +/***************************************************************************** + * Notes + ***************************************************************************** + * + * Implementation based on RFC 5869: HMAC-based Extract-and-Expand + * Key Derivation Function (HKDF). + * + * Refer to "Cryptographic Extraction and Key Derivation: The HKDF Scheme" + * (2010) by Hugo Krawczyk for further details. + */ + + +/***************************************************************************** + * Data Types + *****************************************************************************/ + +struct hkdf_ctx { + unsigned salt_is_allocated:1; + munge_mac_t md; /* message digest / hash function */ + size_t mdlen; /* length of MD output (in bytes) */ + const void *key; /* input keying material */ + size_t keylen; /* length of key (in bytes) */ + const void *salt; /* optional: non-secret random value */ + size_t saltlen; /* length of salt (in bytes) */ + const void *info; /* optional: context specific info */ + size_t infolen; /* length of info (in bytes) */ +}; + + +/***************************************************************************** + * Private Prototypes + *****************************************************************************/ + +static int _hkdf_extract (hkdf_ctx_t *ctxp, void *prk, size_t *prklenp); + +static int _hkdf_expand (hkdf_ctx_t *ctxp, const void *prk, size_t prklen, + void *dst, size_t *dstlenp); + + +/***************************************************************************** + * Public Functions + *****************************************************************************/ + +/* Create a new HKDF context. + * Return a ptr to the context on success, or NULL on error. + */ +hkdf_ctx_t * +hkdf_ctx_create (void) +{ + hkdf_ctx_t *ctxp; + + ctxp = calloc (1, sizeof (*ctxp)); + return ctxp; +} + + +/* Destroy the HKDF context [ctxp]. + */ +void +hkdf_ctx_destroy (hkdf_ctx_t *ctxp) +{ + if (ctxp == NULL) { + return; + } + if ((ctxp->key != NULL) && (ctxp->keylen > 0)) { + ctxp->key = NULL; + ctxp->keylen = 0; + } + if ((ctxp->salt != NULL) && (ctxp->saltlen > 0)) { + if (ctxp->salt_is_allocated) { + free ((void *) ctxp->salt); + ctxp->salt_is_allocated = 0; + } + ctxp->salt = NULL; + ctxp->saltlen = 0; + } + if ((ctxp->info != NULL) && (ctxp->infolen > 0)) { + ctxp->info = NULL; + ctxp->infolen = 0; + } + free (ctxp); +} + + +/* Specify the message digest / hash function [md] for use with the + * HKDF context [ctxp]. + * Return 0 on success, or -1 on error (with errno set). + */ +int +hkdf_ctx_set_md (hkdf_ctx_t *ctxp, munge_mac_t md) +{ + if (ctxp == NULL) { + errno = EINVAL; + return -1; + } + if (mac_map_enum (md, NULL) < 0) { + errno = EINVAL; + return -1; + } + ctxp->md = md; + return 0; +} + + +/* Specify the input keying material [key] of length [keylen] for use with + * the HKDF context [ctxp]. + * Return 0 on success, or -1 on error (with errno set). + */ +int +hkdf_ctx_set_key (hkdf_ctx_t *ctxp, const void *key, size_t keylen) +{ + if ((ctxp == NULL) || ((key == NULL) && (keylen > 0))) { + errno = EINVAL; + return -1; + } + ctxp->key = key; + ctxp->keylen = keylen; + return 0; +} + + +/* Specify an optional [salt] of length [saltlen] for use with the + * HKDF context [ctxp]. + * The salt is a non-secret random value; if not provided, it is set to a + * string of zeros equal in length to the size of the hash function output. + * The use of salt adds significantly to the strength of HKDF, ensuring + * independence between different uses of the hash function, supporting + * source-independent extraction, and strengthening the analytical results + * that back the HKDF design. + * Ideally, the salt value is a random (or pseudorandom) string equal in + * length to the size of the hash function output. Yet, even a salt value + * of less quality (i.e., shorter in size, or with limited entropy) may + * still make a significant contribution to the security of the output + * keying material. + * The salt value should be independent of the input keying material. + * Return 0 on success, or -1 on error (with errno set). + */ +int +hkdf_ctx_set_salt (hkdf_ctx_t *ctxp, const void *salt, size_t saltlen) +{ + if ((ctxp == NULL) || ((salt == NULL) && (saltlen > 0))) { + errno = EINVAL; + return -1; + } + if (ctxp->salt_is_allocated) { + free ((void *) ctxp->salt); + ctxp->salt_is_allocated = 0; + } + ctxp->salt = salt; + ctxp->saltlen = saltlen; + return 0; +} + + +/* Specify optional context and application specific information [info] + * of length [infolen] for use with the HKDF context [ctxp]. + * This information binds the derived key material to application- and + * context-specific information. + * This information should be independent of the input keying material. + * Return 0 on success, or -1 on error (with errno set). + */ +int +hkdf_ctx_set_info (hkdf_ctx_t *ctxp, const void *info, size_t infolen) +{ + if ((ctxp == NULL) || ((info == NULL) && (infolen > 0))) { + errno = EINVAL; + return -1; + } + ctxp->info = info; + ctxp->infolen = infolen; + return 0; +} + + +/* Compute the HMAC-based Key Derivation Function (HKDF) based on the + * HKDF context [ctxp]. + * The resulting output keying material will be written into the buffer [dst]. + * [dstlenp] is a value-result parameter. It must be initialized to the + * size of the [dst] buffer, and will be set on return to the number of + * bytes written into that buffer. + * Return 0 on success, or -1 on error (with errno set). + */ +int +hkdf (hkdf_ctx_t *ctxp, void *dst, size_t *dstlenp) +{ + unsigned char *prk = NULL; /* pseudorandom key */ + size_t prklen; /* length of PRK (in bytes) */ + size_t prklen_used; /* length of PRK used (in bytes) */ + int rv; + + if ((ctxp == NULL) || + (dstlenp == NULL) || + ((dst == NULL) && (*dstlenp > 0))) + { + errno = EINVAL; + return -1; + } + /* Compute length of hash function output. + */ + ctxp->mdlen = mac_size (ctxp->md); + if (ctxp->mdlen == -1) { + errno = EINVAL; + return -1; + } + /* Validate dstlen. + */ + if (*dstlenp > (ctxp->mdlen * 255)) { + errno = ERANGE; + return -1; + } + /* Allocate salt, if not already set. + */ + if (ctxp->salt == NULL) { + ctxp->saltlen = ctxp->mdlen; + ctxp->salt = calloc (1, ctxp->saltlen); + if (ctxp->salt == NULL) { + return -1; + } + ctxp->salt_is_allocated = 1; + } + /* Allocate pseudorandom key. + * The length of the PRK is the length of the hash function output. + */ + prklen = ctxp->mdlen; + prk = calloc (1, prklen); + if (prk == NULL) { + return -1; + } + prklen_used = prklen; + /* + * Extract pseudorandom key. + */ + rv = _hkdf_extract (ctxp, prk, &prklen_used); + if (rv == -1) { + goto cleanup; + } + if (prklen != prklen_used) { + log_err (EMUNGE_SNAFU, LOG_ERR, + "Failed HKDF Extraction: expected %u bytes, received %u bytes", + prklen, prklen_used); + } + /* Expand pseudorandom key to desired length. + */ + rv = _hkdf_expand (ctxp, prk, prklen, dst, dstlenp); + +cleanup: + if (prk != NULL) { + memburn (prk, 0, prklen); + free (prk); + } + return rv; +} + + +/***************************************************************************** + * Private Functions + *****************************************************************************/ + +/* HKDF First Stage. + * Extract (or concentrate) the possibly dispersed entropy of the input + * keying material into a short, but cryptographically strong, + * pseudorandom key (prk). + * [prklenp] is a value-result parameter. It must be initialized to the + * size of the [prk] buffer, and will be set on return to the number of + * bytes written into that buffer. + * Return 0 on success, or -1 on error. + */ +static int +_hkdf_extract (hkdf_ctx_t *ctxp, void *prk, size_t *prklenp) +{ + mac_ctx mac_ctx; + int mac_ctx_is_initialized = 0; + int rv = 0; + + assert (ctxp != NULL); + assert (ctxp->salt != NULL); + assert (ctxp->key != NULL); + assert (prk != NULL); + assert (prklenp != NULL); + assert (*prklenp > 0); + + /* Compute the pseudorandom key. + * prk = HMAC (salt, ikm) + */ + rv = mac_init (&mac_ctx, ctxp->md, ctxp->salt, ctxp->saltlen); + if (rv == -1) { + log_msg (LOG_ERR, "Failed to initialize HKDF MAC ctx for extraction"); + goto err; + } + mac_ctx_is_initialized = 1; + + rv = mac_update (&mac_ctx, ctxp->key, ctxp->keylen); + if (rv == -1) { + log_msg (LOG_ERR, "Failed to update HKDF MAC ctx for extraction"); + goto err; + } + rv = mac_final (&mac_ctx, prk, (int *) prklenp); + if (rv == -1) { + log_msg (LOG_ERR, "Failed to finalize HKDF MAC ctx for extraction"); + goto err; + } +err: + if (mac_ctx_is_initialized) { + if (mac_cleanup (&mac_ctx) == -1) { + log_msg (LOG_ERR, "Failed to cleanup HKDF MAC ctx for extraction"); + return -1; + } + } + return rv; +} + + +/* HKDF Second Stage. + * Expand the pseudorandom key [prk] of length [prklen] to the desired length, + * writing the output keying material into the buffer [dst]. + * [dstlenp] is a value-result parameter. It must be initialized to the + * size of the [dst] buffer, and will be set on return to the number of + * bytes written into that buffer. + * Return 0 on success, or -1 on error. + */ +static int +_hkdf_expand (hkdf_ctx_t *ctxp, const void *prk, size_t prklen, + void *dst, size_t *dstlenp) +{ + unsigned char *dstptr; + size_t dstlen; + unsigned char *okm = NULL; + size_t okmlen; + int num_rounds; + const int max_rounds = 255; + unsigned char round; + mac_ctx mac_ctx; + int mac_ctx_is_initialized = 0; + size_t n; + int rv = 0; + + assert (ctxp != NULL); + assert (prk != NULL); + assert (prklen > 0); + assert (dstlenp != NULL); + + dstptr = dst; + dstlen = *dstlenp; + + /* Allocate buffer for output keying material. + * The buffer size is equal to the size of the hash function output. + */ + okmlen = ctxp->mdlen; + okm = calloc (1, okmlen); + if (okm == NULL) { + rv = -1; + goto err; + } + /* Compute the number of expansion rounds needed to fill [dst]. + * n = CEIL (dstlen / mdlen) + */ + num_rounds = (dstlen + ctxp->mdlen - 1) / ctxp->mdlen; + if (num_rounds > max_rounds) { + log_msg (LOG_ERR, + "Failed to initialize HKDF: %d rounds exceeds max of %d", + num_rounds, max_rounds); + rv = -1; + goto err; + } + /* Compute output keying material for each expansion round. + * okm(i) = HMAC (prk, okm(i-i) | [info] | i) + */ + for (round = 1; round <= num_rounds; round++) { + + rv = mac_init (&mac_ctx, ctxp->md, prk, prklen); + if (rv == -1) { + log_msg (LOG_ERR, + "Failed to initialize HKDF MAC ctx " + "for expansion round #%u", round); + goto err; + } + mac_ctx_is_initialized = 1; + + if (round > 1) { + rv = mac_update (&mac_ctx, okm, okmlen); + if (rv == -1) { + log_msg (LOG_ERR, + "Failed to update HKDF MAC ctx with prev okm " + "for expansion round #%u", round); + goto err; + } + } + if (ctxp->infolen > 0) { + rv = mac_update (&mac_ctx, ctxp->info, ctxp->infolen); + if (rv == -1) { + log_msg (LOG_ERR, + "Failed to update HKDF MAC ctx with info " + "for expansion round #%u", round); + goto err; + } + } + assert (sizeof (round) == 1); + rv = mac_update (&mac_ctx, &round, sizeof (round)); + if (rv == -1) { + log_msg (LOG_ERR, + "Failed to update HKDF MAC ctx with count " + "for expansion round #%u", round); + goto err; + } + rv = mac_final (&mac_ctx, okm, (int *) &okmlen); + if (rv == -1) { + log_msg (LOG_ERR, + "Failed to finalize HKDF MAC ctx " + "for expansion round #%u", round); + goto err; + } + rv = mac_cleanup (&mac_ctx); + mac_ctx_is_initialized = 0; + if (rv == -1) { + log_msg (LOG_ERR, "Failed to cleanup HKDF MAC ctx for expansion"); + goto err; + } + assert (okmlen == ctxp->mdlen); + n = MIN(okmlen, dstlen); + if ((dstptr != NULL) && (n > 0)) { + memcpy (dstptr, okm, n); + dstptr += n; + dstlen -= n; + } + } + rv = 0; + *dstlenp = dstptr - (unsigned char *) dst; +err: + if (mac_ctx_is_initialized) { + rv = mac_cleanup (&mac_ctx); + if (rv == -1) { + log_msg (LOG_ERR, "Failed to cleanup HKDF MAC ctx for expansion"); + } + } + if (okm != NULL) { + memburn (okm, 0, ctxp->mdlen); + free (okm); + } + return rv; +} diff --git a/src/common/hkdf.h b/src/common/hkdf.h new file mode 100644 index 00000000..46224593 --- /dev/null +++ b/src/common/hkdf.h @@ -0,0 +1,62 @@ +/***************************************************************************** + * Written by Chris Dunlap . + * Copyright (C) 2007-2018 Lawrence Livermore National Security, LLC. + * Copyright (C) 2002-2007 The Regents of the University of California. + * UCRL-CODE-155910. + * + * This file is part of the MUNGE Uid 'N' Gid Emporium (MUNGE). + * For details, see . + * + * MUNGE is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) + * any later version. Additionally for the MUNGE library (libmunge), you + * can redistribute it and/or modify it under the terms of the GNU Lesser + * General Public License as published by the Free Software Foundation, + * either version 3 of the License, or (at your option) any later version. + * + * MUNGE is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * and GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * and GNU Lesser General Public License along with MUNGE. If not, see + * . + *****************************************************************************/ + + +#ifndef MUNGE_HKDF_H +#define MUNGE_HKDF_H + +#include +#include + + +/***************************************************************************** + * Data Types + *****************************************************************************/ + +typedef struct hkdf_ctx hkdf_ctx_t; + + +/***************************************************************************** + * Prototypes + *****************************************************************************/ + +hkdf_ctx_t * hkdf_ctx_create (void); + +void hkdf_ctx_destroy (hkdf_ctx_t *ctxp); + +int hkdf_ctx_set_md (hkdf_ctx_t *ctxp, munge_mac_t md); + +int hkdf_ctx_set_key (hkdf_ctx_t *ctxp, const void *key, size_t keylen); + +int hkdf_ctx_set_salt (hkdf_ctx_t *ctxp, const void *salt, size_t saltlen); + +int hkdf_ctx_set_info (hkdf_ctx_t *ctxp, const void *info, size_t infolen); + +int hkdf (hkdf_ctx_t *ctxp, void *dst, size_t *dstlenp); + + +#endif /* !MUNGE_HKDF_H */ diff --git a/src/mungekey/Makefile.am b/src/mungekey/Makefile.am index 1aa9af55..52a2b3d6 100644 --- a/src/mungekey/Makefile.am +++ b/src/mungekey/Makefile.am @@ -25,6 +25,10 @@ mungekey.8: mungekey.8.in sbin_PROGRAMS = \ mungekey +mungekey_CFLAGS = \ + $(AM_CFLAGS) \ + $(CRYPTO_CFLAGS) + mungekey_CPPFLAGS = \ -DSYSCONFDIR='"$(sysconfdir)"' \ -I$(top_srcdir)/src/common \ @@ -35,7 +39,8 @@ mungekey_CPPFLAGS = \ mungekey_LDADD = \ $(top_builddir)/src/libcommon/libcommon.la \ $(top_builddir)/src/libmissing/libmissing.la \ - $(top_builddir)/src/libmunge/libmunge.la + $(top_builddir)/src/libmunge/libmunge.la \ + $(CRYPTO_LIBS) mungekey_SOURCES = \ mungekey.c \ @@ -43,8 +48,16 @@ mungekey_SOURCES = \ conf.h \ key.c \ key.h \ + $(top_srcdir)/src/common/crypto.c \ + $(top_srcdir)/src/common/crypto.h \ $(top_srcdir)/src/common/entropy.c \ $(top_srcdir)/src/common/entropy.h \ + $(top_srcdir)/src/common/hkdf.c \ + $(top_srcdir)/src/common/hkdf.h \ + $(top_srcdir)/src/common/mac.c \ + $(top_srcdir)/src/common/mac.h \ + $(top_srcdir)/src/common/md.c \ + $(top_srcdir)/src/common/md.h \ $(top_srcdir)/src/common/xsignal.c \ $(top_srcdir)/src/common/xsignal.h diff --git a/src/mungekey/key.c b/src/mungekey/key.c index 78979c14..aa0913ac 100644 --- a/src/mungekey/key.c +++ b/src/mungekey/key.c @@ -33,15 +33,26 @@ #include #include #include +#include +#include #include +#include "common.h" #include "conf.h" #include "entropy.h" #include "fd.h" +#include "hkdf.h" #include "log.h" #include "munge_defs.h" #include "str.h" +/***************************************************************************** + * Prototypes + *****************************************************************************/ + +static int _create_key_secret (unsigned char *buf, size_t buflen); + + /***************************************************************************** * Public Functions *****************************************************************************/ @@ -51,18 +62,20 @@ void create_key (conf_t *confp) { - unsigned char buf [MUNGE_KEY_LEN_MAX_BYTES]; - unsigned char *p; - int fd; - int n; - int n_written; - int rv; - const char *src; + unsigned char buf[MUNGE_KEY_LEN_MAX_BYTES]; + int fd; + int n; + int rv; assert (confp != NULL); assert (confp->key_num_bytes <= MUNGE_KEY_LEN_MAX_BYTES); assert (confp->key_num_bytes >= MUNGE_KEY_LEN_MIN_BYTES); + if (confp->key_num_bytes > sizeof (buf)) { + log_err (EMUNGE_SNAFU, LOG_ERR, + "Failed to create \"%s\": %d-byte key exceeds %zu-byte buffer", + confp->key_path, confp->key_num_bytes, sizeof (buf)); + } if (confp->do_force) { rv = unlink (confp->key_path); if ((rv == -1) && (errno != ENOENT)) { @@ -75,19 +88,13 @@ create_key (conf_t *confp) log_errno (EMUNGE_SNAFU, LOG_ERR, "Failed to create \"%s\"", confp->key_path); } - p = buf; - n = confp->key_num_bytes; - while (n > 0) { - rv = entropy_read (p, n, &src); - if (rv <= 0) { - break; - } - p += rv; - n -= rv; - log_msg (LOG_DEBUG, "Read %d bytes of entropy from %s", rv, src); + rv = _create_key_secret (buf, confp->key_num_bytes); + if (rv == -1) { + log_errno (EMUNGE_SNAFU, LOG_ERR, "Failed to create \"%s\"", + confp->key_path); } - n_written = fd_write_n (fd, buf, confp->key_num_bytes); - if (n_written != confp->key_num_bytes) { + n = fd_write_n (fd, buf, confp->key_num_bytes); + if (n != confp->key_num_bytes) { log_errno (EMUNGE_SNAFU, LOG_ERR, "Failed to write %d bytes to \"%s\"", confp->key_num_bytes, confp->key_path); @@ -103,3 +110,97 @@ create_key (conf_t *confp) confp->key_path, confp->key_num_bytes * 8); } } + + +/***************************************************************************** + * Private Functions + *****************************************************************************/ + +/* Create the key secret, writing it to the buffer [buf] of length [buflen]. + * Return 0 on success, or -1 on error. + */ +static int +_create_key_secret (unsigned char *buf, size_t buflen) +{ + unsigned char key[ENTROPY_NUM_BYTES_GUARANTEED]; + unsigned int salt; + const munge_mac_t md = MUNGE_DEFAULT_MAC; + const char *md_str; + const char *info_prefix = "MUNGEKEY"; + int num_bits; + char info[1024]; + hkdf_ctx_t *hkdfp = NULL; + int rv; + + assert (buf != NULL); + assert (buflen > 0); + + /* Read entropy from the kernel's CSPRNG for the input keying material. + */ + rv = entropy_read (key, sizeof (key), NULL); + if (rv == -1) { + goto err; + } + /* Read entropy independent of the kernel's CSPRNG for use as a salt. + */ + rv = entropy_read_uint (&salt); + if (rv == -1) { + goto err; + } + /* Create a distinguisher that embeds the use, algorithm, and key length. + * For example, "MUNGEKEY:sha256:1024:". + */ + md_str = munge_enum_int_to_str (MUNGE_ENUM_MAC, md); + if (md_str == NULL) { + log_msg (LOG_ERR, "Failed to lookup text string for md=%d", md); + rv = -1; + goto err; + } + num_bits = buflen * 8; + rv = snprintf (info, sizeof (info), "%s:%s:%d:", + info_prefix, md_str, num_bits); + if ((rv < 0) || (rv >= sizeof (info))) { + log_msg (LOG_ERR, "Failed to create key distinguisher info: " + "exceeded %zu-byte buffer", sizeof (info)); + rv = -1; + goto err; + } + /* Mix it all together in the key derivation function. + */ + hkdfp = hkdf_ctx_create (); + if (hkdfp == NULL) { + log_msg (LOG_ERR, "Failed to allocate memory for HKDF context"); + rv = -1; + goto err; + } + rv = hkdf_ctx_set_md (hkdfp, md); + if (rv == -1) { + log_msg (LOG_ERR, "Failed to set HKDF message digest to md=%d", md); + goto err; + } + rv = hkdf_ctx_set_key (hkdfp, key, sizeof (key)); + if (rv == -1) { + log_msg (LOG_ERR, "Failed to set HKDF input keying material"); + goto err; + } + rv = hkdf_ctx_set_salt (hkdfp, &salt, sizeof (salt)); + if (rv == -1) { + log_msg (LOG_ERR, "Failed to set HKDF salt"); + goto err; + } + rv = hkdf_ctx_set_info (hkdfp, info, strlen (info)); + if (rv == -1) { + log_msg (LOG_ERR, "Failed to set HKDF info"); + goto err; + } + rv = hkdf (hkdfp, buf, &buflen); + if (rv == -1) { + log_msg (LOG_ERR, "Failed to compute HKDF key derivation"); + goto err; + } +err: + (void) memburn (key, 0, sizeof (key)); + (void) memburn (&salt, 0, sizeof (salt)); + hkdf_ctx_destroy (hkdfp); + return rv; +} diff --git a/src/mungekey/mungekey.c b/src/mungekey/mungekey.c index 7bad998e..3712da12 100644 --- a/src/mungekey/mungekey.c +++ b/src/mungekey/mungekey.c @@ -35,8 +35,10 @@ #include #include #include "conf.h" +#include "crypto.h" #include "key.h" #include "log.h" +#include "md.h" #include "xsignal.h" @@ -62,9 +64,12 @@ main (int argc, char *argv[]) confp = create_conf (); parse_cmdline (confp, argc, argv); + crypto_init (); + md_init_subsystem (); if (confp->do_create) { create_key (confp); } + crypto_fini (); destroy_conf (confp); exit (EXIT_SUCCESS); }