Merge "Refactor GoogleKeymaster's operation table to a new class."
diff --git a/Android.mk b/Android.mk
index cc4f20a..a614e03 100644
--- a/Android.mk
+++ b/Android.mk
@@ -62,6 +62,7 @@
openssl_err.cpp \
openssl_utils.cpp \
operation.cpp \
+ operation_table.cpp \
rsa_key.cpp \
rsa_operation.cpp \
serializable.cpp \
diff --git a/Makefile b/Makefile
index 5ca2992..c5b04c5 100644
--- a/Makefile
+++ b/Makefile
@@ -55,6 +55,7 @@
openssl_err.cpp \
openssl_utils.cpp \
operation.cpp \
+ operation_table.cpp \
rsa_key.cpp \
rsa_operation.cpp \
serializable.cpp \
@@ -162,9 +163,10 @@
key_blob.o \
logger.o \
ocb.o \
- operation.o \
openssl_err.o \
openssl_utils.o \
+ operation.o \
+ operation_table.cpp \
rsa_key.o \
rsa_operation.o \
serializable.o \
diff --git a/google_keymaster.cpp b/google_keymaster.cpp
index 0778887..334dd8f 100644
--- a/google_keymaster.cpp
+++ b/google_keymaster.cpp
@@ -32,6 +32,7 @@
#include "key.h"
#include "openssl_err.h"
#include "operation.h"
+#include "operation_table.h"
#include "unencrypted_key_blob.h"
namespace keymaster {
@@ -41,16 +42,10 @@
const uint8_t SUBMINOR_VER = 0;
GoogleKeymaster::GoogleKeymaster(size_t operation_table_size)
- : operation_table_(new OpTableEntry[operation_table_size]),
- operation_table_size_(operation_table_size) {
- if (operation_table_.get() == NULL)
- operation_table_size_ = 0;
+ : operation_table_(new OperationTable(operation_table_size)) {
}
GoogleKeymaster::~GoogleKeymaster() {
- for (size_t i = 0; i < operation_table_size_; ++i)
- if (operation_table_[i].operation != NULL)
- delete operation_table_[i].operation;
}
struct AE_CTX_Delete {
@@ -250,7 +245,7 @@
if (response->error != KM_ERROR_OK)
return;
- response->error = AddOperation(operation.release(), &response->op_handle);
+ response->error = operation_table_->Add(operation.release(), &response->op_handle);
}
void GoogleKeymaster::UpdateOperation(const UpdateOperationRequest& request,
@@ -258,17 +253,16 @@
if (response == NULL)
return;
- OpTableEntry* entry = FindOperation(request.op_handle);
- if (entry == NULL) {
- response->error = KM_ERROR_INVALID_OPERATION_HANDLE;
+ response->error = KM_ERROR_INVALID_OPERATION_HANDLE;
+ Operation* operation = operation_table_->Find(request.op_handle);
+ if (operation == NULL)
return;
- }
- response->error = entry->operation->Update(request.additional_params, request.input,
- &response->output, &response->input_consumed);
+ response->error = operation->Update(request.additional_params, request.input, &response->output,
+ &response->input_consumed);
if (response->error != KM_ERROR_OK) {
// Any error invalidates the operation.
- DeleteOperation(entry);
+ operation_table_->Delete(request.op_handle);
}
}
@@ -277,23 +271,23 @@
if (response == NULL)
return;
- OpTableEntry* entry = FindOperation(request.op_handle);
- if (entry == NULL) {
- response->error = KM_ERROR_INVALID_OPERATION_HANDLE;
+ response->error = KM_ERROR_INVALID_OPERATION_HANDLE;
+ Operation* operation = operation_table_->Find(request.op_handle);
+ if (operation == NULL)
return;
- }
response->error =
- entry->operation->Finish(request.additional_params, request.signature, &response->output);
- DeleteOperation(entry);
+ operation->Finish(request.additional_params, request.signature, &response->output);
+ operation_table_->Delete(request.op_handle);
}
keymaster_error_t GoogleKeymaster::AbortOperation(const keymaster_operation_handle_t op_handle) {
- OpTableEntry* entry = FindOperation(op_handle);
- if (entry == NULL)
+ Operation* operation = operation_table_->Find(op_handle);
+ if (operation == NULL)
return KM_ERROR_INVALID_OPERATION_HANDLE;
- keymaster_error_t error = entry->operation->Abort();
- DeleteOperation(entry);
+
+ keymaster_error_t error = operation->Abort();
+ operation_table_->Delete(op_handle);
if (error != KM_ERROR_OK)
return error;
return KM_ERROR_OK;
@@ -513,42 +507,4 @@
unenforced->push_back(auth);
}
-keymaster_error_t GoogleKeymaster::AddOperation(Operation* operation,
- keymaster_operation_handle_t* op_handle) {
- UniquePtr<Operation> op(operation);
- if (RAND_bytes(reinterpret_cast<uint8_t*>(op_handle), sizeof(*op_handle)) == 0)
- return TranslateLastOpenSslError();
- if (*op_handle == 0) {
- // Statistically this is vanishingly unlikely, which means if it ever happens in practice,
- // it indicates a broken RNG.
- return KM_ERROR_UNKNOWN_ERROR;
- }
- for (size_t i = 0; i < operation_table_size_; ++i) {
- if (operation_table_[i].operation == NULL) {
- operation_table_[i].operation = op.release();
- operation_table_[i].handle = *op_handle;
- return KM_ERROR_OK;
- }
- }
- return KM_ERROR_TOO_MANY_OPERATIONS;
-}
-
-GoogleKeymaster::OpTableEntry*
-GoogleKeymaster::FindOperation(keymaster_operation_handle_t op_handle) {
- if (op_handle == 0)
- return NULL;
-
- for (size_t i = 0; i < operation_table_size_; ++i) {
- if (operation_table_[i].handle == op_handle)
- return operation_table_.get() + i;
- }
- return NULL;
-}
-
-void GoogleKeymaster::DeleteOperation(OpTableEntry* entry) {
- delete entry->operation;
- entry->operation = NULL;
- entry->handle = 0;
-}
-
} // namespace keymaster
diff --git a/include/keymaster/google_keymaster.h b/include/keymaster/google_keymaster.h
index 2b49f59..bdfe9f4 100644
--- a/include/keymaster/google_keymaster.h
+++ b/include/keymaster/google_keymaster.h
@@ -23,8 +23,8 @@
namespace keymaster {
class Key;
-class Operation;
class UnencryptedKeyBlob;
+class OperationTable;
/**
* OpenSSL-based Keymaster backing implementation, for use as a pure software implmentation
@@ -96,21 +96,7 @@
void AddAuthorization(const keymaster_key_param_t& auth, AuthorizationSet* enforced,
AuthorizationSet* unenforced);
- struct OpTableEntry {
- OpTableEntry() {
- handle = 0;
- operation = NULL;
- }
- keymaster_operation_handle_t handle;
- Operation* operation;
- };
-
- keymaster_error_t AddOperation(Operation* operation, keymaster_operation_handle_t* op_handle);
- OpTableEntry* FindOperation(keymaster_operation_handle_t op_handle);
- void DeleteOperation(OpTableEntry* entry);
-
- UniquePtr<OpTableEntry[]> operation_table_;
- size_t operation_table_size_;
+ UniquePtr<OperationTable> operation_table_;
};
} // namespace keymaster
diff --git a/operation.h b/operation.h
index a046aab..24878ca 100644
--- a/operation.h
+++ b/operation.h
@@ -91,7 +91,7 @@
AuthorizationSet* output_params) = 0;
virtual keymaster_error_t Update(const AuthorizationSet& additional_params, const Buffer& input,
Buffer* output, size_t* input_consumed) = 0;
- virtual keymaster_error_t Finish(const AuthorizationSet& /* additional_params */,
+ virtual keymaster_error_t Finish(const AuthorizationSet& additional_params,
const Buffer& signature, Buffer* output) = 0;
virtual keymaster_error_t Abort() = 0;
diff --git a/operation_table.cpp b/operation_table.cpp
new file mode 100644
index 0000000..bd110df
--- /dev/null
+++ b/operation_table.cpp
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "operation_table.h"
+
+#include <openssl/rand.h>
+
+#include "openssl_err.h"
+#include "operation.h"
+
+namespace keymaster {
+
+OperationTable::Entry::~Entry() {
+ delete operation;
+ operation = NULL;
+ handle = 0;
+}
+
+keymaster_error_t OperationTable::Add(Operation* operation,
+ keymaster_operation_handle_t* op_handle) {
+ if (!table_.get()) {
+ table_.reset(new Entry[table_size_]);
+ if (!table_.get())
+ return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
+
+ UniquePtr<Operation> op(operation);
+ if (RAND_bytes(reinterpret_cast<uint8_t*>(op_handle), sizeof(*op_handle)) == 0)
+ return TranslateLastOpenSslError();
+ if (*op_handle == 0) {
+ // Statistically this is vanishingly unlikely, which means if it ever happens in practice,
+ // it indicates a broken RNG.
+ return KM_ERROR_UNKNOWN_ERROR;
+ }
+
+ for (size_t i = 0; i < table_size_; ++i) {
+ if (table_[i].operation == NULL) {
+ table_[i].operation = op.release();
+ table_[i].handle = *op_handle;
+ return KM_ERROR_OK;
+ }
+ }
+ return KM_ERROR_TOO_MANY_OPERATIONS;
+}
+
+Operation* OperationTable::Find(keymaster_operation_handle_t op_handle) {
+ if (op_handle == 0)
+ return NULL;
+
+ if (!table_.get())
+ return NULL;
+
+ for (size_t i = 0; i < table_size_; ++i) {
+ if (table_[i].handle == op_handle)
+ return table_[i].operation;
+ }
+ return NULL;
+}
+
+bool OperationTable::Delete(keymaster_operation_handle_t op_handle) {
+ if (!table_.get())
+ return false;
+
+ for (size_t i = 0; i < table_size_; ++i) {
+ if (table_[i].handle == op_handle) {
+ // Destructor does the right thing, call it.
+ table_[i].Entry::~Entry();
+ return true;
+ }
+ }
+ return false;
+}
+
+} // namespace keymaster
diff --git a/operation_table.h b/operation_table.h
new file mode 100644
index 0000000..f27c1cd
--- /dev/null
+++ b/operation_table.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEM_KEYMASTER_OPERATION_TABLE_H
+#define SYSTEM_KEYMASTER_OPERATION_TABLE_H
+
+#include <UniquePtr.h>
+
+#include <hardware/keymaster1.h>
+
+namespace keymaster {
+
+class Operation;
+
+class OperationTable {
+ public:
+ OperationTable(size_t table_size) : table_size_(table_size) {}
+
+ struct Entry {
+ Entry() {
+ handle = 0;
+ operation = NULL;
+ };
+ ~Entry();
+ keymaster_operation_handle_t handle;
+ Operation* operation;
+ };
+
+ keymaster_error_t Add(Operation* operation, keymaster_operation_handle_t* op_handle);
+ Operation* Find(keymaster_operation_handle_t op_handle);
+ bool Delete(keymaster_operation_handle_t);
+
+ private:
+ UniquePtr<Entry[]> table_;
+ size_t table_size_;
+};
+
+} // namespace keymaster
+
+#endif // SYSTEM_KEYMASTER_OPERATION_TABLE_H