summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShawn Willden <swillden@google.com>2022-05-27 12:48:25 -0600
committerShawn Willden <swillden@google.com>2022-06-02 07:46:13 -0600
commitfdeafb864cefd667ef85be50fdfa863339046791 (patch)
tree4c53d5085f6633bd4c7d3520b3a78420630b6ef7
parent415260e22f4ee4827a10d3204b8f3438e22ea789 (diff)
downloadkeymaster-fdeafb864cefd667ef85be50fdfa863339046791.tar.gz
Implement alternate SE root-of-trust provisioning.
Bug: 219076736 Test: VtsAidlKeyMintTargetTest Ignore-AOSP-First: Cherry pick from AOSP Change-Id: I28c13d9b201b831a1d339d5dd9d7bb8c2b176f59
-rw-r--r--android_keymaster/android_keymaster.cpp60
-rw-r--r--include/keymaster/android_keymaster.h1
-rw-r--r--include/keymaster/android_keymaster_messages.h36
-rw-r--r--include/keymaster/cppcose/cppcose.h2
-rw-r--r--include/keymaster/keymaster_context.h7
-rw-r--r--include/keymaster/keymaster_enforcement.h13
-rw-r--r--include/keymaster/keymaster_utils.h5
-rw-r--r--tests/android_keymaster_messages_test.cpp23
8 files changed, 144 insertions, 3 deletions
diff --git a/android_keymaster/android_keymaster.cpp b/android_keymaster/android_keymaster.cpp
index 30e5505..828dead 100644
--- a/android_keymaster/android_keymaster.cpp
+++ b/android_keymaster/android_keymaster.cpp
@@ -28,6 +28,7 @@
#include <keymaster/UniquePtr.h>
#include <keymaster/android_keymaster_utils.h>
+#include <keymaster/attestation_context.h>
#include <keymaster/cppcose/cppcose.h>
#include <keymaster/key.h>
#include <keymaster/key_blob_utils/ae.h>
@@ -128,7 +129,12 @@ cppcose::HmacSha256Function getMacFunction(bool test_mode,
};
}
+std::pair<const uint8_t*, size_t> blob2Pair(const keymaster_blob_t& blob) {
+ return {blob.data, blob.data_length};
+}
+
constexpr int kP256AffinePointSize = 32;
+constexpr int kRoTVersion1 = 40001;
} // anonymous namespace
@@ -932,4 +938,58 @@ DeviceLockedResponse AndroidKeymaster::DeviceLocked(const DeviceLockedRequest& r
return response;
}
+GetRootOfTrustResponse AndroidKeymaster::GetRootOfTrust(const GetRootOfTrustRequest& request) {
+ GetRootOfTrustResponse response(message_version());
+
+ if (!context_->attestation_context()) {
+ response.error = KM_ERROR_UNIMPLEMENTED;
+ return response;
+ }
+
+ const AttestationContext::VerifiedBootParams* vbParams =
+ context_->attestation_context()->GetVerifiedBootParams(&response.error);
+ if (response.error != KM_ERROR_OK) return response;
+
+ auto boot_patch_level = context_->GetBootPatchlevel();
+ if (!boot_patch_level) {
+ response.error = KM_ERROR_UNIMPLEMENTED;
+ return response;
+ }
+
+ if (!context_->enforcement_policy()) {
+ response.error = KM_ERROR_UNIMPLEMENTED;
+ return response;
+ }
+
+ auto macFunction =
+ [&](const std::vector<uint8_t>& data) -> cppcose::ErrMsgOr<cppcose::HmacSha256> {
+ auto mac = context_->enforcement_policy()->ComputeHmac(data);
+ if (!mac) return "Failed to compute HMAC";
+ return *std::move(mac);
+ };
+
+ auto maced_root_of_trust = cppcose::constructCoseMac0(
+ macFunction, //
+ request.challenge,
+ cppbor::SemanticTag(kRoTVersion1, cppbor::Array( //
+ blob2Pair(vbParams->verified_boot_key), //
+ vbParams->device_locked, //
+ vbParams->verified_boot_state, //
+ blob2Pair(vbParams->verified_boot_hash), //
+ *boot_patch_level))
+ .encode());
+
+ if (!maced_root_of_trust) {
+ LOG_E("Error MACing RoT: %s", maced_root_of_trust.message().c_str());
+ response.error = KM_ERROR_UNKNOWN_ERROR;
+ } else {
+ response.error = KM_ERROR_OK;
+ response.rootOfTrust =
+ cppbor::SemanticTag(cppcose::kCoseMac0SemanticTag, *std::move(maced_root_of_trust))
+ .encode();
+ }
+
+ return response;
+}
+
} // namespace keymaster
diff --git a/include/keymaster/android_keymaster.h b/include/keymaster/android_keymaster.h
index d8033b4..6c3acc5 100644
--- a/include/keymaster/android_keymaster.h
+++ b/include/keymaster/android_keymaster.h
@@ -99,6 +99,7 @@ class AndroidKeymaster {
ConfigureBootPatchlevel(const ConfigureBootPatchlevelRequest& request);
ConfigureVerifiedBootInfoResponse
ConfigureVerifiedBootInfo(const ConfigureVerifiedBootInfoRequest& request);
+ GetRootOfTrustResponse GetRootOfTrust(const GetRootOfTrustRequest& request);
bool has_operation(keymaster_operation_handle_t op_handle) const;
diff --git a/include/keymaster/android_keymaster_messages.h b/include/keymaster/android_keymaster_messages.h
index 7d43043..6e38860 100644
--- a/include/keymaster/android_keymaster_messages.h
+++ b/include/keymaster/android_keymaster_messages.h
@@ -68,6 +68,7 @@ enum AndroidKeymasterCommand : uint32_t {
CONFIGURE_VENDOR_PATCHLEVEL = 32,
CONFIGURE_BOOT_PATCHLEVEL = 33,
CONFIGURE_VERIFIED_BOOT_INFO = 34,
+ GET_ROOT_OF_TRUST = 35,
};
/**
@@ -838,7 +839,8 @@ struct ComputeSharedHmacRequest : public KeymasterMessage {
struct ComputeSharedHmacResponse : public KeymasterResponse {
explicit ComputeSharedHmacResponse(int32_t ver) : KeymasterResponse(ver) {}
- ComputeSharedHmacResponse(ComputeSharedHmacResponse&& other) : KeymasterResponse(move(other)) {
+ ComputeSharedHmacResponse(ComputeSharedHmacResponse&& other)
+ : KeymasterResponse(other.message_version) {
sharing_check = move(other.sharing_check);
}
@@ -1215,4 +1217,36 @@ struct ConfigureVerifiedBootInfoRequest : public KeymasterMessage {
using ConfigureVerifiedBootInfoResponse = EmptyKeymasterResponse;
+struct GetRootOfTrustRequest : public KeymasterMessage {
+ explicit GetRootOfTrustRequest(int32_t ver) : GetRootOfTrustRequest(ver, {}) {}
+ GetRootOfTrustRequest(int32_t ver, std::vector<uint8_t> challenge_param)
+ : KeymasterMessage(ver), challenge(std::move(challenge_param)){};
+
+ size_t SerializedSize() const override { return sizeof(uint32_t) + challenge.size(); }
+ uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override {
+ return append_collection_to_buf(buf, end, challenge);
+ }
+ bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override {
+ return copy_collection_from_buf(buf_ptr, end, &challenge);
+ }
+
+ std::vector<uint8_t> challenge;
+};
+
+struct GetRootOfTrustResponse : public KeymasterResponse {
+ explicit GetRootOfTrustResponse(uint32_t ver) : GetRootOfTrustResponse(ver, {}) {}
+ GetRootOfTrustResponse(uint32_t ver, std::vector<uint8_t> rootOfTrust_param)
+ : KeymasterResponse(ver), rootOfTrust(std::move(rootOfTrust_param)){};
+
+ size_t NonErrorSerializedSize() const override { return sizeof(uint32_t) + rootOfTrust.size(); }
+ uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t* end) const override {
+ return append_collection_to_buf(buf, end, rootOfTrust);
+ }
+ bool NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end) override {
+ return copy_collection_from_buf(buf_ptr, end, &rootOfTrust);
+ }
+
+ std::vector<uint8_t> rootOfTrust;
+};
+
} // namespace keymaster
diff --git a/include/keymaster/cppcose/cppcose.h b/include/keymaster/cppcose/cppcose.h
index 5803d2d..c000ebe 100644
--- a/include/keymaster/cppcose/cppcose.h
+++ b/include/keymaster/cppcose/cppcose.h
@@ -66,6 +66,8 @@ constexpr int kCoseEncryptUnprotectedParams = 1;
constexpr int kCoseEncryptPayload = 2;
constexpr int kCoseEncryptRecipients = 3;
+constexpr int kCoseMac0SemanticTag = 17;
+
enum Label : int {
ALGORITHM = 1,
KEY_ID = 4,
diff --git a/include/keymaster/keymaster_context.h b/include/keymaster/keymaster_context.h
index 052ccf2..8c4bb57 100644
--- a/include/keymaster/keymaster_context.h
+++ b/include/keymaster/keymaster_context.h
@@ -23,6 +23,7 @@
#include <assert.h>
#include <hardware/keymaster_defs.h>
+
#include <keymaster/android_keymaster_utils.h>
#include <keymaster/keymaster_enforcement.h>
#include <keymaster/km_version.h>
@@ -32,6 +33,7 @@
namespace keymaster {
class AuthorizationSet;
+class AttestationContext;
class KeyFactory;
class OperationFactory;
class SecureDeletionSecretStorage;
@@ -151,6 +153,11 @@ class KeymasterContext {
virtual KeymasterEnforcement* enforcement_policy() = 0;
/**
+ * Return the attestation context for this context.
+ */
+ virtual AttestationContext* attestation_context() { return nullptr; }
+
+ /**
* Generate an attestation certificate, with chain.
*
* If attest_key is null, the certificate will be signed with the factory attestation key (from
diff --git a/include/keymaster/keymaster_enforcement.h b/include/keymaster/keymaster_enforcement.h
index 1d783ba..5400d8f 100644
--- a/include/keymaster/keymaster_enforcement.h
+++ b/include/keymaster/keymaster_enforcement.h
@@ -17,10 +17,13 @@
#ifndef ANDROID_LIBRARY_KEYMASTER_ENFORCEMENT_H
#define ANDROID_LIBRARY_KEYMASTER_ENFORCEMENT_H
+#include <array>
+
#include <stdio.h>
#include <keymaster/android_keymaster_messages.h>
#include <keymaster/authorization_set.h>
+#include <keymaster/keymaster_utils.h>
namespace keymaster {
@@ -181,6 +184,16 @@ class KeymasterEnforcement {
virtual keymaster_error_t GenerateTimestampToken(TimestampToken* token);
/**
+ * Compute an HMAC using the auth token HMAC key.
+ *
+ * Note: Use with caution. MACed data must contain enough structure that it's unambiguous.
+ */
+ virtual KmErrorOr<std::array<uint8_t, 32>>
+ ComputeHmac(const std::vector<uint8_t>& /* data_to_mac */) const {
+ return KM_ERROR_UNIMPLEMENTED;
+ }
+
+ /**
* Creates a key ID for use in subsequent calls to AuthorizeOperation. AndroidKeymaster
* uses this method for creating key IDs. The generated id must be stable in that the same
* key_blob bits yield the same keyid.
diff --git a/include/keymaster/keymaster_utils.h b/include/keymaster/keymaster_utils.h
index 1cfc756..8154c71 100644
--- a/include/keymaster/keymaster_utils.h
+++ b/include/keymaster/keymaster_utils.h
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#pragma once
+
#include <optional>
#include <keymaster/logger.h>
@@ -88,8 +90,7 @@ template <typename T> class KmErrorOr {
T& operator*() & { return value_.value(); }
const T& operator*() const& { return value_.value(); }
- T&& operator*() && { return value_.value(); }
- const T&& operator*() const&& { return value_.value(); }
+ T&& operator*() && { return std::move(value_).value(); }
private:
keymaster_error_t error_ = KM_ERROR_OK;
diff --git a/tests/android_keymaster_messages_test.cpp b/tests/android_keymaster_messages_test.cpp
index db4c7b0..6b873b4 100644
--- a/tests/android_keymaster_messages_test.cpp
+++ b/tests/android_keymaster_messages_test.cpp
@@ -846,6 +846,27 @@ TEST(RoundTrip, GenerateTimestampTokenResponse) {
}
}
+TEST(RoundTrip, GetRootOfTrustRequest) {
+ for (int ver = 0; ver <= kMaxMessageVersion; ++ver) {
+ std::vector<uint8_t> challenge{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
+ GetRootOfTrustRequest msg(ver, challenge);
+
+ UniquePtr<GetRootOfTrustRequest> deserialized(round_trip(ver, msg, 20));
+ EXPECT_EQ(deserialized->challenge, challenge);
+ }
+}
+
+TEST(RoundTrip, GetRootOfTrustResponse) {
+ for (int ver = 0; ver <= kMaxMessageVersion; ++ver) {
+ std::vector<uint8_t> rootOfTrust{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
+ GetRootOfTrustResponse msg(ver, rootOfTrust);
+ msg.error = KM_ERROR_OK;
+
+ UniquePtr<GetRootOfTrustResponse> deserialized(round_trip(ver, msg, 24));
+ EXPECT_EQ(deserialized->rootOfTrust, rootOfTrust);
+ }
+}
+
#define SET_ATTESTATION_ID(x) msg.x.Reinitialize(#x, strlen(#x))
void check_id(const Buffer& id, const char* value) {
@@ -974,6 +995,8 @@ GARBAGE_TEST(GenerateTimestampTokenRequest);
GARBAGE_TEST(GenerateTimestampTokenResponse);
GARBAGE_TEST(SetAttestationIdsRequest);
GARBAGE_TEST(ConfigureVerifiedBootInfoRequest);
+GARBAGE_TEST(GetRootOfTrustRequest);
+GARBAGE_TEST(GetRootOfTrustResponse);
} // namespace test