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:
Igor Ustinov
2025-08-02 19:53:13 +03:00
committed by Tomas Mraz
parent cb7da43fe8
commit bd91eb6658
11 changed files with 462 additions and 17 deletions

View File

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

View File

@@ -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,

View File

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

View File

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

View File

@@ -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.

View File

@@ -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>

View File

@@ -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;

Binary file not shown.

View File

@@ -0,0 +1 @@
123456

View File

@@ -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";

View File

@@ -0,0 +1 @@
ASCII_key_for_HMAC_tests