summaryrefslogtreecommitdiff
Diffstat
-rwxr-xr-x4.0/AmlogicKeymaster4Device.cpp571
-rwxr-xr-x4.0/android.hardware.keymaster@4.0-service.amlogic.rc4
-rwxr-xr-x4.0/service.cpp43
-rwxr-xr-x[-rw-r--r--]8efb1e1c-37e5-4326-a5d68c33726c7d57.ta11646
-rwxr-xr-xAmlogicKeymaster.cpp352
-rwxr-xr-x[-rw-r--r--]Android.mk125
-rw-r--r--aml_keymaster_device.cpp1021
-rw-r--r--aml_keymaster_device.h194
-rw-r--r--aml_keymaster_ipc.cpp128
-rw-r--r--aml_keymaster_ipc.h33
-rwxr-xr-xinclude/amlogic_keymaster/AmlogicKeymaster.h86
-rwxr-xr-xinclude/amlogic_keymaster/AmlogicKeymaster4Device.h105
-rwxr-xr-xinclude/amlogic_keymaster/amlogic_keymaster_messages.h222
-rwxr-xr-xinclude/amlogic_keymaster/ipc/amlogic_keymaster_ipc.h52
-rwxr-xr-x[-rw-r--r--]include/amlogic_keymaster/ipc/keymaster_ipc.h (renamed from keymaster_ipc.h)17
-rwxr-xr-xipc/amlogic_keymaster_ipc.cpp325
-rw-r--r--module.cpp61
-rw-r--r--unit_test/android_keymaster_messages_test.cpp732
-rw-r--r--unit_test/android_keymaster_test.cpp3976
-rw-r--r--unit_test/android_keymaster_test_utils.cpp902
-rw-r--r--unit_test/android_keymaster_test_utils.h470
-rw-r--r--unit_test/android_keymaster_utils.h306
-rw-r--r--unit_test/attestation_record.cpp690
-rw-r--r--unit_test/attestation_record.h62
-rw-r--r--unit_test/attestation_record_test.cpp145
-rw-r--r--unit_test/authorization_set_test.cpp745
-rw-r--r--unit_test/ecies_kem_test.cpp73
-rw-r--r--unit_test/gtest_main.cpp34
-rw-r--r--unit_test/hkdf_test.cpp78
-rw-r--r--unit_test/hmac_test.cpp84
-rw-r--r--unit_test/kdf1_test.cpp60
-rw-r--r--unit_test/kdf2_test.cpp86
-rw-r--r--unit_test/kdf_test.cpp46
-rw-r--r--unit_test/key_blob_test.cpp362
-rw-r--r--unit_test/keymaster0_engine.h103
-rw-r--r--unit_test/keymaster1_engine.h123
-rw-r--r--unit_test/keymaster_configuration_test.cpp68
-rw-r--r--unit_test/keymaster_enforcement_test.cpp872
-rw-r--r--unit_test/keymaster_tags.cpp173
-rw-r--r--unit_test/nist_curve_key_exchange_test.cpp219
-rw-r--r--unit_test/openssl_utils.h100
-rw-r--r--unit_test/sw_rsa_attest_root.key.pem15
42 files changed, 6493 insertions, 19016 deletions
diff --git a/ipc/amlogic_keymaster_ipc.cpp b/ipc/amlogic_keymaster_ipc.cpp
new file mode 100755
index 0000000..00e2d26
--- a/dev/null
+++ b/ipc/amlogic_keymaster_ipc.cpp
@@ -0,0 +1,325 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "AmlogicKeymaster"
+
+// TODO: make this generic in libtrusty
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/uio.h>
+#include <unistd.h>
+
+#include <algorithm>
+
+#include <log/log.h>
+#if !AMLOGIC_MODIFY
+#include <trusty/tipc.h>
+#endif
+#include <amlogic_keymaster/ipc/keymaster_ipc.h>
+#include <amlogic_keymaster/ipc/amlogic_keymaster_ipc.h>
+
+#if AMLOGIC_MODIFY
+TEEC_Result aml_keymaster_connect(TEEC_Context *c, TEEC_Session *s) {
+ TEEC_Result result = TEEC_SUCCESS;
+ TEEC_UUID svc_id = TA_KEYMASTER_UUID;
+ TEEC_Operation operation;
+ uint32_t err_origin;
+ struct timespec time;
+ uint64_t millis = 0;
+
+ memset(&operation, 0, sizeof(operation));
+
+ /* Initialize Context */
+ result = TEEC_InitializeContext(NULL, c);
+
+ if (result != TEEC_SUCCESS) {
+ ALOGD("TEEC_InitializeContext failed with error = %x\n", result);
+ return result;
+ }
+ /* Open Session */
+ result = TEEC_OpenSession(c, s, &svc_id,
+ TEEC_LOGIN_PUBLIC,
+ NULL, NULL,
+ &err_origin);
+
+ if (result != TEEC_SUCCESS) {
+ ALOGD("TEEC_Opensession failed with code 0x%x origin 0x%x",result, err_origin);
+ TEEC_FinalizeContext(c);
+ return result;
+ }
+
+ int res = clock_gettime(CLOCK_BOOTTIME, &time);
+ if (res < 0)
+ millis = 0;
+ else
+ millis = (time.tv_sec * 1000) + (time.tv_nsec / 1000 / 1000);
+
+ /* Init TA */
+ operation.paramTypes = TEEC_PARAM_TYPES(
+ TEEC_VALUE_INPUT, TEEC_NONE,
+ TEEC_NONE, TEEC_NONE);
+
+ operation.params[0].value.a = (millis >> 32);
+ operation.params[0].value.b = (millis & 0xffffffff);
+
+ result = TEEC_InvokeCommand(s,
+ KM_TA_INIT,
+ &operation,
+ NULL);
+
+ ALOGD("create id: %d, ctx: %p, ctx: %p\n", s->session_id, s->ctx, c);
+ return result;
+}
+
+TEEC_Result aml_keymaster_call(TEEC_Session *s, uint32_t cmd, void* in, uint32_t in_size, uint8_t* out,
+ uint32_t* out_size) {
+ TEEC_Result res = TEEC_SUCCESS;
+ TEEC_Operation op;
+ uint32_t ret_orig;
+
+ memset(&op, 0, sizeof(op));
+
+ op.params[0].tmpref.buffer = in;
+ op.params[0].tmpref.size = in_size;
+ op.params[1].tmpref.buffer = out;
+ op.params[1].tmpref.size = *out_size;
+ op.paramTypes = TEEC_PARAM_TYPES(
+ TEEC_MEMREF_TEMP_INPUT,
+ TEEC_MEMREF_TEMP_OUTPUT,
+ TEEC_VALUE_OUTPUT,
+ TEEC_NONE);
+
+ ALOGD("id: %d, ctx: %p, cmd: %d\n", s->session_id, s->ctx, cmd);
+ res = TEEC_InvokeCommand(s, cmd, &op, &ret_orig);
+ if (res != TEEC_SUCCESS) {
+ ALOGE("Invoke cmd: %u failed with res(%x), ret_orig(%x), return(%d)\n",
+ cmd, res, ret_orig, op.params[2].value.a);
+ } else {
+ *out_size = op.params[2].value.b;
+ }
+
+ return res;
+}
+
+TEEC_Result aml_keymaster_disconnect(TEEC_Context *c, TEEC_Session *s) {
+ TEEC_Operation operation;
+ TEEC_Result result = TEEC_SUCCESS;
+
+ operation.paramTypes = TEEC_PARAM_TYPES(
+ TEEC_NONE, TEEC_NONE,
+ TEEC_NONE, TEEC_NONE);
+
+ result = TEEC_InvokeCommand(s,
+ KM_TA_TERM,
+ &operation,
+ NULL);
+
+ TEEC_CloseSession(s);
+ TEEC_FinalizeContext(c);
+
+ return result;
+}
+
+keymaster_error_t aml_keymaster_send(TEEC_Session *s, uint32_t command, const keymaster::Serializable& req,
+ keymaster::KeymasterResponse* rsp) {
+ uint32_t req_size = req.SerializedSize();
+ if (req_size > AMLOGIC_KEYMASTER_SEND_BUF_SIZE) {
+ ALOGE("Request too big: %u Max size: %u", req_size, AMLOGIC_KEYMASTER_SEND_BUF_SIZE);
+ return KM_ERROR_INVALID_INPUT_LENGTH;
+ }
+
+ uint8_t send_buf[AMLOGIC_KEYMASTER_SEND_BUF_SIZE];
+ keymaster::Eraser send_buf_eraser(send_buf, AMLOGIC_KEYMASTER_SEND_BUF_SIZE);
+ req.Serialize(send_buf, send_buf + req_size);
+
+ // Send it
+ uint8_t recv_buf[AMLOGIC_KEYMASTER_RECV_BUF_SIZE];
+ keymaster::Eraser recv_buf_eraser(recv_buf, AMLOGIC_KEYMASTER_RECV_BUF_SIZE);
+ uint32_t rsp_size = AMLOGIC_KEYMASTER_RECV_BUF_SIZE;
+ int rc = aml_keymaster_call(s, command, send_buf, req_size, recv_buf, &rsp_size);
+ if (rc < 0) {
+ ALOGE("tipc error: %d\n", rc);
+ // TODO(swillden): Distinguish permanent from transient errors and set error_ appropriately.
+ return translate_error(rc);
+ } else {
+ ALOGD("Received %d byte response\n", rsp_size);
+ }
+
+ const keymaster_message* msg = (keymaster_message*)recv_buf;
+ const uint8_t* p = msg->payload;
+
+ if (!rsp->Deserialize(&p, p + rsp_size)) {
+ ALOGE("Error deserializing response of size %d\n", (int)rsp_size);
+ return KM_ERROR_UNKNOWN_ERROR;
+ } else if (rsp->error != KM_ERROR_OK) {
+ ALOGE("Response of size %d contained error code %d\n", (int)rsp_size, (int)rsp->error);
+ return rsp->error;
+ }
+ return rsp->error;
+}
+#else
+#define TRUSTY_DEVICE_NAME "/dev/trusty-ipc-dev0"
+
+static int handle_ = -1;
+
+int trusty_keymaster_connect() {
+ int rc = tipc_connect(TRUSTY_DEVICE_NAME, KEYMASTER_PORT);
+ if (rc < 0) {
+ return rc;
+ }
+
+ handle_ = rc;
+ return 0;
+}
+
+int trusty_keymaster_call(uint32_t cmd, void* in, uint32_t in_size, uint8_t* out,
+ uint32_t* out_size) {
+ if (handle_ < 0) {
+ ALOGE("not connected\n");
+ return -EINVAL;
+ }
+
+ size_t msg_size = in_size + sizeof(struct keymaster_message);
+ struct keymaster_message* msg = reinterpret_cast<struct keymaster_message*>(malloc(msg_size));
+ if (!msg) {
+ ALOGE("failed to allocate msg buffer\n");
+ return -EINVAL;
+ }
+
+ msg->cmd = cmd;
+ memcpy(msg->payload, in, in_size);
+
+ ssize_t rc = write(handle_, msg, msg_size);
+ free(msg);
+
+ if (rc < 0) {
+ ALOGE("failed to send cmd (%d) to %s: %s\n", cmd, KEYMASTER_PORT, strerror(errno));
+ return -errno;
+ }
+ size_t out_max_size = *out_size;
+ *out_size = 0;
+ struct iovec iov[2];
+ struct keymaster_message header;
+ iov[0] = {.iov_base = &header, .iov_len = sizeof(struct keymaster_message)};
+ while (true) {
+ iov[1] = {.iov_base = out + *out_size,
+ .iov_len = std::min<uint32_t>(KEYMASTER_MAX_BUFFER_LENGTH,
+ out_max_size - *out_size)};
+ rc = readv(handle_, iov, 2);
+ if (rc < 0) {
+ ALOGE("failed to retrieve response for cmd (%d) to %s: %s\n", cmd, KEYMASTER_PORT,
+ strerror(errno));
+ return -errno;
+ }
+
+ if ((size_t)rc < sizeof(struct keymaster_message)) {
+ ALOGE("invalid response size (%d)\n", (int)rc);
+ return -EINVAL;
+ }
+
+ if ((cmd | KEYMASTER_RESP_BIT) != (header.cmd & ~(KEYMASTER_STOP_BIT))) {
+ ALOGE("invalid command (%d)", header.cmd);
+ return -EINVAL;
+ }
+ *out_size += ((size_t)rc - sizeof(struct keymaster_message));
+ if (header.cmd & KEYMASTER_STOP_BIT) {
+ break;
+ }
+ }
+
+ return rc;
+}
+
+void trusty_keymaster_disconnect() {
+ if (handle_ >= 0) {
+ tipc_close(handle_);
+ }
+ handle_ = -1;
+}
+
+#endif // AMLOGIC_MODIFY
+keymaster_error_t translate_error(int err) {
+ switch (err) {
+ case 0:
+ return KM_ERROR_OK;
+ case -EPERM:
+ case -EACCES:
+ return KM_ERROR_SECURE_HW_ACCESS_DENIED;
+
+ case -ECANCELED:
+ return KM_ERROR_OPERATION_CANCELLED;
+
+ case -ENODEV:
+ return KM_ERROR_UNIMPLEMENTED;
+
+ case -ENOMEM:
+ return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+
+ case -EBUSY:
+ return KM_ERROR_SECURE_HW_BUSY;
+
+ case -EIO:
+ return KM_ERROR_SECURE_HW_COMMUNICATION_FAILED;
+
+ case -EOVERFLOW:
+ return KM_ERROR_INVALID_INPUT_LENGTH;
+
+ default:
+ return KM_ERROR_UNKNOWN_ERROR;
+ }
+}
+#if !AMLOGIC_MODIFY
+keymaster_error_t trusty_keymaster_send(uint32_t command, const keymaster::Serializable& req,
+ keymaster::KeymasterResponse* rsp) {
+ uint32_t req_size = req.SerializedSize();
+ if (req_size > TRUSTY_KEYMASTER_SEND_BUF_SIZE) {
+ ALOGE("Request too big: %u Max size: %u", req_size, TRUSTY_KEYMASTER_SEND_BUF_SIZE);
+ return KM_ERROR_INVALID_INPUT_LENGTH;
+ }
+
+ uint8_t send_buf[TRUSTY_KEYMASTER_SEND_BUF_SIZE];
+ keymaster::Eraser send_buf_eraser(send_buf, TRUSTY_KEYMASTER_SEND_BUF_SIZE);
+ req.Serialize(send_buf, send_buf + req_size);
+
+ // Send it
+ uint8_t recv_buf[TRUSTY_KEYMASTER_RECV_BUF_SIZE];
+ keymaster::Eraser recv_buf_eraser(recv_buf, TRUSTY_KEYMASTER_RECV_BUF_SIZE);
+ uint32_t rsp_size = TRUSTY_KEYMASTER_RECV_BUF_SIZE;
+ int rc = trusty_keymaster_call(command, send_buf, req_size, recv_buf, &rsp_size);
+ if (rc < 0) {
+ // Reset the connection on tipc error
+ trusty_keymaster_disconnect();
+ trusty_keymaster_connect();
+ ALOGE("tipc error: %d\n", rc);
+ // TODO(swillden): Distinguish permanent from transient errors and set error_ appropriately.
+ return translate_error(rc);
+ } else {
+ ALOGV("Received %d byte response\n", rsp_size);
+ }
+
+ const uint8_t* p = recv_buf;
+ if (!rsp->Deserialize(&p, p + rsp_size)) {
+ ALOGE("Error deserializing response of size %d\n", (int)rsp_size);
+ return KM_ERROR_UNKNOWN_ERROR;
+ } else if (rsp->error != KM_ERROR_OK) {
+ ALOGE("Response of size %d contained error code %d\n", (int)rsp_size, (int)rsp->error);
+ return rsp->error;
+ }
+ return rsp->error;
+}
+#endif //!AMLOGIC_MODIFY