summaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
authorNeil Horman <nhorman@openssl.org>2023-11-05 17:51:38 -0500
committerTomas Mraz <tomas@openssl.org>2023-11-13 12:21:34 +0100
commitae9fe65d9f85e027bd7428e0f84aa46ab368880e (patch)
tree8e181641789fe90b86aa786c250c0793ad7f5104 /apps
parent66c27d06e0e9a1bb716c67390ad9e5ac613d45d3 (diff)
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)
Diffstat (limited to 'apps')
-rw-r--r--apps/rand.c93
1 files changed, 86 insertions, 7 deletions
diff --git a/apps/rand.c b/apps/rand.c
index c0ab51dd83..b123a151ea 100644
--- a/apps/rand.c
+++ b/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");