diff options
-rw-r--r-- | android_keymaster/android_keymaster.cpp | 8 | ||||
-rw-r--r-- | android_keymaster/serializable.cpp | 13 | ||||
-rw-r--r-- | contexts/pure_soft_keymaster_context.cpp | 52 | ||||
-rw-r--r-- | contexts/pure_soft_remote_provisioning_context.cpp | 71 | ||||
-rw-r--r-- | include/keymaster/android_keymaster.h | 2 | ||||
-rw-r--r-- | include/keymaster/android_keymaster_messages.h | 37 | ||||
-rw-r--r-- | include/keymaster/contexts/pure_soft_keymaster_context.h | 28 | ||||
-rw-r--r-- | include/keymaster/contexts/pure_soft_remote_provisioning_context.h | 22 | ||||
-rw-r--r-- | include/keymaster/keymaster_context.h | 13 | ||||
-rw-r--r-- | include/keymaster/logger.h | 16 | ||||
-rw-r--r-- | include/keymaster/serializable.h | 51 | ||||
-rw-r--r-- | ng/AndroidKeyMintDevice.cpp | 8 | ||||
-rw-r--r-- | tests/android_keymaster_messages_test.cpp | 20 |
13 files changed, 293 insertions, 48 deletions
diff --git a/android_keymaster/android_keymaster.cpp b/android_keymaster/android_keymaster.cpp index 14fc367..8f57608 100644 --- a/android_keymaster/android_keymaster.cpp +++ b/android_keymaster/android_keymaster.cpp @@ -828,6 +828,14 @@ AndroidKeymaster::ConfigureBootPatchlevel(const ConfigureBootPatchlevelRequest& return rsp; } +ConfigureVerifiedBootInfoResponse +AndroidKeymaster::ConfigureVerifiedBootInfo(const ConfigureVerifiedBootInfoRequest& request) { + ConfigureVerifiedBootInfoResponse rsp(message_version()); + rsp.error = context_->SetVerifiedBootInfo(request.boot_state, request.bootloader_state, + request.vbmeta_digest); + return rsp; +} + bool AndroidKeymaster::has_operation(keymaster_operation_handle_t op_handle) const { return operation_table_->Find(op_handle) != nullptr; } diff --git a/android_keymaster/serializable.cpp b/android_keymaster/serializable.cpp index fe0d742..94b2eea 100644 --- a/android_keymaster/serializable.cpp +++ b/android_keymaster/serializable.cpp @@ -22,19 +22,14 @@ namespace keymaster { -namespace { - -/* Performs an overflow-checked bounds check */ -bool buffer_bound_check(const uint8_t* buf, const uint8_t* end, size_t len) { +bool __buffer_bound_check(const uint8_t* buf, const uint8_t* end, size_t len) { uintptr_t buf_next; bool overflow_occurred = __builtin_add_overflow(__pval(buf), len, &buf_next); return (!overflow_occurred) && (buf_next <= __pval(end)); } -} // namespace - uint8_t* append_to_buf(uint8_t* buf, const uint8_t* end, const void* data, size_t data_len) { - if (buffer_bound_check(buf, end, data_len)) { + if (__buffer_bound_check(buf, end, data_len)) { memcpy(buf, data, data_len); return buf + data_len; } else { @@ -43,7 +38,7 @@ uint8_t* append_to_buf(uint8_t* buf, const uint8_t* end, const void* data, size_ } bool copy_from_buf(const uint8_t** buf_ptr, const uint8_t* end, void* dest, size_t size) { - if (buffer_bound_check(*buf_ptr, end, size)) { + if (__buffer_bound_check(*buf_ptr, end, size)) { memcpy(dest, *buf_ptr, size); *buf_ptr += size; return true; @@ -61,7 +56,7 @@ bool copy_size_and_data_from_buf(const uint8_t** buf_ptr, const uint8_t* end, si return true; } - if (buffer_bound_check(*buf_ptr, end, *size)) { + if (__buffer_bound_check(*buf_ptr, end, *size)) { dest->reset(new (std::nothrow) uint8_t[*size]); if (!dest->get()) { return false; diff --git a/contexts/pure_soft_keymaster_context.cpp b/contexts/pure_soft_keymaster_context.cpp index 292d5a0..e9d8245 100644 --- a/contexts/pure_soft_keymaster_context.cpp +++ b/contexts/pure_soft_keymaster_context.cpp @@ -68,7 +68,7 @@ PureSoftKeymasterContext::PureSoftKeymasterContext(KmVersion version, } if (version >= KmVersion::KEYMINT_1) { pure_soft_remote_provisioning_context_ = - std::make_unique<PureSoftRemoteProvisioningContext>(); + std::make_unique<PureSoftRemoteProvisioningContext>(security_level_); } } @@ -78,6 +78,9 @@ keymaster_error_t PureSoftKeymasterContext::SetSystemVersion(uint32_t os_version uint32_t os_patchlevel) { os_version_ = os_version; os_patchlevel_ = os_patchlevel; + if (pure_soft_remote_provisioning_context_ != nullptr) { + pure_soft_remote_provisioning_context_->SetSystemVersion(os_version, os_patchlevel); + } return KM_ERROR_OK; } @@ -87,6 +90,53 @@ void PureSoftKeymasterContext::GetSystemVersion(uint32_t* os_version, *os_patchlevel = os_patchlevel_; } +keymaster_error_t +PureSoftKeymasterContext::SetVerifiedBootInfo(std::string_view boot_state, + std::string_view bootloader_state, + const std::vector<uint8_t>& vbmeta_digest) { + if (verified_boot_state_.has_value() && boot_state != verified_boot_state_.value()) { + return KM_ERROR_INVALID_ARGUMENT; + } + if (bootloader_state_.has_value() && bootloader_state != bootloader_state_.value()) { + return KM_ERROR_INVALID_ARGUMENT; + } + if (vbmeta_digest_.has_value() && vbmeta_digest != vbmeta_digest_.value()) { + return KM_ERROR_INVALID_ARGUMENT; + } + verified_boot_state_ = boot_state; + bootloader_state_ = bootloader_state; + vbmeta_digest_ = vbmeta_digest; + if (pure_soft_remote_provisioning_context_ != nullptr) { + pure_soft_remote_provisioning_context_->SetVerifiedBootInfo(boot_state, bootloader_state, + vbmeta_digest); + } + return KM_ERROR_OK; +} + +keymaster_error_t PureSoftKeymasterContext::SetVendorPatchlevel(uint32_t vendor_patchlevel) { + if (vendor_patchlevel_.has_value() && vendor_patchlevel != vendor_patchlevel_.value()) { + // Can't set patchlevel to a different value. + return KM_ERROR_INVALID_ARGUMENT; + } + vendor_patchlevel_ = vendor_patchlevel; + if (pure_soft_remote_provisioning_context_ != nullptr) { + pure_soft_remote_provisioning_context_->SetVendorPatchlevel(vendor_patchlevel); + } + return KM_ERROR_OK; +} + +keymaster_error_t PureSoftKeymasterContext::SetBootPatchlevel(uint32_t boot_patchlevel) { + if (boot_patchlevel_.has_value() && boot_patchlevel != boot_patchlevel_.value()) { + // Can't set patchlevel to a different value. + return KM_ERROR_INVALID_ARGUMENT; + } + boot_patchlevel_ = boot_patchlevel; + if (pure_soft_remote_provisioning_context_ != nullptr) { + pure_soft_remote_provisioning_context_->SetBootPatchlevel(boot_patchlevel); + } + return KM_ERROR_OK; +} + KeyFactory* PureSoftKeymasterContext::GetKeyFactory(keymaster_algorithm_t algorithm) const { switch (algorithm) { case KM_ALGORITHM_RSA: diff --git a/contexts/pure_soft_remote_provisioning_context.cpp b/contexts/pure_soft_remote_provisioning_context.cpp index 52e4e16..6919458 100644 --- a/contexts/pure_soft_remote_provisioning_context.cpp +++ b/contexts/pure_soft_remote_provisioning_context.cpp @@ -50,6 +50,10 @@ std::array<uint8_t, 32> GetRandomBytes() { } // namespace +PureSoftRemoteProvisioningContext::PureSoftRemoteProvisioningContext( + keymaster_security_level_t security_level) + : security_level_(security_level) {} + std::vector<uint8_t> PureSoftRemoteProvisioningContext::DeriveBytesFromHbk(const std::string& context, size_t num_bytes) const { @@ -71,17 +75,40 @@ std::unique_ptr<cppbor::Map> PureSoftRemoteProvisioningContext::CreateDeviceInfo auto result = std::make_unique<cppbor::Map>(cppbor::Map()); // The following placeholders show how the DeviceInfo map would be populated. - // result->add(cppbor::Tstr("brand"), cppbor::Tstr("Google")); - // result->add(cppbor::Tstr("manufacturer"), cppbor::Tstr("Google")); - // result->add(cppbor::Tstr("product"), cppbor::Tstr("Fake")); - // result->add(cppbor::Tstr("model"), cppbor::Tstr("Imaginary")); - // result->add(cppbor::Tstr("board"), cppbor::Tstr("Chess")); - // result->add(cppbor::Tstr("vb_state"), cppbor::Tstr("orange")); - // result->add(cppbor::Tstr("bootloader_state"), cppbor::Tstr("unlocked")); - // result->add(cppbor::Tstr("os_version"), cppbor::Tstr("SC")); - // result->add(cppbor::Tstr("system_patch_level"), cppbor::Uint(20210331)); - // result->add(cppbor::Tstr("boot_patch_level"), cppbor::Uint(20210331)); - // result->add(cppbor::Tstr("vendor_patch_level"), cppbor::Uint(20210331)); + result->add(cppbor::Tstr("brand"), cppbor::Tstr("Google")); + result->add(cppbor::Tstr("manufacturer"), cppbor::Tstr("Google")); + result->add(cppbor::Tstr("product"), cppbor::Tstr("Fake Product")); + result->add(cppbor::Tstr("model"), cppbor::Tstr("Fake Model")); + result->add(cppbor::Tstr("device"), cppbor::Tstr("Fake Device")); + if (bootloader_state_) { + result->add(cppbor::Tstr("bootloader_state"), cppbor::Tstr(*bootloader_state_)); + } + if (verified_boot_state_) { + result->add(cppbor::Tstr("vb_state"), cppbor::Tstr(*verified_boot_state_)); + } + if (vbmeta_digest_) { + result->add(cppbor::Tstr("vbmeta_digest"), cppbor::Bstr(*vbmeta_digest_)); + } + if (os_version_) { + result->add(cppbor::Tstr("os_version"), cppbor::Tstr(std::to_string(*os_version_))); + } + if (os_patchlevel_) { + result->add(cppbor::Tstr("system_patch_level"), cppbor::Uint(*os_patchlevel_)); + } + if (boot_patchlevel_) { + result->add(cppbor::Tstr("boot_patch_level"), cppbor::Uint(*boot_patchlevel_)); + } + if (vendor_patchlevel_) { + result->add(cppbor::Tstr("vendor_patch_level"), cppbor::Uint(*vendor_patchlevel_)); + } + result->add(cppbor::Tstr("version"), cppbor::Uint(2)); + result->add(cppbor::Tstr("fused"), cppbor::Uint(0)); + + // "software" security level is not supported, so lie and say we're a TEE + // even if we're software. + const char* security_level = + security_level_ == KM_SECURITY_LEVEL_STRONGBOX ? "strongbox" : "tee"; + result->add(cppbor::Tstr("security_level"), cppbor::Tstr(security_level)); result->canonicalize(); return result; @@ -166,4 +193,26 @@ PureSoftRemoteProvisioningContext::GenerateHmacSha256(const cppcose::bytevec& in return *result; } +void PureSoftRemoteProvisioningContext::SetSystemVersion(uint32_t os_version, + uint32_t os_patchlevel) { + os_version_ = os_version; + os_patchlevel_ = os_patchlevel; +} + +void PureSoftRemoteProvisioningContext::SetVendorPatchlevel(uint32_t vendor_patchlevel) { + vendor_patchlevel_ = vendor_patchlevel; +} + +void PureSoftRemoteProvisioningContext::SetBootPatchlevel(uint32_t boot_patchlevel) { + boot_patchlevel_ = boot_patchlevel; +} + +void PureSoftRemoteProvisioningContext::SetVerifiedBootInfo( + std::string_view boot_state, std::string_view bootloader_state, + const std::vector<uint8_t>& vbmeta_digest) { + verified_boot_state_ = boot_state; + bootloader_state_ = bootloader_state; + vbmeta_digest_ = vbmeta_digest; +} + } // namespace keymaster diff --git a/include/keymaster/android_keymaster.h b/include/keymaster/android_keymaster.h index c463e68..d8033b4 100644 --- a/include/keymaster/android_keymaster.h +++ b/include/keymaster/android_keymaster.h @@ -97,6 +97,8 @@ class AndroidKeymaster { ConfigureVendorPatchlevel(const ConfigureVendorPatchlevelRequest& request); ConfigureBootPatchlevelResponse ConfigureBootPatchlevel(const ConfigureBootPatchlevelRequest& request); + ConfigureVerifiedBootInfoResponse + ConfigureVerifiedBootInfo(const ConfigureVerifiedBootInfoRequest& 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 de674b8..7d43043 100644 --- a/include/keymaster/android_keymaster_messages.h +++ b/include/keymaster/android_keymaster_messages.h @@ -21,6 +21,10 @@ #include <stdlib.h> #include <string.h> +#include <string> +#include <string_view> +#include <vector> + #include <keymaster/android_keymaster_utils.h> #include <keymaster/authorization_set.h> #include <keymaster/km_version.h> @@ -63,6 +67,7 @@ enum AndroidKeymasterCommand : uint32_t { GENERATE_TIMESTAMP_TOKEN = 31, CONFIGURE_VENDOR_PATCHLEVEL = 32, CONFIGURE_BOOT_PATCHLEVEL = 33, + CONFIGURE_VERIFIED_BOOT_INFO = 34, }; /** @@ -1178,4 +1183,36 @@ struct ConfigureBootPatchlevelRequest : public KeymasterMessage { using ConfigureBootPatchlevelResponse = EmptyKeymasterResponse; +struct ConfigureVerifiedBootInfoRequest : public KeymasterMessage { + explicit ConfigureVerifiedBootInfoRequest(int32_t ver) + : ConfigureVerifiedBootInfoRequest(ver, {}, {}, {}) {} + + ConfigureVerifiedBootInfoRequest(int32_t ver, std::string_view boot_state_param, + std::string_view bootloader_state_param, + std::vector<uint8_t> vbmeta_digest_param) + : KeymasterMessage(ver), boot_state(boot_state_param), + bootloader_state(bootloader_state_param), vbmeta_digest(std::move(vbmeta_digest_param)) {} + + size_t SerializedSize() const override { + return sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint32_t) // buffer sizes + + boot_state.size() + bootloader_state.size() + vbmeta_digest.size(); + } + uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override { + buf = append_collection_to_buf(buf, end, boot_state); + buf = append_collection_to_buf(buf, end, bootloader_state); + return append_collection_to_buf(buf, end, vbmeta_digest); + } + bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override { + return copy_collection_from_buf(buf_ptr, end, &boot_state) && + copy_collection_from_buf(buf_ptr, end, &bootloader_state) && + copy_collection_from_buf(buf_ptr, end, &vbmeta_digest); + } + + std::string boot_state; + std::string bootloader_state; + std::vector<uint8_t> vbmeta_digest; +}; + +using ConfigureVerifiedBootInfoResponse = EmptyKeymasterResponse; + } // namespace keymaster diff --git a/include/keymaster/contexts/pure_soft_keymaster_context.h b/include/keymaster/contexts/pure_soft_keymaster_context.h index 5cd74b9..834a092 100644 --- a/include/keymaster/contexts/pure_soft_keymaster_context.h +++ b/include/keymaster/contexts/pure_soft_keymaster_context.h @@ -18,6 +18,7 @@ #include <memory> #include <string> +#include <string_view> #include <keymaster/attestation_context.h> #include <keymaster/contexts/pure_soft_remote_provisioning_context.h> @@ -93,23 +94,13 @@ class PureSoftKeymasterContext : public KeymasterContext, return pure_soft_remote_provisioning_context_.get(); } - keymaster_error_t SetVendorPatchlevel(uint32_t vendor_patchlevel) override { - if (vendor_patchlevel_.has_value() && vendor_patchlevel != vendor_patchlevel_.value()) { - // Can't set patchlevel to a different value. - return KM_ERROR_INVALID_ARGUMENT; - } - vendor_patchlevel_ = vendor_patchlevel; - return KM_ERROR_OK; - } + keymaster_error_t SetVerifiedBootInfo(std::string_view boot_state, + std::string_view bootloader_state, + const std::vector<uint8_t>& vbmeta_digest) override; - keymaster_error_t SetBootPatchlevel(uint32_t boot_patchlevel) override { - if (boot_patchlevel_.has_value() && boot_patchlevel != boot_patchlevel_.value()) { - // Can't set patchlevel to a different value. - return KM_ERROR_INVALID_ARGUMENT; - } - boot_patchlevel_ = boot_patchlevel; - return KM_ERROR_OK; - } + keymaster_error_t SetVendorPatchlevel(uint32_t vendor_patchlevel) override; + + keymaster_error_t SetBootPatchlevel(uint32_t boot_patchlevel) override; std::optional<uint32_t> GetVendorPatchlevel() const override { return vendor_patchlevel_; } @@ -145,12 +136,15 @@ class PureSoftKeymasterContext : public KeymasterContext, std::unique_ptr<KeyFactory> hmac_factory_; uint32_t os_version_; uint32_t os_patchlevel_; + std::optional<std::string> bootloader_state_; + std::optional<std::string> verified_boot_state_; + std::optional<std::vector<uint8_t>> vbmeta_digest_; std::optional<uint32_t> vendor_patchlevel_; std::optional<uint32_t> boot_patchlevel_; SoftKeymasterEnforcement soft_keymaster_enforcement_; const keymaster_security_level_t security_level_; std::unique_ptr<SecureKeyStorage> pure_soft_secure_key_storage_; - std::unique_ptr<RemoteProvisioningContext> pure_soft_remote_provisioning_context_; + std::unique_ptr<PureSoftRemoteProvisioningContext> pure_soft_remote_provisioning_context_; }; } // namespace keymaster diff --git a/include/keymaster/contexts/pure_soft_remote_provisioning_context.h b/include/keymaster/contexts/pure_soft_remote_provisioning_context.h index e1aa40c..90cd79f 100644 --- a/include/keymaster/contexts/pure_soft_remote_provisioning_context.h +++ b/include/keymaster/contexts/pure_soft_remote_provisioning_context.h @@ -16,11 +16,16 @@ #pragma once +#include <hardware/keymaster_defs.h> #include <keymaster/remote_provisioning_context.h> #include <cppbor.h> +#include <cstdint> #include <mutex> +#include <string> +#include <string_view> +#include <vector> namespace keymaster { @@ -29,7 +34,7 @@ namespace keymaster { */ class PureSoftRemoteProvisioningContext : public RemoteProvisioningContext { public: - PureSoftRemoteProvisioningContext() = default; + explicit PureSoftRemoteProvisioningContext(keymaster_security_level_t security_level); ~PureSoftRemoteProvisioningContext() override = default; std::vector<uint8_t> DeriveBytesFromHbk(const std::string& context, size_t numBytes) const override; @@ -41,12 +46,27 @@ class PureSoftRemoteProvisioningContext : public RemoteProvisioningContext { std::optional<cppcose::HmacSha256> GenerateHmacSha256(const cppcose::bytevec& input) const override; + void SetSystemVersion(uint32_t os_version, uint32_t os_patchlevel); + void SetVendorPatchlevel(uint32_t vendor_patchlevel); + void SetBootPatchlevel(uint32_t boot_patchlevel); + void SetVerifiedBootInfo(std::string_view boot_state, std::string_view bootloader_state, + const std::vector<uint8_t>& vbmeta_digest); + private: // Initialize the BCC if it has not yet happened. void LazyInitProdBcc() const; std::pair<std::vector<uint8_t>, cppbor::Array> GenerateBcc(bool testMode) const; + keymaster_security_level_t security_level_; + std::optional<uint32_t> os_version_; + std::optional<uint32_t> os_patchlevel_; + std::optional<uint32_t> vendor_patchlevel_; + std::optional<uint32_t> boot_patchlevel_; + std::optional<std::string> verified_boot_state_; + std::optional<std::string> bootloader_state_; + std::optional<std::vector<uint8_t>> vbmeta_digest_; + mutable std::once_flag bccInitFlag_; // Always call LazyInitProdBcc before accessing these values, as they are diff --git a/include/keymaster/keymaster_context.h b/include/keymaster/keymaster_context.h index 7947b63..052ccf2 100644 --- a/include/keymaster/keymaster_context.h +++ b/include/keymaster/keymaster_context.h @@ -18,6 +18,7 @@ #define SYSTEM_KEYMASTER_KEYMASTER_CONTEXT_H_ #include <optional> +#include <string_view> #include <assert.h> @@ -225,6 +226,16 @@ class KeymasterContext { virtual RemoteProvisioningContext* GetRemoteProvisioningContext() const { return nullptr; } /** + * Sets the verified boot metadata. This value should be set by the bootloader. + * A subsequent to set a different value will return KM_ERROR_INVALID_ARGUMENT. + */ + virtual keymaster_error_t SetVerifiedBootInfo(std::string_view /*verified_boot_state*/, + std::string_view /*bootloader_state*/, + const std::vector<uint8_t>& /*vbmeta_digest*/) { + return KM_ERROR_UNIMPLEMENTED; + } + + /** * Sets the vendor patchlevel (format YYYYMMDD) for the implementation. This value should * be set by the HAL service at start of day. A subsequent attempt to set a different * value will return KM_ERROR_INVALID_ARGUMENT. @@ -236,7 +247,7 @@ class KeymasterContext { /** * Sets the boot patchlevel (format YYYYMMDD) for the implementation. This value should be set * by the bootloader. A subsequent to set a different value will return - * KM_ERROR_INVALID_ARGUMENT; + * KM_ERROR_INVALID_ARGUMENT. */ virtual keymaster_error_t SetBootPatchlevel(uint32_t /* boot_patchlevel */) { return KM_ERROR_UNIMPLEMENTED; diff --git a/include/keymaster/logger.h b/include/keymaster/logger.h index a4fdea3..a9b005b 100644 --- a/include/keymaster/logger.h +++ b/include/keymaster/logger.h @@ -55,15 +55,15 @@ class Logger { static Logger* instance_; }; -#define STR(x) #x -#define STRINGIFY(x) STR(x) -#define FILE_LINE __FILE__ ", Line " STRINGIFY(__LINE__) ": " +#define __KM_STR(x) #x +#define __KM_STRINGIFY(x) __KM_STR(x) +#define __KM_FILE_LINE __FILE__ ", Line " __KM_STRINGIFY(__LINE__) ": " -#define LOG_D(fmt, ...) Logger::Debug(FILE_LINE fmt, __VA_ARGS__) -#define LOG_I(fmt, ...) Logger::Info(FILE_LINE fmt, __VA_ARGS__) -#define LOG_W(fmt, ...) Logger::Warning(FILE_LINE fmt, __VA_ARGS__) -#define LOG_E(fmt, ...) Logger::Error(FILE_LINE fmt, __VA_ARGS__) -#define LOG_S(fmt, ...) Logger::Severe(FILE_LINE fmt, __VA_ARGS__) +#define LOG_D(fmt, ...) Logger::Debug(__KM_FILE_LINE fmt, __VA_ARGS__) +#define LOG_I(fmt, ...) Logger::Info(__KM_FILE_LINE fmt, __VA_ARGS__) +#define LOG_W(fmt, ...) Logger::Warning(__KM_FILE_LINE fmt, __VA_ARGS__) +#define LOG_E(fmt, ...) Logger::Error(__KM_FILE_LINE fmt, __VA_ARGS__) +#define LOG_S(fmt, ...) Logger::Severe(__KM_FILE_LINE fmt, __VA_ARGS__) } // namespace keymaster diff --git a/include/keymaster/serializable.h b/include/keymaster/serializable.h index d31412b..f043574 100644 --- a/include/keymaster/serializable.h +++ b/include/keymaster/serializable.h @@ -21,7 +21,10 @@ #include <stdlib.h> #include <string.h> +#include <iterator> + #include <keymaster/UniquePtr.h> +#include <keymaster/logger.h> #include <keymaster/mem.h> namespace keymaster { @@ -71,6 +74,12 @@ template <typename T> inline uintptr_t __pval(const T* p) { } /** + * Performs an overflow-checked bounds check. Returns true iff \p buf + \p len is less than + * \p end. + */ +bool __buffer_bound_check(const uint8_t* buf, const uint8_t* end, size_t len); + +/** * Append a byte array to a buffer. Note that by itself this function isn't very useful, because it * provides no indication in the serialized buffer of what the array size is. For writing arrays, * see \p append_size_and_data_to_buf(). @@ -111,6 +120,20 @@ inline uint8_t* append_size_and_data_to_buf(uint8_t* buf, const uint8_t* end, co } /** + * Append a collection type to buffer. The type must implement `size` and `data` accessors + * that return, respectively, the size of the data and a pointer to the start of the data. + * Returns a pointer to the first byte after the data written. + */ +template <typename T> +uint8_t* append_collection_to_buf(uint8_t* buf, const uint8_t* end, const T& value) { + if (value.size() > UINT32_MAX) { + LOG_E("Skip collection serialization due to integer overflow", 0); + return buf; + } + return append_size_and_data_to_buf(buf, end, value.data(), value.size()); +} + +/** * Appends an array of values that are convertible to uint32_t as uint32ts to a buffer, prefixing a * count so deserialization knows how many values to read. * @@ -193,6 +216,34 @@ inline bool copy_uint32_array_from_buf(const uint8_t** buf_ptr, const uint8_t* e } /** + * Copies a contiguously-allocated collection type (e.g. string, vector) from \p *buf_ptr. The + * type \p T must implement `reserve` and `push_back` functions. Returns false if there are less + * than 4 bytes remaining in \p *buf_ptr. Advances \p *buf_ptr to the next byte to be read. + */ +template <typename T> +bool copy_collection_from_buf(const uint8_t** buf_ptr, const uint8_t* end, T* value) { + uint32_t buf_size; + if (!copy_uint32_from_buf(buf_ptr, end, &buf_size)) { + return false; + } + + if (!__buffer_bound_check(*buf_ptr, end, buf_size)) { + LOG_E("Skip collection deserialization due size mismatch", 0); + return false; + } + + value->reserve(buf_size); + auto out = std::back_inserter(*value); + const uint8_t* const value_end = *buf_ptr + buf_size; + while (*buf_ptr < value_end) { + *out = **buf_ptr; + ++out; + ++*buf_ptr; + } + return true; +} + +/** * A simple buffer that supports reading and writing. Manages its own memory. */ class Buffer : public Serializable { diff --git a/ng/AndroidKeyMintDevice.cpp b/ng/AndroidKeyMintDevice.cpp index 08a1036..373ec03 100644 --- a/ng/AndroidKeyMintDevice.cpp +++ b/ng/AndroidKeyMintDevice.cpp @@ -225,6 +225,14 @@ AndroidKeyMintDevice::AndroidKeyMintDevice(SecurityLevel securityLevel) // The OS patch level only has a year and a month so we just add the 1st // of the month as day field. context->SetBootPatchlevel(GetOsPatchlevel() * 100 + 1); + auto digest = ::keymaster::GetVbmetaDigest(); + if (digest) { + std::string bootState = ::keymaster::GetVerifiedBootState(); + std::string bootloaderState = ::keymaster::GetBootloaderState(); + context->SetVerifiedBootInfo(bootState, bootloaderState, *digest); + } else { + LOG(ERROR) << "Unable to read vb_meta digest"; + } return context; }(), kOperationTableSize)), diff --git a/tests/android_keymaster_messages_test.cpp b/tests/android_keymaster_messages_test.cpp index 7b523a8..db4c7b0 100644 --- a/tests/android_keymaster_messages_test.cpp +++ b/tests/android_keymaster_messages_test.cpp @@ -716,6 +716,25 @@ TEST(RoundTrip, ConfigureBootPatchlevelResponse) { } } +TEST(RoundTrip, ConfigureVerifiedBootInfoRequest) { + for (int32_t ver = 0; ver <= kMaxMessageVersion; ++ver) { + ConfigureVerifiedBootInfoRequest req(ver, "super", "duper", {1, 2, 3, 4, 5, 6}); + + UniquePtr<ConfigureVerifiedBootInfoRequest> deserialized(round_trip(ver, req, 28)); + ASSERT_NE(deserialized, nullptr); + EXPECT_EQ(deserialized->boot_state, req.boot_state); + EXPECT_EQ(deserialized->bootloader_state, req.bootloader_state); + EXPECT_EQ(deserialized->vbmeta_digest, req.vbmeta_digest); + } +} + +TEST(RoundTrip, ConfigureVerifiedBootInfoResponse) { + for (int ver = 0; ver <= kMaxMessageVersion; ++ver) { + ConfigureVerifiedBootInfoResponse rsp(ver); + UniquePtr<ConfigureVerifiedBootInfoResponse> deserialized(round_trip(ver, rsp, 4)); + } +} + TEST(RoundTrip, AddEntropyRequest) { for (int ver = 0; ver <= kMaxMessageVersion; ++ver) { AddEntropyRequest msg(ver); @@ -954,6 +973,7 @@ GARBAGE_TEST(UpgradeKeyResponse); GARBAGE_TEST(GenerateTimestampTokenRequest); GARBAGE_TEST(GenerateTimestampTokenResponse); GARBAGE_TEST(SetAttestationIdsRequest); +GARBAGE_TEST(ConfigureVerifiedBootInfoRequest); } // namespace test |