summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSeth Moore <sethmo@google.com>2022-02-28 15:02:14 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2022-02-28 15:02:14 +0000
commitd5c896094a8c87a9ce2656dda1f56baaca2c92b8 (patch)
tree6a706e17eed9fae1f3f0b75b14c7faeea81878af
parent355c8480643940874bb0289d3b5a79e73f30038c (diff)
parent975150fcf571be2f5f3147c49fa1744ffd716464 (diff)
downloadkeymaster-d5c896094a8c87a9ce2656dda1f56baaca2c92b8.tar.gz
Merge changes from topic "deviceinfo-update" am: 975150fcf5
Original change: https://android-review.googlesource.com/c/platform/system/keymaster/+/1984097 Change-Id: I2665b146d698e27a7ad99ec24481f11e3448c6d2
-rw-r--r--android_keymaster/android_keymaster.cpp8
-rw-r--r--android_keymaster/serializable.cpp13
-rw-r--r--contexts/pure_soft_keymaster_context.cpp52
-rw-r--r--contexts/pure_soft_remote_provisioning_context.cpp71
-rw-r--r--include/keymaster/android_keymaster.h2
-rw-r--r--include/keymaster/android_keymaster_messages.h37
-rw-r--r--include/keymaster/contexts/pure_soft_keymaster_context.h28
-rw-r--r--include/keymaster/contexts/pure_soft_remote_provisioning_context.h22
-rw-r--r--include/keymaster/keymaster_context.h13
-rw-r--r--include/keymaster/logger.h16
-rw-r--r--include/keymaster/serializable.h51
-rw-r--r--ng/AndroidKeyMintDevice.cpp8
-rw-r--r--tests/android_keymaster_messages_test.cpp20
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