mirror of
https://github.com/openssl/openssl.git
synced 2024-11-21 01:15:20 +08:00
Augment rand argument parsing to allow scaling
Instead of just accepting a number of bytes, allows openssl rand to accept a k|m|g suffix to scale to kbytes/mbytes/gbytes Fixes #22622 Reviewed-by: Paul Dale <pauli@openssl.org> Reviewed-by: Tom Cosgrove <tom.cosgrove@arm.com> Reviewed-by: Matthias St. Pierre <Matthias.St.Pierre@ncp-e.com> Reviewed-by: Tomas Mraz <tomas@openssl.org> (Merged from https://github.com/openssl/openssl/pull/22624)
This commit is contained in:
parent
66c27d06e0
commit
ae9fe65d9f
93
apps/rand.c
93
apps/rand.c
@ -25,7 +25,7 @@ typedef enum OPTION_choice {
|
||||
} OPTION_CHOICE;
|
||||
|
||||
const OPTIONS rand_options[] = {
|
||||
{OPT_HELP_STR, 1, '-', "Usage: %s [options] num\n"},
|
||||
{OPT_HELP_STR, 1, '-', "Usage: %s [options] num[K|M|G|T]\n"},
|
||||
|
||||
OPT_SECTION("General"),
|
||||
{"help", OPT_HELP, '-', "Display this summary"},
|
||||
@ -52,8 +52,10 @@ int rand_main(int argc, char **argv)
|
||||
BIO *out = NULL;
|
||||
char *outfile = NULL, *prog;
|
||||
OPTION_CHOICE o;
|
||||
int format = FORMAT_BINARY, r, i, ret = 1, buflen = 131072;
|
||||
int format = FORMAT_BINARY, r, i, ret = 1;
|
||||
size_t buflen = (1 << 16); /* max rand chunk size is 2^16 bytes */
|
||||
long num = -1;
|
||||
uint64_t scaled_num = 0;
|
||||
uint8_t *buf = NULL;
|
||||
|
||||
prog = opt_init(argc, argv, rand_options);
|
||||
@ -95,8 +97,85 @@ int rand_main(int argc, char **argv)
|
||||
argc = opt_num_rest();
|
||||
argv = opt_rest();
|
||||
if (argc == 1) {
|
||||
if (!opt_long(argv[0], &num) || num <= 0)
|
||||
int factoridx = 0;
|
||||
int shift = 0;
|
||||
|
||||
/*
|
||||
* special case for requesting the max allowed
|
||||
* number of random bytes to be generated
|
||||
*/
|
||||
if (!strcmp(argv[0], "max")) {
|
||||
/*
|
||||
* 2^61 bytes is the limit of random output
|
||||
* per drbg instantiation
|
||||
*/
|
||||
scaled_num = UINT64_MAX >> 3;
|
||||
} else {
|
||||
/*
|
||||
* iterate over the value and check to see if there are
|
||||
* any non-numerical chars
|
||||
* A non digit suffix indicates we need to shift the
|
||||
* number of requested bytes by a factor of:
|
||||
* K = 1024^1 (1 << (10 * 1))
|
||||
* M = 1024^2 (1 << (10 * 2))
|
||||
* G = 1024^3 (1 << (10 * 3))
|
||||
* T = 1024^4 (1 << (10 * 4))
|
||||
* which can be achieved by bit-shifting the number
|
||||
*/
|
||||
while (argv[0][factoridx]) {
|
||||
if (!isdigit((int)(argv[0][factoridx]))) {
|
||||
switch(argv[0][factoridx]) {
|
||||
case 'K':
|
||||
shift = 10;
|
||||
break;
|
||||
case 'M':
|
||||
shift = 20;
|
||||
break;
|
||||
case 'G':
|
||||
shift = 30;
|
||||
break;
|
||||
case 'T':
|
||||
shift = 40;
|
||||
break;
|
||||
default:
|
||||
BIO_printf(bio_err, "Invalid size suffix %s\n",
|
||||
&argv[0][factoridx]);
|
||||
goto opthelp;
|
||||
}
|
||||
break;
|
||||
}
|
||||
factoridx++;
|
||||
}
|
||||
|
||||
if (shift != 0 && strlen(&argv[0][factoridx]) != 1) {
|
||||
BIO_printf(bio_err, "Invalid size suffix %s\n",
|
||||
&argv[0][factoridx]);
|
||||
goto opthelp;
|
||||
}
|
||||
}
|
||||
/* Remove the suffix from the arg so that opt_long works */
|
||||
if (shift != 0)
|
||||
argv[0][factoridx] = '\0';
|
||||
|
||||
if ((scaled_num == 0) && (!opt_long(argv[0], &num) || num <= 0))
|
||||
goto opthelp;
|
||||
|
||||
if (shift != 0) {
|
||||
/* check for overflow */
|
||||
if ((UINT64_MAX >> shift) < (size_t)num) {
|
||||
BIO_printf(bio_err, "%lu bytes with suffix overflows\n",
|
||||
num);
|
||||
goto opthelp;
|
||||
}
|
||||
scaled_num = num << shift;
|
||||
if (scaled_num > (UINT64_MAX >> 3)) {
|
||||
BIO_printf(bio_err, "Request exceeds max allowed output\n");
|
||||
goto opthelp;
|
||||
}
|
||||
} else {
|
||||
if (scaled_num == 0)
|
||||
scaled_num = num;
|
||||
}
|
||||
} else if (!opt_check_rest_arg(NULL)) {
|
||||
goto opthelp;
|
||||
}
|
||||
@ -116,10 +195,10 @@ int rand_main(int argc, char **argv)
|
||||
}
|
||||
|
||||
buf = app_malloc(buflen, "buffer for output file");
|
||||
while (num > 0) {
|
||||
long chunk;
|
||||
while (scaled_num > 0) {
|
||||
int chunk;
|
||||
|
||||
chunk = (num > buflen) ? buflen : num;
|
||||
chunk = scaled_num > buflen ? (int)buflen : (int)scaled_num;
|
||||
r = RAND_bytes(buf, chunk);
|
||||
if (r <= 0)
|
||||
goto end;
|
||||
@ -131,7 +210,7 @@ int rand_main(int argc, char **argv)
|
||||
if (BIO_printf(out, "%02x", buf[i]) != 2)
|
||||
goto end;
|
||||
}
|
||||
num -= chunk;
|
||||
scaled_num -= chunk;
|
||||
}
|
||||
if (format == FORMAT_TEXT)
|
||||
BIO_puts(out, "\n");
|
||||
|
@ -14,12 +14,20 @@ B<openssl rand>
|
||||
[B<-hex>]
|
||||
{- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_r_synopsis -}
|
||||
{- $OpenSSL::safe::opt_provider_synopsis -}
|
||||
I<num>
|
||||
I<num>[K|M|G|T]
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This command generates I<num> random bytes using a cryptographically
|
||||
secure pseudo random number generator (CSPRNG).
|
||||
secure pseudo random number generator (CSPRNG). A suffix [K|M|G|T] may be
|
||||
appended to the num value to indicate the requested value be scaled as a
|
||||
multiple of KiB/MiB/GiB/TiB respectively. Note that suffixes are case
|
||||
sensitive, and that the suffixes represent binary multiples
|
||||
(K = 1024 bytes, M = 1024*1024 bytes, etc).
|
||||
|
||||
The string 'max' may be substituted for a numercial value in num, to request the
|
||||
maximum number of bytes the CSPRNG can produce per instantiation. Currently,
|
||||
this is restricted to 2^61 bytes as per NIST SP 800-90C.
|
||||
|
||||
The random bytes are generated using the L<RAND_bytes(3)> function,
|
||||
which provides a security level of 256 bits, provided it managed to
|
||||
|
@ -32,6 +32,10 @@ SKIP: {
|
||||
ok($success && $randdata[0] eq $expected,
|
||||
"rand with ossltest: Check rand output is as expected");
|
||||
|
||||
@randdata = run(app(['openssl', 'rand', '-hex', '2K' ]),
|
||||
capture => 1, statusvar => \$success);
|
||||
chomp(@randdata);
|
||||
|
||||
@randdata = run(app(['openssl', 'rand', '-engine', 'dasync', '-hex', '16' ]),
|
||||
capture => 1, statusvar => \$success);
|
||||
chomp(@randdata);
|
||||
|
Loading…
Reference in New Issue
Block a user