Merge "Revise keymint_tags.h"

This commit is contained in:
Treehugger Robot 2020-12-21 18:11:08 +00:00 committed by Gerrit Code Review
commit 2528ddcab2
6 changed files with 122 additions and 117 deletions

View file

@ -577,8 +577,8 @@ string KeyMintAidlTestBase::EncryptMessage(const string& message, BlockMode bloc
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;
}

View file

@ -80,7 +80,10 @@ namespace {
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 @@ class NewKeyGenerationTest : public KeyMintAidlTestBase {
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 @@ TEST_P(EncryptionOperationsTest, AesEcbPkcs7PaddingCorrupted) {
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 @@ TEST_P(EncryptionOperationsTest, AesIncremental) {
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 @@ TEST_P(EncryptionOperationsTest, AesCallerNonce) {
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 @@ TEST_P(EncryptionOperationsTest, AesCallerNonceProhibited) {
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 @@ TEST_P(EncryptionOperationsTest, AesGcmTooShortTagOnDecrypt) {
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;

View file

@ -106,10 +106,11 @@ bool AuthorizationSet::erase(int index) {
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,

View file

@ -168,7 +168,7 @@ class AuthorizationSet {
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 @@ class AuthorizationSet {
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 @@ class AuthorizationSet {
}
private:
NullOr<const KeyParameter&> GetEntry(Tag tag) const;
std::optional<std::reference_wrapper<const KeyParameter>> GetEntry(Tag tag) const;
std::vector<KeyParameter> data_;
};

View file

@ -71,7 +71,7 @@ inline ::std::ostream& operator<<(::std::ostream& os, SecurityLevel value) {
}
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 {

View file

@ -58,6 +58,10 @@ struct Tag2TypedTag {
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_APPLICATION_ID);
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_ID);
DECLARE_TYPED_TAG(USER_SECURE_ID);
DECLARE_TYPED_TAG(VENDOR_PATCHLEVEL);
#undef DECLARE_TYPED_TAG
template <typename... Elems>
struct MetaList {};
@ -133,6 +142,7 @@ using all_tags_t = MetaList<
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 @@ using all_tags_t = MetaList<
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::BOOL, boolValue)
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_PURPOSE, keyPurpose)
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 @@ inline KeyParameter makeKeyParameter(TypedTag<TagType::BOOL, tag>) {
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 @@ inline KeyParameter Authorization(TypedTag<tag_type, tag> ttag, Args&&... args)
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);
}