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 <stdlib.h>
     20 
     21 #include <openssl/rand.h>
     22 
     23 #include "internal.h"
     24 
     25 
     26 static const struct argument kArguments[] = {
     27     {
     28      "-hex", kBooleanArgument,
     29      "Hex encoded output."
     30     },
     31     {
     32      "", kOptionalArgument, "",
     33     },
     34 };
     35 
     36 bool Rand(const std::vector<std::string> &args) {
     37   bool forever = true, hex = false;
     38   size_t len = 0;
     39 
     40   if (!args.empty()) {
     41     std::vector<std::string> args_copy(args);
     42     const std::string &last_arg = args.back();
     43 
     44     if (last_arg.size() > 0 && last_arg[0] != '-') {
     45       char *endptr;
     46       unsigned long long num = strtoull(last_arg.c_str(), &endptr, 10);
     47       if (*endptr == 0) {
     48         len = num;
     49         forever = false;
     50         args_copy.pop_back();
     51       }
     52     }
     53 
     54     std::map<std::string, std::string> args_map;
     55     if (!ParseKeyValueArguments(&args_map, args_copy, kArguments)) {
     56       PrintUsage(kArguments);
     57       return false;
     58     }
     59 
     60     hex = args_map.count("-hex") > 0;
     61   }
     62 
     63   uint8_t buf[4096];
     64   uint8_t hex_buf[8192];
     65 
     66   size_t done = 0;
     67   while (forever || done < len) {
     68     size_t todo = sizeof(buf);
     69     if (!forever && todo > len - done) {
     70       todo = len - done;
     71     }
     72     RAND_bytes(buf, todo);
     73     if (hex) {
     74       static const char hextable[] = "0123456789abdef";
     75       for (unsigned i = 0; i < todo; i++) {
     76         hex_buf[i*2] = hextable[buf[i] >> 4];
     77         hex_buf[i*2 + 1] = hextable[buf[i] & 0xf];
     78       }
     79       if (fwrite(hex_buf, todo*2, 1, stdout) != 1) {
     80         return false;
     81       }
     82     } else {
     83       if (fwrite(buf, todo, 1, stdout) != 1) {
     84         return false;
     85       }
     86     }
     87     done += todo;
     88   }
     89 
     90   if (hex && fwrite("\n", 1, 1, stdout) != 1) {
     91     return false;
     92   }
     93 
     94   return true;
     95 }
     96