Add app for fips installation
Reviewed-by: Richard Levitte <levitte@openssl.org> (Merged from https://github.com/openssl/openssl/pull/9634)
This commit is contained in:
parent
e1f8584d47
commit
95214b434f
9 changed files with 708 additions and 37 deletions
50
apps/apps.c
50
apps/apps.c
|
@ -2566,3 +2566,53 @@ int opt_printf_stderr(const char *fmt, ...)
|
|||
va_end(ap);
|
||||
return ret;
|
||||
}
|
||||
|
||||
OSSL_PARAM *app_params_new_from_opts(STACK_OF(OPENSSL_STRING) *opts,
|
||||
const OSSL_PARAM *paramdefs)
|
||||
{
|
||||
OSSL_PARAM *params = NULL;
|
||||
size_t sz = (size_t)sk_OPENSSL_STRING_num(opts);
|
||||
size_t params_n;
|
||||
char *opt = "", *stmp, *vtmp = NULL;
|
||||
|
||||
if (opts == NULL)
|
||||
return NULL;
|
||||
|
||||
params = OPENSSL_zalloc(sizeof(OSSL_PARAM) * (sz + 1));
|
||||
if (params == NULL)
|
||||
return NULL;
|
||||
|
||||
for (params_n = 0; params_n < sz; params_n++) {
|
||||
opt = sk_OPENSSL_STRING_value(opts, (int)params_n);
|
||||
if ((stmp = OPENSSL_strdup(opt)) == NULL
|
||||
|| (vtmp = strchr(stmp, ':')) == NULL)
|
||||
goto err;
|
||||
/* Replace ':' with 0 to terminate the string pointed to by stmp */
|
||||
*vtmp = 0;
|
||||
/* Skip over the separator so that vmtp points to the value */
|
||||
vtmp++;
|
||||
if (!OSSL_PARAM_allocate_from_text(¶ms[params_n], paramdefs,
|
||||
stmp, vtmp, strlen(vtmp)))
|
||||
goto err;
|
||||
OPENSSL_free(stmp);
|
||||
}
|
||||
params[params_n] = OSSL_PARAM_construct_end();
|
||||
return params;
|
||||
err:
|
||||
OPENSSL_free(stmp);
|
||||
BIO_printf(bio_err, "Parameter error '%s'\n", opt);
|
||||
ERR_print_errors(bio_err);
|
||||
app_params_free(params);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void app_params_free(OSSL_PARAM *params)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (params != NULL) {
|
||||
for (i = 0; params[i].key != NULL; ++i)
|
||||
OPENSSL_free(params[i].data);
|
||||
OPENSSL_free(params);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ $OPENSSLSRC={-
|
|||
pkcs8.c pkey.c pkeyparam.c pkeyutl.c prime.c rand.c req.c rsa.c
|
||||
rsautl.c s_client.c s_server.c s_time.c sess_id.c smime.c speed.c
|
||||
spkac.c srp.c ts.c verify.c version.c x509.c rehash.c storeutl.c
|
||||
list.c info.c);
|
||||
list.c info.c fipsinstall.c);
|
||||
join(' ', @opensslsrc); -}
|
||||
# Source for libapps
|
||||
$LIBAPPSSRC=apps.c apps_ui.c opt.c fmt.c s_cb.c s_socket.c app_rand.c \
|
||||
|
|
419
apps/fipsinstall.c
Normal file
419
apps/fipsinstall.c
Normal file
|
@ -0,0 +1,419 @@
|
|||
/*
|
||||
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/provider.h>
|
||||
#include <openssl/params.h>
|
||||
#include <openssl/fips_names.h>
|
||||
#include "apps.h"
|
||||
#include "progs.h"
|
||||
|
||||
#define BUFSIZE 4096
|
||||
#define DEFAULT_MAC_NAME "HMAC"
|
||||
#define DEFAULT_FIPS_SECTION "fips_check_section"
|
||||
|
||||
/* Configuration file values */
|
||||
#define VERSION_KEY "version"
|
||||
#define VERSION_VAL "1"
|
||||
#define INSTALL_STATUS_VAL "INSTALL_SELF_TEST_KATS_RUN"
|
||||
|
||||
typedef enum OPTION_choice {
|
||||
OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
|
||||
OPT_IN, OPT_OUT, OPT_MODULE,
|
||||
OPT_PROV_NAME, OPT_SECTION_NAME, OPT_MAC_NAME, OPT_MACOPT, OPT_VERIFY
|
||||
} OPTION_CHOICE;
|
||||
|
||||
const OPTIONS fipsinstall_options[] = {
|
||||
{"help", OPT_HELP, '-', "Display this summary"},
|
||||
{OPT_MORE_STR, 0, 0, "e.g: openssl fipsinstall -provider_name fips"
|
||||
"-section_name fipsinstall -out fips.conf -module ./fips.so"
|
||||
"-mac_name HMAC -macopt digest:SHA256 -macopt hexkey:00"},
|
||||
{"verify", OPT_VERIFY, '-', "Verification mode, i.e verify a config file "
|
||||
"instead of generating one"},
|
||||
{"in", OPT_IN, '<', "Input config file, used when verifying"},
|
||||
{"out", OPT_OUT, '>', "Output config file, used when generating"},
|
||||
{"module", OPT_MODULE, '<', "File name of the provider module"},
|
||||
{"provider_name", OPT_PROV_NAME, 's', "FIPS provider name"},
|
||||
{"section_name", OPT_SECTION_NAME, 's',
|
||||
"FIPS Provider config section name (optional)"},
|
||||
{"mac_name", OPT_MAC_NAME, 's', "MAC name"},
|
||||
{"macopt", OPT_MACOPT, 's', "MAC algorithm parameters in n:v form. "
|
||||
"See 'PARAMETER NAMES' in the EVP_MAC_ docs"},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
static int do_mac(EVP_MAC_CTX *ctx, unsigned char *tmp, BIO *in,
|
||||
unsigned char *out, size_t *out_len)
|
||||
{
|
||||
int ret = 0;
|
||||
int i;
|
||||
size_t outsz = *out_len;
|
||||
|
||||
if (!EVP_MAC_init(ctx))
|
||||
goto err;
|
||||
if (EVP_MAC_size(ctx) > outsz)
|
||||
goto end;
|
||||
while ((i = BIO_read(in, (char *)tmp, BUFSIZE)) != 0) {
|
||||
if (i < 0 || !EVP_MAC_update(ctx, tmp, i))
|
||||
goto err;
|
||||
}
|
||||
end:
|
||||
if (!EVP_MAC_final(ctx, out, out_len, outsz))
|
||||
goto err;
|
||||
ret = 1;
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int load_fips_prov_and_run_self_test(const char *prov_name)
|
||||
{
|
||||
int ret = 0;
|
||||
OSSL_PROVIDER *prov = NULL;
|
||||
|
||||
prov = OSSL_PROVIDER_load(NULL, prov_name);
|
||||
if (prov == NULL) {
|
||||
BIO_printf(bio_err, "Failed to load FIPS module\n");
|
||||
goto end;
|
||||
}
|
||||
ret = 1;
|
||||
end:
|
||||
OSSL_PROVIDER_unload(prov);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int print_mac(BIO *bio, const char *label, const unsigned char *mac,
|
||||
size_t len)
|
||||
{
|
||||
int ret;
|
||||
char *hexstr = NULL;
|
||||
|
||||
hexstr = OPENSSL_buf2hexstr(mac, (long)len);
|
||||
if (hexstr == NULL)
|
||||
return 0;
|
||||
ret = BIO_printf(bio, "%s = %s\n", label, hexstr);
|
||||
OPENSSL_free(hexstr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int write_config_header(BIO *out, const char *prov_name,
|
||||
const char *section)
|
||||
{
|
||||
return BIO_printf(out, "openssl_conf = openssl_init\n\n")
|
||||
&& BIO_printf(out, "[openssl_init]\n")
|
||||
&& BIO_printf(out, "providers = provider_section\n\n")
|
||||
&& BIO_printf(out, "[provider_section]\n")
|
||||
&& BIO_printf(out, "%s = %s\n\n", prov_name, section);
|
||||
}
|
||||
|
||||
/*
|
||||
* Outputs a fips related config file that contains entries for the fips
|
||||
* module checksum and the installation indicator checksum.
|
||||
*
|
||||
* Returns 1 if the config file is written otherwise it returns 0 on error.
|
||||
*/
|
||||
static int write_config_fips_section(BIO *out, const char *section,
|
||||
unsigned char *module_mac,
|
||||
size_t module_mac_len,
|
||||
unsigned char *install_mac,
|
||||
size_t install_mac_len)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (!(BIO_printf(out, "[%s]\n", section) > 0
|
||||
&& BIO_printf(out, "%s = %s\n", OSSL_PROV_FIPS_PARAM_INSTALL_VERSION,
|
||||
VERSION_VAL) > 0
|
||||
&& print_mac(out, OSSL_PROV_FIPS_PARAM_MODULE_MAC, module_mac,
|
||||
module_mac_len)))
|
||||
goto end;
|
||||
|
||||
if (install_mac != NULL) {
|
||||
if (!(print_mac(out, OSSL_PROV_FIPS_PARAM_INSTALL_MAC, install_mac,
|
||||
install_mac_len)
|
||||
&& BIO_printf(out, "%s = %s\n",
|
||||
OSSL_PROV_FIPS_PARAM_INSTALL_STATUS,
|
||||
INSTALL_STATUS_VAL) > 0))
|
||||
goto end;
|
||||
}
|
||||
ret = 1;
|
||||
end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static CONF *generate_config_and_load(const char *prov_name,
|
||||
const char *section,
|
||||
unsigned char *module_mac,
|
||||
size_t module_mac_len)
|
||||
{
|
||||
BIO *mem_bio = NULL;
|
||||
CONF *conf = NULL;
|
||||
|
||||
mem_bio = BIO_new(BIO_s_mem());
|
||||
if (mem_bio == NULL)
|
||||
return 0;
|
||||
if (!write_config_header(mem_bio, prov_name, section)
|
||||
|| !write_config_fips_section(mem_bio, section, module_mac,
|
||||
module_mac_len, NULL, 0))
|
||||
goto end;
|
||||
|
||||
conf = app_load_config_bio(mem_bio, NULL);
|
||||
if (conf == NULL)
|
||||
goto end;
|
||||
|
||||
if (!CONF_modules_load(conf, NULL, 0))
|
||||
goto end;
|
||||
BIO_free(mem_bio);
|
||||
return conf;
|
||||
end:
|
||||
NCONF_free(conf);
|
||||
BIO_free(mem_bio);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void free_config_and_unload(CONF *conf)
|
||||
{
|
||||
if (conf != NULL) {
|
||||
NCONF_free(conf);
|
||||
CONF_modules_unload(1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns 1 if the config file entries match the passed in module_mac and
|
||||
* install_mac values, otherwise it returns 0.
|
||||
*/
|
||||
static int verify_config(const char *infile, const char *section,
|
||||
unsigned char *module_mac, size_t module_mac_len,
|
||||
unsigned char *install_mac, size_t install_mac_len)
|
||||
{
|
||||
int ret = 0;
|
||||
char *s = NULL;
|
||||
unsigned char *buf1 = NULL, *buf2 = NULL;
|
||||
long len;
|
||||
CONF *conf = NULL;
|
||||
|
||||
/* read in the existing values and check they match the saved values */
|
||||
conf = app_load_config(infile);
|
||||
if (conf == NULL)
|
||||
goto end;
|
||||
|
||||
s = NCONF_get_string(conf, section, OSSL_PROV_FIPS_PARAM_INSTALL_VERSION);
|
||||
if (s == NULL || strcmp(s, VERSION_VAL) != 0) {
|
||||
BIO_printf(bio_err, "version not found\n");
|
||||
goto end;
|
||||
}
|
||||
s = NCONF_get_string(conf, section, OSSL_PROV_FIPS_PARAM_INSTALL_STATUS);
|
||||
if (s == NULL || strcmp(s, INSTALL_STATUS_VAL) != 0) {
|
||||
BIO_printf(bio_err, "install status not found\n");
|
||||
goto end;
|
||||
}
|
||||
s = NCONF_get_string(conf, section, OSSL_PROV_FIPS_PARAM_MODULE_MAC);
|
||||
if (s == NULL) {
|
||||
BIO_printf(bio_err, "Module integrity MAC not found\n");
|
||||
goto end;
|
||||
}
|
||||
buf1 = OPENSSL_hexstr2buf(s, &len);
|
||||
if (buf1 == NULL
|
||||
|| (size_t)len != module_mac_len
|
||||
|| memcmp(module_mac, buf1, module_mac_len) != 0) {
|
||||
BIO_printf(bio_err, "Module integrity mismatch\n");
|
||||
goto end;
|
||||
}
|
||||
s = NCONF_get_string(conf, section, OSSL_PROV_FIPS_PARAM_INSTALL_MAC);
|
||||
if (s == NULL) {
|
||||
BIO_printf(bio_err, "Install indicator MAC not found\n");
|
||||
goto end;
|
||||
}
|
||||
buf2 = OPENSSL_hexstr2buf(s, &len);
|
||||
if (buf2 == NULL
|
||||
|| (size_t)len != install_mac_len
|
||||
|| memcmp(install_mac, buf2, install_mac_len) != 0) {
|
||||
BIO_printf(bio_err, "Install indicator status mismatch\n");
|
||||
goto end;
|
||||
}
|
||||
ret = 1;
|
||||
end:
|
||||
OPENSSL_free(buf1);
|
||||
OPENSSL_free(buf2);
|
||||
NCONF_free(conf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int fipsinstall_main(int argc, char **argv)
|
||||
{
|
||||
int ret = 1, verify = 0;
|
||||
BIO *module_bio = NULL, *mem_bio = NULL, *fout = NULL;
|
||||
char *in_fname = NULL, *out_fname = NULL, *prog, *section_name = NULL;
|
||||
char *prov_name = NULL, *module_fname = NULL;
|
||||
static const char *mac_name = DEFAULT_MAC_NAME;
|
||||
EVP_MAC_CTX *ctx = NULL, *ctx2 = NULL;
|
||||
STACK_OF(OPENSSL_STRING) *opts = NULL;
|
||||
OPTION_CHOICE o;
|
||||
unsigned char *read_buffer = NULL;
|
||||
unsigned char module_mac[EVP_MAX_MD_SIZE];
|
||||
size_t module_mac_len = EVP_MAX_MD_SIZE;
|
||||
unsigned char install_mac[EVP_MAX_MD_SIZE];
|
||||
size_t install_mac_len = EVP_MAX_MD_SIZE;
|
||||
EVP_MAC *mac = NULL;
|
||||
CONF *conf = NULL;
|
||||
|
||||
section_name = DEFAULT_FIPS_SECTION;
|
||||
|
||||
prog = opt_init(argc, argv, fipsinstall_options);
|
||||
while ((o = opt_next()) != OPT_EOF) {
|
||||
switch (o) {
|
||||
case OPT_EOF:
|
||||
case OPT_ERR:
|
||||
opthelp:
|
||||
BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
|
||||
goto end;
|
||||
case OPT_HELP:
|
||||
opt_help(fipsinstall_options);
|
||||
ret = 0;
|
||||
goto end;
|
||||
case OPT_IN:
|
||||
in_fname = opt_arg();
|
||||
break;
|
||||
case OPT_OUT:
|
||||
out_fname = opt_arg();
|
||||
break;
|
||||
case OPT_PROV_NAME:
|
||||
prov_name = opt_arg();
|
||||
break;
|
||||
case OPT_MODULE:
|
||||
module_fname = opt_arg();
|
||||
break;
|
||||
case OPT_SECTION_NAME:
|
||||
section_name = opt_arg();
|
||||
break;
|
||||
case OPT_MAC_NAME:
|
||||
mac_name = opt_arg();
|
||||
break;
|
||||
case OPT_MACOPT:
|
||||
if (opts == NULL)
|
||||
opts = sk_OPENSSL_STRING_new_null();
|
||||
if (opts == NULL || !sk_OPENSSL_STRING_push(opts, opt_arg()))
|
||||
goto opthelp;
|
||||
break;
|
||||
case OPT_VERIFY:
|
||||
verify = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
argc = opt_num_rest();
|
||||
if (module_fname == NULL
|
||||
|| (verify && in_fname == NULL)
|
||||
|| (!verify && (out_fname == NULL || prov_name == NULL))
|
||||
|| opts == NULL
|
||||
|| argc != 0)
|
||||
goto opthelp;
|
||||
|
||||
module_bio = bio_open_default(module_fname, 'r', FORMAT_BINARY);
|
||||
if (module_bio == NULL) {
|
||||
BIO_printf(bio_err, "Failed to open module file\n");
|
||||
goto end;
|
||||
}
|
||||
|
||||
read_buffer = app_malloc(BUFSIZE, "I/O buffer");
|
||||
if (read_buffer == NULL)
|
||||
goto end;
|
||||
|
||||
mac = EVP_MAC_fetch(NULL, mac_name, NULL);
|
||||
if (mac == NULL) {
|
||||
BIO_printf(bio_err, "Unable to get MAC of type %s\n", mac_name);
|
||||
goto end;
|
||||
}
|
||||
|
||||
ctx = EVP_MAC_CTX_new(mac);
|
||||
if (ctx == NULL) {
|
||||
BIO_printf(bio_err, "Unable to create MAC CTX for module check\n");
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (opts != NULL) {
|
||||
int ok = 1;
|
||||
OSSL_PARAM *params =
|
||||
app_params_new_from_opts(opts, EVP_MAC_CTX_settable_params(mac));
|
||||
|
||||
if (params == NULL)
|
||||
goto end;
|
||||
|
||||
if (!EVP_MAC_CTX_set_params(ctx, params)) {
|
||||
BIO_printf(bio_err, "MAC parameter error\n");
|
||||
ERR_print_errors(bio_err);
|
||||
ok = 0;
|
||||
}
|
||||
app_params_free(params);
|
||||
if (!ok)
|
||||
goto end;
|
||||
}
|
||||
|
||||
ctx2 = EVP_MAC_CTX_dup(ctx);
|
||||
if (ctx2 == NULL) {
|
||||
BIO_printf(bio_err, "Unable to create MAC CTX for install indicator\n");
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!do_mac(ctx, read_buffer, module_bio, module_mac, &module_mac_len))
|
||||
goto end;
|
||||
|
||||
mem_bio = BIO_new_mem_buf((const void *)INSTALL_STATUS_VAL,
|
||||
strlen(INSTALL_STATUS_VAL));
|
||||
if (mem_bio == NULL) {
|
||||
BIO_printf(bio_err, "Unable to create memory BIO\n");
|
||||
goto end;
|
||||
}
|
||||
if (!do_mac(ctx2, read_buffer, mem_bio, install_mac, &install_mac_len))
|
||||
goto end;
|
||||
|
||||
if (verify) {
|
||||
if (!verify_config(in_fname, section_name, module_mac, module_mac_len,
|
||||
install_mac, install_mac_len))
|
||||
goto end;
|
||||
BIO_printf(bio_out, "VERIFY PASSED\n");
|
||||
} else {
|
||||
|
||||
conf = generate_config_and_load(prov_name, section_name, module_mac,
|
||||
module_mac_len);
|
||||
if (conf == NULL)
|
||||
goto end;
|
||||
if (!load_fips_prov_and_run_self_test(prov_name))
|
||||
goto end;
|
||||
|
||||
fout = bio_open_default(out_fname, 'w', FORMAT_TEXT);
|
||||
if (fout == NULL) {
|
||||
BIO_printf(bio_err, "Failed to open file\n");
|
||||
goto end;
|
||||
}
|
||||
if (!write_config_fips_section(fout, section_name, module_mac,
|
||||
module_mac_len, install_mac,
|
||||
install_mac_len))
|
||||
goto end;
|
||||
BIO_printf(bio_out, "INSTALL PASSED\n");
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
end:
|
||||
if (ret == 1) {
|
||||
BIO_printf(bio_err, "%s FAILED\n", verify ? "VERIFY" : "INSTALL");
|
||||
ERR_print_errors(bio_err);
|
||||
}
|
||||
|
||||
BIO_free(fout);
|
||||
BIO_free(mem_bio);
|
||||
BIO_free(module_bio);
|
||||
sk_OPENSSL_STRING_free(opts);
|
||||
EVP_MAC_free(mac);
|
||||
EVP_MAC_CTX_free(ctx2);
|
||||
EVP_MAC_CTX_free(ctx);
|
||||
OPENSSL_free(read_buffer);
|
||||
free_config_and_unload(conf);
|
||||
return ret;
|
||||
}
|
|
@ -264,4 +264,8 @@ typedef struct verify_options_st {
|
|||
|
||||
extern VERIFY_CB_ARGS verify_args;
|
||||
|
||||
OSSL_PARAM *app_params_new_from_opts(STACK_OF(OPENSSL_STRING) *opts,
|
||||
const OSSL_PARAM *paramdefs);
|
||||
void app_params_free(OSSL_PARAM *params);
|
||||
|
||||
#endif
|
||||
|
|
41
apps/mac.c
41
apps/mac.c
|
@ -29,8 +29,8 @@ const OPTIONS mac_options[] = {
|
|||
{OPT_HELP_STR, 1, '-', "mac_name\t\t MAC algorithm (See list "
|
||||
"-mac-algorithms)"},
|
||||
{"help", OPT_HELP, '-', "Display this summary"},
|
||||
{"macopt", OPT_MACOPT, 's', "MAC algorithm control parameters in n:v form. "
|
||||
"See 'Supported Controls' in the EVP_MAC_ docs"},
|
||||
{"macopt", OPT_MACOPT, 's', "MAC algorithm parameters in n:v form. "
|
||||
"See 'PARAMETER NAMES' in the EVP_MAC_ docs"},
|
||||
{"in", OPT_IN, '<', "Input file to MAC (default is stdin)"},
|
||||
{"out", OPT_OUT, '>', "Output to filename rather than stdout"},
|
||||
{"binary", OPT_BIN, '-', "Output in binary format (Default is hexadecimal "
|
||||
|
@ -103,43 +103,19 @@ opthelp:
|
|||
goto err;
|
||||
|
||||
if (opts != NULL) {
|
||||
OSSL_PARAM *params =
|
||||
OPENSSL_zalloc(sizeof(OSSL_PARAM)
|
||||
* (sk_OPENSSL_STRING_num(opts) + 1));
|
||||
const OSSL_PARAM *paramdefs = EVP_MAC_CTX_settable_params(mac);
|
||||
size_t params_n;
|
||||
int ok = 1;
|
||||
OSSL_PARAM *params =
|
||||
app_params_new_from_opts(opts, EVP_MAC_CTX_settable_params(mac));
|
||||
|
||||
for (params_n = 0; params_n < (size_t)sk_OPENSSL_STRING_num(opts);
|
||||
params_n++) {
|
||||
char *opt = sk_OPENSSL_STRING_value(opts, (int)params_n);
|
||||
char *stmp, *vtmp = NULL;
|
||||
if (params == NULL)
|
||||
goto err;
|
||||
|
||||
if ((stmp = OPENSSL_strdup(opt)) == NULL
|
||||
|| (vtmp = strchr(stmp, ':')) == NULL
|
||||
|| (*vtmp++ = 0) /* Always zero */
|
||||
|| !OSSL_PARAM_allocate_from_text(¶ms[params_n], paramdefs,
|
||||
stmp, vtmp, strlen(vtmp))) {
|
||||
BIO_printf(bio_err, "MAC parameter error '%s'\n", opt);
|
||||
ERR_print_errors(bio_err);
|
||||
ok = 0;
|
||||
}
|
||||
OPENSSL_free(stmp);
|
||||
if (!ok)
|
||||
break;
|
||||
}
|
||||
if (ok) {
|
||||
params[params_n] = OSSL_PARAM_construct_end();
|
||||
if (!EVP_MAC_CTX_set_params(ctx, params)) {
|
||||
BIO_printf(bio_err, "MAC parameter error\n");
|
||||
ERR_print_errors(bio_err);
|
||||
goto err;
|
||||
ok = 0;
|
||||
}
|
||||
}
|
||||
for (; params_n-- > 0;) {
|
||||
OPENSSL_free(params[params_n].data);
|
||||
}
|
||||
OPENSSL_free(params);
|
||||
app_params_free(params);
|
||||
if (!ok)
|
||||
goto err;
|
||||
}
|
||||
|
@ -160,7 +136,6 @@ opthelp:
|
|||
goto err;
|
||||
}
|
||||
|
||||
|
||||
for (;;) {
|
||||
i = BIO_read(in, (char *)buf, BUFSIZE);
|
||||
if (i < 0) {
|
||||
|
|
|
@ -44,6 +44,7 @@ FUNCTION functions[] = {
|
|||
{FT_general, "engine", engine_main, engine_options},
|
||||
#endif
|
||||
{FT_general, "errstr", errstr_main, errstr_options},
|
||||
{FT_general, "fipsinstall", fipsinstall_main, fipsinstall_options},
|
||||
#ifndef OPENSSL_NO_DSA
|
||||
{FT_general, "gendsa", gendsa_main, gendsa_options},
|
||||
#endif
|
||||
|
|
|
@ -27,6 +27,7 @@ extern int ecparam_main(int argc, char *argv[]);
|
|||
extern int enc_main(int argc, char *argv[]);
|
||||
extern int engine_main(int argc, char *argv[]);
|
||||
extern int errstr_main(int argc, char *argv[]);
|
||||
extern int fipsinstall_main(int argc, char *argv[]);
|
||||
extern int gendsa_main(int argc, char *argv[]);
|
||||
extern int genpkey_main(int argc, char *argv[]);
|
||||
extern int genrsa_main(int argc, char *argv[]);
|
||||
|
@ -79,6 +80,7 @@ extern const OPTIONS ecparam_options[];
|
|||
extern const OPTIONS enc_options[];
|
||||
extern const OPTIONS engine_options[];
|
||||
extern const OPTIONS errstr_options[];
|
||||
extern const OPTIONS fipsinstall_options[];
|
||||
extern const OPTIONS gendsa_options[];
|
||||
extern const OPTIONS genpkey_options[];
|
||||
extern const OPTIONS genrsa_options[];
|
||||
|
|
147
doc/man1/fipsinstall.pod
Normal file
147
doc/man1/fipsinstall.pod
Normal file
|
@ -0,0 +1,147 @@
|
|||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
openssl-fipsinstall - perform FIPS configuration installation
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
B<openssl fipsinstall>
|
||||
[B<-help>]
|
||||
[B<-in configfilename>]
|
||||
[B<-out configfilename>]
|
||||
[B<-module modulefilename>]
|
||||
[B<-provider_name providername>]
|
||||
[B<-section_name sectionname>]
|
||||
[B<-verify>]
|
||||
[B<-mac_name macname>]
|
||||
[B<-macopt>]
|
||||
|
||||
B<openssl> I<fipsinstall> [B<...>]
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This utility is used to generate a FIPS module configuration file.
|
||||
The generated configuration file consists of:
|
||||
|
||||
=over 4
|
||||
|
||||
=item - A mac of the FIPS module file.
|
||||
|
||||
=item - A status indicator that indicates if the known answer Self Tests (KAT's)
|
||||
have successfully run.
|
||||
|
||||
=back
|
||||
|
||||
This configuration file can be used each time a FIPS module is loaded
|
||||
in order to pass data to the FIPS modules self tests. The FIPS module always
|
||||
verifies the modules MAC, but only needs to run the KATS once during install.
|
||||
|
||||
=head1 OPTIONS
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<-help>
|
||||
|
||||
Print a usage message.
|
||||
|
||||
=item B<-module filename>
|
||||
|
||||
Filename of a fips module to perform an integrity check on.
|
||||
|
||||
=item B<-out configfilename>
|
||||
|
||||
Filename to output the configuration data to, or standard output by default.
|
||||
|
||||
=item B<-in configfilename>
|
||||
|
||||
Input filename to load configuration data from. Used with the '-verify' option.
|
||||
Standard input is used if the filename is '-'.
|
||||
|
||||
=item B<-verify>
|
||||
|
||||
Verify that the input configuration file contains the correct information
|
||||
|
||||
=item B<-provider_name providername>
|
||||
|
||||
Name of the provider inside the configuration file.
|
||||
|
||||
=item B<-section_name sectionname>
|
||||
|
||||
Name of the section inside the configuration file.
|
||||
|
||||
=item B<-mac_name name>
|
||||
|
||||
Specifies the name of a supported MAC algorithm which will be used.
|
||||
To see the list of supported MAC's use the command I<list -mac-algorithms>.
|
||||
The default is "HMAC".
|
||||
|
||||
=item B<-macopt nm:v>
|
||||
|
||||
Passes options to the MAC algorithm.
|
||||
A comprehensive list of controls can be found in the EVP_MAC implementation
|
||||
documentation.
|
||||
Common control strings used for fipsinstall are:
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<key:string>
|
||||
|
||||
Specifies the MAC key as an alphanumeric string (use if the key contains
|
||||
printable characters only).
|
||||
The string length must conform to any restrictions of the MAC algorithm.
|
||||
A key must be specified for every MAC algorithm.
|
||||
|
||||
=item B<hexkey:string>
|
||||
|
||||
Specifies the MAC key in hexadecimal form (two hex digits per byte).
|
||||
The key length must conform to any restrictions of the MAC algorithm.
|
||||
A key must be specified for every MAC algorithm.
|
||||
|
||||
=item B<digest:string>
|
||||
|
||||
Used by HMAC as an alphanumeric string (use if the key contains printable
|
||||
characters only).
|
||||
The string length must conform to any restrictions of the MAC algorithm.
|
||||
To see the list of supported digests, use the command I<list -digest-commands>.
|
||||
|
||||
=back
|
||||
|
||||
=back
|
||||
|
||||
=head1 EXAMPLES
|
||||
|
||||
Calculate the mac of a FIPS module 'fips.so' and run a FIPS self test
|
||||
for the module, and save the fips.conf configuration file:
|
||||
|
||||
openssl fipsinstall -module ./fips.so -out fips.conf -provider_name fips \
|
||||
-section_name fipsinstall -mac_name HMAC -macopt digest:SHA256 \
|
||||
-macopt hexkey:000102030405060708090A0B0C0D0E0F10111213
|
||||
|
||||
Verify that the configuration file 'fips.conf' contains the correct info:
|
||||
|
||||
openssl fipsinstall -module ./fips.so -in fips.conf -provider_name fips \
|
||||
-section_name fips_install -mac_name HMAC -macopt digest:SHA256 \
|
||||
-macopt hexkey:000102030405060708090A0B0C0D0E0F10111213 -verify
|
||||
|
||||
=head1 NOTES
|
||||
|
||||
The MAC mechanisms that are available will depend on the options
|
||||
used when building OpenSSL.
|
||||
The B<list -mac-algorithms> command can be used to list them.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<fips_config(5)>,
|
||||
L<EVP_MAC(3)>
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
|
||||
Licensed under the OpenSSL license (the "License"). You may not use
|
||||
this file except in compliance with the License. You can obtain a copy
|
||||
in the file LICENSE in the source distribution or at
|
||||
L<https://www.openssl.org/source/license.html>.
|
||||
|
||||
=cut
|
73
test/recipes/03-test_fipsinstall.t
Normal file
73
test/recipes/03-test_fipsinstall.t
Normal file
|
@ -0,0 +1,73 @@
|
|||
#! /usr/bin/env perl
|
||||
# Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
# this file except in compliance with the License. You can obtain a copy
|
||||
# in the file LICENSE in the source distribution or at
|
||||
# https://www.openssl.org/source/license.html
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use File::Spec;
|
||||
use File::Copy;
|
||||
use OpenSSL::Glob;
|
||||
use OpenSSL::Test qw/:DEFAULT srctop_dir bldtop_dir bldtop_file/;
|
||||
use OpenSSL::Test::Utils;
|
||||
|
||||
BEGIN {
|
||||
setup("test_fipsinstall");
|
||||
}
|
||||
use lib srctop_dir('Configurations');
|
||||
use lib bldtop_dir('.');
|
||||
use platform;
|
||||
|
||||
plan skip_all => "Test only supported in a fips build" if disabled("fips");
|
||||
|
||||
plan tests => 6;
|
||||
|
||||
my $infile = bldtop_file('providers', platform->dso('fips'));
|
||||
$ENV{OPENSSL_MODULES} = bldtop_dir("providers");
|
||||
|
||||
#fail if no module name
|
||||
ok(!run(app(['openssl', 'fipsinstall', '-out', 'fips.conf', '-module',
|
||||
'-provider_name', 'fips',
|
||||
'-macopt', 'digest:SHA256', '-macopt', 'hexkey:00',
|
||||
'-section_name', 'fips_install'])),
|
||||
"fipinstall fail");
|
||||
|
||||
# fail to Verify if the configuration file is missing
|
||||
ok(!run(app(['openssl', 'fipsinstall', '-in', 'dummy.tmp', '-module', $infile,
|
||||
'-provider_name', 'fips', '-mac_name', 'HMAC',
|
||||
'-macopt', 'digest:SHA256', '-macopt', 'hexkey:00',
|
||||
'-section_name', 'fips_install', '-verify'])),
|
||||
"fipinstall verify fail");
|
||||
|
||||
|
||||
# output a fips.conf file containing mac data
|
||||
ok(run(app(['openssl', 'fipsinstall', '-out', 'fips.conf', '-module', $infile,
|
||||
'-provider_name', 'fips', '-mac_name', 'HMAC',
|
||||
'-macopt', 'digest:SHA256', '-macopt', 'hexkey:00',
|
||||
'-section_name', 'fips_install'])),
|
||||
"fipinstall");
|
||||
|
||||
# Verify the fips.conf file
|
||||
ok(run(app(['openssl', 'fipsinstall', '-in', 'fips.conf', '-module', $infile,
|
||||
'-provider_name', 'fips', '-mac_name', 'HMAC',
|
||||
'-macopt', 'digest:SHA256', '-macopt', 'hexkey:00',
|
||||
'-section_name', 'fips_install', '-verify'])),
|
||||
"fipinstall verify");
|
||||
|
||||
# Fail to Verify the fips.conf file if a different key is used
|
||||
ok(!run(app(['openssl', 'fipsinstall', '-in', 'fips.conf', '-module', $infile,
|
||||
'-provider_name', 'fips', '-mac_name', 'HMAC',
|
||||
'-macopt', 'digest:SHA256', '-macopt', 'hexkey:01',
|
||||
'-section_name', 'fips_install', '-verify'])),
|
||||
"fipinstall verify fail bad key");
|
||||
|
||||
# Fail to Verify the fips.conf file if a different mac digest is used
|
||||
ok(!run(app(['openssl', 'fipsinstall', '-in', 'fips.conf', '-module', $infile,
|
||||
'-provider_name', 'fips', '-mac_name', 'HMAC',
|
||||
'-macopt', 'digest:SHA512', '-macopt', 'hexkey:00',
|
||||
'-section_name', 'fips_install', '-verify'])),
|
||||
"fipinstall verify fail incorrect digest");
|
Loading…
Reference in a new issue