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 android { 67 namespace hardware { 68 namespace keymaster { 69 namespace V3_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 keymaster tag 82 * types. Instances are convertible to Tag, so they can be used wherever Tag is expected, and 83 * because they encode the tag type it's possible to create function overloads that only operate on 84 * tags with a particular type. 85 */ 86 template <TagType tag_type, Tag tag> struct TypedTag { 87 inline TypedTag() { 88 // Ensure that it's impossible to create a TypedTag instance whose 'tag' doesn't have type 89 // 'tag_type'. Attempting to instantiate a tag with the wrong type will result in a compile 90 // error (no match for template specialization StaticAssert<false>), with no run-time cost. 91 static_assert(typeFromTag(tag) == tag_type, "mismatch between tag and tag_type"); 92 } 93 constexpr operator Tag() { return tag; } 94 constexpr long maskedTag() { 95 return static_cast<long>(static_cast<uint32_t>(tag) & static_cast<uint32_t>(0x0fffffff)); 96 } 97 }; 98 99 template <Tag tag> struct Tag2TypedTag { typedef TypedTag<typeFromTag(tag), tag> type; }; 100 101 template <Tag tag> struct Tag2String; 102 103 #define _TAGS_STRINGIFY(x) #x 104 #define TAGS_STRINGIFY(x) _TAGS_STRINGIFY(x) 105 106 #define DECLARE_TYPED_TAG(name) \ 107 typedef typename Tag2TypedTag<Tag::name>::type TAG_##name##_t; \ 108 extern TAG_##name##_t TAG_##name; \ 109 template <> struct Tag2String<Tag::name> { \ 110 static const char* value() { return "Tag::" TAGS_STRINGIFY(name); } \ 111 } 112 113 DECLARE_TYPED_TAG(INVALID); 114 DECLARE_TYPED_TAG(KEY_SIZE); 115 DECLARE_TYPED_TAG(MAC_LENGTH); 116 DECLARE_TYPED_TAG(CALLER_NONCE); 117 DECLARE_TYPED_TAG(MIN_MAC_LENGTH); 118 DECLARE_TYPED_TAG(RSA_PUBLIC_EXPONENT); 119 DECLARE_TYPED_TAG(ECIES_SINGLE_HASH_MODE); 120 DECLARE_TYPED_TAG(INCLUDE_UNIQUE_ID); 121 DECLARE_TYPED_TAG(ACTIVE_DATETIME); 122 DECLARE_TYPED_TAG(ORIGINATION_EXPIRE_DATETIME); 123 DECLARE_TYPED_TAG(USAGE_EXPIRE_DATETIME); 124 DECLARE_TYPED_TAG(MIN_SECONDS_BETWEEN_OPS); 125 DECLARE_TYPED_TAG(MAX_USES_PER_BOOT); 126 DECLARE_TYPED_TAG(ALL_USERS); 127 DECLARE_TYPED_TAG(USER_ID); 128 DECLARE_TYPED_TAG(USER_SECURE_ID); 129 DECLARE_TYPED_TAG(NO_AUTH_REQUIRED); 130 DECLARE_TYPED_TAG(AUTH_TIMEOUT); 131 DECLARE_TYPED_TAG(ALLOW_WHILE_ON_BODY); 132 DECLARE_TYPED_TAG(ALL_APPLICATIONS); 133 DECLARE_TYPED_TAG(APPLICATION_ID); 134 DECLARE_TYPED_TAG(APPLICATION_DATA); 135 DECLARE_TYPED_TAG(CREATION_DATETIME); 136 DECLARE_TYPED_TAG(ROLLBACK_RESISTANT); 137 DECLARE_TYPED_TAG(ROOT_OF_TRUST); 138 DECLARE_TYPED_TAG(ASSOCIATED_DATA); 139 DECLARE_TYPED_TAG(NONCE); 140 DECLARE_TYPED_TAG(AUTH_TOKEN); 141 DECLARE_TYPED_TAG(BOOTLOADER_ONLY); 142 DECLARE_TYPED_TAG(OS_VERSION); 143 DECLARE_TYPED_TAG(OS_PATCHLEVEL); 144 DECLARE_TYPED_TAG(UNIQUE_ID); 145 DECLARE_TYPED_TAG(ATTESTATION_CHALLENGE); 146 DECLARE_TYPED_TAG(ATTESTATION_APPLICATION_ID); 147 DECLARE_TYPED_TAG(RESET_SINCE_ID_ROTATION); 148 149 DECLARE_TYPED_TAG(PURPOSE); 150 DECLARE_TYPED_TAG(ALGORITHM); 151 DECLARE_TYPED_TAG(BLOCK_MODE); 152 DECLARE_TYPED_TAG(DIGEST); 153 DECLARE_TYPED_TAG(PADDING); 154 DECLARE_TYPED_TAG(BLOB_USAGE_REQUIREMENTS); 155 DECLARE_TYPED_TAG(ORIGIN); 156 DECLARE_TYPED_TAG(USER_AUTH_TYPE); 157 DECLARE_TYPED_TAG(KDF); 158 DECLARE_TYPED_TAG(EC_CURVE); 159 160 template <typename... Elems> struct MetaList {}; 161 162 using all_tags_t = MetaList< 163 TAG_INVALID_t, TAG_KEY_SIZE_t, TAG_MAC_LENGTH_t, TAG_CALLER_NONCE_t, TAG_MIN_MAC_LENGTH_t, 164 TAG_RSA_PUBLIC_EXPONENT_t, TAG_ECIES_SINGLE_HASH_MODE_t, TAG_INCLUDE_UNIQUE_ID_t, 165 TAG_ACTIVE_DATETIME_t, TAG_ORIGINATION_EXPIRE_DATETIME_t, TAG_USAGE_EXPIRE_DATETIME_t, 166 TAG_MIN_SECONDS_BETWEEN_OPS_t, TAG_MAX_USES_PER_BOOT_t, TAG_ALL_USERS_t, TAG_USER_ID_t, 167 TAG_USER_SECURE_ID_t, TAG_NO_AUTH_REQUIRED_t, TAG_AUTH_TIMEOUT_t, TAG_ALLOW_WHILE_ON_BODY_t, 168 TAG_ALL_APPLICATIONS_t, TAG_APPLICATION_ID_t, TAG_APPLICATION_DATA_t, TAG_CREATION_DATETIME_t, 169 TAG_ROLLBACK_RESISTANT_t, TAG_ROOT_OF_TRUST_t, TAG_ASSOCIATED_DATA_t, TAG_NONCE_t, 170 TAG_AUTH_TOKEN_t, TAG_BOOTLOADER_ONLY_t, TAG_OS_VERSION_t, TAG_OS_PATCHLEVEL_t, TAG_UNIQUE_ID_t, 171 TAG_ATTESTATION_CHALLENGE_t, TAG_ATTESTATION_APPLICATION_ID_t, TAG_RESET_SINCE_ID_ROTATION_t, 172 TAG_PURPOSE_t, TAG_ALGORITHM_t, TAG_BLOCK_MODE_t, TAG_DIGEST_t, TAG_PADDING_t, 173 TAG_BLOB_USAGE_REQUIREMENTS_t, TAG_ORIGIN_t, TAG_USER_AUTH_TYPE_t, TAG_KDF_t, TAG_EC_CURVE_t>; 174 175 /* implementation in keystore_utils.cpp */ 176 extern const char* stringifyTag(Tag tag); 177 178 template <typename TypedTagType> struct TypedTag2ValueType; 179 180 #define MAKE_TAG_VALUE_ACCESSOR(tag_type, field_name) \ 181 template <Tag tag> struct TypedTag2ValueType<TypedTag<tag_type, tag>> { \ 182 typedef decltype(static_cast<KeyParameter*>(nullptr)->field_name) type; \ 183 }; \ 184 template <Tag tag> \ 185 inline auto accessTagValue(TypedTag<tag_type, tag>, const KeyParameter& param) \ 186 ->const decltype(param.field_name)& { \ 187 return param.field_name; \ 188 } \ 189 template <Tag tag> \ 190 inline auto accessTagValue(TypedTag<tag_type, tag>, KeyParameter& param) \ 191 ->decltype(param.field_name)& { \ 192 return param.field_name; \ 193 } 194 195 MAKE_TAG_VALUE_ACCESSOR(TagType::ULONG, f.longInteger) 196 MAKE_TAG_VALUE_ACCESSOR(TagType::ULONG_REP, f.longInteger) 197 MAKE_TAG_VALUE_ACCESSOR(TagType::DATE, f.dateTime) 198 MAKE_TAG_VALUE_ACCESSOR(TagType::UINT, f.integer) 199 MAKE_TAG_VALUE_ACCESSOR(TagType::UINT_REP, f.integer) 200 MAKE_TAG_VALUE_ACCESSOR(TagType::BOOL, f.boolValue) 201 MAKE_TAG_VALUE_ACCESSOR(TagType::BYTES, blob) 202 MAKE_TAG_VALUE_ACCESSOR(TagType::BIGNUM, blob) 203 204 #define MAKE_TAG_ENUM_VALUE_ACCESSOR(typed_tag, field_name) \ 205 template <> struct TypedTag2ValueType<decltype(typed_tag)> { \ 206 typedef decltype(static_cast<KeyParameter*>(nullptr)->field_name) type; \ 207 }; \ 208 inline auto accessTagValue(decltype(typed_tag), const KeyParameter& param) \ 209 ->const decltype(param.field_name)& { \ 210 return param.field_name; \ 211 } \ 212 inline auto accessTagValue(decltype(typed_tag), KeyParameter& param) \ 213 ->decltype(param.field_name)& { \ 214 return param.field_name; \ 215 } 216 217 MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_ALGORITHM, f.algorithm) 218 MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_BLOB_USAGE_REQUIREMENTS, f.keyBlobUsageRequirements) 219 MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_BLOCK_MODE, f.blockMode) 220 MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_DIGEST, f.digest) 221 MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_EC_CURVE, f.ecCurve) 222 MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_KDF, f.keyDerivationFunction) 223 MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_ORIGIN, f.origin) 224 MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_PADDING, f.paddingMode) 225 MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_PURPOSE, f.purpose) 226 MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_USER_AUTH_TYPE, f.hardwareAuthenticatorType) 227 228 template <TagType tag_type, Tag tag, typename ValueT> 229 inline KeyParameter makeKeyParameter(TypedTag<tag_type, tag> ttag, ValueT&& value) { 230 KeyParameter param; 231 param.tag = tag; 232 param.f.longInteger = 0; 233 accessTagValue(ttag, param) = std::forward<ValueT>(value); 234 return param; 235 } 236 237 // the boolean case 238 template <Tag tag> inline KeyParameter makeKeyParameter(TypedTag<TagType::BOOL, tag>) { 239 KeyParameter param; 240 param.tag = tag; 241 param.f.boolValue = true; 242 return param; 243 } 244 245 template <typename... Pack> struct FirstOrNoneHelper; 246 template <typename First> struct FirstOrNoneHelper<First> { typedef First type; }; 247 template <> struct FirstOrNoneHelper<> { 248 struct type {}; 249 }; 250 251 template <typename... Pack> using FirstOrNone = typename FirstOrNoneHelper<Pack...>::type; 252 253 template <TagType tag_type, Tag tag, typename... Args> 254 inline KeyParameter Authorization(TypedTag<tag_type, tag> ttag, Args&&... args) { 255 static_assert(tag_type != TagType::BOOL || (sizeof...(args) == 0), 256 "TagType::BOOL Authorizations do not take parameters. Presence is truth."); 257 static_assert(tag_type == TagType::BOOL || (sizeof...(args) == 1), 258 "Authorization other then TagType::BOOL take exactly one parameter."); 259 static_assert( 260 tag_type == TagType::BOOL || 261 std::is_convertible<std::remove_cv_t<std::remove_reference_t<FirstOrNone<Args...>>>, 262 typename TypedTag2ValueType<TypedTag<tag_type, tag>>::type>::value, 263 "Invalid argument type for given tag."); 264 265 return makeKeyParameter(ttag, std::forward<Args>(args)...); 266 } 267 268 /** 269 * This class wraps a (mostly return) value and stores whether or not the wrapped value is valid out 270 * of band. Note that if the wrapped value is a reference it is unsafe to access the value if 271 * !isOk(). If the wrapped type is a pointer or value and !isOk(), it is still safe to access the 272 * wrapped value. In this case the pointer will be NULL though, and the value will be default 273 * constructed. 274 */ 275 template <typename ValueT> class NullOr { 276 template <typename T> struct reference_initializer { 277 static T&& init() { return *static_cast<std::remove_reference_t<T>*>(nullptr); } 278 }; 279 template <typename T> struct pointer_initializer { 280 static T init() { return nullptr; } 281 }; 282 template <typename T> struct value_initializer { 283 static T init() { return T(); } 284 }; 285 template <typename T> 286 using initializer_t = 287 std::conditional_t<std::is_lvalue_reference<T>::value, reference_initializer<T>, 288 std::conditional_t<std::is_pointer<T>::value, pointer_initializer<T>, 289 value_initializer<T>>>; 290 291 public: 292 NullOr() : value_(initializer_t<ValueT>::init()), null_(true) {} 293 NullOr(ValueT&& value) : value_(std::forward<ValueT>(value)), null_(false) {} 294 295 bool isOk() const { return !null_; } 296 297 const ValueT& value() const & { return value_; } 298 ValueT& value() & { return value_; } 299 ValueT&& value() && { return std::move(value_); } 300 301 private: 302 ValueT value_; 303 bool null_; 304 }; 305 306 template <typename T> std::remove_reference_t<T> NullOrOr(NullOr<T>&& v) { 307 if (v.isOk()) return v; 308 return {}; 309 } 310 311 template <typename Head, typename... Tail> 312 std::remove_reference_t<Head> NullOrOr(Head&& head, Tail&&... tail) { 313 if (head.isOk()) return head; 314 return NullOrOr(std::forward<Tail>(tail)...); 315 } 316 317 template <typename Default, typename Wrapped> 318 std::remove_reference_t<Wrapped> defaultOr(NullOr<Wrapped>&& optional, Default&& def) { 319 static_assert(std::is_convertible<std::remove_reference_t<Default>, 320 std::remove_reference_t<Wrapped>>::value, 321 "Type of default value must match the type wrapped by NullOr"); 322 if (optional.isOk()) return optional.value(); 323 return def; 324 } 325 326 template <TagType tag_type, Tag tag> 327 inline NullOr<const typename TypedTag2ValueType<TypedTag<tag_type, tag>>::type&> 328 authorizationValue(TypedTag<tag_type, tag> ttag, const KeyParameter& param) { 329 if (tag != param.tag) return {}; 330 return accessTagValue(ttag, param); 331 } 332 333 inline const char* stringify(Digest digest) { 334 switch (digest) { 335 case Digest::NONE: 336 return "None"; 337 case Digest::MD5: 338 return "Md5"; 339 case Digest::SHA1: 340 return "Sha1"; 341 case Digest::SHA_2_224: 342 return "Sha224"; 343 case Digest::SHA_2_256: 344 return "Sha256"; 345 case Digest::SHA_2_384: 346 return "Sha384"; 347 case Digest::SHA_2_512: 348 return "Sha512"; 349 } 350 return "UNKNOWN DIGEST!"; 351 } 352 353 inline const char* stringify(Algorithm algorithm) { 354 switch (algorithm) { 355 case Algorithm::RSA: 356 return "Rsa"; 357 case Algorithm::EC: 358 return "Ec"; 359 case Algorithm::AES: 360 return "Aes"; 361 case Algorithm::HMAC: 362 return "Hmac"; 363 } 364 return "UNKNOWN ALGORITHM"; 365 } 366 367 inline const char* stringify(BlockMode block_mode) { 368 switch (block_mode) { 369 case BlockMode::ECB: 370 return "Ecb"; 371 case BlockMode::CBC: 372 return "Cbc"; 373 case BlockMode::CTR: 374 return "Ctr"; 375 case BlockMode::GCM: 376 return "Gcm"; 377 } 378 return "UNKNOWN BLOCK MODE"; 379 } 380 381 inline const char* stringify(PaddingMode padding) { 382 switch (padding) { 383 case PaddingMode::NONE: 384 return "None"; 385 case PaddingMode::RSA_OAEP: 386 return "RsaOaep"; 387 case PaddingMode::RSA_PSS: 388 return "RsaPss"; 389 case PaddingMode::RSA_PKCS1_1_5_ENCRYPT: 390 return "RsaPkcs115Encrypt"; 391 case PaddingMode::RSA_PKCS1_1_5_SIGN: 392 return "RsaPkcs115Sign"; 393 case PaddingMode::PKCS7: 394 return "Pkcs7"; 395 } 396 return "UNKNOWN PADDING MODE"; 397 } 398 399 inline const char* stringify(KeyOrigin origin) { 400 switch (origin) { 401 case KeyOrigin::GENERATED: 402 return "Generated"; 403 case KeyOrigin::DERIVED: 404 return "Derived"; 405 case KeyOrigin::IMPORTED: 406 return "Imported"; 407 case KeyOrigin::UNKNOWN: 408 return "UNKNOWN (keymaster0 didn't record it)"; 409 } 410 return "UNKOWN KEY ORIGIN VALUE"; 411 } 412 413 inline const char* stringify(KeyPurpose purpose) { 414 switch (purpose) { 415 case KeyPurpose::ENCRYPT: 416 return "Encrypt"; 417 case KeyPurpose::DECRYPT: 418 return "Decrypt"; 419 case KeyPurpose::SIGN: 420 return "Sign"; 421 case KeyPurpose::VERIFY: 422 return "Verify"; 423 case KeyPurpose::DERIVE_KEY: 424 return "DeriveKey"; 425 case KeyPurpose::WRAP_KEY: 426 return "WrapKey"; 427 }; 428 return "UNKNOWN KEY PURPOSE"; 429 } 430 431 inline const char* stringify(EcCurve curve) { 432 switch (curve) { 433 case EcCurve::P_224: 434 return "P_224"; 435 case EcCurve::P_256: 436 return "P_256"; 437 case EcCurve::P_384: 438 return "P_384"; 439 case EcCurve::P_521: 440 return "P_521"; 441 } 442 return "UNKNOWN EC CURVE"; 443 } 444 445 } // namespace V3_0 446 } // namespace keymaster 447 } // namespace hardware 448 } // namespace android 449 450 #endif // SYSTEM_SECURITY_KEYSTORE_KEYMASTER_TAGS_H_ 451