Home | History | Annotate | Download | only in keymaster
      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_KEYMASTER_KEYMASTER_TAGS_H_
     18 #define SYSTEM_KEYMASTER_KEYMASTER_TAGS_H_
     19 
     20 /**
     21  * This header contains various definitions that make working with keymaster tags safer and easier.
     22  * It makes use of a fair amount of template metaprogramming, which is genarally a bad idea for
     23  * maintainability, but in this case all of the metaprogramming serves the purpose of making it
     24  * impossible to make certain classes of mistakes when operating on keymaster authorizations.  For
     25  * example, it's an error to create a keymaster_param_t with tag == KM_TAG_PURPOSE and then to
     26  * assign KM_ALGORITHM_RSA to the enumerated element of its union, but because "enumerated" is a
     27  * uint32_t, there's no way for the compiler, ordinarily, to diagnose it.  Also, generic functions
     28  * to manipulate authorizations of multiple types can't be written, because they need to know which
     29  * union parameter to modify.
     30  *
     31  * The machinery in this header solves these problems.  The core elements are two templated classes,
     32  * TypedTag and TypedEnumTag.  These classes are templated on a tag type and a tag value, and in the
     33  * case of TypedEnumTag, an enumeration type as well.  Specializations are created for each
     34  * keymaster tag, associating the tag type with the tag, and an instance of each specialization is
     35  * created, and named the same as the keymaster tag, but with the KM_ prefix omitted.  Because the
     36  * classes include a conversion operator to keymaster_tag_t, they can be used anywhere a
     37  * keymaster_tag_t is expected.
     38  *
     39  * They also define a "value_type" typedef, which specifies the type of values associated with that
     40  * particular tag.  This enables template functions to be written that check that the correct
     41  * parameter type is used for a given tag, and that use the correct union entry for the tag type.  A
     42  * very useful example is the overloaded "Authorization" function defined below, which takes tag and
     43  * value arguments and correctly constructs a keyamster_param_t struct.
     44  *
     45  * Because the classes have no data members and all of their methods are inline, they have ZERO
     46  * run-time cost in and of themselves.  The one way in which they can create code bloat is when
     47  * template functions using them are expanded multiple times.  The standard method of creating
     48  * trivial, inlined template functions which call non-templated functions which are compact but not
     49  * type-safe, allows the program to have both the type-safety of the templates and the compactness
     50  * of the non-templated functions, at the same time.
     51  */
     52 
     53 #include <hardware/hw_auth_token.h>
     54 #include <hardware/keymaster_defs.h>
     55 
     56 namespace keymaster {
     57 
     58 // The following create the numeric values that KM_TAG_PADDING and KM_TAG_DIGEST used to have.  We
     59 // need these old values to be able to support old keys that use them.
     60 static const keymaster_tag_t KM_TAG_DIGEST_OLD = static_cast<keymaster_tag_t>(KM_ENUM | 5);
     61 static const keymaster_tag_t KM_TAG_PADDING_OLD = static_cast<keymaster_tag_t>(KM_ENUM | 7);
     62 
     63 // Until we have C++11, fake std::static_assert.
     64 template <bool b> struct StaticAssert {};
     65 template <> struct StaticAssert<true> {
     66     static void check() {}
     67 };
     68 
     69 // An unusable type that we can associate with tag types that don't have a simple value type.
     70 // That will prevent the associated type from being used inadvertently.
     71 class Void {
     72     Void();
     73     ~Void();
     74 };
     75 
     76 /**
     77  * A template that defines the association between non-enumerated tag types and their value
     78  * types.  For each tag type we define a specialized struct that contains a typedef "value_type".
     79  */
     80 template <keymaster_tag_type_t tag_type> struct TagValueType {};
     81 template <> struct TagValueType<KM_ULONG> { typedef uint64_t value_type; };
     82 template <> struct TagValueType<KM_ULONG_REP> { typedef uint64_t value_type; };
     83 template <> struct TagValueType<KM_DATE> { typedef uint64_t value_type; };
     84 template <> struct TagValueType<KM_UINT> { typedef uint32_t value_type; };
     85 template <> struct TagValueType<KM_UINT_REP> { typedef uint32_t value_type; };
     86 template <> struct TagValueType<KM_INVALID> { typedef Void value_type; };
     87 template <> struct TagValueType<KM_BOOL> { typedef bool value_type; };
     88 template <> struct TagValueType<KM_BYTES> { typedef keymaster_blob_t value_type; };
     89 template <> struct TagValueType<KM_BIGNUM> { typedef keymaster_blob_t value_type; };
     90 
     91 /**
     92  * TypedTag is a templatized version of keymaster_tag_t, which provides compile-time checking of
     93  * keymaster tag types. Instances are convertible to keymaster_tag_t, so they can be used wherever
     94  * keymaster_tag_t is expected, and because they encode the tag type it's possible to create
     95  * function overloadings that only operate on tags with a particular type.
     96  */
     97 template <keymaster_tag_type_t tag_type, keymaster_tag_t tag> class TypedTag {
     98   public:
     99     typedef typename TagValueType<tag_type>::value_type value_type;
    100 
    101     inline TypedTag() {
    102         // Ensure that it's impossible to create a TypedTag instance whose 'tag' doesn't have type
    103         // 'tag_type'.  Attempting to instantiate a tag with the wrong type will result in a compile
    104         // error (no match for template specialization StaticAssert<false>), with no run-time cost.
    105         StaticAssert<(tag & tag_type) == tag_type>::check();
    106         StaticAssert<(tag_type != KM_ENUM) && (tag_type != KM_ENUM_REP)>::check();
    107     }
    108     inline operator keymaster_tag_t() { return tag; }
    109     inline long masked_tag() { return static_cast<long>(keymaster_tag_mask_type(tag)); }
    110 };
    111 
    112 template <keymaster_tag_type_t tag_type, keymaster_tag_t tag, typename KeymasterEnum>
    113 class TypedEnumTag {
    114   public:
    115     typedef KeymasterEnum value_type;
    116 
    117     inline TypedEnumTag() {
    118         // Ensure that it's impossible to create a TypedTag instance whose 'tag' doesn't have type
    119         // 'tag_type'.  Attempting to instantiate a tag with the wrong type will result in a compile
    120         // error (no match for template specialization StaticAssert<false>), with no run-time cost.
    121         StaticAssert<(tag & tag_type) == tag_type>::check();
    122         StaticAssert<(tag_type == KM_ENUM) || (tag_type == KM_ENUM_REP)>::check();
    123     }
    124     inline operator keymaster_tag_t() { return tag; }
    125     inline long masked_tag() { return static_cast<long>(keymaster_tag_mask_type(tag)); }
    126 };
    127 
    128 #ifdef KEYMASTER_NAME_TAGS
    129 const char* StringifyTag(keymaster_tag_t tag);
    130 #endif
    131 
    132 // DECLARE_KEYMASTER_TAG is used to declare TypedTag instances for each non-enum keymaster tag.
    133 #define DECLARE_KEYMASTER_TAG(type, name) extern TypedTag<type, KM_##name> name
    134 
    135 DECLARE_KEYMASTER_TAG(KM_INVALID, TAG_INVALID);
    136 DECLARE_KEYMASTER_TAG(KM_UINT, TAG_KEY_SIZE);
    137 DECLARE_KEYMASTER_TAG(KM_UINT, TAG_MAC_LENGTH);
    138 DECLARE_KEYMASTER_TAG(KM_BOOL, TAG_CALLER_NONCE);
    139 DECLARE_KEYMASTER_TAG(KM_UINT, TAG_MIN_MAC_LENGTH);
    140 DECLARE_KEYMASTER_TAG(KM_ULONG, TAG_RSA_PUBLIC_EXPONENT);
    141 DECLARE_KEYMASTER_TAG(KM_BOOL, TAG_ECIES_SINGLE_HASH_MODE);
    142 DECLARE_KEYMASTER_TAG(KM_BOOL, TAG_INCLUDE_UNIQUE_ID);
    143 DECLARE_KEYMASTER_TAG(KM_DATE, TAG_ACTIVE_DATETIME);
    144 DECLARE_KEYMASTER_TAG(KM_DATE, TAG_ORIGINATION_EXPIRE_DATETIME);
    145 DECLARE_KEYMASTER_TAG(KM_DATE, TAG_USAGE_EXPIRE_DATETIME);
    146 DECLARE_KEYMASTER_TAG(KM_UINT, TAG_MIN_SECONDS_BETWEEN_OPS);
    147 DECLARE_KEYMASTER_TAG(KM_UINT, TAG_MAX_USES_PER_BOOT);
    148 DECLARE_KEYMASTER_TAG(KM_BOOL, TAG_ALL_USERS);
    149 DECLARE_KEYMASTER_TAG(KM_UINT, TAG_USER_ID);
    150 DECLARE_KEYMASTER_TAG(KM_ULONG_REP, TAG_USER_SECURE_ID);
    151 DECLARE_KEYMASTER_TAG(KM_BOOL, TAG_NO_AUTH_REQUIRED);
    152 DECLARE_KEYMASTER_TAG(KM_UINT, TAG_AUTH_TIMEOUT);
    153 DECLARE_KEYMASTER_TAG(KM_BOOL, TAG_ALLOW_WHILE_ON_BODY);
    154 DECLARE_KEYMASTER_TAG(KM_BOOL, TAG_UNLOCKED_DEVICE_REQUIRED);
    155 DECLARE_KEYMASTER_TAG(KM_BOOL, TAG_ALL_APPLICATIONS);
    156 DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_APPLICATION_ID);
    157 DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_APPLICATION_DATA);
    158 DECLARE_KEYMASTER_TAG(KM_DATE, TAG_CREATION_DATETIME);
    159 DECLARE_KEYMASTER_TAG(KM_BOOL, TAG_ROLLBACK_RESISTANT);
    160 DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ROOT_OF_TRUST);
    161 DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ASSOCIATED_DATA);
    162 DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_NONCE);
    163 DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_AUTH_TOKEN);
    164 DECLARE_KEYMASTER_TAG(KM_BOOL, TAG_BOOTLOADER_ONLY);
    165 DECLARE_KEYMASTER_TAG(KM_UINT, TAG_OS_VERSION);
    166 DECLARE_KEYMASTER_TAG(KM_UINT, TAG_OS_PATCHLEVEL);
    167 DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_UNIQUE_ID);
    168 DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_CHALLENGE);
    169 DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_APPLICATION_ID);
    170 DECLARE_KEYMASTER_TAG(KM_BOOL, TAG_RESET_SINCE_ID_ROTATION);
    171 DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_BRAND);
    172 DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_DEVICE);
    173 DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_PRODUCT);
    174 DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_SERIAL);
    175 DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_IMEI);
    176 DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_MEID);
    177 DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_MANUFACTURER);
    178 DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_MODEL);
    179 
    180 // DECLARE_KEYMASTER_ENUM_TAG is used to declare TypedEnumTag instances for each enum keymaster tag.
    181 #define DECLARE_KEYMASTER_ENUM_TAG(type, name, enumtype)                                           \
    182     extern TypedEnumTag<type, KM_##name, enumtype> name
    183 
    184 DECLARE_KEYMASTER_ENUM_TAG(KM_ENUM_REP, TAG_PURPOSE, keymaster_purpose_t);
    185 DECLARE_KEYMASTER_ENUM_TAG(KM_ENUM, TAG_ALGORITHM, keymaster_algorithm_t);
    186 DECLARE_KEYMASTER_ENUM_TAG(KM_ENUM_REP, TAG_BLOCK_MODE, keymaster_block_mode_t);
    187 DECLARE_KEYMASTER_ENUM_TAG(KM_ENUM_REP, TAG_DIGEST, keymaster_digest_t);
    188 DECLARE_KEYMASTER_ENUM_TAG(KM_ENUM, TAG_DIGEST_OLD, keymaster_digest_t);
    189 DECLARE_KEYMASTER_ENUM_TAG(KM_ENUM_REP, TAG_PADDING, keymaster_padding_t);
    190 DECLARE_KEYMASTER_ENUM_TAG(KM_ENUM, TAG_PADDING_OLD, keymaster_padding_t);
    191 DECLARE_KEYMASTER_ENUM_TAG(KM_ENUM, TAG_BLOB_USAGE_REQUIREMENTS,
    192                            keymaster_key_blob_usage_requirements_t);
    193 DECLARE_KEYMASTER_ENUM_TAG(KM_ENUM, TAG_ORIGIN, keymaster_key_origin_t);
    194 DECLARE_KEYMASTER_ENUM_TAG(KM_ENUM, TAG_USER_AUTH_TYPE, hw_authenticator_type_t);
    195 DECLARE_KEYMASTER_ENUM_TAG(KM_ENUM_REP, TAG_KDF, keymaster_kdf_t);
    196 DECLARE_KEYMASTER_ENUM_TAG(KM_ENUM, TAG_EC_CURVE, keymaster_ec_curve_t);
    197 
    198 //
    199 // Overloaded function "Authorization" to create keymaster_key_param_t objects for all of tags.
    200 //
    201 
    202 template <keymaster_tag_t Tag>
    203 inline keymaster_key_param_t Authorization(TypedTag<KM_BOOL, Tag> tag) {
    204     return keymaster_param_bool(tag);
    205 }
    206 
    207 template <keymaster_tag_t Tag>
    208 inline keymaster_key_param_t Authorization(TypedTag<KM_UINT, Tag> tag, uint32_t value) {
    209     return keymaster_param_int(tag, value);
    210 }
    211 
    212 template <keymaster_tag_t Tag>
    213 inline keymaster_key_param_t Authorization(TypedTag<KM_UINT_REP, Tag> tag, uint32_t value) {
    214     return keymaster_param_int(tag, value);
    215 }
    216 
    217 template <keymaster_tag_t Tag>
    218 inline keymaster_key_param_t Authorization(TypedTag<KM_ULONG, Tag> tag, uint64_t value) {
    219     return keymaster_param_long(tag, value);
    220 }
    221 
    222 template <keymaster_tag_t Tag>
    223 inline keymaster_key_param_t Authorization(TypedTag<KM_ULONG_REP, Tag> tag, uint64_t value) {
    224     return keymaster_param_long(tag, value);
    225 }
    226 
    227 template <keymaster_tag_t Tag>
    228 inline keymaster_key_param_t Authorization(TypedTag<KM_DATE, Tag> tag, uint64_t value) {
    229     return keymaster_param_date(tag, value);
    230 }
    231 
    232 template <keymaster_tag_t Tag>
    233 inline keymaster_key_param_t Authorization(TypedTag<KM_BYTES, Tag> tag, const void* bytes,
    234                                            size_t bytes_len) {
    235     return keymaster_param_blob(tag, reinterpret_cast<const uint8_t*>(bytes), bytes_len);
    236 }
    237 
    238 template <keymaster_tag_t Tag>
    239 inline keymaster_key_param_t Authorization(TypedTag<KM_BYTES, Tag> tag,
    240                                            const keymaster_blob_t& blob) {
    241     return keymaster_param_blob(tag, blob.data, blob.data_length);
    242 }
    243 
    244 template <keymaster_tag_t Tag>
    245 inline keymaster_key_param_t Authorization(TypedTag<KM_BIGNUM, Tag> tag, const void* bytes,
    246                                            size_t bytes_len) {
    247     return keymaster_param_blob(tag, reinterpret_cast<const uint8_t*>(bytes), bytes_len);
    248 }
    249 
    250 template <keymaster_tag_t Tag>
    251 inline keymaster_key_param_t Authorization(TypedTag<KM_BIGNUM, Tag> tag,
    252                                            const keymaster_blob_t& blob) {
    253     return keymaster_param_blob(tag, blob.data, blob.data_length);
    254 }
    255 
    256 template <keymaster_tag_t Tag, typename KeymasterEnum>
    257 inline keymaster_key_param_t Authorization(TypedEnumTag<KM_ENUM, Tag, KeymasterEnum> tag,
    258                                            KeymasterEnum value) {
    259     return keymaster_param_enum(tag, value);
    260 }
    261 
    262 template <keymaster_tag_t Tag, typename KeymasterEnum>
    263 inline keymaster_key_param_t Authorization(TypedEnumTag<KM_ENUM_REP, Tag, KeymasterEnum> tag,
    264                                            KeymasterEnum value) {
    265     return keymaster_param_enum(tag, value);
    266 }
    267 
    268 }  // namespace keymaster
    269 
    270 #endif  // SYSTEM_KEYMASTER_KEYMASTER_TAGS_H_
    271