Revise keymint_tags.h
* replace NullOr with std::optional.
* Add mising tag.
* Undefine helper macros so that keymint_tags.h can be used together
with keymaster_tags.h
* Check if KeyParameterValue variant matches KeyParameterTag in
accessors.
Test: VtsAidlKeyMintTargetTest
Change-Id: I6c951071f30fd27c8c21a2e8cc86f421a3bc37d9
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
index 9ba4099..94bc199 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
@@ -577,8 +577,8 @@
string ciphertext = EncryptMessage(message, params, &out_params);
EXPECT_EQ(1U, out_params.size());
auto ivVal = out_params.GetTagValue(TAG_NONCE);
- EXPECT_TRUE(ivVal.isOk());
- if (ivVal.isOk()) *iv_out = ivVal.value();
+ EXPECT_TRUE(ivVal);
+ if (ivVal) *iv_out = *ivVal;
return ciphertext;
}
diff --git a/security/keymint/aidl/vts/functional/KeyMintTest.cpp b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
index 6e38539..3060153 100644
--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
@@ -80,7 +80,10 @@
template <TagType tag_type, Tag tag, typename ValueT>
bool contains(vector<KeyParameter>& set, TypedTag<tag_type, tag> ttag, ValueT expected_value) {
auto it = std::find_if(set.begin(), set.end(), [&](const KeyParameter& param) {
- return param.tag == tag && accessTagValue(ttag, param) == expected_value;
+ if (auto p = authorizationValue(ttag, param)) {
+ return *p == expected_value;
+ }
+ return false;
});
return (it != set.end());
}
@@ -251,10 +254,10 @@
EXPECT_TRUE(auths.Contains(TAG_OS_VERSION, os_version()))
<< "OS version is " << os_version() << " key reported "
- << auths.GetTagValue(TAG_OS_VERSION);
+ << auths.GetTagValue(TAG_OS_VERSION)->get();
EXPECT_TRUE(auths.Contains(TAG_OS_PATCHLEVEL, os_patch_level()))
<< "OS patch level is " << os_patch_level() << " key reported "
- << auths.GetTagValue(TAG_OS_PATCHLEVEL);
+ << auths.GetTagValue(TAG_OS_PATCHLEVEL)->get();
}
};
@@ -2333,8 +2336,8 @@
vector<uint8_t> CopyIv(const AuthorizationSet& set) {
auto iv = set.GetTagValue(TAG_NONCE);
- EXPECT_TRUE(iv.isOk());
- return iv.value();
+ EXPECT_TRUE(iv);
+ return iv->get();
}
/*
@@ -2459,13 +2462,13 @@
case BlockMode::CBC:
case BlockMode::GCM:
case BlockMode::CTR:
- ASSERT_TRUE(iv.isOk()) << "No IV for block mode " << block_mode;
- EXPECT_EQ(block_mode == BlockMode::GCM ? 12U : 16U, iv.value().size());
- params.push_back(TAG_NONCE, iv.value());
+ ASSERT_TRUE(iv) << "No IV for block mode " << block_mode;
+ EXPECT_EQ(block_mode == BlockMode::GCM ? 12U : 16U, iv->get().size());
+ params.push_back(TAG_NONCE, iv->get());
break;
case BlockMode::ECB:
- EXPECT_FALSE(iv.isOk()) << "ECB mode should not generate IV";
+ EXPECT_FALSE(iv) << "ECB mode should not generate IV";
break;
}
@@ -2649,9 +2652,9 @@
AuthorizationSet out_params;
string ciphertext = EncryptMessage(message, params, &out_params);
EXPECT_EQ(message.size(), ciphertext.size());
- EXPECT_EQ(16U, out_params.GetTagValue(TAG_NONCE).value().size());
+ EXPECT_EQ(16U, out_params.GetTagValue(TAG_NONCE)->get().size());
- params.push_back(TAG_NONCE, out_params.GetTagValue(TAG_NONCE).value());
+ params.push_back(TAG_NONCE, out_params.GetTagValue(TAG_NONCE)->get());
string plaintext = DecryptMessage(ciphertext, params);
EXPECT_EQ(message, plaintext);
@@ -2697,9 +2700,9 @@
AuthorizationSet out_params;
string ciphertext = EncryptMessage(message, params, &out_params);
EXPECT_EQ(message.size(), ciphertext.size());
- EXPECT_EQ(16U, out_params.GetTagValue(TAG_NONCE).value().size());
+ EXPECT_EQ(16U, out_params.GetTagValue(TAG_NONCE)->get().size());
- params.push_back(TAG_NONCE, out_params.GetTagValue(TAG_NONCE).value());
+ params.push_back(TAG_NONCE, out_params.GetTagValue(TAG_NONCE)->get());
string plaintext = DecryptMessage(ciphertext, params);
EXPECT_EQ(message, plaintext);
@@ -2893,7 +2896,7 @@
AuthorizationSet begin_out_params;
EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params, &begin_out_params));
EXPECT_EQ(1U, begin_out_params.size());
- ASSERT_TRUE(begin_out_params.GetTagValue(TAG_NONCE).isOk());
+ ASSERT_TRUE(begin_out_params.GetTagValue(TAG_NONCE));
AuthorizationSet finish_out_params;
string ciphertext;
diff --git a/security/keymint/support/authorization_set.cpp b/security/keymint/support/authorization_set.cpp
index 37b6cd1..f98851c 100644
--- a/security/keymint/support/authorization_set.cpp
+++ b/security/keymint/support/authorization_set.cpp
@@ -106,10 +106,11 @@
return false;
}
-NullOr<const KeyParameter&> AuthorizationSet::GetEntry(Tag tag) const {
+std::optional<std::reference_wrapper<const KeyParameter>> AuthorizationSet::GetEntry(
+ Tag tag) const {
int pos = find(tag);
if (pos == -1) return {};
- return data_[pos];
+ return std::reference_wrapper(data_[pos]);
}
AuthorizationSetBuilder& AuthorizationSetBuilder::RsaKey(uint32_t key_size,
diff --git a/security/keymint/support/include/keymint_support/authorization_set.h b/security/keymint/support/include/keymint_support/authorization_set.h
index c85f305..4ff1705 100644
--- a/security/keymint/support/include/keymint_support/authorization_set.h
+++ b/security/keymint/support/include/keymint_support/authorization_set.h
@@ -168,7 +168,7 @@
bool Contains(TypedTag<tag_type, tag> ttag, const ValueT& value) const {
for (const auto& param : data_) {
auto entry = authorizationValue(ttag, param);
- if (entry.isOk() && static_cast<ValueT>(entry.value()) == value) return true;
+ if (entry && static_cast<ValueT>(*entry) == value) return true;
}
return false;
}
@@ -178,9 +178,9 @@
size_t GetTagCount(Tag tag) const;
template <typename T>
- inline NullOr<const typename TypedTag2ValueType<T>::type&> GetTagValue(T tag) const {
+ inline auto GetTagValue(T tag) const -> decltype(authorizationValue(tag, KeyParameter())) {
auto entry = GetEntry(tag);
- if (entry.isOk()) return authorizationValue(tag, entry.value());
+ if (entry) return authorizationValue(tag, *entry);
return {};
}
@@ -219,7 +219,7 @@
}
private:
- NullOr<const KeyParameter&> GetEntry(Tag tag) const;
+ std::optional<std::reference_wrapper<const KeyParameter>> GetEntry(Tag tag) const;
std::vector<KeyParameter> data_;
};
diff --git a/security/keymint/support/include/keymint_support/key_param_output.h b/security/keymint/support/include/keymint_support/key_param_output.h
index 6e0e35d..5f004fe 100644
--- a/security/keymint/support/include/keymint_support/key_param_output.h
+++ b/security/keymint/support/include/keymint_support/key_param_output.h
@@ -71,7 +71,7 @@
}
template <typename ValueT>
-::std::ostream& operator<<(::std::ostream& os, const NullOr<ValueT>& value) {
+::std::ostream& operator<<(::std::ostream& os, const std::optional<ValueT>& value) {
if (!value.isOk()) {
os << "(value not present)";
} else {
diff --git a/security/keymint/support/include/keymint_support/keymint_tags.h b/security/keymint/support/include/keymint_support/keymint_tags.h
index c443c53..d932b40 100644
--- a/security/keymint/support/include/keymint_support/keymint_tags.h
+++ b/security/keymint/support/include/keymint_support/keymint_tags.h
@@ -58,6 +58,10 @@
typedef TypedTag<typeFromTag(tag), tag> type;
};
+#ifdef DECLARE_TYPED_TAG
+#undef DECLARE_TYPED_TAG
+#endif
+
#define DECLARE_TYPED_TAG(name) \
typedef typename Tag2TypedTag<Tag::name>::type TAG_##name##_t; \
static TAG_##name##_t TAG_##name;
@@ -72,9 +76,12 @@
DECLARE_TYPED_TAG(ATTESTATION_CHALLENGE);
DECLARE_TYPED_TAG(ATTESTATION_ID_BRAND);
DECLARE_TYPED_TAG(ATTESTATION_ID_DEVICE);
-DECLARE_TYPED_TAG(ATTESTATION_ID_PRODUCT);
+DECLARE_TYPED_TAG(ATTESTATION_ID_IMEI);
DECLARE_TYPED_TAG(ATTESTATION_ID_MANUFACTURER);
+DECLARE_TYPED_TAG(ATTESTATION_ID_MEID);
+DECLARE_TYPED_TAG(ATTESTATION_ID_PRODUCT);
DECLARE_TYPED_TAG(ATTESTATION_ID_MODEL);
+DECLARE_TYPED_TAG(ATTESTATION_ID_SERIAL);
DECLARE_TYPED_TAG(AUTH_TIMEOUT);
DECLARE_TYPED_TAG(BLOCK_MODE);
DECLARE_TYPED_TAG(BOOTLOADER_ONLY);
@@ -118,6 +125,8 @@
DECLARE_TYPED_TAG(USER_SECURE_ID);
DECLARE_TYPED_TAG(VENDOR_PATCHLEVEL);
+#undef DECLARE_TYPED_TAG
+
template <typename... Elems>
struct MetaList {};
@@ -133,6 +142,7 @@
TAG_OS_VERSION_t, TAG_OS_PATCHLEVEL_t, TAG_UNIQUE_ID_t, TAG_ATTESTATION_CHALLENGE_t,
TAG_ATTESTATION_APPLICATION_ID_t, TAG_ATTESTATION_ID_BRAND_t, TAG_ATTESTATION_ID_DEVICE_t,
TAG_ATTESTATION_ID_PRODUCT_t, TAG_ATTESTATION_ID_MANUFACTURER_t, TAG_ATTESTATION_ID_MODEL_t,
+ TAG_ATTESTATION_ID_SERIAL_t, TAG_ATTESTATION_ID_IMEI_t, TAG_ATTESTATION_ID_MEID_t,
TAG_RESET_SINCE_ID_ROTATION_t, TAG_PURPOSE_t, TAG_ALGORITHM_t, TAG_BLOCK_MODE_t,
TAG_DIGEST_t, TAG_PADDING_t, TAG_ORIGIN_t, TAG_USER_AUTH_TYPE_t, TAG_EC_CURVE_t,
TAG_BOOT_PATCHLEVEL_t, TAG_VENDOR_PATCHLEVEL_t, TAG_TRUSTED_CONFIRMATION_REQUIRED_t,
@@ -141,21 +151,39 @@
template <typename TypedTagType>
struct TypedTag2ValueType;
-#define MAKE_TAG_VALUE_ACCESSOR(tag_type, field_name) \
- template <Tag tag> \
- struct TypedTag2ValueType<TypedTag<tag_type, tag>> { \
- using type = std::remove_reference<decltype( \
- static_cast<KeyParameterValue*>(nullptr) \
- ->get<KeyParameterValue::field_name>())>::type; \
- static constexpr KeyParameterValue::Tag unionTag = KeyParameterValue::field_name; \
- }; \
- template <Tag tag> \
- inline auto& accessTagValue(TypedTag<tag_type, tag>, const KeyParameter& param) { \
- return param.value.get<KeyParameterValue::field_name>(); \
- } \
- template <Tag tag> \
- inline auto& accessTagValue(TypedTag<tag_type, tag>, KeyParameter& param) { \
- return param.value.get<KeyParameterValue::field_name>(); \
+#ifdef MAKE_TAG_VALUE_ACCESSOR
+#undef MAKE_TAG_VALUE_ACCESSOR
+#endif
+
+#define MAKE_TAG_VALUE_ACCESSOR(tag_type, field_name) \
+ template <Tag tag> \
+ struct TypedTag2ValueType<TypedTag<tag_type, tag>> { \
+ using type = std::remove_reference< \
+ decltype(static_cast<KeyParameterValue*>(nullptr) \
+ ->get<KeyParameterValue::field_name>())>::type; \
+ static constexpr KeyParameterValue::Tag unionTag = KeyParameterValue::field_name; \
+ }; \
+ template <Tag tag> \
+ inline std::optional<std::reference_wrapper< \
+ const typename TypedTag2ValueType<TypedTag<tag_type, tag>>::type>> \
+ accessTagValue(TypedTag<tag_type, tag>, const KeyParameter& param) { \
+ if (param.value.getTag() == KeyParameterValue::field_name) { \
+ return std::optional( \
+ std::reference_wrapper(param.value.get<KeyParameterValue::field_name>())); \
+ } else { \
+ return std::nullopt; \
+ } \
+ } \
+ template <Tag tag> \
+ inline std::optional< \
+ std::reference_wrapper<typename TypedTag2ValueType<TypedTag<tag_type, tag>>::type>> \
+ accessTagValue(TypedTag<tag_type, tag>, KeyParameter& param) { \
+ if (param.value.getTag() == KeyParameterValue::field_name) { \
+ return std::optional( \
+ std::reference_wrapper(param.value.get<KeyParameterValue::field_name>())); \
+ } else { \
+ return std::nullopt; \
+ } \
}
MAKE_TAG_VALUE_ACCESSOR(TagType::ULONG, longInteger)
@@ -167,19 +195,39 @@
MAKE_TAG_VALUE_ACCESSOR(TagType::BYTES, blob)
MAKE_TAG_VALUE_ACCESSOR(TagType::BIGNUM, blob)
-#define MAKE_TAG_ENUM_VALUE_ACCESSOR(typed_tag, field_name) \
- template <> \
- struct TypedTag2ValueType<decltype(typed_tag)> { \
- using type = std::remove_reference<decltype( \
- static_cast<KeyParameterValue*>(nullptr) \
- ->get<KeyParameterValue::field_name>())>::type; \
- static constexpr KeyParameterValue::Tag unionTag = KeyParameterValue::field_name; \
- }; \
- inline auto& accessTagValue(decltype(typed_tag), const KeyParameter& param) { \
- return param.value.get<KeyParameterValue::field_name>(); \
- } \
- inline auto& accessTagValue(decltype(typed_tag), KeyParameter& param) { \
- return param.value.get<KeyParameterValue::field_name>(); \
+#undef MAKE_TAG_VALUE_ACCESSOR
+
+#ifdef MAKE_TAG_ENUM_VALUE_ACCESSOR
+#undef MAKE_TAG_ENUM_VALUE_ACCESSOR
+#endif
+
+#define MAKE_TAG_ENUM_VALUE_ACCESSOR(typed_tag, field_name) \
+ template <> \
+ struct TypedTag2ValueType<decltype(typed_tag)> { \
+ using type = std::remove_reference< \
+ decltype(static_cast<KeyParameterValue*>(nullptr) \
+ ->get<KeyParameterValue::field_name>())>::type; \
+ static constexpr KeyParameterValue::Tag unionTag = KeyParameterValue::field_name; \
+ }; \
+ inline std::optional< \
+ std::reference_wrapper<const typename TypedTag2ValueType<decltype(typed_tag)>::type>> \
+ accessTagValue(decltype(typed_tag), const KeyParameter& param) { \
+ if (param.value.getTag() == KeyParameterValue::field_name) { \
+ return std::optional( \
+ std::reference_wrapper(param.value.get<KeyParameterValue::field_name>())); \
+ } else { \
+ return std::nullopt; \
+ } \
+ } \
+ inline std::optional< \
+ std::reference_wrapper<typename TypedTag2ValueType<decltype(typed_tag)>::type>> \
+ accessTagValue(decltype(typed_tag), KeyParameter& param) { \
+ if (param.value.getTag() == KeyParameterValue::field_name) { \
+ return std::optional( \
+ std::reference_wrapper(param.value.get<KeyParameterValue::field_name>())); \
+ } else { \
+ return std::nullopt; \
+ } \
}
MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_ALGORITHM, algorithm)
@@ -192,6 +240,8 @@
MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_USER_AUTH_TYPE, hardwareAuthenticatorType)
MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_HARDWARE_TYPE, securityLevel)
+#undef MAKE_TAG_ENUM_VALUE_ACCESSOR
+
template <TagType tag_type, Tag tag, typename ValueT>
inline KeyParameter makeKeyParameter(TypedTag<tag_type, tag> ttag, ValueT&& value) {
KeyParameter retval;
@@ -210,6 +260,14 @@
return retval;
}
+// the invalid case
+inline KeyParameter makeKeyParameter(TypedTag<TagType::INVALID, Tag::INVALID>) {
+ KeyParameter retval;
+ retval.tag = Tag::INVALID;
+ retval.value = KeyParameterValue::make<KeyParameterValue::invalid>(0);
+ return retval;
+}
+
template <typename... Pack>
struct FirstOrNoneHelper;
template <typename First>
@@ -240,88 +298,31 @@
return makeKeyParameter(ttag, std::forward<Args>(args)...);
}
-/**
- * This class wraps a (mostly return) value and stores whether or not the wrapped value is valid out
- * of band. Note that if the wrapped value is a reference it is unsafe to access the value if
- * !isOk(). If the wrapped type is a pointer or value and !isOk(), it is still safe to access the
- * wrapped value. In this case the pointer will be NULL though, and the value will be default
- * constructed.
- *
- * TODO(seleneh) replace this with std::optional.
- */
-template <typename ValueT>
-class NullOr {
- using internal_t = std::conditional_t<std::is_lvalue_reference<ValueT>::value,
- std::remove_reference_t<ValueT>*, ValueT>;
-
- struct pointer_initializer {
- static std::nullptr_t init() { return nullptr; }
- };
- struct value_initializer {
- static ValueT init() { return ValueT(); }
- };
- struct value_pointer_deref_t {
- static ValueT& deref(ValueT& v) { return v; }
- };
- struct reference_deref_t {
- static auto& deref(internal_t v) { return *v; }
- };
- using initializer_t = std::conditional_t<std::is_lvalue_reference<ValueT>::value ||
- std::is_pointer<ValueT>::value,
- pointer_initializer, value_initializer>;
- using deref_t = std::conditional_t<std::is_lvalue_reference<ValueT>::value, reference_deref_t,
- value_pointer_deref_t>;
-
- public:
- NullOr() : value_(initializer_t::init()), null_(true) {}
- template <typename T>
- NullOr(T&& value, typename std::enable_if<
- !std::is_lvalue_reference<ValueT>::value &&
- std::is_same<std::decay_t<ValueT>, std::decay_t<T>>::value,
- int>::type = 0)
- : value_(std::forward<ValueT>(value)), null_(false) {}
- template <typename T>
- NullOr(T& value, typename std::enable_if<
- std::is_lvalue_reference<ValueT>::value &&
- std::is_same<std::decay_t<ValueT>, std::decay_t<T>>::value,
- int>::type = 0)
- : value_(&value), null_(false) {}
-
- bool isOk() const { return !null_; }
-
- const ValueT& value() const& { return deref_t::deref(value_); }
- ValueT& value() & { return deref_t::deref(value_); }
- ValueT&& value() && { return std::move(deref_t::deref(value_)); }
-
- private:
- internal_t value_;
- bool null_;
-};
-
template <typename T>
std::remove_reference_t<T> NullOrOr(T&& v) {
- if (v.isOk()) return v;
+ if (v) return v;
return {};
}
template <typename Head, typename... Tail>
std::remove_reference_t<Head> NullOrOr(Head&& head, Tail&&... tail) {
- if (head.isOk()) return head;
+ if (head) return head;
return NullOrOr(std::forward<Tail>(tail)...);
}
template <typename Default, typename Wrapped>
-std::remove_reference_t<Wrapped> defaultOr(NullOr<Wrapped>&& optional, Default&& def) {
+std::remove_reference_t<Wrapped> defaultOr(std::optional<Wrapped>&& optional, Default&& def) {
static_assert(std::is_convertible<std::remove_reference_t<Default>,
std::remove_reference_t<Wrapped>>::value,
- "Type of default value must match the type wrapped by NullOr");
- if (optional.isOk()) return optional.value();
+ "Type of default value must match the type wrapped by std::optional");
+ if (optional) return *optional;
return def;
}
template <TagType tag_type, Tag tag>
-inline NullOr<const typename TypedTag2ValueType<TypedTag<tag_type, tag>>::type&> authorizationValue(
- TypedTag<tag_type, tag> ttag, const KeyParameter& param) {
+inline std::optional<
+ std::reference_wrapper<const typename TypedTag2ValueType<TypedTag<tag_type, tag>>::type>>
+authorizationValue(TypedTag<tag_type, tag> ttag, const KeyParameter& param) {
if (TypedTag2ValueType<TypedTag<tag_type, tag>>::unionTag != param.value.getTag()) return {};
return accessTagValue(ttag, param);
}