Add method to get random bytes from the TPM.

Change-Id: I66d8a746be5add2d277e2a0783c562206084fcb4

BUG=227
TEST=manual

Review URL: http://codereview.chromium.org/3116014
diff --git a/tpm.cc b/tpm.cc
index 4de12a2..66cb57f 100644
--- a/tpm.cc
+++ b/tpm.cc
@@ -585,4 +585,34 @@
  return took_ownership;
 }
 
+bool Tpm::GetRandomData(size_t length, chromeos::Blob* data) {
+  TSS_HCONTEXT context_handle;
+  if (!OpenAndConnectTpm(&context_handle)) {
+    LOG(ERROR) << "Could not open the TPM";
+    return false;
+  }
+
+  TSS_HTPM tpm_handle;
+  if (!GetTpm(context_handle, &tpm_handle)) {
+    LOG(ERROR) << "Could not get a handle to the TPM.";
+    Tspi_Context_Close(context_handle);
+    return false;
+  }
+
+  TSS_RESULT result;
+  SecureBlob random(length);
+  BYTE* tpm_data = NULL;
+  if ((result = Tspi_TPM_GetRandom(tpm_handle, random.size(), &tpm_data))) {
+    LOG(ERROR) << "Could not get random data from the TPM: " << result;
+    Tspi_Context_Close(context_handle);
+    return false;
+  }
+  memcpy(random.data(), tpm_data, random.size());
+  Tspi_Context_FreeMemory(context_handle, tpm_data);
+  chromeos::SecureMemset(tpm_data, 0, random.size());
+  Tspi_Context_Close(context_handle);
+  data->swap(random);
+  return true;
+}
+
 } // namespace tpm_init
diff --git a/tpm.h b/tpm.h
index 559c053..97c4d7d 100644
--- a/tpm.h
+++ b/tpm.h
@@ -68,6 +68,13 @@
   // call to Tspi_TPM_TakeOwnership.
   bool InitializeTpm();
 
+  // Gets random bytes from the TPM
+  //
+  // Parameters
+  //   length - The number of bytes to get
+  //   data (OUT) - The random data from the TPM
+  bool GetRandomData(size_t length, chromeos::Blob* data);
+
  private:
   // Attempts to connect to tcsd
   //
diff --git a/tpm_init.cc b/tpm_init.cc
index 92f1c7e..e792141 100644
--- a/tpm_init.cc
+++ b/tpm_init.cc
@@ -28,6 +28,7 @@
   bool IsTpmEnabled();
   bool GetTpmPassword(chromeos::Blob* password);
   long GetInitializationMillis();
+  bool GetRandomData(int length, chromeos::Blob* data);
 
  private:
   scoped_ptr<tpm_init::Tpm> default_tpm_;
@@ -44,6 +45,10 @@
 TpmInit::~TpmInit() {
 }
 
+bool TpmInit::GetRandomData(int length, chromeos::Blob* data) {
+  return tpm_init_->GetRandomData(length, data);
+}
+
 bool TpmInit::StartInitializeTpm() {
   tpm_init_->Init();
   if (!PlatformThread::CreateNonJoinable(0, tpm_init_.get())) {
@@ -125,4 +130,8 @@
   return initialization_time_;
 }
 
+bool TpmInitTask::GetRandomData(int length, chromeos::Blob* data) {
+  return tpm_->GetRandomData(length, data);
+}
+
 }  // namespace tpm_init
diff --git a/tpm_init.h b/tpm_init.h
index 0dc1086..e2e6bd1 100644
--- a/tpm_init.h
+++ b/tpm_init.h
@@ -23,6 +23,13 @@
 
   virtual ~TpmInit();
 
+  // Gets random data from the TPM
+  //
+  // Parameters
+  //   length - The number of bytes to get
+  //   data (OUT) - Receives the random bytes
+  virtual bool GetRandomData(int length, chromeos::Blob* data);
+
   // Starts asynchronous initialization of the TPM
   virtual bool StartInitializeTpm();