Home | History | Annotate | Download | only in tool
      1 /* Copyright (c) 2015, Google Inc.
      2  *
      3  * Permission to use, copy, modify, and/or distribute this software for any
      4  * purpose with or without fee is hereby granted, provided that the above
      5  * copyright notice and this permission notice appear in all copies.
      6  *
      7  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      8  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      9  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
     10  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     11  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
     12  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
     13  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
     14 
     15 #include <string>
     16 #include <vector>
     17 
     18 #include <stdint.h>
     19 #include <stdio.h>
     20 #include <stdlib.h>
     21 
     22 #include <openssl/rand.h>
     23 
     24 #include "internal.h"
     25 
     26 
     27 static const struct argument kArguments[] = {
     28     {
     29      "-hex", kBooleanArgument,
     30      "Hex encoded output."
     31     },
     32     {
     33      "", kOptionalArgument, "",
     34     },
     35 };
     36 
     37 bool Rand(const std::vector<std::string> &args) {
     38   bool forever = true, hex = false;
     39   size_t len = 0;
     40 
     41   if (!args.empty()) {
     42     std::vector<std::string> args_copy(args);
     43     const std::string &last_arg = args.back();
     44 
     45     if (!last_arg.empty() && last_arg[0] != '-') {
     46       char *endptr;
     47       unsigned long long num = strtoull(last_arg.c_str(), &endptr, 10);
     48       if (*endptr == 0) {
     49         len = num;
     50         forever = false;
     51         args_copy.pop_back();
     52       }
     53     }
     54 
     55     std::map<std::string, std::string> args_map;
     56     if (!ParseKeyValueArguments(&args_map, args_copy, kArguments)) {
     57       PrintUsage(kArguments);
     58       return false;
     59     }
     60 
     61     hex = args_map.count("-hex") > 0;
     62   }
     63 
     64   uint8_t buf[4096];
     65   uint8_t hex_buf[8192];
     66 
     67   size_t done = 0;
     68   while (forever || done < len) {
     69     size_t todo = sizeof(buf);
     70     if (!forever && todo > len - done) {
     71       todo = len - done;
     72     }
     73     RAND_bytes(buf, todo);
     74     if (hex) {
     75       static const char hextable[16 + 1] = "0123456789abcdef";
     76       for (unsigned i = 0; i < todo; i++) {
     77         hex_buf[i*2] = hextable[buf[i] >> 4];
     78         hex_buf[i*2 + 1] = hextable[buf[i] & 0xf];
     79       }
     80       if (fwrite(hex_buf, todo*2, 1, stdout) != 1) {
     81         return false;
     82       }
     83     } else {
     84       if (fwrite(buf, todo, 1, stdout) != 1) {
     85         return false;
     86       }
     87     }
     88     done += todo;
     89   }
     90 
     91   if (hex && fwrite("\n", 1, 1, stdout) != 1) {
     92     return false;
     93   }
     94 
     95   return true;
     96 }
     97