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
63namespace keymaster {
64
65// Until we have C++11, fake std::static_assert.
66template <bool b> struct StaticAssert {};
67template <> 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.
73class 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 */
82template <keymaster_tag_type_t tag_type> struct TagValueType {};
83template <> struct TagValueType<KM_LONG> { typedef uint64_t value_type; };
84template <> struct TagValueType<KM_DATE> { typedef uint64_t value_type; };
85template <> struct TagValueType<KM_INT> { typedef uint32_t value_type; };
86template <> struct TagValueType<KM_INT_REP> { typedef uint32_t value_type; };
87template <> struct TagValueType<KM_INVALID> { typedef Void value_type; };
88template <> struct TagValueType<KM_BOOL> { typedef bool value_type; };
89template <> struct TagValueType<KM_BYTES> { typedef keymaster_blob_t value_type; };
90template <> 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 */
98template <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
122template <keymaster_tag_type_t tag_type, keymaster_tag_t tag, typename KeymasterEnum>
123class 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
154DEFINE_KEYMASTER_TAG(KM_INVALID, TAG_INVALID);
155DEFINE_KEYMASTER_TAG(KM_INT, TAG_KEY_SIZE);
156DEFINE_KEYMASTER_TAG(KM_INT, TAG_MAC_LENGTH);
157DEFINE_KEYMASTER_TAG(KM_INT, TAG_CHUNK_LENGTH);
158DEFINE_KEYMASTER_TAG(KM_LONG, TAG_RSA_PUBLIC_EXPONENT);
159DEFINE_KEYMASTER_TAG(KM_BIGNUM, TAG_DSA_GENERATOR);
160DEFINE_KEYMASTER_TAG(KM_BIGNUM, TAG_DSA_P);
161DEFINE_KEYMASTER_TAG(KM_BIGNUM, TAG_DSA_Q);
162DEFINE_KEYMASTER_TAG(KM_DATE, TAG_ACTIVE_DATETIME);
163DEFINE_KEYMASTER_TAG(KM_DATE, TAG_ORIGINATION_EXPIRE_DATETIME);
164DEFINE_KEYMASTER_TAG(KM_DATE, TAG_USAGE_EXPIRE_DATETIME);
165DEFINE_KEYMASTER_TAG(KM_INT, TAG_MIN_SECONDS_BETWEEN_OPS);
166DEFINE_KEYMASTER_TAG(KM_BOOL, TAG_SINGLE_USE_PER_BOOT);
167DEFINE_KEYMASTER_TAG(KM_BOOL, TAG_ALL_USERS);
168DEFINE_KEYMASTER_TAG(KM_INT, TAG_USER_ID);
169DEFINE_KEYMASTER_TAG(KM_BOOL, TAG_NO_AUTH_REQUIRED);
170DEFINE_KEYMASTER_TAG(KM_INT_REP, TAG_USER_AUTH_ID);
171DEFINE_KEYMASTER_TAG(KM_INT, TAG_AUTH_TIMEOUT);
172DEFINE_KEYMASTER_TAG(KM_INT, TAG_RESCOPE_AUTH_TIMEOUT);
173DEFINE_KEYMASTER_TAG(KM_BOOL, TAG_ALL_APPLICATIONS);
174DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_APPLICATION_ID);
175DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_APPLICATION_DATA);
176DEFINE_KEYMASTER_TAG(KM_DATE, TAG_CREATION_DATETIME);
177DEFINE_KEYMASTER_TAG(KM_BOOL, TAG_ROLLBACK_RESISTANT);
178DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_ROOT_OF_TRUST);
179DEFINE_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
189DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM_REP, TAG_PURPOSE, keymaster_purpose_t);
190DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM, TAG_ALGORITHM, keymaster_algorithm_t);
191DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM, TAG_BLOCK_MODE, keymaster_block_mode_t);
192DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM, TAG_DIGEST, keymaster_digest_t);
193DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM, TAG_PADDING, keymaster_padding_t);
194DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM_REP, TAG_RESCOPING_ADD, keymaster_tag_t);
195DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM_REP, TAG_RESCOPING_DEL, keymaster_tag_t);
196DEFINE_KEYMASTER_ENUM_TAG(KM_ENUM, TAG_BLOB_USAGE_REQUIREMENTS,
197                          keymaster_key_blob_usage_requirements_t);
198DEFINE_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
204template <keymaster_tag_t Tag>
205inline keymaster_key_param_t Authorization(TypedTag<KM_BOOL, Tag> tag) {
206    return keymaster_param_bool(tag);
207}
208
209template <keymaster_tag_t Tag>
210inline keymaster_key_param_t Authorization(TypedTag<KM_INT, Tag> tag, uint32_t value) {
211    return keymaster_param_int(tag, value);
212}
213
214template <keymaster_tag_t Tag>
215inline keymaster_key_param_t Authorization(TypedTag<KM_INT_REP, Tag> tag, uint32_t value) {
216    return keymaster_param_int(tag, value);
217}
218
219template <keymaster_tag_t Tag>
220inline keymaster_key_param_t Authorization(TypedTag<KM_LONG, Tag> tag, uint64_t value) {
221    return keymaster_param_long(tag, value);
222}
223
224template <keymaster_tag_t Tag>
225inline keymaster_key_param_t Authorization(TypedTag<KM_DATE, Tag> tag, uint64_t value) {
226    return keymaster_param_date(tag, value);
227}
228
229template <keymaster_tag_t Tag>
230inline 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
235template <keymaster_tag_t Tag>
236inline 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
241template <keymaster_tag_t Tag>
242inline 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
247template <keymaster_tag_t Tag>
248inline 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
253template <keymaster_tag_t Tag, typename KeymasterEnum>
254inline keymaster_key_param_t Authorization(TypedEnumTag<KM_ENUM, Tag, KeymasterEnum> tag,
255                                           KeymasterEnum value) {
256    return keymaster_param_enum(tag, value);
257}
258
259template <keymaster_tag_t Tag, typename KeymasterEnum>
260inline 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