• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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 #pragma once
18 
19 #include <aidl/android/hardware/security/keymint/Algorithm.h>
20 #include <aidl/android/hardware/security/keymint/BlockMode.h>
21 #include <aidl/android/hardware/security/keymint/Digest.h>
22 #include <aidl/android/hardware/security/keymint/EcCurve.h>
23 #include <aidl/android/hardware/security/keymint/HardwareAuthenticatorType.h>
24 #include <aidl/android/hardware/security/keymint/KeyOrigin.h>
25 #include <aidl/android/hardware/security/keymint/KeyParameter.h>
26 #include <aidl/android/hardware/security/keymint/KeyPurpose.h>
27 #include <aidl/android/hardware/security/keymint/PaddingMode.h>
28 #include <aidl/android/hardware/security/keymint/SecurityLevel.h>
29 #include <aidl/android/hardware/security/keymint/Tag.h>
30 #include <aidl/android/hardware/security/keymint/TagType.h>
31 
32 namespace aidl::android::hardware::security::keymint {
33 
typeFromTag(Tag tag)34 constexpr TagType typeFromTag(Tag tag) {
35     return static_cast<TagType>(static_cast<uint32_t>(tag) & static_cast<uint32_t>(0xf0000000));
36 }
37 
38 /**
39  * TypedTag is a templatized version of Tag, which provides compile-time checking of KeyMint tag
40  * types.  Instances are convertible to Tag, so they can be used wherever Tag is expected, and
41  * because they encode the tag type it's possible to create function overloads that only operate on
42  * tags with a particular type.
43  */
44 template <TagType tag_type, Tag tag>
45 struct TypedTag {
TypedTagTypedTag46     inline TypedTag() {
47         // Ensure that it's impossible to create a TypedTag instance whose 'tag' doesn't have type
48         // 'tag_type'.  Attempting to instantiate a tag with the wrong type will result in a compile
49         // error (no match for template specialization StaticAssert<false>), with no run-time cost.
50         static_assert(typeFromTag(tag) == tag_type, "mismatch between tag and tag_type");
51     }
TagTypedTag52     operator Tag() const { return tag; }
maskedTagTypedTag53     int32_t maskedTag() { return static_cast<uint32_t>(tag) & 0x0FFFFFFF; }
54 };
55 
56 template <Tag tag>
57 struct Tag2TypedTag {
58     typedef TypedTag<typeFromTag(tag), tag> type;
59 };
60 
61 #ifdef DECLARE_TYPED_TAG
62 #undef DECLARE_TYPED_TAG
63 #endif
64 
65 #define DECLARE_TYPED_TAG(name)                                    \
66     typedef typename Tag2TypedTag<Tag::name>::type TAG_##name##_t; \
67     static TAG_##name##_t TAG_##name;
68 
69 DECLARE_TYPED_TAG(ACTIVE_DATETIME);
70 DECLARE_TYPED_TAG(ALGORITHM);
71 DECLARE_TYPED_TAG(ALLOW_WHILE_ON_BODY);
72 DECLARE_TYPED_TAG(APPLICATION_DATA);
73 DECLARE_TYPED_TAG(APPLICATION_ID);
74 DECLARE_TYPED_TAG(ASSOCIATED_DATA);
75 DECLARE_TYPED_TAG(ATTESTATION_APPLICATION_ID);
76 DECLARE_TYPED_TAG(ATTESTATION_CHALLENGE);
77 DECLARE_TYPED_TAG(ATTESTATION_ID_BRAND);
78 DECLARE_TYPED_TAG(ATTESTATION_ID_DEVICE);
79 DECLARE_TYPED_TAG(ATTESTATION_ID_IMEI);
80 DECLARE_TYPED_TAG(ATTESTATION_ID_SECOND_IMEI);
81 DECLARE_TYPED_TAG(ATTESTATION_ID_MANUFACTURER);
82 DECLARE_TYPED_TAG(ATTESTATION_ID_MEID);
83 DECLARE_TYPED_TAG(ATTESTATION_ID_PRODUCT);
84 DECLARE_TYPED_TAG(ATTESTATION_ID_MODEL);
85 DECLARE_TYPED_TAG(ATTESTATION_ID_SERIAL);
86 DECLARE_TYPED_TAG(AUTH_TIMEOUT);
87 DECLARE_TYPED_TAG(BLOCK_MODE);
88 DECLARE_TYPED_TAG(BOOTLOADER_ONLY);
89 DECLARE_TYPED_TAG(BOOT_PATCHLEVEL);
90 DECLARE_TYPED_TAG(CALLER_NONCE);
91 DECLARE_TYPED_TAG(CONFIRMATION_TOKEN);
92 DECLARE_TYPED_TAG(CREATION_DATETIME);
93 DECLARE_TYPED_TAG(DEVICE_UNIQUE_ATTESTATION);
94 DECLARE_TYPED_TAG(DIGEST);
95 DECLARE_TYPED_TAG(EARLY_BOOT_ONLY);
96 DECLARE_TYPED_TAG(EC_CURVE);
97 DECLARE_TYPED_TAG(HARDWARE_TYPE);
98 DECLARE_TYPED_TAG(IDENTITY_CREDENTIAL_KEY);
99 DECLARE_TYPED_TAG(INCLUDE_UNIQUE_ID);
100 DECLARE_TYPED_TAG(INVALID);
101 DECLARE_TYPED_TAG(KEY_SIZE);
102 DECLARE_TYPED_TAG(MAC_LENGTH);
103 DECLARE_TYPED_TAG(MAX_USES_PER_BOOT);
104 DECLARE_TYPED_TAG(MIN_MAC_LENGTH);
105 DECLARE_TYPED_TAG(MIN_SECONDS_BETWEEN_OPS);
106 // TODO: remove special case macro once v4 HAL is frozen
107 #ifdef KEYMINT_HAL_V4
108 DECLARE_TYPED_TAG(MODULE_HASH);
109 #else
110 // When building for previous frozen HAL, the `Tag::MODULE_NAME` constant is not available.
111 static const Tag Tag_MODULE_HASH = static_cast<Tag>(-1879047468);
112 typedef typename Tag2TypedTag<Tag_MODULE_HASH>::type TAG_MODULE_HASH_t;
113 static TAG_MODULE_HASH_t TAG_MODULE_HASH;
114 #endif
115 DECLARE_TYPED_TAG(NONCE);
116 DECLARE_TYPED_TAG(NO_AUTH_REQUIRED);
117 DECLARE_TYPED_TAG(ORIGIN);
118 DECLARE_TYPED_TAG(ORIGINATION_EXPIRE_DATETIME);
119 DECLARE_TYPED_TAG(OS_PATCHLEVEL);
120 DECLARE_TYPED_TAG(OS_VERSION);
121 DECLARE_TYPED_TAG(PADDING);
122 DECLARE_TYPED_TAG(PURPOSE);
123 DECLARE_TYPED_TAG(RESET_SINCE_ID_ROTATION);
124 DECLARE_TYPED_TAG(ROLLBACK_RESISTANCE);
125 DECLARE_TYPED_TAG(ROOT_OF_TRUST);
126 DECLARE_TYPED_TAG(RSA_PUBLIC_EXPONENT);
127 DECLARE_TYPED_TAG(STORAGE_KEY);
128 DECLARE_TYPED_TAG(TRUSTED_CONFIRMATION_REQUIRED);
129 DECLARE_TYPED_TAG(TRUSTED_USER_PRESENCE_REQUIRED);
130 DECLARE_TYPED_TAG(UNIQUE_ID);
131 DECLARE_TYPED_TAG(UNLOCKED_DEVICE_REQUIRED);
132 DECLARE_TYPED_TAG(USAGE_COUNT_LIMIT);
133 DECLARE_TYPED_TAG(USAGE_EXPIRE_DATETIME);
134 DECLARE_TYPED_TAG(USER_AUTH_TYPE);
135 DECLARE_TYPED_TAG(USER_ID);
136 DECLARE_TYPED_TAG(USER_SECURE_ID);
137 DECLARE_TYPED_TAG(VENDOR_PATCHLEVEL);
138 DECLARE_TYPED_TAG(RSA_OAEP_MGF_DIGEST);
139 DECLARE_TYPED_TAG(CERTIFICATE_SERIAL);
140 DECLARE_TYPED_TAG(CERTIFICATE_SUBJECT);
141 DECLARE_TYPED_TAG(CERTIFICATE_NOT_BEFORE);
142 DECLARE_TYPED_TAG(CERTIFICATE_NOT_AFTER);
143 DECLARE_TYPED_TAG(MAX_BOOT_LEVEL);
144 
145 #undef DECLARE_TYPED_TAG
146 
147 template <typename... Elems>
148 struct MetaList {};
149 
150 using all_tags_t = MetaList<
151         TAG_INVALID_t, TAG_KEY_SIZE_t, TAG_MAC_LENGTH_t, TAG_CALLER_NONCE_t, TAG_MIN_MAC_LENGTH_t,
152         TAG_RSA_PUBLIC_EXPONENT_t, TAG_INCLUDE_UNIQUE_ID_t, TAG_ACTIVE_DATETIME_t,
153         TAG_ORIGINATION_EXPIRE_DATETIME_t, TAG_USAGE_EXPIRE_DATETIME_t,
154         TAG_MIN_SECONDS_BETWEEN_OPS_t, TAG_MAX_USES_PER_BOOT_t, TAG_USAGE_COUNT_LIMIT_t,
155         TAG_USER_ID_t, TAG_USER_SECURE_ID_t, TAG_NO_AUTH_REQUIRED_t, TAG_AUTH_TIMEOUT_t,
156         TAG_ALLOW_WHILE_ON_BODY_t, TAG_UNLOCKED_DEVICE_REQUIRED_t, TAG_APPLICATION_ID_t,
157         TAG_APPLICATION_DATA_t, TAG_CREATION_DATETIME_t, TAG_ROLLBACK_RESISTANCE_t,
158         TAG_HARDWARE_TYPE_t, TAG_ROOT_OF_TRUST_t, TAG_ASSOCIATED_DATA_t, TAG_NONCE_t,
159         TAG_BOOTLOADER_ONLY_t, TAG_OS_VERSION_t, TAG_OS_PATCHLEVEL_t, TAG_UNIQUE_ID_t,
160         TAG_ATTESTATION_CHALLENGE_t, TAG_ATTESTATION_APPLICATION_ID_t, TAG_ATTESTATION_ID_BRAND_t,
161         TAG_ATTESTATION_ID_DEVICE_t, TAG_ATTESTATION_ID_PRODUCT_t,
162         TAG_ATTESTATION_ID_MANUFACTURER_t, TAG_ATTESTATION_ID_MODEL_t,
163         TAG_RESET_SINCE_ID_ROTATION_t, TAG_PURPOSE_t, TAG_ALGORITHM_t, TAG_BLOCK_MODE_t,
164         TAG_DIGEST_t, TAG_PADDING_t, TAG_ORIGIN_t, TAG_USER_AUTH_TYPE_t, TAG_EC_CURVE_t,
165         TAG_BOOT_PATCHLEVEL_t, TAG_VENDOR_PATCHLEVEL_t, TAG_TRUSTED_CONFIRMATION_REQUIRED_t,
166         TAG_TRUSTED_USER_PRESENCE_REQUIRED_t, TAG_CERTIFICATE_SERIAL_t, TAG_CERTIFICATE_SUBJECT_t>;
167 
168 template <typename TypedTagType>
169 struct TypedTag2ValueType;
170 
171 #ifdef MAKE_TAG_VALUE_ACCESSOR
172 #undef MAKE_TAG_VALUE_ACCESSOR
173 #endif
174 
175 #define MAKE_TAG_VALUE_ACCESSOR(tag_type, field_name)                                           \
176     template <Tag tag>                                                                          \
177     struct TypedTag2ValueType<TypedTag<tag_type, tag>> {                                        \
178         using type = std::remove_reference<                                                     \
179                 decltype(static_cast<KeyParameterValue*>(nullptr)                               \
180                                  ->get<KeyParameterValue::field_name>())>::type;                \
181         static constexpr KeyParameterValue::Tag unionTag = KeyParameterValue::field_name;       \
182     };                                                                                          \
183     template <Tag tag>                                                                          \
184     inline std::optional<std::reference_wrapper<                                                \
185             const typename TypedTag2ValueType<TypedTag<tag_type, tag>>::type>>                  \
186     accessTagValue(TypedTag<tag_type, tag>, const KeyParameter& param) {                        \
187         if (param.value.getTag() == KeyParameterValue::field_name) {                            \
188             return std::optional(                                                               \
189                     std::reference_wrapper(param.value.get<KeyParameterValue::field_name>()));  \
190         } else {                                                                                \
191             return std::nullopt;                                                                \
192         }                                                                                       \
193     }                                                                                           \
194     template <Tag tag>                                                                          \
195     inline std::optional<                                                                       \
196             std::reference_wrapper<typename TypedTag2ValueType<TypedTag<tag_type, tag>>::type>> \
197     accessTagValue(TypedTag<tag_type, tag>, KeyParameter& param) {                              \
198         if (param.value.getTag() == KeyParameterValue::field_name) {                            \
199             return std::optional(                                                               \
200                     std::reference_wrapper(param.value.get<KeyParameterValue::field_name>()));  \
201         } else {                                                                                \
202             return std::nullopt;                                                                \
203         }                                                                                       \
204     }
205 
MAKE_TAG_VALUE_ACCESSOR(TagType::ULONG,longInteger)206 MAKE_TAG_VALUE_ACCESSOR(TagType::ULONG, longInteger)
207 MAKE_TAG_VALUE_ACCESSOR(TagType::ULONG_REP, longInteger)
208 MAKE_TAG_VALUE_ACCESSOR(TagType::DATE, dateTime)
209 MAKE_TAG_VALUE_ACCESSOR(TagType::UINT, integer)
210 MAKE_TAG_VALUE_ACCESSOR(TagType::UINT_REP, integer)
211 MAKE_TAG_VALUE_ACCESSOR(TagType::BOOL, boolValue)
212 MAKE_TAG_VALUE_ACCESSOR(TagType::BYTES, blob)
213 MAKE_TAG_VALUE_ACCESSOR(TagType::BIGNUM, blob)
214 
215 #undef MAKE_TAG_VALUE_ACCESSOR
216 
217 #ifdef MAKE_TAG_ENUM_VALUE_ACCESSOR
218 #undef MAKE_TAG_ENUM_VALUE_ACCESSOR
219 #endif
220 
221 #define MAKE_TAG_ENUM_VALUE_ACCESSOR(typed_tag, field_name)                                       \
222     template <>                                                                                   \
223     struct TypedTag2ValueType<decltype(typed_tag)> {                                              \
224         using type = std::remove_reference<                                                       \
225                 decltype(static_cast<KeyParameterValue*>(nullptr)                                 \
226                                  ->get<KeyParameterValue::field_name>())>::type;                  \
227         static constexpr KeyParameterValue::Tag unionTag = KeyParameterValue::field_name;         \
228     };                                                                                            \
229     inline std::optional<                                                                         \
230             std::reference_wrapper<const typename TypedTag2ValueType<decltype(typed_tag)>::type>> \
231     accessTagValue(decltype(typed_tag), const KeyParameter& param) {                              \
232         if (param.value.getTag() == KeyParameterValue::field_name) {                              \
233             return std::optional(                                                                 \
234                     std::reference_wrapper(param.value.get<KeyParameterValue::field_name>()));    \
235         } else {                                                                                  \
236             return std::nullopt;                                                                  \
237         }                                                                                         \
238     }                                                                                             \
239     inline std::optional<                                                                         \
240             std::reference_wrapper<typename TypedTag2ValueType<decltype(typed_tag)>::type>>       \
241     accessTagValue(decltype(typed_tag), KeyParameter& param) {                                    \
242         if (param.value.getTag() == KeyParameterValue::field_name) {                              \
243             return std::optional(                                                                 \
244                     std::reference_wrapper(param.value.get<KeyParameterValue::field_name>()));    \
245         } else {                                                                                  \
246             return std::nullopt;                                                                  \
247         }                                                                                         \
248     }
249 
250 MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_ALGORITHM, algorithm)
251 MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_BLOCK_MODE, blockMode)
252 MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_DIGEST, digest)
253 MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_EC_CURVE, ecCurve)
254 MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_ORIGIN, origin)
255 MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_PADDING, paddingMode)
256 MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_PURPOSE, keyPurpose)
257 MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_USER_AUTH_TYPE, hardwareAuthenticatorType)
258 MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_HARDWARE_TYPE, securityLevel)
259 MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_RSA_OAEP_MGF_DIGEST, digest)
260 
261 #undef MAKE_TAG_ENUM_VALUE_ACCESSOR
262 
263 template <TagType tag_type, Tag tag, typename ValueT>
264 inline KeyParameter makeKeyParameter(TypedTag<tag_type, tag> ttag, ValueT&& value) {
265     KeyParameter retval;
266     retval.tag = tag;
267     retval.value = KeyParameterValue::make<TypedTag2ValueType<decltype(ttag)>::unionTag>(
268             std::forward<ValueT>(value));
269     return retval;
270 }
271 
272 // the boolean case
273 template <Tag tag>
makeKeyParameter(TypedTag<TagType::BOOL,tag>)274 inline KeyParameter makeKeyParameter(TypedTag<TagType::BOOL, tag>) {
275     KeyParameter retval;
276     retval.tag = tag;
277     retval.value = KeyParameterValue::make<KeyParameterValue::boolValue>(true);
278     return retval;
279 }
280 
281 // the invalid case
makeKeyParameter(TypedTag<TagType::INVALID,Tag::INVALID>)282 inline KeyParameter makeKeyParameter(TypedTag<TagType::INVALID, Tag::INVALID>) {
283     KeyParameter retval;
284     retval.tag = Tag::INVALID;
285     retval.value = KeyParameterValue::make<KeyParameterValue::invalid>(0);
286     return retval;
287 }
288 
289 template <typename... Pack>
290 struct FirstOrNoneHelper;
291 template <typename First>
292 struct FirstOrNoneHelper<First> {
293     typedef First type;
294 };
295 template <>
296 struct FirstOrNoneHelper<> {
297     struct type {};
298 };
299 
300 template <typename... Pack>
301 using FirstOrNone = typename FirstOrNoneHelper<Pack...>::type;
302 
303 template <TagType tag_type, Tag tag, typename... Args>
304 inline KeyParameter Authorization(TypedTag<tag_type, tag> ttag, Args&&... args) {
305     static_assert(tag_type != TagType::BOOL || (sizeof...(args) == 0),
306                   "TagType::BOOL Authorizations do not take parameters. Presence is truth.");
307     static_assert(tag_type == TagType::BOOL || (sizeof...(args) == 1),
308                   "Authorization other then TagType::BOOL take exactly one parameter.");
309     static_assert(
310             tag_type == TagType::BOOL ||
311                     std::is_convertible<
312                             std::remove_cv_t<std::remove_reference_t<FirstOrNone<Args...>>>,
313                             typename TypedTag2ValueType<TypedTag<tag_type, tag>>::type>::value,
314             "Invalid argument type for given tag.");
315 
316     return makeKeyParameter(ttag, std::forward<Args>(args)...);
317 }
318 
319 template <typename T>
320 std::remove_reference_t<T> NullOrOr(T&& v) {
321     if (v) return v;
322     return {};
323 }
324 
325 template <typename Head, typename... Tail>
326 std::remove_reference_t<Head> NullOrOr(Head&& head, Tail&&... tail) {
327     if (head) return head;
328     return NullOrOr(std::forward<Tail>(tail)...);
329 }
330 
331 template <typename Default, typename Wrapped>
332 std::remove_reference_t<Wrapped> defaultOr(std::optional<Wrapped>&& optional, Default&& def) {
333     static_assert(std::is_convertible<std::remove_reference_t<Default>,
334                                       std::remove_reference_t<Wrapped>>::value,
335                   "Type of default value must match the type wrapped by std::optional");
336     if (optional) return *optional;
337     return def;
338 }
339 
340 template <TagType tag_type, Tag tag>
341 inline std::optional<
342         std::reference_wrapper<const typename TypedTag2ValueType<TypedTag<tag_type, tag>>::type>>
343 authorizationValue(TypedTag<tag_type, tag> ttag, const KeyParameter& param) {
344     // We only check if the parameter has the correct tag here; accessTagValue checks if the correct
345     // union field was initialized.
346     if (tag != param.tag) return {};
347     return accessTagValue(ttag, param);
348 }
349 
350 }  // namespace aidl::android::hardware::security::keymint
351