} 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"},
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);
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;
}
}
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;
if (BIO_printf(out, "%02x", buf[i]) != 2)
goto end;
}
- num -= chunk;
+ scaled_num -= chunk;
}
if (format == FORMAT_TEXT)
BIO_puts(out, "\n");
[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