Add optional additional entropy to finish

If provided the extra entropy will be added to the device before calling
finish. If entropy is provided and the device does not support supplying
additional entropy then finish will fail with KM_ERROR_UNIMPLEMENTED.

Change-Id: If26be118bf382604f6f8e96e833b76e6f9e94d58
diff --git a/keystore/IKeystoreService.cpp b/keystore/IKeystoreService.cpp
index bd74002..0fb3fcb 100644
--- a/keystore/IKeystoreService.cpp
+++ b/keystore/IKeystoreService.cpp
@@ -1130,7 +1130,9 @@
     }
 
     virtual void finish(const sp<IBinder>& token, const KeymasterArguments& params,
-                        const uint8_t* signature, size_t signatureLength, OperationResult* result)
+                        const uint8_t* signature, size_t signatureLength,
+                        const uint8_t* entropy, size_t entropyLength,
+                        OperationResult* result)
     {
         if (!result) {
             return;
@@ -1141,6 +1143,7 @@
         data.writeInt32(1);
         params.writeToParcel(&data);
         data.writeByteArray(signatureLength, signature);
+        data.writeByteArray(entropyLength, entropy);
         status_t status = remote()->transact(BnKeystoreService::FINISH, data, &reply);
         if (status != NO_ERROR) {
             ALOGD("finish() could not contact remote: %d\n", status);
@@ -1683,11 +1686,14 @@
             if (data.readInt32() != 0) {
                 args.readFromParcel(data);
             }
-            const uint8_t* buf = NULL;
-            size_t bufLength = 0;
-            readByteArray(data, &buf, &bufLength);
+            const uint8_t* signature = NULL;
+            size_t signatureLength = 0;
+            readByteArray(data, &signature, &signatureLength);
+            const uint8_t* entropy = NULL;
+            size_t entropyLength = 0;
+            readByteArray(data, &entropy, &entropyLength);
             OperationResult result;
-            finish(token, args, buf, bufLength, &result);
+            finish(token, args, signature, signatureLength, entropy, entropyLength,  &result);
             reply->writeNoException();
             reply->writeInt32(1);
             result.writeToParcel(reply);
diff --git a/keystore/include/keystore/IKeystoreService.h b/keystore/include/keystore/IKeystoreService.h
index d208325..3750f2f 100644
--- a/keystore/include/keystore/IKeystoreService.h
+++ b/keystore/include/keystore/IKeystoreService.h
@@ -218,6 +218,7 @@
 
     virtual void finish(const sp<IBinder>& token, const KeymasterArguments& params,
                         const uint8_t* signature, size_t signatureLength,
+                        const uint8_t* entropy, size_t entropyLength,
                         OperationResult* result) = 0;
 
     virtual int32_t abort(const sp<IBinder>& handle) = 0;
diff --git a/keystore/keystore.cpp b/keystore/keystore.cpp
index 980b0e9..384f158 100644
--- a/keystore/keystore.cpp
+++ b/keystore/keystore.cpp
@@ -2667,7 +2667,8 @@
     }
 
     void finish(const sp<IBinder>& token, const KeymasterArguments& params,
-                const uint8_t* signature, size_t signatureLength, OperationResult* result) {
+                const uint8_t* signature, size_t signatureLength,
+                const uint8_t* entropy, size_t entropyLength, OperationResult* result) {
         if (!checkAllowedOperationParams(params.params)) {
             result->resultCode = KM_ERROR_INVALID_ARGUMENT;
             return;
@@ -2686,8 +2687,20 @@
             result->resultCode = authResult;
             return;
         }
+        keymaster_error_t err;
+        if (entropy) {
+            if (dev->add_rng_entropy) {
+                err = dev->add_rng_entropy(dev, entropy, entropyLength);
+            } else {
+                err = KM_ERROR_UNIMPLEMENTED;
+            }
+            if (err) {
+                result->resultCode = err;
+                return;
+            }
+        }
 
-        keymaster_error_t err = dev->finish(dev, handle, opParams.data(), opParams.size(),
+        err = dev->finish(dev, handle, opParams.data(), opParams.size(),
                                             signature, signatureLength, &output_buf,
                                             &output_length);
         // Remove the operation regardless of the result