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
56namespace 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.
60static const keymaster_tag_t KM_TAG_DIGEST_OLD = static_cast<keymaster_tag_t>(KM_ENUM | 5);
61static 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.
64template <bool b> struct StaticAssert {};
65template <> 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.
71class 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 */
80template <keymaster_tag_type_t tag_type> struct TagValueType {};
81template <> struct TagValueType<KM_ULONG> { typedef uint64_t value_type; };
82template <> struct TagValueType<KM_ULONG_REP> { typedef uint64_t value_type; };
83template <> struct TagValueType<KM_DATE> { typedef uint64_t value_type; };
84template <> struct TagValueType<KM_UINT> { typedef uint32_t value_type; };
85template <> struct TagValueType<KM_UINT_REP> { typedef uint32_t value_type; };
86template <> struct TagValueType<KM_INVALID> { typedef Void value_type; };
87template <> struct TagValueType<KM_BOOL> { typedef bool value_type; };
88template <> struct TagValueType<KM_BYTES> { typedef keymaster_blob_t value_type; };
89template <> 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 */
97template <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
112template <keymaster_tag_type_t tag_type, keymaster_tag_t tag, typename KeymasterEnum>
113class 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
129const 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
135DECLARE_KEYMASTER_TAG(KM_INVALID, TAG_INVALID);
136DECLARE_KEYMASTER_TAG(KM_UINT, TAG_KEY_SIZE);
137DECLARE_KEYMASTER_TAG(KM_UINT, TAG_MAC_LENGTH);
138DECLARE_KEYMASTER_TAG(KM_BOOL, TAG_CALLER_NONCE);
139DECLARE_KEYMASTER_TAG(KM_UINT, TAG_MIN_MAC_LENGTH);
140DECLARE_KEYMASTER_TAG(KM_ULONG, TAG_RSA_PUBLIC_EXPONENT);
141DECLARE_KEYMASTER_TAG(KM_BOOL, TAG_ECIES_SINGLE_HASH_MODE);
142DECLARE_KEYMASTER_TAG(KM_BOOL, TAG_INCLUDE_UNIQUE_ID);
143DECLARE_KEYMASTER_TAG(KM_DATE, TAG_ACTIVE_DATETIME);
144DECLARE_KEYMASTER_TAG(KM_DATE, TAG_ORIGINATION_EXPIRE_DATETIME);
145DECLARE_KEYMASTER_TAG(KM_DATE, TAG_USAGE_EXPIRE_DATETIME);
146DECLARE_KEYMASTER_TAG(KM_UINT, TAG_MIN_SECONDS_BETWEEN_OPS);
147DECLARE_KEYMASTER_TAG(KM_UINT, TAG_MAX_USES_PER_BOOT);
148DECLARE_KEYMASTER_TAG(KM_BOOL, TAG_ALL_USERS);
149DECLARE_KEYMASTER_TAG(KM_UINT, TAG_USER_ID);
150DECLARE_KEYMASTER_TAG(KM_ULONG_REP, TAG_USER_SECURE_ID);
151DECLARE_KEYMASTER_TAG(KM_BOOL, TAG_NO_AUTH_REQUIRED);
152DECLARE_KEYMASTER_TAG(KM_UINT, TAG_AUTH_TIMEOUT);
153DECLARE_KEYMASTER_TAG(KM_BOOL, TAG_ALLOW_WHILE_ON_BODY);
154DECLARE_KEYMASTER_TAG(KM_BOOL, TAG_ALL_APPLICATIONS);
155DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_APPLICATION_ID);
156DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_APPLICATION_DATA);
157DECLARE_KEYMASTER_TAG(KM_DATE, TAG_CREATION_DATETIME);
158DECLARE_KEYMASTER_TAG(KM_BOOL, TAG_ROLLBACK_RESISTANT);
159DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ROOT_OF_TRUST);
160DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ASSOCIATED_DATA);
161DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_NONCE);
162DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_AUTH_TOKEN);
163DECLARE_KEYMASTER_TAG(KM_BOOL, TAG_BOOTLOADER_ONLY);
164DECLARE_KEYMASTER_TAG(KM_UINT, TAG_OS_VERSION);
165DECLARE_KEYMASTER_TAG(KM_UINT, TAG_OS_PATCHLEVEL);
166DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_UNIQUE_ID);
167DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_CHALLENGE);
168DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_APPLICATION_ID);
169DECLARE_KEYMASTER_TAG(KM_BOOL, TAG_RESET_SINCE_ID_ROTATION);
170DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_BRAND);
171DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_DEVICE);
172DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_PRODUCT);
173DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_SERIAL);
174DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_IMEI);
175DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_MEID);
176DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_MANUFACTURER);
177DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_MODEL);
178
179// DECLARE_KEYMASTER_ENUM_TAG is used to declare TypedEnumTag instances for each enum keymaster tag.
180#define DECLARE_KEYMASTER_ENUM_TAG(type, name, enumtype)                                           \
181    extern TypedEnumTag<type, KM_##name, enumtype> name
182
183DECLARE_KEYMASTER_ENUM_TAG(KM_ENUM_REP, TAG_PURPOSE, keymaster_purpose_t);
184DECLARE_KEYMASTER_ENUM_TAG(KM_ENUM, TAG_ALGORITHM, keymaster_algorithm_t);
185DECLARE_KEYMASTER_ENUM_TAG(KM_ENUM_REP, TAG_BLOCK_MODE, keymaster_block_mode_t);
186DECLARE_KEYMASTER_ENUM_TAG(KM_ENUM_REP, TAG_DIGEST, keymaster_digest_t);
187DECLARE_KEYMASTER_ENUM_TAG(KM_ENUM, TAG_DIGEST_OLD, keymaster_digest_t);
188DECLARE_KEYMASTER_ENUM_TAG(KM_ENUM_REP, TAG_PADDING, keymaster_padding_t);
189DECLARE_KEYMASTER_ENUM_TAG(KM_ENUM, TAG_PADDING_OLD, keymaster_padding_t);
190DECLARE_KEYMASTER_ENUM_TAG(KM_ENUM, TAG_BLOB_USAGE_REQUIREMENTS,
191                           keymaster_key_blob_usage_requirements_t);
192DECLARE_KEYMASTER_ENUM_TAG(KM_ENUM, TAG_ORIGIN, keymaster_key_origin_t);
193DECLARE_KEYMASTER_ENUM_TAG(KM_ENUM, TAG_USER_AUTH_TYPE, hw_authenticator_type_t);
194DECLARE_KEYMASTER_ENUM_TAG(KM_ENUM_REP, TAG_KDF, keymaster_kdf_t);
195DECLARE_KEYMASTER_ENUM_TAG(KM_ENUM, TAG_EC_CURVE, keymaster_ec_curve_t);
196
197//
198// Overloaded function "Authorization" to create keymaster_key_param_t objects for all of tags.
199//
200
201template <keymaster_tag_t Tag>
202inline keymaster_key_param_t Authorization(TypedTag<KM_BOOL, Tag> tag) {
203    return keymaster_param_bool(tag);
204}
205
206template <keymaster_tag_t Tag>
207inline keymaster_key_param_t Authorization(TypedTag<KM_UINT, Tag> tag, uint32_t value) {
208    return keymaster_param_int(tag, value);
209}
210
211template <keymaster_tag_t Tag>
212inline keymaster_key_param_t Authorization(TypedTag<KM_UINT_REP, Tag> tag, uint32_t value) {
213    return keymaster_param_int(tag, value);
214}
215
216template <keymaster_tag_t Tag>
217inline keymaster_key_param_t Authorization(TypedTag<KM_ULONG, Tag> tag, uint64_t value) {
218    return keymaster_param_long(tag, value);
219}
220
221template <keymaster_tag_t Tag>
222inline keymaster_key_param_t Authorization(TypedTag<KM_ULONG_REP, Tag> tag, uint64_t value) {
223    return keymaster_param_long(tag, value);
224}
225
226template <keymaster_tag_t Tag>
227inline keymaster_key_param_t Authorization(TypedTag<KM_DATE, Tag> tag, uint64_t value) {
228    return keymaster_param_date(tag, value);
229}
230
231template <keymaster_tag_t Tag>
232inline keymaster_key_param_t Authorization(TypedTag<KM_BYTES, Tag> tag, const void* bytes,
233                                           size_t bytes_len) {
234    return keymaster_param_blob(tag, reinterpret_cast<const uint8_t*>(bytes), bytes_len);
235}
236
237template <keymaster_tag_t Tag>
238inline keymaster_key_param_t Authorization(TypedTag<KM_BYTES, Tag> tag,
239                                           const keymaster_blob_t& blob) {
240    return keymaster_param_blob(tag, blob.data, blob.data_length);
241}
242
243template <keymaster_tag_t Tag>
244inline keymaster_key_param_t Authorization(TypedTag<KM_BIGNUM, Tag> tag, const void* bytes,
245                                           size_t bytes_len) {
246    return keymaster_param_blob(tag, reinterpret_cast<const uint8_t*>(bytes), bytes_len);
247}
248
249template <keymaster_tag_t Tag>
250inline keymaster_key_param_t Authorization(TypedTag<KM_BIGNUM, Tag> tag,
251                                           const keymaster_blob_t& blob) {
252    return keymaster_param_blob(tag, blob.data, blob.data_length);
253}
254
255template <keymaster_tag_t Tag, typename KeymasterEnum>
256inline keymaster_key_param_t Authorization(TypedEnumTag<KM_ENUM, Tag, KeymasterEnum> tag,
257                                           KeymasterEnum value) {
258    return keymaster_param_enum(tag, value);
259}
260
261template <keymaster_tag_t Tag, typename KeymasterEnum>
262inline keymaster_key_param_t Authorization(TypedEnumTag<KM_ENUM_REP, Tag, KeymasterEnum> tag,
263                                           KeymasterEnum value) {
264    return keymaster_param_enum(tag, value);
265}
266
267}  // namespace keymaster
268
269#endif  // SYSTEM_KEYMASTER_KEYMASTER_TAGS_H_
270