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); }