1 /*
2  * Copyright 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef SYSTEM_SECURITY_KEYSTORE_KEYMASTER_TAGS_H_
18 #define SYSTEM_SECURITY_KEYSTORE_KEYMASTER_TAGS_H_
19 
20 /**
21  * This header contains various definitions that make working with keymaster tags safer and easier.
22  *
23  * It makes use of a fair amount of template metaprogramming. The metaprogramming serves the purpose
24  * of making it impossible to make certain classes of mistakes when operating on keymaster
25  * authorizations.  For example, it's an error to create a KeyParameter with tag == Tag::PURPOSE
26  * and then to assign Algorithm::RSA to algorithm element of its union. But because the user
27  * must choose the union field, there could be a mismatch which the compiler has now way to
28  * diagnose.
29  *
30  * The machinery in this header solves these problems by describing which union field corresponds
31  * to which Tag. Central to this mechanism is the template TypedTag. It has zero size and binds a
32  * numeric Tag to a type that the compiler understands. By means of the macro DECLARE_TYPED_TAG,
33  * we declare types for each of the tags defined in hardware/interfaces/keymaster/2.0/types.hal.
34  *
35  * The macro DECLARE_TYPED_TAG(name) generates a typename TAG_name_t and a zero sized instance
36  * TAG_name. Once these typed tags have been declared we define metafunctions mapping the each tag
37  * to its value c++ type and the correct union element of KeyParameter. This is done by means of
38  * the macros MAKE_TAG_*VALUE_ACCESSOR, which generates TypedTag2ValueType, a metafunction mapping
39  * a typed tag to the corresponding c++ type, and access function, accessTagValue returning a
40  * reference to the correct element of KeyParameter.
41  * E.g.:
42  *      given "KeyParameter param;" then "accessTagValue(TAG_PURPOSE, param)"
43  *      yields a reference to param.f.purpose
44  * If used in an assignment the compiler can now check the compatibility of the assigned value.
45  *
46  * For convenience we also provide the constructor like function Authorization().
47  * Authorization takes a typed tag and a value and checks at compile time whether the value given
48  * is suitable for the given tag. At runtime it creates a new KeyParameter initialized with the
49  * given tag and value and returns it by value.
50  *
51  * The second convenience function, authorizationValue, allows access to the KeyParameter value in
52  * a safe way. It takes a typed tag and a KeyParameter and returns a reference to the value wrapped
53  * by NullOr. NullOr has out-of-band information about whether it is save to access the wrapped
54  * reference.
55  * E.g.:
56  *      auto param = Authorization(TAG_ALGORITM, Algorithm::RSA);
57  *      auto value1 = authorizationValue(TAG_PURPOSE, param);
58  *      auto value2 = authorizationValue(TAG_ALGORITM, param);
59  * value1.isOk() yields false, but value2.isOk() yields true, thus value2.value() is save to access.
60  */
61 
62 #include <android/hardware/keymaster/3.0/IHwKeymasterDevice.h>
63 #include <hardware/hw_auth_token.h>
64 #include <type_traits>
65 
66 namespace keymaster {
67 namespace ng {
68 
69 using ::android::hardware::keymaster::V3_0::Algorithm;
70 using ::android::hardware::keymaster::V3_0::BlockMode;
71 using ::android::hardware::keymaster::V3_0::Digest;
72 using ::android::hardware::keymaster::V3_0::EcCurve;
73 using ::android::hardware::keymaster::V3_0::ErrorCode;
74 using ::android::hardware::keymaster::V3_0::HardwareAuthToken;
75 using ::android::hardware::keymaster::V3_0::HardwareAuthenticatorType;
76 using ::android::hardware::keymaster::V3_0::IKeymasterDevice;
77 using ::android::hardware::keymaster::V3_0::KeyBlobUsageRequirements;
78 using ::android::hardware::keymaster::V3_0::KeyCharacteristics;
79 using ::android::hardware::keymaster::V3_0::KeyDerivationFunction;
80 using ::android::hardware::keymaster::V3_0::KeyFormat;
81 using ::android::hardware::keymaster::V3_0::KeyOrigin;
82 using ::android::hardware::keymaster::V3_0::KeyParameter;
83 using ::android::hardware::keymaster::V3_0::KeyPurpose;
84 using ::android::hardware::keymaster::V3_0::PaddingMode;
85 using ::android::hardware::keymaster::V3_0::Tag;
86 using ::android::hardware::keymaster::V3_0::TagType;
87 
88 using ::android::hardware::hidl_vec;
89 using ::android::hardware::Return;
90 using ::android::hardware::Status;
91 
92 // The following create the numeric values that KM_TAG_PADDING and KM_TAG_DIGEST used to have.  We
93 // need these old values to be able to support old keys that use them.
94 static const int32_t KM_TAG_DIGEST_OLD = static_cast<int32_t>(TagType::ENUM) | 5;
95 static const int32_t KM_TAG_PADDING_OLD = static_cast<int32_t>(TagType::ENUM) | 7;
96 
typeFromTag(Tag tag)97 constexpr TagType typeFromTag(Tag tag) {
98     return static_cast<TagType>(static_cast<uint32_t>(tag) & static_cast<uint32_t>(0xf0000000));
99 }
100 
101 /**
102  * TypedTag is a templatized version of Tag, which provides compile-time checking of
103  * keymaster tag types. Instances are convertible to Tag, so they can be used wherever
104  * Tag is expected, and because they encode the tag type it's possible to create
105  * function overloads that only operate on tags with a particular type.
106  */
107 template <TagType tag_type, Tag tag> struct TypedTag {
TypedTagTypedTag108     inline TypedTag() {
109         // Ensure that it's impossible to create a TypedTag instance whose 'tag' doesn't have type
110         // 'tag_type'.  Attempting to instantiate a tag with the wrong type will result in a compile
111         // error (no match for template specialization StaticAssert<false>), with no run-time cost.
112         static_assert(typeFromTag(tag) == tag_type, "mismatch between tag and tag_type");
113     }
114     // NOLINTNEXTLINE(google-explicit-constructor)
TagTypedTag115     operator Tag() const { return tag; }
116 };
117 
118 template <Tag tag> struct Tag2TypedTag { typedef TypedTag<typeFromTag(tag), tag> type; };
119 
120 template <Tag tag> struct Tag2String;
121 
122 #define _TAGS_STRINGIFY(x) #x
123 #define TAGS_STRINGIFY(x) _TAGS_STRINGIFY(x)
124 
125 #define DECLARE_TYPED_TAG(name)                                                                    \
126     typedef typename Tag2TypedTag<Tag::name>::type TAG_##name##_t;                                 \
127     extern TAG_##name##_t TAG_##name;                                                              \
128     template <> struct Tag2String<Tag::name> {                                                     \
129         static const char* value() { return "Tag::" TAGS_STRINGIFY(name); }                        \
130     }
131 
132 DECLARE_TYPED_TAG(INVALID);
133 DECLARE_TYPED_TAG(KEY_SIZE);
134 DECLARE_TYPED_TAG(MAC_LENGTH);
135 DECLARE_TYPED_TAG(CALLER_NONCE);
136 DECLARE_TYPED_TAG(MIN_MAC_LENGTH);
137 DECLARE_TYPED_TAG(RSA_PUBLIC_EXPONENT);
138 DECLARE_TYPED_TAG(ECIES_SINGLE_HASH_MODE);
139 DECLARE_TYPED_TAG(INCLUDE_UNIQUE_ID);
140 DECLARE_TYPED_TAG(ACTIVE_DATETIME);
141 DECLARE_TYPED_TAG(ORIGINATION_EXPIRE_DATETIME);
142 DECLARE_TYPED_TAG(USAGE_EXPIRE_DATETIME);
143 DECLARE_TYPED_TAG(MIN_SECONDS_BETWEEN_OPS);
144 DECLARE_TYPED_TAG(MAX_USES_PER_BOOT);
145 DECLARE_TYPED_TAG(ALL_USERS);
146 DECLARE_TYPED_TAG(USER_ID);
147 DECLARE_TYPED_TAG(USER_SECURE_ID);
148 DECLARE_TYPED_TAG(NO_AUTH_REQUIRED);
149 DECLARE_TYPED_TAG(AUTH_TIMEOUT);
150 DECLARE_TYPED_TAG(ALLOW_WHILE_ON_BODY);
151 DECLARE_TYPED_TAG(ALL_APPLICATIONS);
152 DECLARE_TYPED_TAG(APPLICATION_ID);
153 DECLARE_TYPED_TAG(APPLICATION_DATA);
154 DECLARE_TYPED_TAG(CREATION_DATETIME);
155 DECLARE_TYPED_TAG(ROLLBACK_RESISTANT);
156 DECLARE_TYPED_TAG(ROOT_OF_TRUST);
157 DECLARE_TYPED_TAG(ASSOCIATED_DATA);
158 DECLARE_TYPED_TAG(NONCE);
159 DECLARE_TYPED_TAG(AUTH_TOKEN);
160 DECLARE_TYPED_TAG(BOOTLOADER_ONLY);
161 DECLARE_TYPED_TAG(OS_VERSION);
162 DECLARE_TYPED_TAG(OS_PATCHLEVEL);
163 DECLARE_TYPED_TAG(UNIQUE_ID);
164 DECLARE_TYPED_TAG(ATTESTATION_CHALLENGE);
165 DECLARE_TYPED_TAG(ATTESTATION_APPLICATION_ID);
166 DECLARE_TYPED_TAG(RESET_SINCE_ID_ROTATION);
167 
168 DECLARE_TYPED_TAG(PURPOSE);
169 DECLARE_TYPED_TAG(ALGORITHM);
170 DECLARE_TYPED_TAG(BLOCK_MODE);
171 DECLARE_TYPED_TAG(DIGEST);
172 DECLARE_TYPED_TAG(PADDING);
173 DECLARE_TYPED_TAG(BLOB_USAGE_REQUIREMENTS);
174 DECLARE_TYPED_TAG(ORIGIN);
175 DECLARE_TYPED_TAG(USER_AUTH_TYPE);
176 DECLARE_TYPED_TAG(KDF);
177 DECLARE_TYPED_TAG(EC_CURVE);
178 
179 template <typename... Elems> struct MetaList {};
180 
181 using all_tags_t = MetaList<
182     TAG_INVALID_t, TAG_KEY_SIZE_t, TAG_MAC_LENGTH_t, TAG_CALLER_NONCE_t, TAG_MIN_MAC_LENGTH_t,
183     TAG_RSA_PUBLIC_EXPONENT_t, TAG_ECIES_SINGLE_HASH_MODE_t, TAG_INCLUDE_UNIQUE_ID_t,
184     TAG_ACTIVE_DATETIME_t, TAG_ORIGINATION_EXPIRE_DATETIME_t, TAG_USAGE_EXPIRE_DATETIME_t,
185     TAG_MIN_SECONDS_BETWEEN_OPS_t, TAG_MAX_USES_PER_BOOT_t, TAG_ALL_USERS_t, TAG_USER_ID_t,
186     TAG_USER_SECURE_ID_t, TAG_NO_AUTH_REQUIRED_t, TAG_AUTH_TIMEOUT_t, TAG_ALLOW_WHILE_ON_BODY_t,
187     TAG_ALL_APPLICATIONS_t, TAG_APPLICATION_ID_t, TAG_APPLICATION_DATA_t, TAG_CREATION_DATETIME_t,
188     TAG_ROLLBACK_RESISTANT_t, TAG_ROOT_OF_TRUST_t, TAG_ASSOCIATED_DATA_t, TAG_NONCE_t,
189     TAG_AUTH_TOKEN_t, TAG_BOOTLOADER_ONLY_t, TAG_OS_VERSION_t, TAG_OS_PATCHLEVEL_t, TAG_UNIQUE_ID_t,
190     TAG_ATTESTATION_CHALLENGE_t, TAG_ATTESTATION_APPLICATION_ID_t, TAG_RESET_SINCE_ID_ROTATION_t,
191     TAG_PURPOSE_t, TAG_ALGORITHM_t, TAG_BLOCK_MODE_t, TAG_DIGEST_t, TAG_PADDING_t,
192     TAG_BLOB_USAGE_REQUIREMENTS_t, TAG_ORIGIN_t, TAG_USER_AUTH_TYPE_t, TAG_KDF_t, TAG_EC_CURVE_t>;
193 
194 /* implementation in keystore_utils.cpp */
195 extern const char* stringifyTag(Tag tag);
196 
197 template <typename TypedTagType> struct TypedTag2ValueType;
198 
199 #define MAKE_TAG_VALUE_ACCESSOR(tag_type, field_name)                                              \
200     template <Tag tag> struct TypedTag2ValueType<TypedTag<tag_type, tag>> {                        \
201         typedef decltype(static_cast<KeyParameter*>(nullptr)->field_name) type;                    \
202     };                                                                                             \
203     template <Tag tag>                                                                             \
204     inline auto accessTagValue(TypedTag<tag_type, tag>, const KeyParameter& param)                 \
205         ->const decltype(param.field_name)& {                                                      \
206         return param.field_name;                                                                   \
207     }                                                                                              \
208     template <Tag tag>                                                                             \
209     inline auto accessTagValue(TypedTag<tag_type, tag>, KeyParameter& param)                       \
210         ->decltype(param.field_name)& {                                                            \
211         return param.field_name;                                                                   \
212     }
213 
214 MAKE_TAG_VALUE_ACCESSOR(TagType::ULONG, f.longInteger)
215 MAKE_TAG_VALUE_ACCESSOR(TagType::ULONG_REP, f.longInteger)
216 MAKE_TAG_VALUE_ACCESSOR(TagType::DATE, f.dateTime)
217 MAKE_TAG_VALUE_ACCESSOR(TagType::UINT, f.integer)
218 MAKE_TAG_VALUE_ACCESSOR(TagType::UINT_REP, f.integer)
219 MAKE_TAG_VALUE_ACCESSOR(TagType::BOOL, f.boolValue)
MAKE_TAG_VALUE_ACCESSOR(TagType::BYTES,blob)220 MAKE_TAG_VALUE_ACCESSOR(TagType::BYTES, blob)
221 MAKE_TAG_VALUE_ACCESSOR(TagType::BIGNUM, blob)
222 
223 #define MAKE_TAG_ENUM_VALUE_ACCESSOR(typed_tag, field_name)                                        \
224     template <> struct TypedTag2ValueType<decltype(typed_tag)> {                                   \
225         typedef decltype(static_cast<KeyParameter*>(nullptr)->field_name) type;                    \
226     };                                                                                             \
227     inline auto accessTagValue(decltype(typed_tag), const KeyParameter& param)                     \
228         ->const decltype(param.field_name)& {                                                      \
229         return param.field_name;                                                                   \
230     }                                                                                              \
231     inline auto accessTagValue(decltype(typed_tag), KeyParameter& param)                           \
232         ->decltype(param.field_name)& {                                                            \
233         return param.field_name;                                                                   \
234     }
235 
236 MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_ALGORITHM, f.algorithm)
237 MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_BLOB_USAGE_REQUIREMENTS, f.keyBlobUsageRequirements)
238 MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_BLOCK_MODE, f.blockMode)
239 MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_DIGEST, f.digest)
240 MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_EC_CURVE, f.ecCurve)
241 MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_KDF, f.keyDerivationFunction)
242 MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_ORIGIN, f.origin)
243 MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_PADDING, f.paddingMode)
244 MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_PURPOSE, f.purpose)
245 MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_USER_AUTH_TYPE, f.hardwareAuthenticatorType)
246 
247 template <TagType tag_type, Tag tag, typename ValueT>
248 inline KeyParameter makeKeyParameter(TypedTag<tag_type, tag> ttag, ValueT&& value) {
249     KeyParameter param;
250     param.tag = tag;
251     param.f.longInteger = 0;
252     accessTagValue(ttag, param) = std::forward<ValueT>(value);
253     return param;
254 }
255 
256 // the boolean case
makeKeyParameter(TypedTag<TagType::BOOL,tag>)257 template <Tag tag> inline KeyParameter makeKeyParameter(TypedTag<TagType::BOOL, tag>) {
258     KeyParameter param;
259     param.tag = tag;
260     param.f.boolValue = true;
261     return param;
262 }
263 
264 template <typename... Pack> struct FirstOrNoneHelper;
265 template <typename First> struct FirstOrNoneHelper<First> { typedef First type; };
266 template <> struct FirstOrNoneHelper<> {
267     struct type {};
268 };
269 
270 template <typename... Pack> using FirstOrNone = typename FirstOrNoneHelper<Pack...>::type;
271 
272 template <TagType tag_type, Tag tag, typename... Args>
273 inline KeyParameter Authorization(TypedTag<tag_type, tag> ttag, Args&&... args) {
274     static_assert(tag_type != TagType::BOOL || (sizeof...(args) == 0),
275                   "TagType::BOOL Authorizations do not take parameters. Presence is truth.");
276     static_assert(tag_type == TagType::BOOL || (sizeof...(args) == 1),
277                   "Authorization other then TagType::BOOL take exactly one parameter.");
278     static_assert(
279         tag_type == TagType::BOOL ||
280             std::is_convertible<std::remove_cv_t<std::remove_reference_t<FirstOrNone<Args...>>>,
281                                 typename TypedTag2ValueType<TypedTag<tag_type, tag>>::type>::value,
282         "Invalid argument type for given tag.");
283 
284     return makeKeyParameter(ttag, std::forward<Args>(args)...);
285 }
286 
287 /**
288  * This class wraps a (mostly return) value and stores whether or not the wrapped value is valid out
289  * of band. Note that if the wrapped value is a reference it is unsafe to access the value if
290  * !isOk(). If the wrapped type is a pointer or value and !isOk(), it is still safe to access the
291  * wrapped value. In this case the pointer will be NULL though, and the value will be default
292  * constructed.
293  */
294 template <typename ValueT> class NullOr {
295     template <typename T> struct reference_initializer {
296         static T&& init() { return *static_cast<std::remove_reference_t<T>*>(nullptr); }
297     };
298     template <typename T> struct pointer_initializer {
299         static T init() { return nullptr; }
300     };
301     template <typename T> struct value_initializer {
302         static T init() { return T(); }
303     };
304     template <typename T>
305     using initializer_t =
306         std::conditional_t<std::is_lvalue_reference<T>::value, reference_initializer<T>,
307                            std::conditional_t<std::is_pointer<T>::value, pointer_initializer<T>,
308                                               value_initializer<T>>>;
309 
310   public:
311     NullOr() : value_(initializer_t<ValueT>::init()), null_(true) {}
312     // NOLINTNEXTLINE(google-explicit-constructor)
313     NullOr(ValueT&& value) : value_(std::forward<ValueT>(value)), null_(false) {}
314 
315     bool isOk() const { return !null_; }
316 
317     const ValueT& value() const & { return value_; }
318     ValueT& value() & { return value_; }
319     ValueT&& value() && { return std::move(value_); }
320 
321   private:
322     ValueT value_;
323     bool null_;
324 };
325 
326 template <typename T> std::remove_reference_t<T> NullOrOr(T&& v) {
327     if (v.isOk()) return v;
328     return {};
329 }
330 
331 template <typename Head, typename... Tail>
332 std::remove_reference_t<Head> NullOrOr(Head&& head, Tail&&... tail) {
333     if (head.isOk()) return head;
334     return NullOrOr(std::forward<Tail>(tail)...);
335 }
336 
337 template <typename Default, typename Wrapped>
338 std::remove_reference_t<Wrapped> defaultOr(NullOr<Wrapped>&& optional, Default&& def) {
339     static_assert(std::is_convertible<std::remove_reference_t<Default>,
340                                       std::remove_reference_t<Wrapped>>::value,
341                   "Type of default value must match the type wrapped by NullOr");
342     if (optional.isOk()) return optional.value();
343     return def;
344 }
345 
346 template <TagType tag_type, Tag tag>
347 inline NullOr<const typename TypedTag2ValueType<TypedTag<tag_type, tag>>::type&>
348 authorizationValue(TypedTag<tag_type, tag> ttag, const KeyParameter& param) {
349     if (tag != param.tag) return {};
350     return accessTagValue(ttag, param);
351 }
352 
353 }  // namespace ng
354 }  // namespace keymaster
355 
356 #endif  // SYSTEM_SECURITY_KEYSTORE_KEYMASTER_TAGS_H_
357