mirror of
https://github.com/openssl/openssl.git
synced 2025-12-20 01:22:19 +08:00
dgst and mac apps: Added new ways for obtaining a MAC key
Resolves #24584 It is now possible to obtain a MAC key from an environment variable, a file or read it from the standard input. Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com> Reviewed-by: Tomas Mraz <tomas@openssl.org> (Merged from https://github.com/openssl/openssl/pull/28160)
This commit is contained in:
43
apps/dgst.c
43
apps/dgst.c
@@ -44,7 +44,7 @@ typedef enum OPTION_choice {
|
||||
OPT_C, OPT_R, OPT_OUT, OPT_SIGN, OPT_PASSIN, OPT_VERIFY,
|
||||
OPT_PRVERIFY, OPT_SIGNATURE, OPT_KEYFORM, OPT_ENGINE, OPT_ENGINE_IMPL,
|
||||
OPT_HEX, OPT_BINARY, OPT_DEBUG, OPT_FIPS_FINGERPRINT,
|
||||
OPT_HMAC, OPT_MAC, OPT_SIGOPT, OPT_MACOPT, OPT_XOFLEN,
|
||||
OPT_HMAC, OPT_HMAC_ENV, OPT_HMAC_STDIN, OPT_MAC, OPT_SIGOPT, OPT_MACOPT, OPT_XOFLEN,
|
||||
OPT_DIGEST,
|
||||
OPT_R_ENUM, OPT_PROV_ENUM
|
||||
} OPTION_CHOICE;
|
||||
@@ -80,6 +80,8 @@ const OPTIONS dgst_options[] = {
|
||||
{"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"},
|
||||
{"signature", OPT_SIGNATURE, '<', "File with signature to verify"},
|
||||
{"hmac", OPT_HMAC, 's', "Create hashed MAC with key"},
|
||||
{"hmac-env", OPT_HMAC_ENV, 's', "Create hashed MAC with key from environment variable"},
|
||||
{"hmac-stdin", OPT_HMAC_STDIN, '-', "Create hashed MAC with key from stdin"},
|
||||
{"mac", OPT_MAC, 's', "Create MAC (not necessarily HMAC)"},
|
||||
{"macopt", OPT_MACOPT, 's', "MAC algorithm parameters in n:v form or key"},
|
||||
{"", OPT_DIGEST, '-', "Any supported digest"},
|
||||
@@ -107,6 +109,9 @@ int dgst_main(int argc, char **argv)
|
||||
const char *outfile = NULL, *keyfile = NULL, *prog = NULL;
|
||||
const char *sigfile = NULL;
|
||||
const char *md_name = NULL;
|
||||
char *env_var = NULL;
|
||||
char *new_opt = NULL;
|
||||
char *key_from_stdin = NULL;
|
||||
OPTION_CHOICE o;
|
||||
int separator = 0, debug = 0, keyform = FORMAT_UNDEF, siglen = 0;
|
||||
int i, ret = EXIT_FAILURE, out_bin = -1, want_pub = 0, do_verify = 0;
|
||||
@@ -202,6 +207,29 @@ int dgst_main(int argc, char **argv)
|
||||
case OPT_HMAC:
|
||||
hmac_key = opt_arg();
|
||||
break;
|
||||
case OPT_HMAC_ENV:
|
||||
env_var = opt_arg();
|
||||
hmac_key = getenv(env_var);
|
||||
if (hmac_key == NULL) {
|
||||
BIO_printf(bio_err, "No environment variable %s\n", env_var);
|
||||
ret = EXIT_FAILURE;
|
||||
goto end;
|
||||
}
|
||||
break;
|
||||
case OPT_HMAC_STDIN:
|
||||
if (key_from_stdin == NULL)
|
||||
key_from_stdin = get_str_from_file(NULL);
|
||||
if (key_from_stdin == NULL) {
|
||||
ret = EXIT_FAILURE;
|
||||
goto end;
|
||||
}
|
||||
if (strlen(key_from_stdin) == 0) {
|
||||
BIO_printf(bio_err, "Empty key\n");
|
||||
ret = EXIT_FAILURE;
|
||||
goto end;
|
||||
}
|
||||
hmac_key = key_from_stdin;
|
||||
break;
|
||||
case OPT_MAC:
|
||||
mac_name = opt_arg();
|
||||
break;
|
||||
@@ -212,10 +240,17 @@ int dgst_main(int argc, char **argv)
|
||||
goto opthelp;
|
||||
break;
|
||||
case OPT_MACOPT:
|
||||
new_opt = process_additional_mac_key_arguments(opt_arg());
|
||||
if (new_opt == NULL) {
|
||||
ret = EXIT_FAILURE;
|
||||
goto end;
|
||||
}
|
||||
if (!macopts)
|
||||
macopts = sk_OPENSSL_STRING_new_null();
|
||||
if (!macopts || !sk_OPENSSL_STRING_push(macopts, opt_arg()))
|
||||
if (!macopts || !sk_OPENSSL_STRING_push(macopts, new_opt)) {
|
||||
clear_free(new_opt);
|
||||
goto opthelp;
|
||||
}
|
||||
break;
|
||||
case OPT_DIGEST:
|
||||
digestname = opt_unknown();
|
||||
@@ -487,6 +522,8 @@ int dgst_main(int argc, char **argv)
|
||||
if (ret != EXIT_SUCCESS)
|
||||
ERR_print_errors(bio_err);
|
||||
OPENSSL_clear_free(buf, BUFSIZE);
|
||||
if (key_from_stdin != NULL)
|
||||
clear_free(key_from_stdin);
|
||||
BIO_free(in);
|
||||
OPENSSL_free(passin);
|
||||
BIO_free_all(out);
|
||||
@@ -494,7 +531,7 @@ int dgst_main(int argc, char **argv)
|
||||
EVP_PKEY_free(sigkey);
|
||||
EVP_MD_CTX_free(signctx);
|
||||
sk_OPENSSL_STRING_free(sigopts);
|
||||
sk_OPENSSL_STRING_free(macopts);
|
||||
sk_OPENSSL_STRING_pop_free(macopts, clear_free);
|
||||
OPENSSL_free(sigbuf);
|
||||
BIO_free(bmd);
|
||||
release_engine(e);
|
||||
|
||||
@@ -139,6 +139,8 @@ EVP_PKEY *load_keyparams_suppress(const char *uri, int format, int maybe_stdin,
|
||||
const char *keytype, const char *desc,
|
||||
int suppress_decode_errors);
|
||||
char *next_item(char *opt); /* in list separated by comma and/or space */
|
||||
char *process_additional_mac_key_arguments(const char *arg);
|
||||
char *get_str_from_file(const char *filename);
|
||||
int load_cert_certs(const char *uri,
|
||||
X509 **pcert, STACK_OF(X509) **pcerts,
|
||||
int exclude_http, const char *pass, const char *desc,
|
||||
|
||||
154
apps/lib/apps.c
154
apps/lib/apps.c
@@ -3513,3 +3513,157 @@ int opt_legacy_okay(void)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define MAX_KEY_SIZE 2048 /* Hope nobody needs mac key longer than 2048 bytes */
|
||||
|
||||
/*
|
||||
* Implementations of mac algorithms only support getting a key via the
|
||||
* key and hexkey parameters. This function processes additional parameters
|
||||
* for reading a key from an environment variable or from a file or stdin
|
||||
* and forms a key or hexkey parameter with the read key.
|
||||
* Leaves other parameters unchanged.
|
||||
* Allocates a string with a new parameter and returns a pointer to this
|
||||
* string, the calling code must free this string by calling OPENSSL_clear_free.
|
||||
* Returns NULL in case of an error.
|
||||
*/
|
||||
char *process_additional_mac_key_arguments(const char *arg)
|
||||
{
|
||||
static BIO *keybio = NULL;
|
||||
char *val = NULL, *inbuf = NULL, *outbuf = NULL;
|
||||
int total_read = 0;
|
||||
int n;
|
||||
char dummy;
|
||||
int too_long;
|
||||
|
||||
if (CHECK_AND_SKIP_PREFIX(arg, "keyenv:")) {
|
||||
if (strlen(arg) == 0) {
|
||||
BIO_printf(bio_err, "Empty environment variable name\n");
|
||||
return NULL;
|
||||
}
|
||||
val = getenv(arg);
|
||||
if (val == NULL) {
|
||||
BIO_printf(bio_err, "No environment variable %s\n", arg);
|
||||
return NULL;
|
||||
}
|
||||
outbuf = app_malloc(strlen("key:") + strlen(val) + 1, "MACOPT KEYENV");
|
||||
strcpy(outbuf, "key:");
|
||||
strcat(outbuf, val);
|
||||
return outbuf;
|
||||
}
|
||||
|
||||
if (CHECK_AND_SKIP_PREFIX(arg, "keyenvhex:")) {
|
||||
if (strlen(arg) == 0) {
|
||||
BIO_printf(bio_err, "Empty environment variable name\n");
|
||||
return NULL;
|
||||
}
|
||||
val = getenv(arg);
|
||||
if (val == NULL) {
|
||||
BIO_printf(bio_err, "No environment variable %s\n", arg);
|
||||
return NULL;
|
||||
}
|
||||
outbuf = app_malloc(strlen("hexkey:") + strlen(val) + 1, "MACOPT KEYENVHEX");
|
||||
strcpy(outbuf, "hexkey:");
|
||||
strcat(outbuf, val);
|
||||
return outbuf;
|
||||
}
|
||||
|
||||
if (CHECK_AND_SKIP_PREFIX(arg, "keyfile:")) {
|
||||
if (strlen(arg) == 0) {
|
||||
BIO_printf(bio_err, "Empty key file name\n");
|
||||
return NULL;
|
||||
}
|
||||
keybio = BIO_new_file(arg, "rb");
|
||||
if (keybio == NULL) {
|
||||
BIO_printf(bio_err, "Can't open file %s\n", arg);
|
||||
return NULL;
|
||||
}
|
||||
inbuf = app_malloc(MAX_KEY_SIZE, "MACOPT KEYFILE");
|
||||
while (total_read < MAX_KEY_SIZE) {
|
||||
n = BIO_read(keybio, inbuf + total_read, MAX_KEY_SIZE - total_read);
|
||||
if (n < 0) {
|
||||
BIO_printf(bio_err, "Can't read file %s\n", arg);
|
||||
OPENSSL_clear_free(inbuf, MAX_KEY_SIZE);
|
||||
BIO_free(keybio);
|
||||
return NULL;
|
||||
}
|
||||
if (n == 0) /* EOF */
|
||||
break;
|
||||
total_read += n;
|
||||
}
|
||||
too_long = (total_read == MAX_KEY_SIZE && BIO_read(keybio, &dummy, 1) > 0);
|
||||
BIO_free(keybio);
|
||||
if (total_read == 0 || too_long) {
|
||||
/* File is empty or longer than MAX_KEY_SIZE */
|
||||
BIO_printf(bio_err, (too_long) ? "File %s is too long\n" : "File %s is empty\n", arg);
|
||||
OPENSSL_clear_free(inbuf, MAX_KEY_SIZE);
|
||||
return NULL;
|
||||
}
|
||||
outbuf = app_malloc(strlen("hexkey:") + total_read * 2 + 1, "MACOPT KEYFILE");
|
||||
strcpy(outbuf, "hexkey:");
|
||||
OPENSSL_buf2hexstr_ex(outbuf + strlen("hexkey:"), total_read * 2 + 1,
|
||||
NULL, (unsigned char *)inbuf, total_read, '\0');
|
||||
OPENSSL_clear_free(inbuf, MAX_KEY_SIZE);
|
||||
return outbuf;
|
||||
}
|
||||
|
||||
if (strcmp(arg, "keystdin") == 0) {
|
||||
inbuf = get_str_from_file(NULL);
|
||||
if (inbuf == NULL)
|
||||
return NULL;
|
||||
if (strlen(inbuf) == 0) {
|
||||
BIO_printf(bio_err, "Empty key\n");
|
||||
clear_free(inbuf);
|
||||
return NULL;
|
||||
}
|
||||
outbuf = app_malloc(strlen("key:") + strlen(inbuf) + 1, "MACOPT KEYSTDIN");
|
||||
strcpy(outbuf, "key:");
|
||||
strcat(outbuf, inbuf);
|
||||
clear_free(inbuf);
|
||||
return outbuf;
|
||||
}
|
||||
|
||||
return OPENSSL_strdup(arg);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read one line from file.
|
||||
* Allocates a string with the data read and returns a pointer to this
|
||||
* string, the calling code must free this string.
|
||||
* If filename == NULL, read from standard input.
|
||||
* Returns NULL in case of any error.
|
||||
*/
|
||||
char *get_str_from_file(const char *filename)
|
||||
{
|
||||
static BIO *bio = NULL;
|
||||
int n;
|
||||
char *buf = NULL;
|
||||
char *tmp;
|
||||
|
||||
if (filename == NULL) {
|
||||
unbuffer(stdin);
|
||||
bio = dup_bio_in(FORMAT_TEXT);
|
||||
if (bio == NULL) {
|
||||
BIO_printf(bio_err, "Can't open BIO for stdin\n");
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
bio = BIO_new_file(filename, "r");
|
||||
if (bio == NULL) {
|
||||
BIO_printf(bio_err, "Can't open file %s\n", filename);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
buf = app_malloc(MAX_KEY_SIZE, "get_str_from_file");
|
||||
memset(buf, 0, MAX_KEY_SIZE);
|
||||
n = BIO_gets(bio, buf, MAX_KEY_SIZE - 1);
|
||||
BIO_free_all(bio);
|
||||
bio = NULL;
|
||||
if (n <= 0) {
|
||||
BIO_printf(bio_err, "Error reading from %s\n", filename);
|
||||
return NULL;
|
||||
}
|
||||
tmp = strchr(buf, '\n');
|
||||
if (tmp != NULL)
|
||||
*tmp = 0;
|
||||
return buf;
|
||||
}
|
||||
|
||||
14
apps/mac.c
14
apps/mac.c
@@ -89,6 +89,7 @@ int mac_main(int argc, char **argv)
|
||||
int inform = FORMAT_BINARY;
|
||||
char *digest = NULL, *cipher = NULL;
|
||||
OSSL_PARAM *params = NULL;
|
||||
char *new_opt = NULL;
|
||||
|
||||
prog = opt_init(argc, argv, mac_options);
|
||||
buf = app_malloc(BUFSIZE, "I/O buffer");
|
||||
@@ -112,10 +113,17 @@ opthelp:
|
||||
outfile = opt_arg();
|
||||
break;
|
||||
case OPT_MACOPT:
|
||||
new_opt = process_additional_mac_key_arguments(opt_arg());
|
||||
if (new_opt == NULL) {
|
||||
ret = 1;
|
||||
goto err;
|
||||
}
|
||||
if (opts == NULL)
|
||||
opts = sk_OPENSSL_STRING_new_null();
|
||||
if (opts == NULL || !sk_OPENSSL_STRING_push(opts, opt_arg()))
|
||||
if (opts == NULL || !sk_OPENSSL_STRING_push(opts, new_opt)) {
|
||||
clear_free(new_opt);
|
||||
goto opthelp;
|
||||
}
|
||||
break;
|
||||
case OPT_CIPHER:
|
||||
OPENSSL_free(cipher);
|
||||
@@ -225,9 +233,7 @@ err:
|
||||
if (ret != 0)
|
||||
ERR_print_errors(bio_err);
|
||||
OPENSSL_clear_free(buf, BUFSIZE);
|
||||
OPENSSL_free(cipher);
|
||||
OPENSSL_free(digest);
|
||||
sk_OPENSSL_STRING_free(opts);
|
||||
sk_OPENSSL_STRING_pop_free(opts, clear_free);
|
||||
BIO_free(in);
|
||||
BIO_free(out);
|
||||
EVP_MAC_CTX_free(ctx);
|
||||
|
||||
@@ -27,6 +27,8 @@ B<openssl> B<dgst>|I<digest>
|
||||
[B<-signature> I<filename>]
|
||||
[B<-sigopt> I<nm>:I<v>]
|
||||
[B<-hmac> I<key>]
|
||||
[B<-hmac-env> I<var>]
|
||||
[B<-hmac-stdin>]
|
||||
[B<-mac> I<alg>]
|
||||
[B<-macopt> I<nm>:I<v>]
|
||||
[B<-fips-fingerprint>]
|
||||
@@ -157,6 +159,33 @@ The actual signature to verify.
|
||||
|
||||
Create a hashed MAC using "key".
|
||||
|
||||
Cannot be used together with -mac option.
|
||||
If multiple -hmac, -hmac-env or -hmac-stdin options are specified, the last
|
||||
one is applied.
|
||||
|
||||
The L<openssl-mac(1)> command should be preferred to using this command line
|
||||
option.
|
||||
|
||||
=item B<-hmac-env> I<var>
|
||||
|
||||
Create a hashed MAC using a key from the environment variable "var".
|
||||
|
||||
Cannot be used together with -mac option.
|
||||
If multiple -hmac, -hmac-env or -hmac-stdin options are specified, the last
|
||||
one is applied.
|
||||
|
||||
The L<openssl-mac(1)> command should be preferred to using this command line
|
||||
option.
|
||||
|
||||
=item B<-hmac-stdin>
|
||||
|
||||
Create a hashed MAC using a key obtained from the standard input. Only the
|
||||
first line from stdin is read, and the \0 character also terminates the key.
|
||||
|
||||
Cannot be used together with -mac option.
|
||||
If multiple -hmac, -hmac-env or -hmac-stdin options are specified, the last
|
||||
one is applied.
|
||||
|
||||
The L<openssl-mac(1)> command should be preferred to using this command line
|
||||
option.
|
||||
|
||||
@@ -168,6 +197,8 @@ which are not based on hash, for instance B<gost-mac> algorithm,
|
||||
supported by the B<gost> engine. MAC keys and other options should be set
|
||||
via B<-macopt> parameter.
|
||||
|
||||
Cannot be used together with -hmac, -hmac-env and -hmac-stdin.
|
||||
|
||||
The L<openssl-mac(1)> command should be preferred to using this command line
|
||||
option.
|
||||
|
||||
@@ -190,8 +221,37 @@ Specifies MAC key in hexadecimal form (two hex digits per byte).
|
||||
Key length must conform to any restrictions of the MAC algorithm
|
||||
for example exactly 32 chars for gost-mac.
|
||||
|
||||
=item B<keyenv:>I<var>
|
||||
|
||||
Read the MAC key as an alphanumeric string from the environment variable
|
||||
(use if the key contains printable characters only).
|
||||
The the key length must conform to any restrictions of the MAC algorithm.
|
||||
A key must be specified for every MAC algorithm.
|
||||
|
||||
=item B<keyenvhex:>I<var>
|
||||
|
||||
Read the MAC key in hexadecimal form (two hex digits per byte)
|
||||
from the environment variable.
|
||||
The key length must conform to any restrictions of the MAC algorithm.
|
||||
A key must be specified for every MAC algorithm.
|
||||
|
||||
=item B<keyfile:>I<filename>
|
||||
|
||||
Read the MAC key from the specified file. The key is read as binary data.
|
||||
The key length must conform to any restrictions of the MAC algorithm.
|
||||
A key must be specified for every MAC algorithm.
|
||||
|
||||
=item B<keystdin>
|
||||
|
||||
Read the MAC key from the standard input. Only the first line from stdin is
|
||||
read, and the \0 character also terminates the key.
|
||||
The key length must conform to any restrictions of the MAC algorithm.
|
||||
A key must be specified for every MAC algorithm.
|
||||
|
||||
=back
|
||||
|
||||
If multiple MAC key options are specified, the last one is applied.
|
||||
|
||||
The L<openssl-mac(1)> command should be preferred to using this command line
|
||||
option.
|
||||
|
||||
@@ -283,6 +343,8 @@ The FIPS-related options were removed in OpenSSL 1.1.0.
|
||||
|
||||
The B<-engine> and B<-engine_impl> options were deprecated in OpenSSL 3.0.
|
||||
|
||||
The B<-hmac-env> and B<-hmac-stdin> options ware added in OpenSSL 3.6.
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright 2000-2025 The OpenSSL Project Authors. All Rights Reserved.
|
||||
|
||||
@@ -109,6 +109,41 @@ This option is identical to the B<-cipher> option.
|
||||
|
||||
=back
|
||||
|
||||
Some additional options can be used only as command-line parameters.
|
||||
They are not passed to the MAC algorithm, but translated into
|
||||
key and hexkey parameters instead:
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<keyenv:>I<var>
|
||||
|
||||
Read the MAC key as an alphanumeric string from the environment variable
|
||||
(use if the key contains printable characters only).
|
||||
The the key length must conform to any restrictions of the MAC algorithm.
|
||||
A key must be specified for every MAC algorithm.
|
||||
|
||||
=item B<keyenvhex:>I<var>
|
||||
|
||||
Read the MAC key in hexadecimal form (two hex digits per byte)
|
||||
from the environment variable.
|
||||
The key length must conform to any restrictions of the MAC algorithm.
|
||||
A key must be specified for every MAC algorithm.
|
||||
|
||||
=item B<keyfile:>I<filename>
|
||||
|
||||
Read the MAC key from the specified file. The key is read as binary data.
|
||||
The key length must conform to any restrictions of the MAC algorithm.
|
||||
A key must be specified for every MAC algorithm.
|
||||
|
||||
=item B<keystdin>
|
||||
|
||||
Read the MAC key from the standard input. Only the first line from stdin
|
||||
is read, and the \0 character also terminates the key.
|
||||
The key length must conform to any restrictions of the MAC algorithm.
|
||||
A key must be specified for every MAC algorithm.
|
||||
|
||||
=back
|
||||
|
||||
{- $OpenSSL::safe::opt_provider_item -}
|
||||
|
||||
=item I<mac_name>
|
||||
|
||||
@@ -12,12 +12,12 @@ use warnings;
|
||||
|
||||
use File::Spec;
|
||||
use File::Basename;
|
||||
use OpenSSL::Test qw/:DEFAULT with srctop_file bldtop_dir/;
|
||||
use OpenSSL::Test qw/:DEFAULT with srctop_file data_file bldtop_dir/;
|
||||
use OpenSSL::Test::Utils;
|
||||
|
||||
setup("test_dgst");
|
||||
|
||||
plan tests => 17;
|
||||
plan tests => 24;
|
||||
|
||||
sub tsignverify {
|
||||
my $testtext = shift;
|
||||
@@ -212,7 +212,51 @@ subtest "HMAC generation with `dgst` CLI, default digest" => sub {
|
||||
"HMAC: Check second HMAC value is consistent with the first ($hmacdata[1]) vs ($expected)");
|
||||
};
|
||||
|
||||
subtest "HMAC generation with `dgst` CLI, key via option" => sub {
|
||||
subtest "HMAC generation with `dgst` CLI, key via environment" => sub {
|
||||
plan tests => 2;
|
||||
|
||||
my $testdata = srctop_file('test', 'data.bin');
|
||||
#HMAC the data twice to check consistency
|
||||
local $ENV{MYKEY} = 123456;
|
||||
my @hmacdata = run(app(['openssl', 'dgst', '-sha256', '-hmac-env', 'MYKEY',
|
||||
$testdata, $testdata]), capture => 1);
|
||||
chomp(@hmacdata);
|
||||
my $expected = qr/HMAC-SHA2-256\(\Q$testdata\E\)= 6f12484129c4a761747f13d8234a1ff0e074adb34e9e9bf3a155c391b97b9a7c/;
|
||||
ok($hmacdata[0] =~ $expected, "HMAC: Check HMAC value is as expected ($hmacdata[0]) vs ($expected)");
|
||||
ok($hmacdata[1] =~ $expected,
|
||||
"HMAC: Check second HMAC value is consistent with the first ($hmacdata[1]) vs ($expected)");
|
||||
};
|
||||
|
||||
subtest "HMAC generation with `dgst` CLI, key via stdin" => sub {
|
||||
plan tests => 2;
|
||||
|
||||
my $testdata = srctop_file('test', 'data.bin');
|
||||
#HMAC the data twice to check consistency
|
||||
my @hmacdata = run(app(['openssl', 'dgst', '-sha256', '-hmac-stdin',
|
||||
$testdata, $testdata], stdin => data_file("keyfile.txt")), capture => 1);
|
||||
chomp(@hmacdata);
|
||||
my $expected = qr/HMAC-SHA2-256\(\Q$testdata\E\)= 6f12484129c4a761747f13d8234a1ff0e074adb34e9e9bf3a155c391b97b9a7c/;
|
||||
ok($hmacdata[0] =~ $expected, "HMAC: Check HMAC value is as expected ($hmacdata[0]) vs ($expected)");
|
||||
ok($hmacdata[1] =~ $expected,
|
||||
"HMAC: Check second HMAC value is consistent with the first ($hmacdata[1]) vs ($expected)");
|
||||
};
|
||||
|
||||
subtest "HMAC generation with `dgst` CLI, key via option key" => sub {
|
||||
plan tests => 2;
|
||||
|
||||
my $testdata = srctop_file('test', 'data.bin');
|
||||
#HMAC the data twice to check consistency
|
||||
my @hmacdata = run(app(['openssl', 'dgst', '-sha256', '-mac', 'HMAC',
|
||||
'-macopt', 'key:123456',
|
||||
$testdata, $testdata]), capture => 1);
|
||||
chomp(@hmacdata);
|
||||
my $expected = qr/HMAC-SHA2-256\(\Q$testdata\E\)= 6f12484129c4a761747f13d8234a1ff0e074adb34e9e9bf3a155c391b97b9a7c/;
|
||||
ok($hmacdata[0] =~ $expected, "HMAC: Check HMAC value is as expected ($hmacdata[0]) vs ($expected)");
|
||||
ok($hmacdata[1] =~ $expected,
|
||||
"HMAC: Check second HMAC value is consistent with the first ($hmacdata[1]) vs ($expected)");
|
||||
};
|
||||
|
||||
subtest "HMAC generation with `dgst` CLI, key via option hexkey" => sub {
|
||||
plan tests => 2;
|
||||
|
||||
my $testdata = srctop_file('test', 'data.bin');
|
||||
@@ -227,6 +271,68 @@ subtest "HMAC generation with `dgst` CLI, key via option" => sub {
|
||||
"HMAC: Check second HMAC value is consistent with the first ($hmacdata[1]) vs ($expected)");
|
||||
};
|
||||
|
||||
subtest "HMAC generation with `dgst` CLI, key via option keyenv" => sub {
|
||||
plan tests => 2;
|
||||
|
||||
my $testdata = srctop_file('test', 'data.bin');
|
||||
#HMAC the data twice to check consistency
|
||||
local $ENV{MYKEY} = '123456';
|
||||
my @hmacdata = run(app(['openssl', 'dgst', '-sha256', '-mac', 'HMAC',
|
||||
'-macopt', 'keyenv:MYKEY',
|
||||
$testdata, $testdata]), capture => 1);
|
||||
chomp(@hmacdata);
|
||||
my $expected = qr/HMAC-SHA2-256\(\Q$testdata\E\)= 6f12484129c4a761747f13d8234a1ff0e074adb34e9e9bf3a155c391b97b9a7c/;
|
||||
ok($hmacdata[0] =~ $expected, "HMAC: Check HMAC value is as expected ($hmacdata[0]) vs ($expected)");
|
||||
ok($hmacdata[1] =~ $expected,
|
||||
"HMAC: Check second HMAC value is consistent with the first ($hmacdata[1]) vs ($expected)");
|
||||
};
|
||||
|
||||
subtest "HMAC generation with `dgst` CLI, key via option keyenvhex" => sub {
|
||||
plan tests => 2;
|
||||
|
||||
my $testdata = srctop_file('test', 'data.bin');
|
||||
#HMAC the data twice to check consistency
|
||||
local $ENV{MYKEY} = 'FFFF';
|
||||
my @hmacdata = run(app(['openssl', 'dgst', '-sha256', '-mac', 'HMAC',
|
||||
'-macopt', 'keyenvhex:MYKEY',
|
||||
$testdata, $testdata]), capture => 1);
|
||||
chomp(@hmacdata);
|
||||
my $expected = qr/HMAC-SHA2-256\(\Q$testdata\E\)= 7c02d4a17d2560a5bb6763edbf33f3a34f415398f8f2e07f04b83ffd7c087dae/;
|
||||
ok($hmacdata[0] =~ $expected, "HMAC: Check HMAC value is as expected ($hmacdata[0]) vs ($expected)");
|
||||
ok($hmacdata[1] =~ $expected,
|
||||
"HMAC: Check second HMAC value is consistent with the first ($hmacdata[1]) vs ($expected)");
|
||||
};
|
||||
|
||||
subtest "HMAC generation with `dgst` CLI, key via option keyfile" => sub {
|
||||
plan tests => 2;
|
||||
|
||||
my $testdata = srctop_file('test', 'data.bin');
|
||||
#HMAC the data twice to check consistency
|
||||
my @hmacdata = run(app(['openssl', 'dgst', '-sha256', '-mac', 'HMAC',
|
||||
'-macopt', 'keyfile:' . data_file("keyfile.bin"),
|
||||
$testdata, $testdata]), capture => 1);
|
||||
chomp(@hmacdata);
|
||||
my $expected = qr/HMAC-SHA2-256\(\Q$testdata\E\)= 7c02d4a17d2560a5bb6763edbf33f3a34f415398f8f2e07f04b83ffd7c087dae/;
|
||||
ok($hmacdata[0] =~ $expected, "HMAC: Check HMAC value is as expected ($hmacdata[0]) vs ($expected)");
|
||||
ok($hmacdata[1] =~ $expected,
|
||||
"HMAC: Check second HMAC value is consistent with the first ($hmacdata[1]) vs ($expected)");
|
||||
};
|
||||
|
||||
subtest "HMAC generation with `dgst` CLI, key via option keystdin" => sub {
|
||||
plan tests => 2;
|
||||
|
||||
my $testdata = srctop_file('test', 'data.bin');
|
||||
#HMAC the data twice to check consistency
|
||||
my @hmacdata = run(app(['openssl', 'dgst', '-sha256', '-mac', 'HMAC',
|
||||
'-macopt', 'keystdin',
|
||||
$testdata, $testdata], stdin => data_file("keyfile.txt")), capture => 1);
|
||||
chomp(@hmacdata);
|
||||
my $expected = qr/HMAC-SHA2-256\(\Q$testdata\E\)= 6f12484129c4a761747f13d8234a1ff0e074adb34e9e9bf3a155c391b97b9a7c/;
|
||||
ok($hmacdata[0] =~ $expected, "HMAC: Check HMAC value is as expected ($hmacdata[0]) vs ($expected)");
|
||||
ok($hmacdata[1] =~ $expected,
|
||||
"HMAC: Check second HMAC value is consistent with the first ($hmacdata[1]) vs ($expected)");
|
||||
};
|
||||
|
||||
subtest "Custom length XOF digest generation with `dgst` CLI" => sub {
|
||||
plan tests => 2;
|
||||
|
||||
|
||||
BIN
test/recipes/20-test_dgst_data/keyfile.bin
Normal file
BIN
test/recipes/20-test_dgst_data/keyfile.bin
Normal file
Binary file not shown.
1
test/recipes/20-test_dgst_data/keyfile.txt
Normal file
1
test/recipes/20-test_dgst_data/keyfile.txt
Normal file
@@ -0,0 +1 @@
|
||||
123456
|
||||
@@ -10,7 +10,7 @@
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use OpenSSL::Test;
|
||||
use OpenSSL::Test qw(:DEFAULT data_file);
|
||||
use OpenSSL::Test::Utils;
|
||||
use Storable qw(dclone);
|
||||
|
||||
@@ -52,6 +52,29 @@ my @mac_tests = (
|
||||
input => '000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7',
|
||||
expected => 'D5BE731C954ED7732846BB59DBE3A8E30F83E77A4BFF4459F2F1C2B4ECEBB8CE67BA01C62E8AB8578D2D499BD1BB276768781190020A306A97DE281DCC30305D',
|
||||
desc => 'KMAC256 with xof len of 64' },
|
||||
{ cmd => [qw{openssl mac -digest SHA256 -macopt keyenv:MACKEY}],
|
||||
env => {'MACKEY' => 'ASCII_key_for_HMAC_tests' },
|
||||
type => 'HMAC',
|
||||
input => unpack("H*", "Sample message for additional key options"),
|
||||
expected => '70B1E97C0EDDBD4CB4866E28FEBA45343BD35FD88437F17880B7ADAC058B161B',
|
||||
desc => 'HMAC with keyenv' },
|
||||
{ cmd => [qw{openssl mac -digest SHA256 -macopt keyenvhex:MACKEY}],
|
||||
env => {'MACKEY' => '41534349495F6B65795F666F725F484D41435F7465737473' },
|
||||
type => 'HMAC',
|
||||
input => unpack("H*", "Sample message for additional key options"),
|
||||
expected => '70B1E97C0EDDBD4CB4866E28FEBA45343BD35FD88437F17880B7ADAC058B161B',
|
||||
desc => 'HMAC with keyenvhex' },
|
||||
{ cmd => [qw{openssl mac -digest SHA256}, '-macopt', 'keyfile:' . data_file("keyfile.dat")],
|
||||
type => 'HMAC',
|
||||
input => unpack("H*", "Sample message for additional key options"),
|
||||
expected => '70B1E97C0EDDBD4CB4866E28FEBA45343BD35FD88437F17880B7ADAC058B161B',
|
||||
desc => 'HMAC with keyfile' },
|
||||
{ cmd => [qw{openssl mac -digest SHA256 -macopt keystdin}],
|
||||
keyinput => data_file("keyfile.dat"),
|
||||
type => 'HMAC',
|
||||
input => unpack("H*", "Sample message for additional key options"),
|
||||
expected => '70B1E97C0EDDBD4CB4866E28FEBA45343BD35FD88437F17880B7ADAC058B161B',
|
||||
desc => 'HMAC with keystdin' },
|
||||
);
|
||||
|
||||
my @siphash_tests = (
|
||||
@@ -121,11 +144,29 @@ my $test_count = 0;
|
||||
|
||||
foreach (@mac_tests) {
|
||||
$test_count++;
|
||||
ok(compareline($_->{cmd}, $_->{type}, $_->{input}, $_->{expected}, $_->{err}), $_->{desc});
|
||||
if ($_->{env}) {
|
||||
ok( do {
|
||||
local @ENV{keys %{$_->{env}}} = values %{$_->{env}};
|
||||
compareline($_->{cmd}, $_->{type}, $_->{input}, $_->{expected}, $_->{err})
|
||||
}, $_->{desc});
|
||||
} elsif ($_->{keyinput}) {
|
||||
ok(compareline($_->{cmd}, $_->{type}, $_->{input}, $_->{expected}, $_->{err}, $_->{keyinput}), $_->{desc});
|
||||
} else {
|
||||
ok(compareline($_->{cmd}, $_->{type}, $_->{input}, $_->{expected}, $_->{err}), $_->{desc});
|
||||
}
|
||||
}
|
||||
foreach (@mac_tests) {
|
||||
$test_count++;
|
||||
ok(comparefile($_->{cmd}, $_->{type}, $_->{input}, $_->{expected}), $_->{desc});
|
||||
if ($_->{env}) {
|
||||
ok( do {
|
||||
local @ENV{keys %{$_->{env}}} = values %{$_->{env}};
|
||||
comparefile($_->{cmd}, $_->{type}, $_->{input}, $_->{expected})
|
||||
}, $_->{desc});
|
||||
} elsif ($_->{keyinput}) {
|
||||
ok(comparefile($_->{cmd}, $_->{type}, $_->{input}, $_->{expected}, $_->{keyinput}), $_->{desc});
|
||||
} else {
|
||||
ok(comparefile($_->{cmd}, $_->{type}, $_->{input}, $_->{expected}), $_->{desc});
|
||||
}
|
||||
}
|
||||
|
||||
foreach (@mac_fail_tests) {
|
||||
@@ -137,7 +178,7 @@ foreach (@mac_fail_tests) {
|
||||
# then compare the stdout output matches the expected value.
|
||||
sub compareline {
|
||||
my $tmpfile = "input-$test_count.bin";
|
||||
my ($cmdarray_orig, $type, $input, $expect, $err) = @_;
|
||||
my ($cmdarray_orig, $type, $input, $expect, $err, $keyinput) = @_;
|
||||
my $cmdarray = dclone $cmdarray_orig;
|
||||
if (defined($expect)) {
|
||||
$expect = uc $expect;
|
||||
@@ -153,7 +194,7 @@ sub compareline {
|
||||
my @other = ('-in', $tmpfile, $type);
|
||||
push @$cmdarray, @other;
|
||||
|
||||
my @lines = run(app($cmdarray), capture => 1);
|
||||
my @lines = run(app($cmdarray, stdin => $keyinput), capture => 1);
|
||||
# Not unlinking $tmpfile
|
||||
|
||||
if (defined($expect)) {
|
||||
@@ -189,7 +230,7 @@ sub compareline {
|
||||
sub comparefile {
|
||||
my $tmpfile = "input-$test_count.bin";
|
||||
my $outfile = "output-$test_count.bin";
|
||||
my ($cmdarray, $type, $input, $expect) = @_;
|
||||
my ($cmdarray, $type, $input, $expect, $keyinput) = @_;
|
||||
$expect = uc $expect;
|
||||
|
||||
# Open a temporary input file and write $input to it
|
||||
@@ -202,7 +243,7 @@ sub comparefile {
|
||||
my @other = ("-binary", "-in", $tmpfile, "-out", $outfile, $type);
|
||||
push @$cmdarray, @other;
|
||||
|
||||
run(app($cmdarray));
|
||||
run(app($cmdarray, stdin => $keyinput));
|
||||
# Not unlinking $tmpfile
|
||||
|
||||
open(my $out, '<', $outfile) or die "Could not open file";
|
||||
|
||||
1
test/recipes/20-test_mac_data/keyfile.dat
Normal file
1
test/recipes/20-test_mac_data/keyfile.dat
Normal file
@@ -0,0 +1 @@
|
||||
ASCII_key_for_HMAC_tests
|
||||
Reference in New Issue
Block a user