trusty: keymaster: Implement attest_key
Test: builds
Change-Id: Ic5bf59db43b4301cbc2fa216470b9f07de8336b0
diff --git a/trusty/keymaster/keymaster_ipc.h b/trusty/keymaster/keymaster_ipc.h
index f970e36..6a7378c 100644
--- a/trusty/keymaster/keymaster_ipc.h
+++ b/trusty/keymaster/keymaster_ipc.h
@@ -42,6 +42,7 @@
KM_GET_SUPPORTED_IMPORT_FORMATS = (13 << KEYMASTER_REQ_SHIFT),
KM_GET_SUPPORTED_EXPORT_FORMATS = (14 << KEYMASTER_REQ_SHIFT),
KM_GET_KEY_CHARACTERISTICS = (15 << KEYMASTER_REQ_SHIFT),
+ KM_ATTEST_KEY = (16 << KEYMASTER_REQ_SHIFT),
KM_CONFIGURE = (18 << KEYMASTER_REQ_SHIFT),
};
diff --git a/trusty/keymaster/trusty_keymaster_device.cpp b/trusty/keymaster/trusty_keymaster_device.cpp
index 3610456..08a1c6a 100644
--- a/trusty/keymaster/trusty_keymaster_device.cpp
+++ b/trusty/keymaster/trusty_keymaster_device.cpp
@@ -39,6 +39,8 @@
const uint32_t RECV_BUF_SIZE = PAGE_SIZE;
const uint32_t SEND_BUF_SIZE = (PAGE_SIZE - sizeof(struct keymaster_message) - 16 /* tipc header */);
+const size_t kMaximumAttestationChallengeLength = 128;
+
namespace keymaster {
static keymaster_error_t translate_error(int err) {
@@ -361,6 +363,62 @@
const keymaster_key_param_set_t* attest_params,
keymaster_cert_chain_t* cert_chain) {
ALOGD("Device received attest_key");
+
+ if (error_ != KM_ERROR_OK) {
+ return error_;
+ }
+ if (!key_to_attest || !attest_params) {
+ return KM_ERROR_UNEXPECTED_NULL_POINTER;
+ }
+ if (!cert_chain) {
+ return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ }
+
+ cert_chain->entry_count = 0;
+ cert_chain->entries = nullptr;
+
+ AttestKeyRequest request;
+ request.SetKeyMaterial(*key_to_attest);
+ request.attest_params.Reinitialize(*attest_params);
+
+ keymaster_blob_t attestation_challenge = {};
+ request.attest_params.GetTagValue(TAG_ATTESTATION_CHALLENGE, &attestation_challenge);
+ if (attestation_challenge.data_length > kMaximumAttestationChallengeLength) {
+ ALOGE("%zu-byte attestation challenge; only %zu bytes allowed",
+ attestation_challenge.data_length, kMaximumAttestationChallengeLength);
+ return KM_ERROR_INVALID_INPUT_LENGTH;
+ }
+
+ AttestKeyResponse response;
+ keymaster_error_t err = Send(KM_ATTEST_KEY, request, &response);
+ if (err != KM_ERROR_OK) {
+ return err;
+ }
+
+ // Allocate and clear storage for cert_chain.
+ keymaster_cert_chain_t& rsp_chain = response.certificate_chain;
+ cert_chain->entries = reinterpret_cast<keymaster_blob_t*>(
+ malloc(rsp_chain.entry_count * sizeof(*cert_chain->entries)));
+ if (!cert_chain->entries) {
+ return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
+ cert_chain->entry_count = rsp_chain.entry_count;
+ for (keymaster_blob_t& entry : array_range(cert_chain->entries, cert_chain->entry_count)) {
+ entry = {};
+ }
+
+ // Copy cert_chain contents
+ size_t i = 0;
+ for (keymaster_blob_t& entry : array_range(rsp_chain.entries, rsp_chain.entry_count)) {
+ cert_chain->entries[i].data = DuplicateBuffer(entry.data, entry.data_length);
+ if (!cert_chain->entries[i].data) {
+ keymaster_free_cert_chain(cert_chain);
+ return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ }
+ cert_chain->entries[i].data_length = entry.data_length;
+ ++i;
+ }
+
return KM_ERROR_OK;
}