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 * For debugging purposes, one additional element of TypedTag and TypedEnumTag can be conditionally 53 * compiled in. If the "KEYMASTER_NAME_TAGS" macro symbol is defined, both classes will have a 54 * name() method which returns a string equal to the tame of the tag (e.g. TAG_PURPOSE). Activating 55 * this option means the classes _do_ contain a data member, a pointer to the string, and also 56 * causes static data space to be allocated for the strings. So the run-time cost of these classes 57 * is no longer zero. Note that it can cause problems if KEYMASTER_NAME_TAGS is defined for some 58 * compilation units and not others. 59 */ 60 61 #include <keymaster/keymaster_defs.h> 62 63 namespace keymaster { 64 65 // Until we have C++11, fake std::static_assert. 66 template <bool b> struct StaticAssert {}; 67 template <> struct StaticAssert<true> { 68 static void check() {} 69 }; 70 71 // An unusable type that we can associate with tag types that don't have a simple value type. 72 // That will prevent the associated type from being used inadvertently. 73 class Void { 74 Void(); 75 ~Void(); 76 }; 77 78 /** 79 * A template that defines the association between non-enumerated tag types and their value 80 * types. For each tag type we define a specialized struct that contains a typedef "value_type". 81 */ 82 template <keymaster_tag_type_t tag_type> struct TagValueType {}; 83 template <> struct TagValueType<KM_LONG> { typedef uint64_t value_type; }; 84 template <> struct TagValueType<KM_DATE> { typedef uint64_t value_type; }; 85 template <> struct TagValueType<KM_INT> { typedef uint32_t value_type; }; 86 template <> struct TagValueType<KM_INT_REP> { typedef uint32_t value_type; }; 87 template <> struct TagValueType<KM_INVALID> { typedef Void value_type; }; 88 template <> struct TagValueType<KM_BOOL> { typedef bool value_type; }; 89 template <> struct TagValueType<KM_BYTES> { typedef keymaster_blob_t value_type; }; 90 template <> struct TagValueType<KM_BIGNUM> { typedef keymaster_blob_t value_type; }; 91 92 /** 93 * TypedTag is a templatized version of keymaster_tag_t, which provides compile-time checking of 94 * keymaster tag types. Instances are convertible to keymaster_tag_t, so they can be used wherever 95 * keymaster_tag_t is expected, and because they encode the tag type it's possible to create 96 * function overloadings that only operate on tags with a particular type. 97 */ 98 template <keymaster_tag_type_t tag_type, keymaster_tag_t tag> class TypedTag { 99 public: 100 typedef typename TagValueType<tag_type>::value_type value_type; 101 102 #ifdef KEYMASTER_NAME_TAGS 103 inline TypedTag(const char* name) : name_(name) { 104 #else 105 inline TypedTag() { 106 #endif 107 // Ensure that it's impossible to create a TypedTag instance whose 'tag' doesn't have type 108 // 'tag_type'. Attempting to instantiate a tag with the wrong type will result in a compile 109 // error (no match for template specialization StaticAssert<false>), with no run-time cost. 110 StaticAssert<(tag & tag_type) == tag_type>::check(); 111 StaticAssert<(tag_type != KM_ENUM) && (tag_type != KM_ENUM_REP)>::check(); 112 } 113 inline operator keymaster_tag_t() { return tag; } 114 #ifdef KEYMASTER_NAME_TAGS 115 const char* name() { return name_; } 116 117 private: 118 const char* name_; 119 #endif 120 }; 121 122 template <keymaster_tag_type_t tag_type, keymaster_tag_t tag, typename KeymasterEnum> 123 class TypedEnumTag { 124 public: 125 typedef KeymasterEnum value_type; 126 127 #ifdef KEYMASTER_NAME_TAGS 128 inline TypedEnumTag(const char* name) : name_(name) { 129 #else 130 inline TypedEnumTag() { 131 #endif 132 // Ensure that it's impossible to create a TypedTag instance whose 'tag' doesn't have type 133 // 'tag_type'. Attempting to instantiate a tag with the wrong type will result in a compile 134 // error (no match for template specialization StaticAssert<false>), with no run-time cost. 135 StaticAssert<(tag & tag_type) == tag_type>::check(); 136 StaticAssert<(tag_type == KM_ENUM) || (tag_type == KM_ENUM_REP)>::check(); 137 } 138 inline operator keymaster_tag_t() { return tag; } 139 #ifdef KEYMASTER_NAME_TAGS 140 const char* name() { return name_; } 141 142 private: 143 const char* name_; 144 #endif 145 }; 146 147 // DEFINE_KEYMASTER_TAG is used to create TypedTag instances for each non-enum keymaster tag. 148 #ifdef KEYMASTER_NAME_TAGS 149 #define DEFINE_KEYMASTER_TAG(type, name) static TypedTag<type, KM_##name> name(#name) 150 #else 151 #define DEFINE_KEYMASTER_TAG(type, name) static TypedTag<type, KM_##name> name 152 #endif 153 154 DEFINE_KEYMASTER_TAG(KM_INVALID, TAG_INVALID); 155 DEFINE_KEYMASTER_TAG(KM_INT, TAG_KEY_SIZE); 156 DEFINE_KEYMASTER_TAG(KM_INT, TAG_MAC_LENGTH); 157 DEFINE_KEYMASTER_TAG(KM_INT, TAG_CHUNK_LENGTH); 158 DEFINE_KEYMASTER_TAG(KM_LONG, TAG_RSA_PUBLIC_EXPONENT); 159 DEFINE_KEYMASTER_TAG(KM_BIGNUM, TAG_DSA_GENERATOR); 160 DEFINE_KEYMASTER_TAG(KM_BIGNUM, TAG_DSA_P); 161 DEFINE_KEYMASTER_TAG(KM_BIGNUM, TAG_DSA_Q); 162 DEFINE_KEYMASTER_TAG(KM_DATE, TAG_ACTIVE_DATETIME); 163 DEFINE_KEYMASTER_TAG(KM_DATE, TAG_ORIGINATION_EXPIRE_DATETIME); 164 DEFINE_KEYMASTER_TAG(KM_DATE, TAG_USAGE_EXPIRE_DATETIME); 165 DEFINE_KEYMASTER_TAG(KM_INT, TAG_MIN_SECONDS_BETWEEN_OPS); 166 DEFINE_KEYMASTER_TAG(KM_BOOL, TAG_SINGLE_USE_PER_BOOT); 167 DEFINE_KEYMASTER_TAG(KM_BOOL, TAG_ALL_USERS); 168 DEFINE_KEYMASTER_TAG(KM_INT, TAG_USER_ID); 169 DEFINE_KEYMASTER_TAG(KM_BOOL, TAG_NO_AUTH_REQUIRED); 170 DEFINE_KEYMASTER_TAG(KM_INT_REP, TAG_USER_AUTH_ID); 171 DEFINE_KEYMASTER_TAG(KM_INT, TAG_AUTH_TIMEOUT); 172 DEFINE_KEYMASTER_TAG(KM_INT, TAG_RESCOPE_AUTH_TIMEOUT); 173 DEFINE_KEYMASTER_TAG(KM_BOOL, TAG_ALL_APPLICATIONS); 174 DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_APPLICATION_ID); 175 DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_APPLICATION_DATA); 176 DEFINE_KEYMASTER_TAG(KM_DATE, TAG_CREATION_DATETIME); 177 DEFINE_KEYMASTER_TAG(KM_BOOL, TAG_ROLLBACK_RESISTANT); 178 DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_ROOT_OF_TRUST); 179 DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_ADDITIONAL_DATA); 180 181 #ifdef KEYMASTER_NAME_TAGS 182 #define DEFINE_KEYMASTER_ENUM_TAG(type, name, enumtype) \ 183 static TypedEnumTag<type, KM_##name, enumtype> name(#name) 184 #else 185 #define DEFINE_KEYMASTER_ENUM_TAG(type, name, enumtype) \ 186 static TypedEnumTag<type, KM_##name, enumtype> name 187 #endif 188 189 DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM_REP, TAG_PURPOSE, keymaster_purpose_t); 190 DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM, TAG_ALGORITHM, keymaster_algorithm_t); 191 DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM, TAG_BLOCK_MODE, keymaster_block_mode_t); 192 DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM, TAG_DIGEST, keymaster_digest_t); 193 DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM, TAG_PADDING, keymaster_padding_t); 194 DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM_REP, TAG_RESCOPING_ADD, keymaster_tag_t); 195 DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM_REP, TAG_RESCOPING_DEL, keymaster_tag_t); 196 DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM, TAG_BLOB_USAGE_REQUIREMENTS, 197 keymaster_key_blob_usage_requirements_t); 198 DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM, TAG_ORIGIN, keymaster_key_origin_t); 199 200 // 201 // Overloaded function "Authorization" to create keymaster_key_param_t objects for all of tags. 202 // 203 204 template <keymaster_tag_t Tag> 205 inline keymaster_key_param_t Authorization(TypedTag<KM_BOOL, Tag> tag) { 206 return keymaster_param_bool(tag); 207 } 208 209 template <keymaster_tag_t Tag> 210 inline keymaster_key_param_t Authorization(TypedTag<KM_INT, Tag> tag, uint32_t value) { 211 return keymaster_param_int(tag, value); 212 } 213 214 template <keymaster_tag_t Tag> 215 inline keymaster_key_param_t Authorization(TypedTag<KM_INT_REP, Tag> tag, uint32_t value) { 216 return keymaster_param_int(tag, value); 217 } 218 219 template <keymaster_tag_t Tag> 220 inline keymaster_key_param_t Authorization(TypedTag<KM_LONG, Tag> tag, uint64_t value) { 221 return keymaster_param_long(tag, value); 222 } 223 224 template <keymaster_tag_t Tag> 225 inline keymaster_key_param_t Authorization(TypedTag<KM_DATE, Tag> tag, uint64_t value) { 226 return keymaster_param_date(tag, value); 227 } 228 229 template <keymaster_tag_t Tag> 230 inline keymaster_key_param_t Authorization(TypedTag<KM_BYTES, Tag> tag, const void* bytes, 231 size_t bytes_len) { 232 return keymaster_param_blob(tag, reinterpret_cast<const uint8_t*>(bytes), bytes_len); 233 } 234 235 template <keymaster_tag_t Tag> 236 inline keymaster_key_param_t Authorization(TypedTag<KM_BYTES, Tag> tag, 237 const keymaster_blob_t& blob) { 238 return keymaster_param_blob(tag, blob.data, blob.data_length); 239 } 240 241 template <keymaster_tag_t Tag> 242 inline keymaster_key_param_t Authorization(TypedTag<KM_BIGNUM, Tag> tag, const void* bytes, 243 size_t bytes_len) { 244 return keymaster_param_blob(tag, reinterpret_cast<const uint8_t*>(bytes), bytes_len); 245 } 246 247 template <keymaster_tag_t Tag> 248 inline keymaster_key_param_t Authorization(TypedTag<KM_BIGNUM, Tag> tag, 249 const keymaster_blob_t& blob) { 250 return keymaster_param_blob(tag, blob.data, blob.data_length); 251 } 252 253 template <keymaster_tag_t Tag, typename KeymasterEnum> 254 inline keymaster_key_param_t Authorization(TypedEnumTag<KM_ENUM, Tag, KeymasterEnum> tag, 255 KeymasterEnum value) { 256 return keymaster_param_enum(tag, value); 257 } 258 259 template <keymaster_tag_t Tag, typename KeymasterEnum> 260 inline keymaster_key_param_t Authorization(TypedEnumTag<KM_ENUM_REP, Tag, KeymasterEnum> tag, 261 KeymasterEnum value) { 262 return keymaster_param_enum(tag, value); 263 } 264 265 } // namespace keymaster 266 267 #endif // SYSTEM_KEYMASTER_KEYMASTER_TAGS_H_ 268