From 5922208b0518d7da6f60c4cf64f52c249ac274b4 Mon Sep 17 00:00:00 2001 From: "Yan, Shaopu" Date: Fri, 21 Sep 2018 19:42:36 +0800 Subject: [PATCH 1/3] Add implementation of keybox provision operation the new IPC call of ProvisionAttesationKeybox can only be called from bootloader which used to provision the keybox into RPMB storage. the original keybox will be retrieved from CSE in xml format, then it will be decompressed by lzma and parsed by tinyxml2 Change-Id: Id0ba8bf580a21c5915b423c17faa49addb5fdf12 Tracked-On: https://jira01.devtools.intel.com/browse/OAM-69557 Signed-off-by: Yan, Shaopu Reviewed-on: https://android.intel.com/646433 Reviewed-by: Wang, Kai Z --- ipc/keymaster_ipc.cpp | 5 + ipc/keymaster_ipc.h | 1 + provision/provision_keybox.cpp | 555 +++++++++++++++++++++++++++++++++ provision/provision_keybox.h | 60 ++++ provision/rules.mk | 22 ++ rules.mk | 1 + trusty_keymaster.h | 4 +- 7 files changed, 647 insertions(+), 1 deletion(-) create mode 100644 provision/provision_keybox.cpp create mode 100644 provision/provision_keybox.h create mode 100644 provision/rules.mk diff --git a/ipc/keymaster_ipc.cpp b/ipc/keymaster_ipc.cpp index 455d82e..f273d81 100644 --- a/ipc/keymaster_ipc.cpp +++ b/ipc/keymaster_ipc.cpp @@ -505,6 +505,11 @@ static long keymaster_dispatch_non_secure(keymaster_chan_ctx* ctx, return do_dispatch(&TrustyKeymaster::SetBootParams, msg, payload_size, out, out_size); + case KM_PROVISION_KEYBOX: + LOG_D("Dispatching KM_PROVISION_KEYBOX, size %d", payload_size); + return do_dispatch(&TrustyKeymaster::ProvisionAttesationKeybox, msg, payload_size, + out, out_size); + case KM_SET_ATTESTATION_KEY: LOG_D("Dispatching SET_ATTESTION_KEY, size %d", payload_size); return do_dispatch(&TrustyKeymaster::SetAttestationKey, msg, diff --git a/ipc/keymaster_ipc.h b/ipc/keymaster_ipc.h index 98d9028..abe12f1 100644 --- a/ipc/keymaster_ipc.h +++ b/ipc/keymaster_ipc.h @@ -54,6 +54,7 @@ enum keymaster_command { // Bootloader calls. KM_SET_BOOT_PARAMS = (0x1000 << KEYMASTER_REQ_SHIFT), + KM_PROVISION_KEYBOX = (0x1001 << KEYMASTER_REQ_SHIFT), KM_SET_ATTESTATION_KEY = (0x2000 << KEYMASTER_REQ_SHIFT), KM_APPEND_ATTESTATION_CERT_CHAIN = (0x3000 << KEYMASTER_REQ_SHIFT), KM_ATAP_GET_CA_REQUEST = (0x4000 << KEYMASTER_REQ_SHIFT), diff --git a/provision/provision_keybox.cpp b/provision/provision_keybox.cpp new file mode 100644 index 0000000..7c4c325 --- /dev/null +++ b/provision/provision_keybox.cpp @@ -0,0 +1,555 @@ +/* +** +** Copyright 2018, The Android Open Source Project +** Copyright (C) 2018 Intel Corporation +** +** 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 +#include +#include +#include +#include +#include "secure_storage.h" +#include "trusty_logger.h" +#include +#include "trusty_device_info.h" +#include "trusty_syscalls_x86.h" +#include "trusty_keymaster_context.h" + +#include "tinyxml2.h" +#include "provision_keybox.h" +#include "LzmaDec.h" + +using namespace tinyxml2; + +namespace keymaster { + +#define XML_KEY_ALGORITHM_EC_STRING "ecdsa" +#define XML_KEY_ALGORITHM_RSA_STRING "rsa" + +#define LZMA_HEADER_SIZE (LZMA_PROPS_SIZE + 8) +#define UNUSED_VAR(x) (void)x; +static void *AllocForLzma(void *p, size_t size) { UNUSED_VAR(p); return malloc(size); } +static void FreeForLzma(void *p, void *address) { UNUSED_VAR(p); free(address); } +static ISzAlloc g_AllocForLzma = { &AllocForLzma, &FreeForLzma }; + + +typedef struct attk_keybox_header { + uint16_t version; // version 1 supports plan and LZMA + uint16_t size; // decompressed size excluding this header + uint8_t format; // indicates file format, 0 = plain, 1 = LZMA + uint8_t reserved[3]; // not used +} attkb_header_t; + + +static XMLElement *tinyxml2_WalkNextElement(XMLElement *root, XMLElement *element) +{ + XMLElement *next_element; + XMLNode *next_node; + + if ((root == NULL) || (element == NULL)) + return NULL; + + next_element = element->FirstChildElement(); + if (next_element) + return next_element; + + next_element = element->NextSiblingElement(); + if (next_element) + return next_element; + + next_node = dynamic_cast(element)->Parent(); + while (1) { + if ((next_node == NULL) || (next_node->ToElement() == root)) + return NULL; + + next_element = next_node->ToElement()->NextSiblingElement(); + if (next_element) + return next_element; + next_node = next_node->Parent(); + } +} + +static XMLElement *tinyxml2_FindElement(XMLElement *root, XMLElement *element, const char *name, const char *attr, const char *value) +{ + XMLElement *get_element; + + if ((root == NULL) || (name == NULL)) + return NULL; + + if (root && (element == NULL)) { + if (strcmp(root->Name(), name) == 0) { + if (attr && value) { + if (root->Attribute(attr, value)) + return root; + } + else + return root; + } + + for (element = root->FirstChildElement(); element; element = element->NextSiblingElement()) { + get_element = tinyxml2_FindElement(element, NULL, name, attr, value); + if (get_element) + return get_element; + } + + return NULL; + } + + if (root && element) { + while (1) { + element = tinyxml2_WalkNextElement(root, element); + if (element == NULL) + return NULL; + if (strcmp(element->Name(), name) == 0) { + if (attr && value) { + if (element->Attribute(attr, value)) + return element; + } + else + return element; + } + } + } + return NULL; +} + +static uint8_t *decompress_attkb(uint8_t* keybox, size_t compressed_size) { + size_t outlen = 0, inlen = compressed_size - LZMA_HEADER_SIZE; + uint8_t *s = NULL, *decompressed_attkb = NULL; + ELzmaStatus status; + SRes res; + + s = keybox; + outlen = s[LZMA_PROPS_SIZE] | + (s[LZMA_PROPS_SIZE + 1] << 8) | + (s[LZMA_PROPS_SIZE + 2] << 16) | + (s[LZMA_PROPS_SIZE + 3] << 24); + + decompressed_attkb = (uint8_t *)malloc(outlen); + if(decompressed_attkb == NULL) + return NULL; + + res = LzmaDecode(decompressed_attkb, &outlen, s + LZMA_HEADER_SIZE, &inlen, + s, LZMA_PROPS_SIZE, LZMA_FINISH_ANY, &status, &g_AllocForLzma); + if(res) { + LOG_E("attkb decompression failed! res (%d), status(%d)", res, status); + free(decompressed_attkb); + return NULL; + } + + return decompressed_attkb; +} + + +/* the keybox will be retrieved from the CSE side */ +keymaster_error_t RetrieveKeybox(uint8_t** keybox, uint32_t* keybox_size) { + int rc = -1; + keymaster_error_t ret = KM_ERROR_OK; + trusty_device_info_t *dev_info = NULL; + uint32_t buffer_size = sizeof(trusty_device_info_t) + MAX_ATTKB_SIZE; + attkb_header_t *attkb_hdr = NULL; + size_t attkb_hdr_size = 0; + + if((keybox_size == NULL) || (keybox == NULL)) + return KM_ERROR_UNEXPECTED_NULL_POINTER; + + dev_info = (trusty_device_info_t *)malloc(buffer_size); + if(!dev_info) + return KM_ERROR_MEMORY_ALLOCATION_FAILED; + memset(dev_info, 0, buffer_size); + rc = get_device_info(dev_info); + if(rc != 0) { + LOG_E("RetrieveKeybox failed!", 0); + ret = KM_ERROR_UNKNOWN_ERROR; + goto clear_sensitive_data; + } + + *keybox_size = dev_info->attkb_size; + *keybox = (uint8_t *)malloc(dev_info->attkb_size); + if(*keybox == NULL) { + ret = KM_ERROR_UNKNOWN_ERROR; + goto clear_sensitive_data; + } + memcpy_s(*keybox, *keybox_size, dev_info->attkb, *keybox_size); + + attkb_hdr = (attkb_header_t *)(*keybox); + /* indicates file format, 0 = plain, 1 = LZMA */ + if((attkb_hdr->version == 1) && (attkb_hdr->format == 1)) { + uint8_t* decompressed_attkb = NULL; + attkb_hdr_size = sizeof(attkb_header_t); + decompressed_attkb = decompress_attkb(*keybox + attkb_hdr_size, attkb_hdr->size); + free(*keybox); + *keybox = decompressed_attkb; + if(decompressed_attkb == NULL) { + ret = KM_ERROR_UNKNOWN_ERROR; + goto clear_sensitive_data; + } + } + +clear_sensitive_data: + memset(dev_info, 0, buffer_size); + free(dev_info); + return ret; +} + +keymaster_error_t keybox_xml_initialize(const uint8_t* keybox, XMLElement** xml_root) { + if ((keybox == NULL) || (xml_root == NULL)) + return KM_ERROR_INVALID_ARGUMENT; + + XMLDocument *doc = new XMLDocument; + if (doc == NULL) + return KM_ERROR_MEMORY_ALLOCATION_FAILED; + + doc->LoadXmlData((char *)keybox); + + if (doc->Error()) { + LOG_E("Parsing XML data failed!", 0); + return KM_ERROR_UNKNOWN_ERROR; + } + *xml_root = doc->RootElement(); + if (*xml_root == NULL) { + LOG_E("Parsing XML data failed!", 0); + return KM_ERROR_UNKNOWN_ERROR; + } + + return KM_ERROR_OK; +} + +keymaster_error_t get_prikey_from_keybox(XMLElement* xml_root, + keymaster_algorithm_t algorithm, + uint8_t** key, + uint32_t* key_size) { + XMLElement *subroot, *element; + char *base64data; + uint8_t *decodedata; + char *p, *pstart, *pend; + char *text; + size_t count; + + if ((key == NULL) || (key_size == NULL)) + return KM_ERROR_INVALID_ARGUMENT; + + if (xml_root == NULL) + return KM_ERROR_INVALID_ARGUMENT; + + if (algorithm == KM_ALGORITHM_RSA) { + subroot = tinyxml2_FindElement(xml_root, NULL, "Key", "algorithm", XML_KEY_ALGORITHM_RSA_STRING); + element = tinyxml2_FindElement(subroot, NULL, "PrivateKey", NULL, NULL); + if (element == NULL) + return KM_ERROR_UNKNOWN_ERROR; + text = (char *)element->GetText(); + if (text == NULL) + return KM_ERROR_UNKNOWN_ERROR; + count = strlen(text); + if ((p = strstr(text, "-----BEGIN RSA PRIVATE KEY-----")) == NULL) + return KM_ERROR_UNKNOWN_ERROR; + pstart = p + strlen("-----BEGIN RSA PRIVATE KEY-----"); + if ((pend = strstr(text, "-----END RSA PRIVATE KEY-----")) == NULL) + return KM_ERROR_UNKNOWN_ERROR; + base64data = new char[count]; + if (base64data == NULL) + return KM_ERROR_MEMORY_ALLOCATION_FAILED; + count = 0; + for (p = pstart; p < pend; p++) { + if (!isspace(*p)) + base64data[count++] = *p; + } + base64data[count] = 0x00; + } else if (algorithm == KM_ALGORITHM_EC) { + subroot = tinyxml2_FindElement(xml_root, NULL, "Key", "algorithm", XML_KEY_ALGORITHM_EC_STRING); + element = tinyxml2_FindElement(subroot, NULL, "PrivateKey", NULL, NULL); + if (element == NULL) + return KM_ERROR_UNKNOWN_ERROR; + text = (char *)element->GetText(); + if (text == NULL) + return KM_ERROR_UNKNOWN_ERROR; + count = strlen(text); + if ((p = strstr(text, "-----BEGIN EC PRIVATE KEY-----")) == NULL) + return KM_ERROR_UNKNOWN_ERROR; + pstart = p + strlen("-----BEGIN EC PRIVATE KEY-----"); + if ((pend = strstr(text, "-----END EC PRIVATE KEY-----")) == NULL) + return KM_ERROR_UNKNOWN_ERROR; + base64data = new char[count]; + if (base64data == NULL) + return KM_ERROR_MEMORY_ALLOCATION_FAILED; + count = 0; + for (p = pstart; p < pend; p++) { + if (!isspace(*p)) + base64data[count++] = *p; + } + base64data[count] = 0x00; + } else { + LOG_E("No matched key in keybox!", 0); + return KM_ERROR_UNKNOWN_ERROR; + } + + decodedata = new uint8_t[count]; + if (decodedata == NULL) + return KM_ERROR_MEMORY_ALLOCATION_FAILED; + if (!EVP_DecodeBase64(decodedata, (size_t *)&count, count, (const uint8_t *)base64data, strlen(base64data))) { + LOG_E("Failed to do base64 decode!", 0); + return KM_ERROR_UNKNOWN_ERROR; + } + *key = decodedata; + *key_size = count; + delete [] base64data; + + return KM_ERROR_OK; +} + +keymaster_error_t get_cert_chain_len_from_keybox(XMLElement* xml_root, + keymaster_algorithm_t algorithm, + uint32_t* cert_chain_len) { + XMLElement *subroot, *element; + int count; + + if (cert_chain_len == NULL) + return KM_ERROR_INVALID_ARGUMENT; + + if (xml_root == NULL) + return KM_ERROR_INVALID_ARGUMENT; + + if (algorithm == KM_ALGORITHM_RSA) { + subroot = tinyxml2_FindElement(xml_root, + NULL, + "Key", + "algorithm", + XML_KEY_ALGORITHM_RSA_STRING); + if (subroot == NULL) + return KM_ERROR_UNKNOWN_ERROR; + count = 0; + for (element = tinyxml2_FindElement(subroot, NULL, "Certificate", NULL, NULL); element; + element = tinyxml2_FindElement(subroot, element, "Certificate", NULL, NULL)) { + count++; + } + } else if (algorithm == KM_ALGORITHM_EC) { + subroot = tinyxml2_FindElement(xml_root, + NULL, + "Key", + "algorithm", + XML_KEY_ALGORITHM_EC_STRING); + if (subroot == NULL) + return KM_ERROR_UNKNOWN_ERROR; + count = 0; + for (element = tinyxml2_FindElement(subroot, NULL, "Certificate", NULL, NULL); element; + element = tinyxml2_FindElement(subroot, element, "Certificate", NULL, NULL)) { + count++; + } + } else { + LOG_E("No matched key in keybox!", 0); + return KM_ERROR_UNKNOWN_ERROR; + } + + *cert_chain_len = count; + + return KM_ERROR_OK; +} + +keymaster_error_t get_cert_from_keybox(XMLElement* xml_root, + keymaster_algorithm_t algorithm, + uint32_t cert_index, + uint8_t** cert, + uint32_t* cert_size) { + XMLElement *subroot, *element; + char *base64data; + uint8_t *decodedata; + char *p, *pstart, *pend; + char *text; + size_t count; + + if ((cert == NULL) || (cert_size == NULL)) + return KM_ERROR_INVALID_ARGUMENT; + + if (xml_root == NULL) + return KM_ERROR_INVALID_ARGUMENT; + + if (algorithm == KM_ALGORITHM_RSA) + subroot = tinyxml2_FindElement(xml_root, NULL, "Key", "algorithm", XML_KEY_ALGORITHM_RSA_STRING); + else if (algorithm == KM_ALGORITHM_EC) + subroot = tinyxml2_FindElement(xml_root, NULL, "Key", "algorithm", XML_KEY_ALGORITHM_EC_STRING); + else { + LOG_E("No matched key in keybox!", 0); + return KM_ERROR_UNKNOWN_ERROR; + } + if (subroot == NULL) + return KM_ERROR_UNKNOWN_ERROR; + count = 0; + for (element = tinyxml2_FindElement(subroot, NULL, "Certificate", NULL, NULL); element; + element = tinyxml2_FindElement(subroot, element, "Certificate", NULL, NULL)) { + if (cert_index == count) + break; + else + count++; + } + if (element == NULL) + return KM_ERROR_UNKNOWN_ERROR; + text = (char *)element->GetText(); + if (text == NULL) + return KM_ERROR_UNKNOWN_ERROR; + count = strlen(text); + if ((p = strstr(text, "-----BEGIN CERTIFICATE-----")) == NULL) + return KM_ERROR_UNKNOWN_ERROR; + pstart = p + strlen("-----BEGIN CERTIFICATE-----"); + if ((pend = strstr(text, "-----END CERTIFICATE-----")) == NULL) + return KM_ERROR_UNKNOWN_ERROR; + base64data = new char[count]; + if (base64data == NULL) + return KM_ERROR_MEMORY_ALLOCATION_FAILED; + count = 0; + for (p = pstart; p < pend; p++) { + if (!isspace(*p)) + base64data[count++] = *p; + } + base64data[count] = 0x00; + + decodedata = new uint8_t[count]; + if (decodedata == NULL) + return KM_ERROR_MEMORY_ALLOCATION_FAILED; + if (!EVP_DecodeBase64(decodedata, (size_t *)&count, count, (const uint8_t *)base64data, strlen(base64data))) { + LOG_E("Failed to do base64 decode!", 0); + return KM_ERROR_UNKNOWN_ERROR; + } + *cert = decodedata; + *cert_size = count; + delete [] base64data; + + return KM_ERROR_OK; +} + +keymaster_error_t ParseKeyboxToStorage( + keymaster_algorithm_t algorithm, XMLElement* xml_root) { + keymaster_error_t error = KM_ERROR_OK; + AttestationKeySlot key_slot; + + switch (algorithm) { + case KM_ALGORITHM_RSA: + key_slot = AttestationKeySlot::kRsa; + break; + case KM_ALGORITHM_EC: + key_slot = AttestationKeySlot::kEcdsa; + break; + default: + return KM_ERROR_UNSUPPORTED_ALGORITHM; + } + + /* provision the private key to secure storage */ + uint8_t* attest_key = NULL; + uint32_t attest_keysize = 0; + error = get_prikey_from_keybox(xml_root, algorithm, &attest_key, &attest_keysize); + if (error != KM_ERROR_OK || !attest_key ||!attest_keysize) { + LOG_E("failed(%d) to get the prikey with algo(%d)", error, algorithm); + return KM_ERROR_UNKNOWN_ERROR; + } + bool exists; + error = AttestationKeyExists(key_slot, &exists); + if (error != KM_ERROR_OK) { + return KM_ERROR_UNKNOWN_ERROR; + } + error = WriteKeyToStorage(key_slot, attest_key, attest_keysize); + if (error != KM_ERROR_OK) { + LOG_E("failed(%d) to write pri_key into RPMB with algo(%d)", error, algorithm); + return KM_ERROR_UNKNOWN_ERROR; + } + + /* provision the cert chain into secure storage */ + uint32_t cert_chain_len = 0; + uint32_t index = 0; + error = get_cert_chain_len_from_keybox(xml_root, algorithm, &cert_chain_len); + if (error != KM_ERROR_OK) { + LOG_E("failed(%d) to get the cert_chain_len", error); + return KM_ERROR_UNKNOWN_ERROR; + } + /* write the certs one-by-one into securestorage */ + for (index = 0; index= kMaxCertChainLength) { + // Delete the cert chain when it hits max length + error = DeleteCertChain(key_slot); + if (error != KM_ERROR_OK) { + return error; + } + // Validate that cert chain was actually deleted + error = ReadCertChainLength(key_slot, &cert_chain_length); + if (error != KM_ERROR_OK) { + return error; + } + if (cert_chain_length != 0) { + LOG_E("Cert chain could not be deleted\n", 0); + return KM_ERROR_UNKNOWN_ERROR; + } + } + error = WriteCertToStorage(key_slot, cert, cert_size, cert_chain_length); + if (error != KM_ERROR_OK) { + LOG_E("failed(%d) to write the cert(%d) with algo(%d)", error, index, algorithm); + return KM_ERROR_UNKNOWN_ERROR; + } + } + + return KM_ERROR_OK; +} + +void ProvisionKeyboxOperation::ProvisionAttesationKeybox( + const ProvisionAttesationKeyboxRequest& request, + ProvisionAttesationKeyboxResponse* response) { + if (response == nullptr) + return; + + uint32_t keybox_size = request.keybox_data.buffer_size(); + const uint8_t* keybox = request.keybox_data.begin(); + + /* if keybox is NULL, it means need to retrieve it from the CSE by HECI */ + if (keybox == NULL) { + response->error = RetrieveKeybox((uint8_t**)&keybox, &keybox_size); + if(response->error != KM_ERROR_OK ||!keybox || !keybox_size) { + LOG_E("failed(%d) to RetrieveKeybox from CSE", response->error); + return; + } + } + + XMLElement* xml_root = NULL; + response->error = keybox_xml_initialize(keybox, &xml_root); + if (response->error != KM_ERROR_OK || !xml_root) { + LOG_E("failed(%d) to initialize the keybox", response->error); + return; + } + + response->error = ParseKeyboxToStorage(KM_ALGORITHM_RSA, xml_root); + if(response->error != KM_ERROR_OK) { + LOG_E("failed(%d) to parse the keybox wih KM_ALGORITHM_RSA", response->error); + return; + } + + response->error = ParseKeyboxToStorage(KM_ALGORITHM_EC, xml_root); + if(response->error != KM_ERROR_OK) { + LOG_E("failed(%d) to parse the keybox with KM_ALGORITHM_EC", response->error); + return; + } + + response->error = KM_ERROR_OK; +} + +} // namespace keymaster diff --git a/provision/provision_keybox.h b/provision/provision_keybox.h new file mode 100644 index 0000000..2652134 --- /dev/null +++ b/provision/provision_keybox.h @@ -0,0 +1,60 @@ +/* +** +** Copyright 2018, The Android Open Source Project +** Copyright (C) 2018 Intel Corporation +** +** 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 INCLUDE_PROVISION_ATTESTATION_KEYBOX__H_ +#define INCLUDE_PROVISION_ATTESTATION_KEYBOX__H_ + +#include +#include + +namespace keymaster { + +struct ProvisionAttesationKeyboxRequest : public KeymasterMessage { + explicit ProvisionAttesationKeyboxRequest + (int32_t ver = MAX_MESSAGE_VERSION) : KeymasterMessage(ver) {} + + size_t SerializedSize() const override { + return keybox_data.SerializedSize(); + } + uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override { + return keybox_data.Serialize(buf, end); + } + bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override { + return keybox_data.Deserialize(buf_ptr, end); + } + + Buffer keybox_data; +}; + +struct ProvisionAttesationKeyboxResponse : public NoResponse {}; + + +class ProvisionKeyboxOperation { +public: + // ProvisionAttesationKeybox can only be called from bootloader + // it used to provision the keybox into RPMB storage + // the original keybox will be retrieved from CSE + void ProvisionAttesationKeybox( + const ProvisionAttesationKeyboxRequest& request, + ProvisionAttesationKeyboxResponse* response); +}; + +} // namespace keymaster + +#endif // INCLUDE_PROVISION_ATTESTATION_KEYBOX__H_ + diff --git a/provision/rules.mk b/provision/rules.mk new file mode 100644 index 0000000..4d51993 --- /dev/null +++ b/provision/rules.mk @@ -0,0 +1,22 @@ +# Copyright (C) 2018 The Android Open Source Project +# Copyright (C) 2018 Intel Corporation +# +# 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. +# +CUR_DIR := $(GET_LOCAL_DIR) + +MODULE_SRCS += $(CUR_DIR)/provision_keybox.cpp + +MODULE_DEPS += interface/keymaster + +CUR_DIR = diff --git a/rules.mk b/rules.mk index 2ab3542..78bfce0 100644 --- a/rules.mk +++ b/rules.mk @@ -88,5 +88,6 @@ MODULE_DEPS += \ include $(LOCAL_DIR)/atap/rules.mk include $(LOCAL_DIR)/ipc/rules.mk +include $(LOCAL_DIR)/provision/rules.mk include make/module.mk diff --git a/trusty_keymaster.h b/trusty_keymaster.h index af82731..d000965 100644 --- a/trusty_keymaster.h +++ b/trusty_keymaster.h @@ -21,6 +21,7 @@ #include "trusty_keymaster_context.h" #include "trusty_keymaster_messages.h" +#include "provision/provision_keybox.h" #ifndef DISABLE_ATAP_SUPPORT #include "atap/trusty_atap_ops.h" #include "ops/atap_ops_provider.h" @@ -32,7 +33,8 @@ namespace keymaster { // implemented by AndroidKeymaster but some operations which are not part of the // interface with Android are implemented here. These operations are expected to // be called from a bootloader or another Trusty application. -class TrustyKeymaster : public AndroidKeymaster { +class TrustyKeymaster : public AndroidKeymaster, + public ProvisionKeyboxOperation { public: TrustyKeymaster(TrustyKeymasterContext* context, size_t operation_table_size) From d2ca315dd58d73d9a333a35d0472b1190664e9bb Mon Sep 17 00:00:00 2001 From: "Yan, Shaopu" Date: Wed, 19 Sep 2018 18:22:03 +0800 Subject: [PATCH 2/3] fix the memory leak issue in GenerateAttestation change the return type to CertChainPtr, which will help to release the memory, or it will have memory leak issue Test: testEcAttestation testRsaAttestation Bug: 116169953 Change-Id: I963ec719c5d5ef274cd4d0ecb4a738c43fae6278 Tracked-On: https://jira01.devtools.intel.com/browse/OAM-69557 Signed-off-by: Yan, Shaopu Reviewed-on: https://android.intel.com/646434 Reviewed-by: Wang, Kai Z --- trusty_keymaster_context.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/trusty_keymaster_context.cpp b/trusty_keymaster_context.cpp index 6ee8826..7990272 100644 --- a/trusty_keymaster_context.cpp +++ b/trusty_keymaster_context.cpp @@ -573,10 +573,9 @@ KeymasterKeyBlob AttestationKey(keymaster_algorithm_t algorithm, return result; } -keymaster_cert_chain_t* AttestationChain(keymaster_algorithm_t algorithm, +CertChainPtr AttestationChain(keymaster_algorithm_t algorithm, keymaster_error_t* error) { - UniquePtr chain( - new keymaster_cert_chain_t); + CertChainPtr chain(new keymaster_cert_chain_t); if (!chain.get()) { *error = KM_ERROR_MEMORY_ALLOCATION_FAILED; return nullptr; @@ -603,7 +602,7 @@ keymaster_cert_chain_t* AttestationChain(keymaster_algorithm_t algorithm, } if (*error != KM_ERROR_OK) return nullptr; - return chain.release(); + return chain; } keymaster_error_t TrustyKeymasterContext::GenerateAttestation( From e9eadac8996acb4f71933d8df1637a0a83e2488d Mon Sep 17 00:00:00 2001 From: "Yan, Shaopu" Date: Thu, 20 Sep 2018 17:28:23 +0800 Subject: [PATCH 3/3] make the app/keymaster build pass Change-Id: If44674dc6652580c37b7074d68543dfeeaa7c69c Tracked-On: https://jira01.devtools.intel.com/browse/OAM-69557 Signed-off-by: Yan, Shaopu Reviewed-on: https://android.intel.com/646244 Reviewed-by: Wang, Kai Z --- ipc/keymaster_ipc.cpp | 2 ++ ipc/rules.mk | 2 +- rules.mk | 23 ++++++++++++++--------- secure_storage.cpp | 4 ++-- trusty_keymaster_enforcement.cpp | 2 +- 5 files changed, 20 insertions(+), 13 deletions(-) diff --git a/ipc/keymaster_ipc.cpp b/ipc/keymaster_ipc.cpp index f273d81..95d2d17 100644 --- a/ipc/keymaster_ipc.cpp +++ b/ipc/keymaster_ipc.cpp @@ -29,6 +29,8 @@ #include "trusty_keymaster.h" #include "trusty_logger.h" +#include +#include using namespace keymaster; diff --git a/ipc/rules.mk b/ipc/rules.mk index a8226e6..a74428d 100644 --- a/ipc/rules.mk +++ b/ipc/rules.mk @@ -17,6 +17,6 @@ CUR_DIR := $(GET_LOCAL_DIR) MODULE_SRCS += $(CUR_DIR)/keymaster_ipc.cpp -MODULE_DEPS += trusty/user/base/interface/keymaster +MODULE_DEPS += interface/keymaster CUR_DIR = diff --git a/rules.mk b/rules.mk index 78bfce0..96bd8d1 100644 --- a/rules.mk +++ b/rules.mk @@ -17,7 +17,8 @@ LOCAL_DIR := $(GET_LOCAL_DIR) MODULE := $(LOCAL_DIR) -KEYMASTER_ROOT := $(TRUSTY_TOP)/system/keymaster +ANDROID_ROOT := $(LOCAL_DIR)/../../.. +KEYMASTER_ROOT := $(ANDROID_ROOT)/system/keymaster MODULE_SRCS += \ $(KEYMASTER_ROOT)/android_keymaster/android_keymaster.cpp \ @@ -65,7 +66,7 @@ MODULE_SRCS += \ MODULE_INCLUDES := \ $(KEYMASTER_ROOT)/include \ $(KEYMASTER_ROOT) \ - $(TRUSTY_TOP)/hardware/libhardware/include \ + $(ANDROID_ROOT)/hardware/libhardware/include \ $(LOCAL_DIR) MODULE_CPPFLAGS := -std=c++14 -fno-short-enums @@ -77,16 +78,20 @@ MODULE_COMPILEFLAGS := -U__ANDROID__ -D__TRUSTY__ # trust from bootloader. # #MODULE_COMPILEFLAGS += -DKEYMASTER_DEBUG +MODULE_COMPILEFLAGS += -DDISABLE_ATAP_SUPPORT MODULE_DEPS += \ - trusty/user/base/lib/libc-trusty \ - trusty/user/base/lib/libstdc++-trusty \ - trusty/user/base/lib/rng \ - trusty/user/base/lib/hwkey \ - trusty/user/base/lib/storage \ - external/boringssl \ + app/trusty \ + lib/libc-trusty \ + lib/libstdc++-trusty \ + lib/rng \ + lib/storage \ + lib/hwkey \ + lib/tinyxml2 \ + lib/lzma \ + lib/trusty_syscall_x86 -include $(LOCAL_DIR)/atap/rules.mk +#include $(LOCAL_DIR)/atap/rules.mk include $(LOCAL_DIR)/ipc/rules.mk include $(LOCAL_DIR)/provision/rules.mk diff --git a/secure_storage.cpp b/secure_storage.cpp index 2ceb57b..6ce5606 100644 --- a/secure_storage.cpp +++ b/secure_storage.cpp @@ -291,7 +291,7 @@ keymaster_error_t ReadCertChainFromStorage(AttestationKeySlot key_slot, sizeof(cert_chain->entries[0]) * cert_chain_length); // Read |cert_chain_length| certs from storage - for (size_t i = 0; i < cert_chain_length; i++) { + for (uint32_t i = 0; i < cert_chain_length; i++) { snprintf(cert_file.get(), kStorageIdLengthMax, "%s.%s.%d", kAttestCertPrefix, GetKeySlotStr(key_slot), i); if (!SecureStorageGetFileSize(cert_file.get(), &cert_size) || @@ -401,7 +401,7 @@ keymaster_error_t DeleteCertChain(AttestationKeySlot key_slot) { if (ReadCertChainLength(key_slot, &cert_chain_length) != KM_ERROR_OK) { return KM_ERROR_UNKNOWN_ERROR; } - for (size_t i = 0; i < cert_chain_length; ++i) { + for (uint32_t i = 0; i < cert_chain_length; ++i) { snprintf(cert_file.get(), kStorageIdLengthMax, "%s.%s.%d", kAttestCertPrefix, GetKeySlotStr(key_slot), i); if (!SecureStorageDeleteFile(cert_file.get())) { diff --git a/trusty_keymaster_enforcement.cpp b/trusty_keymaster_enforcement.cpp index 6560132..77c1df9 100644 --- a/trusty_keymaster_enforcement.cpp +++ b/trusty_keymaster_enforcement.cpp @@ -23,7 +23,7 @@ #include #include "trusty_keymaster_context.h" - +#include namespace keymaster { keymaster_security_level_t TrustyKeymasterEnforcement::SecurityLevel() const {