Skip to content

Commit

Permalink
Augment rand argument parsing to allow scaling
Browse files Browse the repository at this point in the history
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
  • Loading branch information
nhorman committed Nov 6, 2023
1 parent 1aa0864 commit 567e9c5
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 6 deletions.
52 changes: 48 additions & 4 deletions apps/rand.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
size_t scaled_num = 0;
uint8_t *buf = NULL;

prog = opt_init(argc, argv, rand_options);
Expand Down Expand Up @@ -95,8 +97,50 @@ int rand_main(int argc, char **argv)
argc = opt_num_rest();
argv = opt_rest();
if (argc == 1) {
int factoridx = 0;
int scale = 0;
/*
* iterate over the value and check to see if there are
* any non-numerical chars
* A non digit suffix indicates we need to scale the
* number of requested bytes by a factor of:
* k = 1024^1 (10 * 1)
* m = 1024^2 (10 * 2)
* g = 1024^3 (10 * 3)
*/
while (argv[0][factoridx]) {
if (!isdigit(argv[0][factoridx])) {
switch(argv[0][factoridx]) {
case 'k':
scale = 1;
break;
case 'm':
scale = 2;
break;
case 'g':
scale = 3;
break;
default:
goto opthelp;
}
break;
}
factoridx++;
}
if (scale != 0)
argv[0][factoridx] = '\0';

if (!opt_long(argv[0], &num) || num <= 0)
goto opthelp;

if (scale != 0) {
/* check for overflow */
if ((SIZE_MAX - (1 << (scale * 10)) > (size_t)num))
goto opthelp;
scaled_num = num * (1 << (scale * 10));
} else {
scaled_num = num;
}
} else if (!opt_check_rest_arg(NULL)) {
goto opthelp;
}
Expand All @@ -116,10 +160,10 @@ int rand_main(int argc, char **argv)
}

buf = app_malloc(buflen, "buffer for output file");
while (num > 0) {
while (scaled_num > 0) {
long chunk;

chunk = (num > buflen) ? buflen : num;
chunk = (scaled_num > buflen) ? buflen : scaled_num;
r = RAND_bytes(buf, chunk);
if (r <= 0)
goto end;
Expand All @@ -131,7 +175,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");
Expand Down
6 changes: 4 additions & 2 deletions doc/man1/openssl-rand.pod.in
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ 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]

=head1 DESCRIPTION

This command generates I<num> random bytes using a cryptographically
secure pseudo random number generator (CSPRNG).
secure pseudo random number generator (CSPRNG). the suffix k, m or g may be
added to the num value to indicate the request value be scaled as a multiple of
kilobytes, megabytes, or gigabytes respectively.

The random bytes are generated using the L<RAND_bytes(3)> function,
which provides a security level of 256 bits, provided it managed to
Expand Down

0 comments on commit 567e9c5

Please sign in to comment.