summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2021-07-23 01:09:21 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2021-07-23 01:09:21 +0000
commit87a32b53e6571b2e10c308b9ecfcf16d168d6b48 (patch)
treefd6f4dd844232594d5f2e95d907daa7badd8686d
parentf69958ed388742a5c3866360d77a11c718dc23d0 (diff)
parent08e0b28fbc82184b8d0646de199f1f684a06b16e (diff)
downloadkeymaster-87a32b53e6571b2e10c308b9ecfcf16d168d6b48.tar.gz
Snap for 7574908 from 08e0b28fbc82184b8d0646de199f1f684a06b16e to sc-d2-release
Change-Id: Ib48204b67abbe2956a27fd4511134268b585ec07
-rw-r--r--android_keymaster/android_keymaster.cpp53
-rw-r--r--android_keymaster/keymaster_configuration.cpp75
-rw-r--r--contexts/pure_soft_keymaster_context.cpp6
-rw-r--r--include/keymaster/android_keymaster.h4
-rw-r--r--include/keymaster/android_keymaster_messages.h36
-rw-r--r--include/keymaster/contexts/pure_soft_keymaster_context.h25
-rw-r--r--include/keymaster/key_blob_utils/software_keyblobs.h15
-rw-r--r--include/keymaster/keymaster_configuration.h11
-rw-r--r--include/keymaster/keymaster_context.h32
-rw-r--r--key_blob_utils/software_keyblobs.cpp39
-rw-r--r--tests/android_keymaster_messages_test.cpp41
11 files changed, 299 insertions, 38 deletions
diff --git a/android_keymaster/android_keymaster.cpp b/android_keymaster/android_keymaster.cpp
index 3850481..00fa837 100644
--- a/android_keymaster/android_keymaster.cpp
+++ b/android_keymaster/android_keymaster.cpp
@@ -56,6 +56,22 @@ using cppcose::kAesGcmNonceLength;
using cppcose::P256;
using cppcose::x25519_HKDF_DeriveKey;
+template <keymaster_tag_t T>
+keymaster_error_t CheckPatchLevel(const AuthorizationSet& tee_enforced,
+ const AuthorizationSet& sw_enforced, TypedTag<KM_UINT, T> tag,
+ uint32_t current_patchlevel) {
+ uint32_t key_patchlevel;
+ if (tee_enforced.GetTagValue(tag, &key_patchlevel) ||
+ sw_enforced.GetTagValue(tag, &key_patchlevel)) {
+ if (key_patchlevel < current_patchlevel) {
+ return KM_ERROR_KEY_REQUIRES_UPGRADE;
+ } else if (key_patchlevel > current_patchlevel) {
+ return KM_ERROR_INVALID_KEY_BLOB;
+ }
+ }
+ return KM_ERROR_OK;
+}
+
keymaster_error_t CheckVersionInfo(const AuthorizationSet& tee_enforced,
const AuthorizationSet& sw_enforced,
const KeymasterContext& context) {
@@ -63,13 +79,22 @@ keymaster_error_t CheckVersionInfo(const AuthorizationSet& tee_enforced,
uint32_t os_patchlevel;
context.GetSystemVersion(&os_version, &os_patchlevel);
- uint32_t key_os_patchlevel;
- if (tee_enforced.GetTagValue(TAG_OS_PATCHLEVEL, &key_os_patchlevel) ||
- sw_enforced.GetTagValue(TAG_OS_PATCHLEVEL, &key_os_patchlevel)) {
- if (key_os_patchlevel < os_patchlevel)
- return KM_ERROR_KEY_REQUIRES_UPGRADE;
- else if (key_os_patchlevel > os_patchlevel)
- return KM_ERROR_INVALID_KEY_BLOB;
+ keymaster_error_t err =
+ CheckPatchLevel(tee_enforced, sw_enforced, TAG_OS_PATCHLEVEL, os_patchlevel);
+ if (err != KM_ERROR_OK) return err;
+
+ // Also check the vendor and boot patchlevels if available.
+ auto vendor_patchlevel = context.GetVendorPatchlevel();
+ if (vendor_patchlevel.has_value()) {
+ err = CheckPatchLevel(tee_enforced, sw_enforced, TAG_VENDOR_PATCHLEVEL,
+ vendor_patchlevel.value());
+ if (err != KM_ERROR_OK) return err;
+ }
+ auto boot_patchlevel = context.GetBootPatchlevel();
+ if (boot_patchlevel.has_value()) {
+ err = CheckPatchLevel(tee_enforced, sw_enforced, TAG_BOOT_PATCHLEVEL,
+ boot_patchlevel.value());
+ if (err != KM_ERROR_OK) return err;
}
return KM_ERROR_OK;
@@ -782,6 +807,20 @@ void AndroidKeymaster::Configure(const ConfigureRequest& request, ConfigureRespo
response->error = context_->SetSystemVersion(request.os_version, request.os_patchlevel);
}
+ConfigureVendorPatchlevelResponse
+AndroidKeymaster::ConfigureVendorPatchlevel(const ConfigureVendorPatchlevelRequest& request) {
+ ConfigureVendorPatchlevelResponse rsp(message_version());
+ rsp.error = context_->SetVendorPatchlevel(request.vendor_patchlevel);
+ return rsp;
+}
+
+ConfigureBootPatchlevelResponse
+AndroidKeymaster::ConfigureBootPatchlevel(const ConfigureBootPatchlevelRequest& request) {
+ ConfigureBootPatchlevelResponse rsp(message_version());
+ rsp.error = context_->SetBootPatchlevel(request.boot_patchlevel);
+ 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/keymaster_configuration.cpp b/android_keymaster/keymaster_configuration.cpp
index 7bf51c4..ca78863 100644
--- a/android_keymaster/keymaster_configuration.cpp
+++ b/android_keymaster/keymaster_configuration.cpp
@@ -40,10 +40,12 @@ constexpr size_t kSubminorVersionMatch = 5;
constexpr size_t kPlatformVersionMatchCount = kSubminorVersionMatch + 1;
constexpr char kPlatformPatchlevelProp[] = "ro.build.version.security_patch";
-constexpr char kPlatformPatchlevelRegex[] = "^([0-9]{4})-([0-9]{2})-[0-9]{2}$";
+constexpr char kVendorPatchlevelProp[] = "ro.vendor.build.security_patch";
+constexpr char kPatchlevelRegex[] = "^([0-9]{4})-([0-9]{2})-([0-9]{2})$";
constexpr size_t kYearMatch = 1;
constexpr size_t kMonthMatch = 2;
-constexpr size_t kPlatformPatchlevelMatchCount = kMonthMatch + 1;
+constexpr size_t kDayMatch = 3;
+constexpr size_t kPatchlevelMatchCount = kDayMatch + 1;
uint32_t match_to_uint32(const char* expression, const regmatch_t& match) {
if (match.rm_so == -1) return 0;
@@ -64,6 +66,46 @@ std::string wait_and_get_property(const char* prop) {
return prop_value;
}
+enum class PatchlevelOutput { kYearMonthDay, kYearMonth };
+
+uint32_t GetPatchlevel(const char* patchlevel_str, PatchlevelOutput detail) {
+ regex_t regex;
+ if (regcomp(&regex, kPatchlevelRegex, REG_EXTENDED) != 0) {
+ ALOGE("Failed to compile platform patchlevel regex! (%s)", kPatchlevelRegex);
+ return 0;
+ }
+
+ regmatch_t matches[kPatchlevelMatchCount];
+ int not_match = regexec(&regex, patchlevel_str, kPatchlevelMatchCount, matches, 0 /* flags */);
+ regfree(&regex);
+ if (not_match) {
+ ALOGI(" patchlevel string does not match expected format. Using patchlevel 0");
+ return 0;
+ }
+
+ uint32_t year = match_to_uint32(patchlevel_str, matches[kYearMatch]);
+ uint32_t month = match_to_uint32(patchlevel_str, matches[kMonthMatch]);
+
+ if (month < 1 || month > 12) {
+ ALOGE("Invalid patch month %d", month);
+ return 0;
+ }
+
+ switch (detail) {
+ case PatchlevelOutput::kYearMonthDay: {
+ uint32_t day = match_to_uint32(patchlevel_str, matches[kDayMatch]);
+ if (day < 1 || day > 31) {
+ ALOGE("Invalid patch day %d", day);
+ return 0;
+ }
+ return year * 10000 + month * 100 + day;
+ }
+ case PatchlevelOutput::kYearMonth:
+ return year * 100 + month;
+ }
+ return 0;
+}
+
} // anonymous namespace
keymaster_error_t ConfigureDevice(keymaster2_device_t* dev, uint32_t os_version,
@@ -108,29 +150,7 @@ uint32_t GetOsVersion() {
}
uint32_t GetOsPatchlevel(const char* patchlevel_str) {
- regex_t regex;
- if (regcomp(&regex, kPlatformPatchlevelRegex, REG_EXTENDED) != 0) {
- ALOGE("Failed to compile platform patchlevel regex! (%s)", kPlatformPatchlevelRegex);
- return 0;
- }
-
- regmatch_t matches[kPlatformPatchlevelMatchCount];
- int not_match =
- regexec(&regex, patchlevel_str, kPlatformPatchlevelMatchCount, matches, 0 /* flags */);
- regfree(&regex);
- if (not_match) {
- ALOGI("Platform patchlevel string does not match expected format. Using patchlevel 0");
- return 0;
- }
-
- uint32_t year = match_to_uint32(patchlevel_str, matches[kYearMatch]);
- uint32_t month = match_to_uint32(patchlevel_str, matches[kMonthMatch]);
-
- if (month < 1 || month > 12) {
- ALOGE("Invalid patch month %d", month);
- return 0;
- }
- return year * 100 + month;
+ return GetPatchlevel(patchlevel_str, PatchlevelOutput::kYearMonth);
}
uint32_t GetOsPatchlevel() {
@@ -138,4 +158,9 @@ uint32_t GetOsPatchlevel() {
return GetOsPatchlevel(patchlevel.c_str());
}
+uint32_t GetVendorPatchlevel() {
+ std::string patchlevel = wait_and_get_property(kVendorPatchlevelProp);
+ return GetPatchlevel(patchlevel.c_str(), PatchlevelOutput::kYearMonthDay);
+}
+
} // namespace keymaster
diff --git a/contexts/pure_soft_keymaster_context.cpp b/contexts/pure_soft_keymaster_context.cpp
index c04475e..bfa92a4 100644
--- a/contexts/pure_soft_keymaster_context.cpp
+++ b/contexts/pure_soft_keymaster_context.cpp
@@ -187,6 +187,9 @@ keymaster_error_t PureSoftKeymasterContext::CreateKeyBlob(const AuthorizationSet
keymaster_error_t error = SetKeyBlobAuthorizations(key_description, origin, os_version_,
os_patchlevel_, hw_enforced, sw_enforced);
if (error != KM_ERROR_OK) return error;
+ error =
+ ExtendKeyBlobAuthorizations(hw_enforced, sw_enforced, vendor_patchlevel_, boot_patchlevel_);
+ if (error != KM_ERROR_OK) return error;
AuthorizationSet hidden;
error = BuildHiddenAuthorizations(key_description, &hidden, softwareRootOfTrust);
@@ -210,7 +213,8 @@ keymaster_error_t PureSoftKeymasterContext::UpgradeKeyBlob(const KeymasterKeyBlo
keymaster_error_t error = ParseKeyBlob(key_to_upgrade, upgrade_params, &key);
if (error != KM_ERROR_OK) return error;
- return UpgradeSoftKeyBlob(key, os_version_, os_patchlevel_, upgrade_params, upgraded_key);
+ return FullUpgradeSoftKeyBlob(key, os_version_, os_patchlevel_, vendor_patchlevel_,
+ boot_patchlevel_, upgrade_params, upgraded_key);
}
keymaster_error_t PureSoftKeymasterContext::ParseKeyBlob(const KeymasterKeyBlob& blob,
diff --git a/include/keymaster/android_keymaster.h b/include/keymaster/android_keymaster.h
index e1f4eee..bbeb81a 100644
--- a/include/keymaster/android_keymaster.h
+++ b/include/keymaster/android_keymaster.h
@@ -93,6 +93,10 @@ class AndroidKeymaster {
EarlyBootEndedResponse EarlyBootEnded();
DeviceLockedResponse DeviceLocked(const DeviceLockedRequest& request);
GetVersion2Response GetVersion2(const GetVersion2Request& request);
+ ConfigureVendorPatchlevelResponse
+ ConfigureVendorPatchlevel(const ConfigureVendorPatchlevelRequest& request);
+ ConfigureBootPatchlevelResponse
+ ConfigureBootPatchlevel(const ConfigureBootPatchlevelRequest& 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 4fcfc1b..2ec473f 100644
--- a/include/keymaster/android_keymaster_messages.h
+++ b/include/keymaster/android_keymaster_messages.h
@@ -61,6 +61,8 @@ enum AndroidKeymasterCommand : uint32_t {
GENERATE_RKP_KEY = 29,
GENERATE_CSR = 30,
GENERATE_TIMESTAMP_TOKEN = 31,
+ CONFIGURE_VENDOR_PATCHLEVEL = 32,
+ CONFIGURE_BOOT_PATCHLEVEL = 33,
};
/**
@@ -751,7 +753,7 @@ struct ConfigureRequest : public KeymasterMessage {
}
uint32_t os_version;
- uint32_t os_patchlevel;
+ uint32_t os_patchlevel; // YYYYMM
};
using ConfigureResponse = EmptyKeymasterResponse;
@@ -1143,4 +1145,36 @@ struct SetAttestationIdsRequest : public KeymasterMessage {
using SetAttestationIdsResponse = EmptyKeymasterResponse;
+struct ConfigureVendorPatchlevelRequest : public KeymasterMessage {
+ explicit ConfigureVendorPatchlevelRequest(int32_t ver) : KeymasterMessage(ver) {}
+
+ size_t SerializedSize() const override { return sizeof(vendor_patchlevel); }
+ uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override {
+ return append_uint32_to_buf(buf, end, vendor_patchlevel);
+ }
+ bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override {
+ return copy_uint32_from_buf(buf_ptr, end, &vendor_patchlevel);
+ }
+
+ uint32_t vendor_patchlevel{}; // YYYYMMDD
+};
+
+using ConfigureVendorPatchlevelResponse = EmptyKeymasterResponse;
+
+struct ConfigureBootPatchlevelRequest : public KeymasterMessage {
+ explicit ConfigureBootPatchlevelRequest(int32_t ver) : KeymasterMessage(ver) {}
+
+ size_t SerializedSize() const override { return sizeof(boot_patchlevel); }
+ uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override {
+ return append_uint32_to_buf(buf, end, boot_patchlevel);
+ }
+ bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override {
+ return copy_uint32_from_buf(buf_ptr, end, &boot_patchlevel);
+ }
+
+ uint32_t boot_patchlevel{}; // YYYYMMDD
+};
+
+using ConfigureBootPatchlevelResponse = EmptyKeymasterResponse;
+
} // namespace keymaster
diff --git a/include/keymaster/contexts/pure_soft_keymaster_context.h b/include/keymaster/contexts/pure_soft_keymaster_context.h
index 892af5d..2f7f098 100644
--- a/include/keymaster/contexts/pure_soft_keymaster_context.h
+++ b/include/keymaster/contexts/pure_soft_keymaster_context.h
@@ -89,6 +89,29 @@ class PureSoftKeymasterContext : public KeymasterContext,
RemoteProvisioningContext* GetRemoteProvisioningContext() const override {
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 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;
+ }
+
+ std::optional<uint32_t> GetVendorPatchlevel() const override { return vendor_patchlevel_; }
+
+ std::optional<uint32_t> GetBootPatchlevel() const override { return boot_patchlevel_; }
+
/*********************************************************************************************
* Implement SoftwareKeyBlobMaker
*/
@@ -119,6 +142,8 @@ class PureSoftKeymasterContext : public KeymasterContext,
std::unique_ptr<KeyFactory> hmac_factory_;
uint32_t os_version_;
uint32_t os_patchlevel_;
+ 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_;
diff --git a/include/keymaster/key_blob_utils/software_keyblobs.h b/include/keymaster/key_blob_utils/software_keyblobs.h
index 65e7ff5..962ed5a 100644
--- a/include/keymaster/key_blob_utils/software_keyblobs.h
+++ b/include/keymaster/key_blob_utils/software_keyblobs.h
@@ -17,6 +17,8 @@
#pragma once
+#include <optional>
+
#include <hardware/keymaster_defs.h>
#include <keymaster/android_keymaster_utils.h>
#include <openssl/base.h>
@@ -52,8 +54,21 @@ keymaster_error_t SetKeyBlobAuthorizations(const AuthorizationSet& key_descripti
keymaster_key_origin_t origin, uint32_t os_version,
uint32_t os_patchlevel, AuthorizationSet* hw_enforced,
AuthorizationSet* sw_enforced);
+
+keymaster_error_t ExtendKeyBlobAuthorizations(AuthorizationSet* hw_enforced,
+ AuthorizationSet* sw_enforced,
+ std::optional<uint32_t> vendor_patchlevel,
+ std::optional<uint32_t> boot_patchlevel);
+
keymaster_error_t UpgradeSoftKeyBlob(const UniquePtr<Key>& key, const uint32_t os_version,
const uint32_t os_patchlevel,
const AuthorizationSet& upgrade_params,
KeymasterKeyBlob* upgraded_key);
+
+keymaster_error_t FullUpgradeSoftKeyBlob(const UniquePtr<Key>& key, const uint32_t os_version,
+ uint32_t os_patchlevel,
+ std::optional<uint32_t> vendor_patchlevel,
+ std::optional<uint32_t> boot_patchlevel,
+ const AuthorizationSet& upgrade_params,
+ KeymasterKeyBlob* upgraded_key);
} // namespace keymaster
diff --git a/include/keymaster/keymaster_configuration.h b/include/keymaster/keymaster_configuration.h
index 69738fd..32da101 100644
--- a/include/keymaster/keymaster_configuration.h
+++ b/include/keymaster/keymaster_configuration.h
@@ -48,16 +48,23 @@ uint32_t GetOsVersion();
/**
* Parses OS patch level string, returning year and month in integer form. For example, "2016-03-25"
* will be returned as 201603. Returns 0 if the string doesn't contain a date in the form
- * YYYY-MM-DD.
+ * YYYY-MM-DD; returns YYYMM on success.
*/
uint32_t GetOsPatchlevel(const char* patchlevel_string);
/**
* Retrieves and parses OS patch level from build properties. Returns 0 if the string doesn't
- * contain a date in the form YYYY-MM-DD.
+ * contain a date in the form YYYY-MM-DD; returns YYYYMM on success.
*/
uint32_t GetOsPatchlevel();
+/**
+ * Retrieves and parses vendor patch level from build properties (which may require SELinux
+ * permission). Returns 0 if the string doesn't contain a date in the form YYYY-MM-DD; returns
+ * YYYYMMDD on success.
+ */
+uint32_t GetVendorPatchlevel();
+
} // namespace keymaster
#endif // SYSTEM_KEYMASTER_KEYMASTER_CONFIGURATION_H_
diff --git a/include/keymaster/keymaster_context.h b/include/keymaster/keymaster_context.h
index 3eebfc5..65c1b73 100644
--- a/include/keymaster/keymaster_context.h
+++ b/include/keymaster/keymaster_context.h
@@ -17,6 +17,8 @@
#ifndef SYSTEM_KEYMASTER_KEYMASTER_CONTEXT_H_
#define SYSTEM_KEYMASTER_KEYMASTER_CONTEXT_H_
+#include <optional>
+
#include <assert.h>
#include <hardware/keymaster_defs.h>
@@ -213,6 +215,36 @@ class KeymasterContext {
*/
virtual RemoteProvisioningContext* GetRemoteProvisioningContext() const { return nullptr; }
+ /**
+ * 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.
+ */
+ virtual keymaster_error_t SetVendorPatchlevel(uint32_t /* vendor_patchlevel */) {
+ return KM_ERROR_UNIMPLEMENTED;
+ }
+
+ /**
+ * 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;
+ */
+ virtual keymaster_error_t SetBootPatchlevel(uint32_t /* boot_patchlevel */) {
+ return KM_ERROR_UNIMPLEMENTED;
+ }
+
+ /**
+ * Returns the vendor patchlevel, as set by the HAL service using SetVendorPatchlevel.
+ */
+ virtual std::optional<uint32_t> GetVendorPatchlevel() const { return std::nullopt; }
+
+ /**
+ * Returns the boot patchlevel. For hardware-based implementations this will be the value set by
+ * the bootloader. For software implementations this will be the information set by
+ * SetBootPatchLevel.
+ */
+ virtual std::optional<uint32_t> GetBootPatchlevel() const { return std::nullopt; }
+
private:
// Uncopyable.
KeymasterContext(const KeymasterContext&);
diff --git a/key_blob_utils/software_keyblobs.cpp b/key_blob_utils/software_keyblobs.cpp
index de038f0..764ebcb 100644
--- a/key_blob_utils/software_keyblobs.cpp
+++ b/key_blob_utils/software_keyblobs.cpp
@@ -381,10 +381,37 @@ keymaster_error_t SetKeyBlobAuthorizations(const AuthorizationSet& key_descripti
return TranslateAuthorizationSetError(sw_enforced->is_valid());
}
+keymaster_error_t ExtendKeyBlobAuthorizations(AuthorizationSet* hw_enforced,
+ AuthorizationSet* sw_enforced,
+ std::optional<uint32_t> vendor_patchlevel,
+ std::optional<uint32_t> boot_patchlevel) {
+ // If hw_enforced is non-empty, we're pretending to be some sort of secure hardware.
+ AuthorizationSet* pseudo_hw_enforced = (hw_enforced->empty()) ? sw_enforced : hw_enforced;
+ if (vendor_patchlevel.has_value()) {
+ pseudo_hw_enforced->push_back(TAG_VENDOR_PATCHLEVEL, vendor_patchlevel.value());
+ }
+ if (boot_patchlevel.has_value()) {
+ pseudo_hw_enforced->push_back(TAG_BOOT_PATCHLEVEL, boot_patchlevel.value());
+ }
+ return TranslateAuthorizationSetError(sw_enforced->is_valid());
+}
+
keymaster_error_t UpgradeSoftKeyBlob(const UniquePtr<Key>& key, const uint32_t os_version,
const uint32_t os_patchlevel,
const AuthorizationSet& upgrade_params,
KeymasterKeyBlob* upgraded_key) {
+ return FullUpgradeSoftKeyBlob(key, os_version, os_patchlevel,
+ /* vendor_patchlevel= */ std::nullopt,
+ /* boot_patchlevel= */ std::nullopt, //
+ upgrade_params, upgraded_key);
+}
+
+keymaster_error_t FullUpgradeSoftKeyBlob(const UniquePtr<Key>& key, const uint32_t os_version,
+ uint32_t os_patchlevel,
+ std::optional<uint32_t> vendor_patchlevel,
+ std::optional<uint32_t> boot_patchlevel,
+ const AuthorizationSet& upgrade_params,
+ KeymasterKeyBlob* upgraded_key) {
bool set_changed = false;
if (os_version == 0) {
@@ -402,13 +429,21 @@ keymaster_error_t UpgradeSoftKeyBlob(const UniquePtr<Key>& key, const uint32_t o
}
if (!UpgradeIntegerTag(TAG_OS_VERSION, os_version, &key->sw_enforced(), &set_changed) ||
- !UpgradeIntegerTag(TAG_OS_PATCHLEVEL, os_patchlevel, &key->sw_enforced(), &set_changed))
+ !UpgradeIntegerTag(TAG_OS_PATCHLEVEL, os_patchlevel, &key->sw_enforced(), &set_changed) ||
+ (vendor_patchlevel.has_value() &&
+ !UpgradeIntegerTag(TAG_VENDOR_PATCHLEVEL, vendor_patchlevel.value(), &key->sw_enforced(),
+ &set_changed)) ||
+ (boot_patchlevel.has_value() &&
+ !UpgradeIntegerTag(TAG_BOOT_PATCHLEVEL, boot_patchlevel.value(), &key->sw_enforced(),
+ &set_changed))) {
// One of the version fields would have been a downgrade. Not allowed.
return KM_ERROR_INVALID_ARGUMENT;
+ }
- if (!set_changed)
+ if (!set_changed) {
// Dont' need an upgrade.
return KM_ERROR_OK;
+ }
AuthorizationSet hidden;
auto error = BuildHiddenAuthorizations(upgrade_params, &hidden, softwareRootOfTrust);
diff --git a/tests/android_keymaster_messages_test.cpp b/tests/android_keymaster_messages_test.cpp
index 2c4ea0b..7b523a8 100644
--- a/tests/android_keymaster_messages_test.cpp
+++ b/tests/android_keymaster_messages_test.cpp
@@ -675,6 +675,47 @@ TEST(RoundTrip, ConfigureRequest) {
}
}
+TEST(RoundTrip, ConfigureResponse) {
+ for (int ver = 0; ver <= kMaxMessageVersion; ++ver) {
+ ConfigureResponse rsp(ver);
+ UniquePtr<ConfigureResponse> deserialized(round_trip(ver, rsp, 4));
+ }
+}
+
+TEST(RoundTrip, ConfigureVendorPatchlevelRequest) {
+ for (int ver = 0; ver <= kMaxMessageVersion; ++ver) {
+ ConfigureVendorPatchlevelRequest req(ver);
+ req.vendor_patchlevel = 2;
+
+ UniquePtr<ConfigureVendorPatchlevelRequest> deserialized(round_trip(ver, req, 4));
+ EXPECT_EQ(deserialized->vendor_patchlevel, req.vendor_patchlevel);
+ }
+}
+
+TEST(RoundTrip, ConfigureVendorPatchlevelResponse) {
+ for (int ver = 0; ver <= kMaxMessageVersion; ++ver) {
+ ConfigureVendorPatchlevelResponse rsp(ver);
+ UniquePtr<ConfigureVendorPatchlevelResponse> deserialized(round_trip(ver, rsp, 4));
+ }
+}
+
+TEST(RoundTrip, ConfigureBootPatchlevelRequest) {
+ for (int ver = 0; ver <= kMaxMessageVersion; ++ver) {
+ ConfigureBootPatchlevelRequest req(ver);
+ req.boot_patchlevel = 2;
+
+ UniquePtr<ConfigureBootPatchlevelRequest> deserialized(round_trip(ver, req, 4));
+ EXPECT_EQ(deserialized->boot_patchlevel, req.boot_patchlevel);
+ }
+}
+
+TEST(RoundTrip, ConfigureBootPatchlevelResponse) {
+ for (int ver = 0; ver <= kMaxMessageVersion; ++ver) {
+ ConfigureBootPatchlevelResponse rsp(ver);
+ UniquePtr<ConfigureBootPatchlevelResponse> deserialized(round_trip(ver, rsp, 4));
+ }
+}
+
TEST(RoundTrip, AddEntropyRequest) {
for (int ver = 0; ver <= kMaxMessageVersion; ++ver) {
AddEntropyRequest msg(ver);