verity: support salt=random generation

Many CrOS build scripts generate a salt randomly (using things like xxd
on /dev/urandom).  Add support for that directly to verity so we don't
have to copy these ad-hoc implementations around.

BUG=chromium:660209
TEST=`verity mode=create alg=sha1 payload=img hashtree=hash salt=random` outputs a random salt each time

Change-Id: Iee631a1eb72945a011d4c64c930b1331330f32cd
Reviewed-on: https://chromium-review.googlesource.com/404728
Commit-Ready: Mike Frysinger <vapier@chromium.org>
Tested-by: Mike Frysinger <vapier@chromium.org>
Reviewed-by: Dylan Reid <dgreid@chromium.org>
diff --git a/file_hasher.cc b/file_hasher.cc
index a6282a6..d98186e 100644
--- a/file_hasher.cc
+++ b/file_hasher.cc
@@ -94,6 +94,23 @@
   return !dm_bht_compute(&tree_);
 }
 
+const char *FileHasher::RandomSalt() {
+  uint8_t buf[DM_BHT_SALT_SIZE];
+  const char urandom_path[] = "/dev/urandom";
+  simple_file::File source;
+
+  LOG_IF(FATAL, !source.Initialize(urandom_path, O_RDONLY, NULL))
+    << "Failed to open the random source: " << urandom_path;
+  PLOG_IF(FATAL, !source.Read(sizeof(buf), buf))
+    << "Failed to read the random source";
+
+  for (size_t i = 0; i < sizeof(buf); ++i)
+    sprintf(&random_salt_[i * 2], "%02x", buf[i]);
+  random_salt_[sizeof(random_salt_) - 1] = '\0';
+
+  return random_salt_;
+}
+
 void FileHasher::PrintTable(bool colocated) {
   // Grab the digest (up to 1kbit supported)
   uint8_t digest[128];
diff --git a/file_hasher.h b/file_hasher.h
index 48e075e..add1836 100644
--- a/file_hasher.h
+++ b/file_hasher.h
@@ -35,7 +35,10 @@
   // Print a table to stdout which contains a dmsetup compatible format
   virtual void PrintTable(bool colocated);
 
+  virtual const char *RandomSalt();
   virtual void set_salt(const char *salt) {
+    if (!strcmp(salt, "random"))
+      salt = RandomSalt();
     dm_bht_set_salt(&tree_, salt);
     salt_ = salt;
   }
@@ -53,6 +56,7 @@
   unsigned int block_limit_;
   const char *alg_;
   const char *salt_;
+  char random_salt_[DM_BHT_SALT_SIZE * 2 + 1];
   u8 *hash_data_;
   struct dm_bht tree_;
   sector_t sectors_;