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_MANUFACTURER);
81 DECLARE_TYPED_TAG(ATTESTATION_ID_MEID);
82 DECLARE_TYPED_TAG(ATTESTATION_ID_PRODUCT);
83 DECLARE_TYPED_TAG(ATTESTATION_ID_MODEL);
84 DECLARE_TYPED_TAG(ATTESTATION_ID_SERIAL);
85 DECLARE_TYPED_TAG(AUTH_TIMEOUT);
86 DECLARE_TYPED_TAG(BLOCK_MODE);
87 DECLARE_TYPED_TAG(BOOTLOADER_ONLY);
88 DECLARE_TYPED_TAG(BOOT_PATCHLEVEL);
89 DECLARE_TYPED_TAG(CALLER_NONCE);
90 DECLARE_TYPED_TAG(CONFIRMATION_TOKEN);
91 DECLARE_TYPED_TAG(CREATION_DATETIME);
92 DECLARE_TYPED_TAG(DEVICE_UNIQUE_ATTESTATION);
93 DECLARE_TYPED_TAG(DIGEST);
94 DECLARE_TYPED_TAG(EARLY_BOOT_ONLY);
95 DECLARE_TYPED_TAG(EC_CURVE);
96 DECLARE_TYPED_TAG(HARDWARE_TYPE);
97 DECLARE_TYPED_TAG(IDENTITY_CREDENTIAL_KEY);
98 DECLARE_TYPED_TAG(INCLUDE_UNIQUE_ID);
99 DECLARE_TYPED_TAG(INVALID);
100 DECLARE_TYPED_TAG(KEY_SIZE);
101 DECLARE_TYPED_TAG(MAC_LENGTH);
102 DECLARE_TYPED_TAG(MAX_USES_PER_BOOT);
103 DECLARE_TYPED_TAG(MIN_MAC_LENGTH);
104 DECLARE_TYPED_TAG(MIN_SECONDS_BETWEEN_OPS);
105 DECLARE_TYPED_TAG(NONCE);
106 DECLARE_TYPED_TAG(NO_AUTH_REQUIRED);
107 DECLARE_TYPED_TAG(ORIGIN);
108 DECLARE_TYPED_TAG(ORIGINATION_EXPIRE_DATETIME);
109 DECLARE_TYPED_TAG(OS_PATCHLEVEL);
110 DECLARE_TYPED_TAG(OS_VERSION);
111 DECLARE_TYPED_TAG(PADDING);
112 DECLARE_TYPED_TAG(PURPOSE);
113 DECLARE_TYPED_TAG(RESET_SINCE_ID_ROTATION);
114 DECLARE_TYPED_TAG(ROLLBACK_RESISTANCE);
115 DECLARE_TYPED_TAG(ROOT_OF_TRUST);
116 DECLARE_TYPED_TAG(RSA_PUBLIC_EXPONENT);
117 DECLARE_TYPED_TAG(STORAGE_KEY);
118 DECLARE_TYPED_TAG(TRUSTED_CONFIRMATION_REQUIRED);
119 DECLARE_TYPED_TAG(TRUSTED_USER_PRESENCE_REQUIRED);
120 DECLARE_TYPED_TAG(UNIQUE_ID);
121 DECLARE_TYPED_TAG(UNLOCKED_DEVICE_REQUIRED);
122 DECLARE_TYPED_TAG(USAGE_COUNT_LIMIT);
123 DECLARE_TYPED_TAG(USAGE_EXPIRE_DATETIME);
124 DECLARE_TYPED_TAG(USER_AUTH_TYPE);
125 DECLARE_TYPED_TAG(USER_ID);
126 DECLARE_TYPED_TAG(USER_SECURE_ID);
127 DECLARE_TYPED_TAG(VENDOR_PATCHLEVEL);
128 DECLARE_TYPED_TAG(RSA_OAEP_MGF_DIGEST);
129 DECLARE_TYPED_TAG(CERTIFICATE_SERIAL);
130 DECLARE_TYPED_TAG(CERTIFICATE_SUBJECT);
131 DECLARE_TYPED_TAG(CERTIFICATE_NOT_BEFORE);
132 DECLARE_TYPED_TAG(CERTIFICATE_NOT_AFTER);
133 DECLARE_TYPED_TAG(MAX_BOOT_LEVEL);
134
135 #undef DECLARE_TYPED_TAG
136
137 template <typename... Elems>
138 struct MetaList {};
139
140 using all_tags_t = MetaList<
141 TAG_INVALID_t, TAG_KEY_SIZE_t, TAG_MAC_LENGTH_t, TAG_CALLER_NONCE_t, TAG_MIN_MAC_LENGTH_t,
142 TAG_RSA_PUBLIC_EXPONENT_t, TAG_INCLUDE_UNIQUE_ID_t, TAG_ACTIVE_DATETIME_t,
143 TAG_ORIGINATION_EXPIRE_DATETIME_t, TAG_USAGE_EXPIRE_DATETIME_t,
144 TAG_MIN_SECONDS_BETWEEN_OPS_t, TAG_MAX_USES_PER_BOOT_t, TAG_USAGE_COUNT_LIMIT_t,
145 TAG_USER_ID_t, TAG_USER_SECURE_ID_t, TAG_NO_AUTH_REQUIRED_t, TAG_AUTH_TIMEOUT_t,
146 TAG_ALLOW_WHILE_ON_BODY_t, TAG_UNLOCKED_DEVICE_REQUIRED_t, TAG_APPLICATION_ID_t,
147 TAG_APPLICATION_DATA_t, TAG_CREATION_DATETIME_t, TAG_ROLLBACK_RESISTANCE_t,
148 TAG_HARDWARE_TYPE_t, TAG_ROOT_OF_TRUST_t, TAG_ASSOCIATED_DATA_t, TAG_NONCE_t,
149 TAG_BOOTLOADER_ONLY_t, TAG_OS_VERSION_t, TAG_OS_PATCHLEVEL_t, TAG_UNIQUE_ID_t,
150 TAG_ATTESTATION_CHALLENGE_t, TAG_ATTESTATION_APPLICATION_ID_t, TAG_ATTESTATION_ID_BRAND_t,
151 TAG_ATTESTATION_ID_DEVICE_t, TAG_ATTESTATION_ID_PRODUCT_t,
152 TAG_ATTESTATION_ID_MANUFACTURER_t, TAG_ATTESTATION_ID_MODEL_t,
153 TAG_RESET_SINCE_ID_ROTATION_t, TAG_PURPOSE_t, TAG_ALGORITHM_t, TAG_BLOCK_MODE_t,
154 TAG_DIGEST_t, TAG_PADDING_t, TAG_ORIGIN_t, TAG_USER_AUTH_TYPE_t, TAG_EC_CURVE_t,
155 TAG_BOOT_PATCHLEVEL_t, TAG_VENDOR_PATCHLEVEL_t, TAG_TRUSTED_CONFIRMATION_REQUIRED_t,
156 TAG_TRUSTED_USER_PRESENCE_REQUIRED_t, TAG_CERTIFICATE_SERIAL_t, TAG_CERTIFICATE_SUBJECT_t>;
157
158 template <typename TypedTagType>
159 struct TypedTag2ValueType;
160
161 #ifdef MAKE_TAG_VALUE_ACCESSOR
162 #undef MAKE_TAG_VALUE_ACCESSOR
163 #endif
164
165 #define MAKE_TAG_VALUE_ACCESSOR(tag_type, field_name) \
166 template <Tag tag> \
167 struct TypedTag2ValueType<TypedTag<tag_type, tag>> { \
168 using type = std::remove_reference< \
169 decltype(static_cast<KeyParameterValue*>(nullptr) \
170 ->get<KeyParameterValue::field_name>())>::type; \
171 static constexpr KeyParameterValue::Tag unionTag = KeyParameterValue::field_name; \
172 }; \
173 template <Tag tag> \
174 inline std::optional<std::reference_wrapper< \
175 const typename TypedTag2ValueType<TypedTag<tag_type, tag>>::type>> \
176 accessTagValue(TypedTag<tag_type, tag>, const KeyParameter& param) { \
177 if (param.value.getTag() == KeyParameterValue::field_name) { \
178 return std::optional( \
179 std::reference_wrapper(param.value.get<KeyParameterValue::field_name>())); \
180 } else { \
181 return std::nullopt; \
182 } \
183 } \
184 template <Tag tag> \
185 inline std::optional< \
186 std::reference_wrapper<typename TypedTag2ValueType<TypedTag<tag_type, tag>>::type>> \
187 accessTagValue(TypedTag<tag_type, tag>, KeyParameter& param) { \
188 if (param.value.getTag() == KeyParameterValue::field_name) { \
189 return std::optional( \
190 std::reference_wrapper(param.value.get<KeyParameterValue::field_name>())); \
191 } else { \
192 return std::nullopt; \
193 } \
194 }
195
MAKE_TAG_VALUE_ACCESSOR(TagType::ULONG,longInteger)196 MAKE_TAG_VALUE_ACCESSOR(TagType::ULONG, longInteger)
197 MAKE_TAG_VALUE_ACCESSOR(TagType::ULONG_REP, longInteger)
198 MAKE_TAG_VALUE_ACCESSOR(TagType::DATE, dateTime)
199 MAKE_TAG_VALUE_ACCESSOR(TagType::UINT, integer)
200 MAKE_TAG_VALUE_ACCESSOR(TagType::UINT_REP, integer)
201 MAKE_TAG_VALUE_ACCESSOR(TagType::BOOL, boolValue)
202 MAKE_TAG_VALUE_ACCESSOR(TagType::BYTES, blob)
203 MAKE_TAG_VALUE_ACCESSOR(TagType::BIGNUM, blob)
204
205 #undef MAKE_TAG_VALUE_ACCESSOR
206
207 #ifdef MAKE_TAG_ENUM_VALUE_ACCESSOR
208 #undef MAKE_TAG_ENUM_VALUE_ACCESSOR
209 #endif
210
211 #define MAKE_TAG_ENUM_VALUE_ACCESSOR(typed_tag, field_name) \
212 template <> \
213 struct TypedTag2ValueType<decltype(typed_tag)> { \
214 using type = std::remove_reference< \
215 decltype(static_cast<KeyParameterValue*>(nullptr) \
216 ->get<KeyParameterValue::field_name>())>::type; \
217 static constexpr KeyParameterValue::Tag unionTag = KeyParameterValue::field_name; \
218 }; \
219 inline std::optional< \
220 std::reference_wrapper<const typename TypedTag2ValueType<decltype(typed_tag)>::type>> \
221 accessTagValue(decltype(typed_tag), const KeyParameter& param) { \
222 if (param.value.getTag() == KeyParameterValue::field_name) { \
223 return std::optional( \
224 std::reference_wrapper(param.value.get<KeyParameterValue::field_name>())); \
225 } else { \
226 return std::nullopt; \
227 } \
228 } \
229 inline std::optional< \
230 std::reference_wrapper<typename TypedTag2ValueType<decltype(typed_tag)>::type>> \
231 accessTagValue(decltype(typed_tag), 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
240 MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_ALGORITHM, algorithm)
241 MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_BLOCK_MODE, blockMode)
242 MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_DIGEST, digest)
243 MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_EC_CURVE, ecCurve)
244 MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_ORIGIN, origin)
245 MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_PADDING, paddingMode)
246 MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_PURPOSE, keyPurpose)
247 MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_USER_AUTH_TYPE, hardwareAuthenticatorType)
248 MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_HARDWARE_TYPE, securityLevel)
249 MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_RSA_OAEP_MGF_DIGEST, digest)
250
251 #undef MAKE_TAG_ENUM_VALUE_ACCESSOR
252
253 template <TagType tag_type, Tag tag, typename ValueT>
254 inline KeyParameter makeKeyParameter(TypedTag<tag_type, tag> ttag, ValueT&& value) {
255 KeyParameter retval;
256 retval.tag = tag;
257 retval.value = KeyParameterValue::make<TypedTag2ValueType<decltype(ttag)>::unionTag>(
258 std::forward<ValueT>(value));
259 return retval;
260 }
261
262 // the boolean case
263 template <Tag tag>
makeKeyParameter(TypedTag<TagType::BOOL,tag>)264 inline KeyParameter makeKeyParameter(TypedTag<TagType::BOOL, tag>) {
265 KeyParameter retval;
266 retval.tag = tag;
267 retval.value = KeyParameterValue::make<KeyParameterValue::boolValue>(true);
268 return retval;
269 }
270
271 // the invalid case
makeKeyParameter(TypedTag<TagType::INVALID,Tag::INVALID>)272 inline KeyParameter makeKeyParameter(TypedTag<TagType::INVALID, Tag::INVALID>) {
273 KeyParameter retval;
274 retval.tag = Tag::INVALID;
275 retval.value = KeyParameterValue::make<KeyParameterValue::invalid>(0);
276 return retval;
277 }
278
279 template <typename... Pack>
280 struct FirstOrNoneHelper;
281 template <typename First>
282 struct FirstOrNoneHelper<First> {
283 typedef First type;
284 };
285 template <>
286 struct FirstOrNoneHelper<> {
287 struct type {};
288 };
289
290 template <typename... Pack>
291 using FirstOrNone = typename FirstOrNoneHelper<Pack...>::type;
292
293 template <TagType tag_type, Tag tag, typename... Args>
294 inline KeyParameter Authorization(TypedTag<tag_type, tag> ttag, Args&&... args) {
295 static_assert(tag_type != TagType::BOOL || (sizeof...(args) == 0),
296 "TagType::BOOL Authorizations do not take parameters. Presence is truth.");
297 static_assert(tag_type == TagType::BOOL || (sizeof...(args) == 1),
298 "Authorization other then TagType::BOOL take exactly one parameter.");
299 static_assert(
300 tag_type == TagType::BOOL ||
301 std::is_convertible<
302 std::remove_cv_t<std::remove_reference_t<FirstOrNone<Args...>>>,
303 typename TypedTag2ValueType<TypedTag<tag_type, tag>>::type>::value,
304 "Invalid argument type for given tag.");
305
306 return makeKeyParameter(ttag, std::forward<Args>(args)...);
307 }
308
309 template <typename T>
310 std::remove_reference_t<T> NullOrOr(T&& v) {
311 if (v) return v;
312 return {};
313 }
314
315 template <typename Head, typename... Tail>
316 std::remove_reference_t<Head> NullOrOr(Head&& head, Tail&&... tail) {
317 if (head) return head;
318 return NullOrOr(std::forward<Tail>(tail)...);
319 }
320
321 template <typename Default, typename Wrapped>
322 std::remove_reference_t<Wrapped> defaultOr(std::optional<Wrapped>&& optional, Default&& def) {
323 static_assert(std::is_convertible<std::remove_reference_t<Default>,
324 std::remove_reference_t<Wrapped>>::value,
325 "Type of default value must match the type wrapped by std::optional");
326 if (optional) return *optional;
327 return def;
328 }
329
330 template <TagType tag_type, Tag tag>
331 inline std::optional<
332 std::reference_wrapper<const typename TypedTag2ValueType<TypedTag<tag_type, tag>>::type>>
333 authorizationValue(TypedTag<tag_type, tag> ttag, const KeyParameter& param) {
334 // We only check if the parameter has the correct tag here; accessTagValue checks if the correct
335 // union field was initialized.
336 if (tag != param.tag) return {};
337 return accessTagValue(ttag, param);
338 }
339
340 } // namespace aidl::android::hardware::security::keymint
341