1 /* 2 * Copyright 2017 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/4.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/4.0/IKeymasterDevice.h> 63 64 #include <type_traits> 65 66 namespace android { 67 namespace hardware { 68 namespace keymaster { 69 namespace V4_0 { 70 71 // The following create the numeric values that KM_TAG_PADDING and KM_TAG_DIGEST used to have. We 72 // need these old values to be able to support old keys that use them. 73 static const int32_t KM_TAG_DIGEST_OLD = static_cast<int32_t>(TagType::ENUM) | 5; 74 static const int32_t KM_TAG_PADDING_OLD = static_cast<int32_t>(TagType::ENUM) | 7; 75 76 constexpr TagType typeFromTag(Tag tag) { 77 return static_cast<TagType>(static_cast<uint32_t>(tag) & static_cast<uint32_t>(0xf0000000)); 78 } 79 80 /** 81 * TypedTag is a templatized version of Tag, which provides compile-time checking of 82 * keymaster tag types. Instances are convertible to Tag, so they can be used wherever 83 * Tag is expected, and because they encode the tag type it's possible to create 84 * function overloads that only operate on tags with a particular type. 85 */ 86 template <TagType tag_type, Tag tag> 87 struct TypedTag { 88 inline TypedTag() { 89 // Ensure that it's impossible to create a TypedTag instance whose 'tag' doesn't have type 90 // 'tag_type'. Attempting to instantiate a tag with the wrong type will result in a compile 91 // error (no match for template specialization StaticAssert<false>), with no run-time cost. 92 static_assert(typeFromTag(tag) == tag_type, "mismatch between tag and tag_type"); 93 } 94 operator Tag() const { return tag; } 95 int32_t maskedTag() { return tag & 0x0FFFFFFF; } 96 }; 97 98 template <Tag tag> 99 struct Tag2TypedTag { 100 typedef TypedTag<typeFromTag(tag), tag> type; 101 }; 102 103 #define DECLARE_TYPED_TAG(name) \ 104 typedef typename Tag2TypedTag<Tag::name>::type TAG_##name##_t; \ 105 static TAG_##name##_t TAG_##name; 106 107 DECLARE_TYPED_TAG(ACTIVE_DATETIME); 108 DECLARE_TYPED_TAG(ALGORITHM); 109 DECLARE_TYPED_TAG(ALLOW_WHILE_ON_BODY); 110 DECLARE_TYPED_TAG(APPLICATION_DATA); 111 DECLARE_TYPED_TAG(APPLICATION_ID); 112 DECLARE_TYPED_TAG(ASSOCIATED_DATA); 113 DECLARE_TYPED_TAG(ATTESTATION_APPLICATION_ID); 114 DECLARE_TYPED_TAG(ATTESTATION_CHALLENGE); 115 DECLARE_TYPED_TAG(AUTH_TIMEOUT); 116 DECLARE_TYPED_TAG(BLOB_USAGE_REQUIREMENTS); 117 DECLARE_TYPED_TAG(BLOCK_MODE); 118 DECLARE_TYPED_TAG(BOOTLOADER_ONLY); 119 DECLARE_TYPED_TAG(CALLER_NONCE); 120 DECLARE_TYPED_TAG(CONFIRMATION_TOKEN); 121 DECLARE_TYPED_TAG(CREATION_DATETIME); 122 DECLARE_TYPED_TAG(DIGEST); 123 DECLARE_TYPED_TAG(EC_CURVE); 124 DECLARE_TYPED_TAG(INCLUDE_UNIQUE_ID); 125 DECLARE_TYPED_TAG(INVALID); 126 DECLARE_TYPED_TAG(KEY_SIZE); 127 DECLARE_TYPED_TAG(MAC_LENGTH); 128 DECLARE_TYPED_TAG(MAX_USES_PER_BOOT); 129 DECLARE_TYPED_TAG(MIN_MAC_LENGTH); 130 DECLARE_TYPED_TAG(MIN_SECONDS_BETWEEN_OPS); 131 DECLARE_TYPED_TAG(NONCE); 132 DECLARE_TYPED_TAG(NO_AUTH_REQUIRED); 133 DECLARE_TYPED_TAG(ORIGIN); 134 DECLARE_TYPED_TAG(ORIGINATION_EXPIRE_DATETIME); 135 DECLARE_TYPED_TAG(OS_PATCHLEVEL); 136 DECLARE_TYPED_TAG(OS_VERSION); 137 DECLARE_TYPED_TAG(PADDING); 138 DECLARE_TYPED_TAG(PURPOSE); 139 DECLARE_TYPED_TAG(RESET_SINCE_ID_ROTATION); 140 DECLARE_TYPED_TAG(ROLLBACK_RESISTANCE); 141 DECLARE_TYPED_TAG(ROOT_OF_TRUST); 142 DECLARE_TYPED_TAG(RSA_PUBLIC_EXPONENT); 143 DECLARE_TYPED_TAG(TRUSTED_CONFIRMATION_REQUIRED); 144 DECLARE_TYPED_TAG(UNIQUE_ID); 145 DECLARE_TYPED_TAG(UNLOCKED_DEVICE_REQUIRED); 146 DECLARE_TYPED_TAG(USAGE_EXPIRE_DATETIME); 147 DECLARE_TYPED_TAG(USER_AUTH_TYPE); 148 DECLARE_TYPED_TAG(USER_ID); 149 DECLARE_TYPED_TAG(USER_SECURE_ID); 150 151 template <typename... Elems> 152 struct MetaList {}; 153 154 using all_tags_t = 155 MetaList<TAG_INVALID_t, TAG_KEY_SIZE_t, TAG_MAC_LENGTH_t, TAG_CALLER_NONCE_t, 156 TAG_MIN_MAC_LENGTH_t, TAG_RSA_PUBLIC_EXPONENT_t, TAG_INCLUDE_UNIQUE_ID_t, 157 TAG_ACTIVE_DATETIME_t, TAG_ORIGINATION_EXPIRE_DATETIME_t, TAG_USAGE_EXPIRE_DATETIME_t, 158 TAG_MIN_SECONDS_BETWEEN_OPS_t, TAG_MAX_USES_PER_BOOT_t, TAG_USER_ID_t, 159 TAG_USER_SECURE_ID_t, TAG_NO_AUTH_REQUIRED_t, TAG_AUTH_TIMEOUT_t, 160 TAG_ALLOW_WHILE_ON_BODY_t, TAG_UNLOCKED_DEVICE_REQUIRED_t, TAG_APPLICATION_ID_t, 161 TAG_APPLICATION_DATA_t, TAG_CREATION_DATETIME_t, TAG_ROLLBACK_RESISTANCE_t, 162 TAG_ROOT_OF_TRUST_t, TAG_ASSOCIATED_DATA_t, TAG_NONCE_t, TAG_BOOTLOADER_ONLY_t, 163 TAG_OS_VERSION_t, TAG_OS_PATCHLEVEL_t, TAG_UNIQUE_ID_t, TAG_ATTESTATION_CHALLENGE_t, 164 TAG_ATTESTATION_APPLICATION_ID_t, TAG_RESET_SINCE_ID_ROTATION_t, TAG_PURPOSE_t, 165 TAG_ALGORITHM_t, TAG_BLOCK_MODE_t, TAG_DIGEST_t, TAG_PADDING_t, 166 TAG_BLOB_USAGE_REQUIREMENTS_t, TAG_ORIGIN_t, TAG_USER_AUTH_TYPE_t, TAG_EC_CURVE_t>; 167 168 template <typename TypedTagType> 169 struct TypedTag2ValueType; 170 171 #define MAKE_TAG_VALUE_ACCESSOR(tag_type, field_name) \ 172 template <Tag tag> \ 173 struct TypedTag2ValueType<TypedTag<tag_type, tag>> { \ 174 typedef decltype(static_cast<KeyParameter*>(nullptr)->field_name) type; \ 175 }; \ 176 template <Tag tag> \ 177 inline auto accessTagValue(TypedTag<tag_type, tag>, const KeyParameter& param) \ 178 ->const decltype(param.field_name)& { \ 179 return param.field_name; \ 180 } \ 181 template <Tag tag> \ 182 inline auto accessTagValue(TypedTag<tag_type, tag>, KeyParameter& param) \ 183 ->decltype(param.field_name)& { \ 184 return param.field_name; \ 185 } 186 187 MAKE_TAG_VALUE_ACCESSOR(TagType::ULONG, f.longInteger) 188 MAKE_TAG_VALUE_ACCESSOR(TagType::ULONG_REP, f.longInteger) 189 MAKE_TAG_VALUE_ACCESSOR(TagType::DATE, f.dateTime) 190 MAKE_TAG_VALUE_ACCESSOR(TagType::UINT, f.integer) 191 MAKE_TAG_VALUE_ACCESSOR(TagType::UINT_REP, f.integer) 192 MAKE_TAG_VALUE_ACCESSOR(TagType::BOOL, f.boolValue) 193 MAKE_TAG_VALUE_ACCESSOR(TagType::BYTES, blob) 194 MAKE_TAG_VALUE_ACCESSOR(TagType::BIGNUM, blob) 195 196 #define MAKE_TAG_ENUM_VALUE_ACCESSOR(typed_tag, field_name) \ 197 template <> \ 198 struct TypedTag2ValueType<decltype(typed_tag)> { \ 199 typedef decltype(static_cast<KeyParameter*>(nullptr)->field_name) type; \ 200 }; \ 201 inline auto accessTagValue(decltype(typed_tag), const KeyParameter& param) \ 202 ->const decltype(param.field_name)& { \ 203 return param.field_name; \ 204 } \ 205 inline auto accessTagValue(decltype(typed_tag), KeyParameter& param) \ 206 ->decltype(param.field_name)& { \ 207 return param.field_name; \ 208 } 209 210 MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_ALGORITHM, f.algorithm) 211 MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_BLOB_USAGE_REQUIREMENTS, f.keyBlobUsageRequirements) 212 MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_BLOCK_MODE, f.blockMode) 213 MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_DIGEST, f.digest) 214 MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_EC_CURVE, f.ecCurve) 215 MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_ORIGIN, f.origin) 216 MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_PADDING, f.paddingMode) 217 MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_PURPOSE, f.purpose) 218 MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_USER_AUTH_TYPE, f.hardwareAuthenticatorType) 219 220 template <TagType tag_type, Tag tag, typename ValueT> 221 inline KeyParameter makeKeyParameter(TypedTag<tag_type, tag> ttag, ValueT&& value) { 222 KeyParameter param; 223 param.tag = tag; 224 param.f.longInteger = 0; 225 accessTagValue(ttag, param) = std::forward<ValueT>(value); 226 return param; 227 } 228 229 // the boolean case 230 template <Tag tag> 231 inline KeyParameter makeKeyParameter(TypedTag<TagType::BOOL, tag>) { 232 KeyParameter param; 233 param.tag = tag; 234 param.f.boolValue = true; 235 return param; 236 } 237 238 template <typename... Pack> 239 struct FirstOrNoneHelper; 240 template <typename First> 241 struct FirstOrNoneHelper<First> { 242 typedef First type; 243 }; 244 template <> 245 struct FirstOrNoneHelper<> { 246 struct type {}; 247 }; 248 249 template <typename... Pack> 250 using FirstOrNone = typename FirstOrNoneHelper<Pack...>::type; 251 252 template <TagType tag_type, Tag tag, typename... Args> 253 inline KeyParameter Authorization(TypedTag<tag_type, tag> ttag, Args&&... args) { 254 static_assert(tag_type != TagType::BOOL || (sizeof...(args) == 0), 255 "TagType::BOOL Authorizations do not take parameters. Presence is truth."); 256 static_assert(tag_type == TagType::BOOL || (sizeof...(args) == 1), 257 "Authorization other then TagType::BOOL take exactly one parameter."); 258 static_assert( 259 tag_type == TagType::BOOL || 260 std::is_convertible<std::remove_cv_t<std::remove_reference_t<FirstOrNone<Args...>>>, 261 typename TypedTag2ValueType<TypedTag<tag_type, tag>>::type>::value, 262 "Invalid argument type for given tag."); 263 264 return makeKeyParameter(ttag, std::forward<Args>(args)...); 265 } 266 267 /** 268 * This class wraps a (mostly return) value and stores whether or not the wrapped value is valid out 269 * of band. Note that if the wrapped value is a reference it is unsafe to access the value if 270 * !isOk(). If the wrapped type is a pointer or value and !isOk(), it is still safe to access the 271 * wrapped value. In this case the pointer will be NULL though, and the value will be default 272 * constructed. 273 */ 274 template <typename ValueT> 275 class NullOr { 276 template <typename T> 277 struct reference_initializer { 278 static T&& init() { return *static_cast<std::remove_reference_t<T>*>(nullptr); } 279 }; 280 template <typename T> 281 struct pointer_initializer { 282 static T init() { return nullptr; } 283 }; 284 template <typename T> 285 struct value_initializer { 286 static T init() { return T(); } 287 }; 288 template <typename T> 289 using initializer_t = 290 std::conditional_t<std::is_lvalue_reference<T>::value, reference_initializer<T>, 291 std::conditional_t<std::is_pointer<T>::value, pointer_initializer<T>, 292 value_initializer<T>>>; 293 294 public: 295 NullOr() : value_(initializer_t<ValueT>::init()), null_(true) {} 296 NullOr(ValueT&& value) : value_(std::forward<ValueT>(value)), null_(false) {} 297 298 bool isOk() const { return !null_; } 299 300 const ValueT& value() const & { return value_; } 301 ValueT& value() & { return value_; } 302 ValueT&& value() && { return std::move(value_); } 303 304 private: 305 ValueT value_; 306 bool null_; 307 }; 308 309 template <typename T> 310 std::remove_reference_t<T> NullOrOr(T&& v) { 311 if (v.isOk()) 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.isOk()) return head; 318 return NullOrOr(std::forward<Tail>(tail)...); 319 } 320 321 template <typename Default, typename Wrapped> 322 std::remove_reference_t<Wrapped> defaultOr(NullOr<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 NullOr"); 326 if (optional.isOk()) return optional.value(); 327 return def; 328 } 329 330 template <TagType tag_type, Tag tag> 331 inline NullOr<const typename TypedTag2ValueType<TypedTag<tag_type, tag>>::type&> authorizationValue( 332 TypedTag<tag_type, tag> ttag, const KeyParameter& param) { 333 if (tag != param.tag) return {}; 334 return accessTagValue(ttag, param); 335 } 336 337 inline bool operator==(const KeyParameter& a, const KeyParameter& b) { 338 if (a.tag != b.tag) { 339 return false; 340 } 341 342 switch (a.tag) { 343 /* Boolean tags */ 344 case Tag::INVALID: 345 case Tag::CALLER_NONCE: 346 case Tag::INCLUDE_UNIQUE_ID: 347 case Tag::BOOTLOADER_ONLY: 348 case Tag::NO_AUTH_REQUIRED: 349 case Tag::ALLOW_WHILE_ON_BODY: 350 case Tag::UNLOCKED_DEVICE_REQUIRED: 351 case Tag::ROLLBACK_RESISTANCE: 352 case Tag::RESET_SINCE_ID_ROTATION: 353 case Tag::TRUSTED_CONFIRMATION_REQUIRED: 354 case Tag::TRUSTED_USER_PRESENCE_REQUIRED: 355 return true; 356 357 /* Integer tags */ 358 case Tag::KEY_SIZE: 359 case Tag::MIN_MAC_LENGTH: 360 case Tag::MIN_SECONDS_BETWEEN_OPS: 361 case Tag::MAX_USES_PER_BOOT: 362 case Tag::OS_VERSION: 363 case Tag::OS_PATCHLEVEL: 364 case Tag::MAC_LENGTH: 365 case Tag::USER_ID: 366 case Tag::AUTH_TIMEOUT: 367 case Tag::VENDOR_PATCHLEVEL: 368 case Tag::BOOT_PATCHLEVEL: 369 return a.f.integer == b.f.integer; 370 371 /* Long integer tags */ 372 case Tag::RSA_PUBLIC_EXPONENT: 373 case Tag::USER_SECURE_ID: 374 return a.f.longInteger == b.f.longInteger; 375 376 /* Date-time tags */ 377 case Tag::ACTIVE_DATETIME: 378 case Tag::ORIGINATION_EXPIRE_DATETIME: 379 case Tag::USAGE_EXPIRE_DATETIME: 380 case Tag::CREATION_DATETIME: 381 return a.f.dateTime == b.f.dateTime; 382 383 /* Bytes tags */ 384 case Tag::APPLICATION_ID: 385 case Tag::APPLICATION_DATA: 386 case Tag::ROOT_OF_TRUST: 387 case Tag::UNIQUE_ID: 388 case Tag::ATTESTATION_CHALLENGE: 389 case Tag::ATTESTATION_APPLICATION_ID: 390 case Tag::ATTESTATION_ID_BRAND: 391 case Tag::ATTESTATION_ID_DEVICE: 392 case Tag::ATTESTATION_ID_PRODUCT: 393 case Tag::ATTESTATION_ID_SERIAL: 394 case Tag::ATTESTATION_ID_IMEI: 395 case Tag::ATTESTATION_ID_MEID: 396 case Tag::ATTESTATION_ID_MANUFACTURER: 397 case Tag::ATTESTATION_ID_MODEL: 398 case Tag::ASSOCIATED_DATA: 399 case Tag::CONFIRMATION_TOKEN: 400 case Tag::NONCE: 401 return a.blob == b.blob; 402 403 /* Enum tags */ 404 case Tag::PURPOSE: 405 return a.f.purpose == b.f.purpose; 406 case Tag::ALGORITHM: 407 return a.f.algorithm == b.f.algorithm; 408 case Tag::BLOCK_MODE: 409 return a.f.blockMode == b.f.blockMode; 410 case Tag::DIGEST: 411 return a.f.digest == b.f.digest; 412 case Tag::PADDING: 413 return a.f.paddingMode == b.f.paddingMode; 414 case Tag::EC_CURVE: 415 return a.f.ecCurve == b.f.ecCurve; 416 case Tag::BLOB_USAGE_REQUIREMENTS: 417 return a.f.keyBlobUsageRequirements == b.f.keyBlobUsageRequirements; 418 case Tag::USER_AUTH_TYPE: 419 return a.f.integer == b.f.integer; 420 case Tag::ORIGIN: 421 return a.f.origin == b.f.origin; 422 case Tag::HARDWARE_TYPE: 423 return a.f.hardwareType == b.f.hardwareType; 424 } 425 426 return false; 427 } 428 429 } // namespace V4_0 430 } // namespace keymaster 431 } // namespace hardware 432 } // namespace android 433 434 #endif // SYSTEM_SECURITY_KEYSTORE_KEYMASTER_TAGS_H_ 435