Add authorization enforcement to AndroidKeymaster.

Note: Moving List.h into system/keymaster is unfortunate, but required
to allow Trusty to use it.  b/22088154 tracks cleaning this up.

Bug: 19511945
Change-Id: Ia1dfe5fda5ea78935611b0a7656b323770edcbae
diff --git a/android_keymaster_test.cpp b/android_keymaster_test.cpp
index f7b37d3..d2ef08d 100644
--- a/android_keymaster_test.cpp
+++ b/android_keymaster_test.cpp
@@ -19,10 +19,13 @@
 #include <vector>
 
 #include <hardware/keymaster0.h>
+#include <keymaster/key_factory.h>
+#include <keymaster/soft_keymaster_context.h>
 #include <keymaster/soft_keymaster_device.h>
 #include <keymaster/softkeymaster.h>
 
 #include "android_keymaster_test_utils.h"
+#include "keymaster0_engine.h"
 
 using std::ifstream;
 using std::istreambuf_iterator;
@@ -43,11 +46,36 @@
 
 StdoutLogger logger;
 
+class TestKeymasterEnforcement : public KeymasterEnforcement {
+  public:
+    TestKeymasterEnforcement() : KeymasterEnforcement(3, 3) {}
+
+    virtual bool activation_date_valid(uint64_t /* activation_date */) const { return true; }
+    virtual bool expiration_date_passed(uint64_t /* expiration_date */) const { return false; }
+    virtual bool auth_token_timed_out(const hw_auth_token_t& /* token */,
+                                      uint32_t /* timeout */) const {
+        return false;
+    }
+    virtual uint32_t get_current_time() const { return 0; }
+    virtual bool ValidateTokenSignature(const hw_auth_token_t& /* token */) const { return true; }
+};
+
+class TestKeymasterContext : public SoftKeymasterContext {
+  public:
+    TestKeymasterContext(keymaster0_device_t* keymaster0 = nullptr)
+        : SoftKeymasterContext(keymaster0) {}
+
+    KeymasterEnforcement* enforcement_policy() override { return &test_policy_; }
+
+  private:
+    TestKeymasterEnforcement test_policy_;
+};
+
 class SoftKeymasterTestInstanceCreator : public Keymaster1TestInstanceCreator {
   public:
     keymaster1_device_t* CreateDevice() const override {
         std::cerr << "Creating software-only device" << std::endl;
-        SoftKeymasterDevice* device = new SoftKeymasterDevice;
+        SoftKeymasterDevice* device = new SoftKeymasterDevice(new TestKeymasterContext);
         return device->keymaster_device();
     }
 
@@ -77,7 +105,8 @@
 
         counting_keymaster0_device_ = new Keymaster0CountingWrapper(keymaster0_device);
 
-        SoftKeymasterDevice* keymaster = new SoftKeymasterDevice(counting_keymaster0_device_);
+        SoftKeymasterDevice* keymaster =
+            new SoftKeymasterDevice(new TestKeymasterContext(counting_keymaster0_device_));
         return keymaster->keymaster_device();
     }
 
@@ -641,7 +670,10 @@
                                            .RsaEncryptionKey(256, 3)
                                            .Digest(KM_DIGEST_NONE)
                                            .Padding(KM_PAD_NONE)));
-    ASSERT_EQ(KM_ERROR_INCOMPATIBLE_PURPOSE, BeginOperation(KM_PURPOSE_SIGN));
+    AuthorizationSet begin_params(client_params());
+    begin_params.push_back(TAG_PADDING, KM_PAD_NONE);
+    begin_params.push_back(TAG_DIGEST, KM_DIGEST_NONE);
+    ASSERT_EQ(KM_ERROR_INCOMPATIBLE_PURPOSE, BeginOperation(KM_PURPOSE_SIGN, begin_params));
 
     if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(2, GetParam()->keymaster0_calls());
@@ -1939,7 +1971,10 @@
 TEST_P(EncryptionOperationsTest, RsaEncryptWithSigningKey) {
     ASSERT_EQ(KM_ERROR_OK,
               GenerateKey(AuthorizationSetBuilder().RsaSigningKey(256, 3).Padding(KM_PAD_NONE)));
-    ASSERT_EQ(KM_ERROR_INCOMPATIBLE_PURPOSE, BeginOperation(KM_PURPOSE_DECRYPT));
+
+    AuthorizationSet begin_params(client_params());
+    begin_params.push_back(TAG_PADDING, KM_PAD_NONE);
+    ASSERT_EQ(KM_ERROR_INCOMPATIBLE_PURPOSE, BeginOperation(KM_PURPOSE_DECRYPT, begin_params));
 
     if (GetParam()->algorithm_in_hardware(KM_ALGORITHM_RSA))
         EXPECT_EQ(2, GetParam()->keymaster0_calls());
@@ -2746,6 +2781,51 @@
     EXPECT_EQ(0, GetParam()->keymaster0_calls());
 }
 
+typedef Keymaster1Test MaxOperationsTest;
+INSTANTIATE_TEST_CASE_P(AndroidKeymasterTest, MaxOperationsTest, test_params);
+
+TEST_P(MaxOperationsTest, TestLimit) {
+    ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
+                                           .AesEncryptionKey(128)
+                                           .EcbMode()
+                                           .Authorization(TAG_PADDING, KM_PAD_NONE)
+                                           .Authorization(TAG_MAX_USES_PER_BOOT, 3)));
+
+    string message = "1234567890123456";
+    string ciphertext1 = EncryptMessage(message, KM_MODE_ECB, KM_PAD_NONE);
+    string ciphertext2 = EncryptMessage(message, KM_MODE_ECB, KM_PAD_NONE);
+    string ciphertext3 = EncryptMessage(message, KM_MODE_ECB, KM_PAD_NONE);
+
+    // Fourth time should fail.
+    AuthorizationSet begin_params(client_params());
+    begin_params.push_back(TAG_BLOCK_MODE, KM_MODE_ECB);
+    begin_params.push_back(TAG_PADDING, KM_PAD_NONE);
+    EXPECT_EQ(KM_ERROR_KEY_MAX_OPS_EXCEEDED, BeginOperation(KM_PURPOSE_ENCRYPT, begin_params));
+
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
+}
+
+TEST_P(MaxOperationsTest, TestAbort) {
+    ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
+                                           .AesEncryptionKey(128)
+                                           .EcbMode()
+                                           .Authorization(TAG_PADDING, KM_PAD_NONE)
+                                           .Authorization(TAG_MAX_USES_PER_BOOT, 3)));
+
+    string message = "1234567890123456";
+    string ciphertext1 = EncryptMessage(message, KM_MODE_ECB, KM_PAD_NONE);
+    string ciphertext2 = EncryptMessage(message, KM_MODE_ECB, KM_PAD_NONE);
+    string ciphertext3 = EncryptMessage(message, KM_MODE_ECB, KM_PAD_NONE);
+
+    // Fourth time should fail.
+    AuthorizationSet begin_params(client_params());
+    begin_params.push_back(TAG_BLOCK_MODE, KM_MODE_ECB);
+    begin_params.push_back(TAG_PADDING, KM_PAD_NONE);
+    EXPECT_EQ(KM_ERROR_KEY_MAX_OPS_EXCEEDED, BeginOperation(KM_PURPOSE_ENCRYPT, begin_params));
+
+    EXPECT_EQ(0, GetParam()->keymaster0_calls());
+}
+
 typedef Keymaster1Test AddEntropyTest;
 INSTANTIATE_TEST_CASE_P(AndroidKeymasterTest, AddEntropyTest, test_params);