Home | History | Annotate | Download | only in functional
      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