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.cpp b/android_keymaster.cpp
index 7ebc8de..2bc6ea7 100644
--- a/android_keymaster.cpp
+++ b/android_keymaster.cpp
@@ -234,21 +234,30 @@
     if (!factory)
         return;
 
-    response->error = KM_ERROR_INCOMPATIBLE_PURPOSE;
-    if (!key->authorizations().Contains(TAG_PURPOSE, request.purpose) &&
-        !factory->is_public_key_operation())
-        return;
-
     UniquePtr<Operation> operation(
         factory->CreateOperation(*key, request.additional_params, &response->error));
     if (operation.get() == NULL)
         return;
 
+    if (context_->enforcement_policy()) {
+        km_id_t key_id;
+        response->error = KM_ERROR_UNKNOWN_ERROR;
+        if (!context_->enforcement_policy()->CreateKeyId(request.key_blob, &key_id))
+            return;
+        operation->set_key_id(key_id);
+        response->error = context_->enforcement_policy()->AuthorizeOperation(
+            request.purpose, key_id, key->authorizations(), request.additional_params,
+            0 /* op_handle */, true /* is_begin_operation */);
+        if (response->error != KM_ERROR_OK)
+            return;
+    }
+
     response->output_params.Clear();
     response->error = operation->Begin(request.additional_params, &response->output_params);
     if (response->error != KM_ERROR_OK)
         return;
 
+    operation->SetAuthorizations(key->authorizations());
     response->error = operation_table_->Add(operation.release(), &response->op_handle);
 }
 
@@ -262,6 +271,14 @@
     if (operation == NULL)
         return;
 
+    if (context_->enforcement_policy()) {
+        response->error = context_->enforcement_policy()->AuthorizeOperation(
+            operation->purpose(), operation->key_id(), operation->authorizations(),
+            request.additional_params, request.op_handle, false /* is_begin_operation */);
+        if (response->error != KM_ERROR_OK)
+            return;
+    }
+
     response->error =
         operation->Update(request.additional_params, request.input, &response->output_params,
                           &response->output, &response->input_consumed);
@@ -281,6 +298,14 @@
     if (operation == NULL)
         return;
 
+    if (context_->enforcement_policy()) {
+        response->error = context_->enforcement_policy()->AuthorizeOperation(
+            operation->purpose(), operation->key_id(), operation->authorizations(),
+            request.additional_params, request.op_handle, false /* is_begin_operation */);
+        if (response->error != KM_ERROR_OK)
+            return;
+    }
+
     response->error = operation->Finish(request.additional_params, request.signature,
                                         &response->output_params, &response->output);
     operation_table_->Delete(request.op_handle);