diff options
author | Shawn Willden <swillden@google.com> | 2022-05-27 12:48:25 -0600 |
---|---|---|
committer | Shawn Willden <swillden@google.com> | 2022-06-02 07:46:13 -0600 |
commit | fdeafb864cefd667ef85be50fdfa863339046791 (patch) | |
tree | 4c53d5085f6633bd4c7d3520b3a78420630b6ef7 | |
parent | 415260e22f4ee4827a10d3204b8f3438e22ea789 (diff) | |
download | keymaster-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.cpp | 60 | ||||
-rw-r--r-- | include/keymaster/android_keymaster.h | 1 | ||||
-rw-r--r-- | include/keymaster/android_keymaster_messages.h | 36 | ||||
-rw-r--r-- | include/keymaster/cppcose/cppcose.h | 2 | ||||
-rw-r--r-- | include/keymaster/keymaster_context.h | 7 | ||||
-rw-r--r-- | include/keymaster/keymaster_enforcement.h | 13 | ||||
-rw-r--r-- | include/keymaster/keymaster_utils.h | 5 | ||||
-rw-r--r-- | tests/android_keymaster_messages_test.cpp | 23 |
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 |