Implement AddRngEntropy.

Change-Id: I8308b23d900b0f6132dd480516e123c82ee8bcb3
diff --git a/Android.mk b/Android.mk
index 407db46..d329136 100644
--- a/Android.mk
+++ b/Android.mk
@@ -93,7 +93,7 @@
 LOCAL_CFLAGS = -Wall -Werror
 # Ignore benigh warnings for now.
 LOCAL_CLANG_CFLAGS += -Wno-error=unused-const-variable
-LOCAL_SHARED_LIBRARIES := libkeymaster liblog
+LOCAL_SHARED_LIBRARIES := libkeymaster liblog libcrypto
 LOCAL_MODULE_TAGS := optional
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
diff --git a/google_keymaster_messages.cpp b/google_keymaster_messages.cpp
index f73dabb..2bc6f73 100644
--- a/google_keymaster_messages.cpp
+++ b/google_keymaster_messages.cpp
@@ -261,6 +261,18 @@
     return output.Deserialize(buf_ptr, end);
 }
 
+size_t AddEntropyRequest::SerializedSize() const {
+    return random_data.SerializedSize();
+}
+
+uint8_t* AddEntropyRequest::Serialize(uint8_t* buf, const uint8_t* end) const {
+    return random_data.Serialize(buf, end);
+}
+
+bool AddEntropyRequest::Deserialize(const uint8_t** buf_ptr, const uint8_t* end) {
+    return random_data.Deserialize(buf_ptr, end);
+}
+
 void ImportKeyRequest::SetKeyMaterial(const void* key_material, size_t length) {
     delete[] key_data;
     key_data = dup_buffer(key_material, length);
diff --git a/google_keymaster_messages_test.cpp b/google_keymaster_messages_test.cpp
index 60c5f08..aa0f571 100644
--- a/google_keymaster_messages_test.cpp
+++ b/google_keymaster_messages_test.cpp
@@ -441,6 +441,17 @@
     EXPECT_EQ(38, msg.subminor_ver);
 }
 
+TEST(RoundTrip, AddEntropyRequest) {
+    for (int ver = 0; ver <= MAX_MESSAGE_VERSION; ++ver) {
+        AddEntropyRequest msg(ver);
+        msg.random_data.Reinitialize("foo", 3);
+
+        UniquePtr<AddEntropyRequest> deserialized(round_trip(ver, msg, 7));
+        EXPECT_EQ(3U, deserialized->random_data.available_read());
+        EXPECT_EQ(0, memcmp("foo", deserialized->random_data.peek_read(), 3));
+    }
+}
+
 uint8_t msgbuf[] = {
     220, 88,  183, 255, 71,  1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
     0,   173, 0,   0,   0,   228, 174, 98,  187, 191, 135, 253, 200, 51,  230, 114, 247, 151, 109,
@@ -500,7 +511,7 @@
 GARBAGE_TEST(UpdateOperationResponse);
 GARBAGE_TEST(FinishOperationRequest);
 GARBAGE_TEST(FinishOperationResponse);
-// GARBAGE_TEST(AddEntropyRequest);
+GARBAGE_TEST(AddEntropyRequest);
 GARBAGE_TEST(ImportKeyRequest);
 GARBAGE_TEST(ImportKeyResponse);
 GARBAGE_TEST(ExportKeyRequest);
diff --git a/google_keymaster_test.cpp b/google_keymaster_test.cpp
index 06479a7..73b1fae 100644
--- a/google_keymaster_test.cpp
+++ b/google_keymaster_test.cpp
@@ -2349,5 +2349,13 @@
     }
 }
 
+typedef KeymasterTest AddEntropyTest;
+TEST_F(AddEntropyTest, AddEntropy) {
+    // There's no obvious way to test that entropy is actually added, but we can test that the API
+    // doesn't blow up or return an error.
+    EXPECT_EQ(KM_ERROR_OK,
+              device()->add_rng_entropy(device(), reinterpret_cast<const uint8_t*>("foo"), 3));
+}
+
 }  // namespace test
 }  // namespace keymaster
diff --git a/google_softkeymaster.h b/google_softkeymaster.h
index e8b958e..107e617 100644
--- a/google_softkeymaster.h
+++ b/google_softkeymaster.h
@@ -19,6 +19,10 @@
 
 #include <keymaster/google_keymaster.h>
 
+#include <openssl/rand.h>
+
+#include "openssl_err.h"
+
 namespace keymaster {
 
 class GoogleSoftKeymaster : public GoogleKeymaster {
@@ -31,6 +35,11 @@
     bool is_enforced(keymaster_tag_t /* tag */) { return false; }
     keymaster_key_origin_t origin() { return KM_ORIGIN_SOFTWARE; }
 
+    keymaster_error_t AddRngEntropy(const AddEntropyRequest& request) {
+        RAND_seed(request.random_data.peek_read(), request.random_data.available_read());
+        return KM_ERROR_OK;
+    }
+
   private:
     static uint8_t master_key_[];
 
diff --git a/include/keymaster/google_keymaster.h b/include/keymaster/google_keymaster.h
index 166eb09..c78dbee 100644
--- a/include/keymaster/google_keymaster.h
+++ b/include/keymaster/google_keymaster.h
@@ -58,10 +58,7 @@
     void SupportedExportFormats(keymaster_algorithm_t algorithm,
                                 SupportedResponse<keymaster_key_format_t>* response) const;
 
-    virtual keymaster_error_t AddRngEntropy(AddEntropyRequest& /* request */) {
-        // Not going to implement until post-L.
-        return KM_ERROR_UNIMPLEMENTED;
-    }
+    virtual keymaster_error_t AddRngEntropy(const AddEntropyRequest& request) = 0;
     void GenerateKey(const GenerateKeyRequest& request, GenerateKeyResponse* response);
     void GetKeyCharacteristics(const GetKeyCharacteristicsRequest& request,
                                GetKeyCharacteristicsResponse* response);
diff --git a/soft_keymaster_device.cpp b/soft_keymaster_device.cpp
index 9bc4861..77d0e9a 100644
--- a/soft_keymaster_device.cpp
+++ b/soft_keymaster_device.cpp
@@ -512,10 +512,11 @@
 }
 
 /* static */
-keymaster_error_t SoftKeymasterDevice::add_rng_entropy(const keymaster1_device_t* /* dev */,
-                                                       const uint8_t* /* data */,
-                                                       size_t /* data_length */) {
-    return KM_ERROR_UNIMPLEMENTED;
+keymaster_error_t SoftKeymasterDevice::add_rng_entropy(const keymaster1_device_t* dev,
+                                                       const uint8_t* data, size_t data_length) {
+    AddEntropyRequest request;
+    request.random_data.Reinitialize(data, data_length);
+    return convert_device(dev)->impl_->AddRngEntropy(request);
 }
 
 /* static */