• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_AUTHORIZATION_SET_H_
18 #define SYSTEM_KEYMASTER_AUTHORIZATION_SET_H_
19 
20 #include <keymaster/UniquePtr.h>
21 
22 #include <hardware/keymaster_defs.h>
23 #include <keymaster/android_keymaster_utils.h>
24 #include <keymaster/keymaster_tags.h>
25 #include <keymaster/serializable.h>
26 
27 namespace keymaster {
28 
29 class AuthorizationSetBuilder;
30 
31 /**
32  * An extension of the keymaster_key_param_set_t struct, which provides serialization memory
33  * management and methods for easy manipulation and construction.
34  */
35 class AuthorizationSet : public Serializable, public keymaster_key_param_set_t {
36   public:
37     /**
38      * Construct an empty, dynamically-allocated, growable AuthorizationSet.  Does not actually
39      * allocate any storage until elements are added, so there is no cost to creating an
40      * AuthorizationSet with this constructor and then reinitializing it to point at pre-allocated
41      * buffers, with \p Reinitialize.
42      */
AuthorizationSet()43     AuthorizationSet()
44         : elems_capacity_(0), indirect_data_(nullptr), indirect_data_size_(0),
45           indirect_data_capacity_(0), error_(OK) {
46         elems_ = nullptr;
47         elems_size_ = 0;
48     }
49 
50     /**
51      * Construct an AuthorizationSet from the provided array.  The AuthorizationSet copies the data
52      * from the provided array (and the data referenced by its embedded pointers, if any) into
53      * dynamically-allocated storage.  If allocation of the needed storage fails, \p is_valid() will
54      * return ALLOCATION_FAILURE. It is the responsibility of the caller to check before using the
55      * set, if allocations might fail.
56      */
AuthorizationSet(const keymaster_key_param_t * elems,size_t count)57     AuthorizationSet(const keymaster_key_param_t* elems, size_t count)
58         : elems_capacity_(0), indirect_data_(nullptr), indirect_data_size_(0),
59           indirect_data_capacity_(0), error_(OK) {
60         elems_ = nullptr;
61         Reinitialize(elems, count);
62     }
63 
AuthorizationSet(const keymaster_key_param_set_t & set)64     explicit AuthorizationSet(const keymaster_key_param_set_t& set)
65         : elems_capacity_(0), indirect_data_(nullptr), indirect_data_size_(0),
66           indirect_data_capacity_(0), error_(OK) {
67         elems_ = nullptr;
68         Reinitialize(set.params, set.length);
69     }
70 
AuthorizationSet(const uint8_t * serialized_set,size_t serialized_size)71     explicit AuthorizationSet(const uint8_t* serialized_set, size_t serialized_size)
72         : elems_capacity_(0), indirect_data_(nullptr), indirect_data_size_(0),
73           indirect_data_capacity_(0), error_(OK) {
74         elems_ = nullptr;
75         Deserialize(&serialized_set, serialized_set + serialized_size);
76     }
77 
78     /**
79      * Construct an AuthorizationSet from the provided builder.  This extracts the data from the
80      * builder, rather than copying it, so after this call the builder is empty.
81      */
82     explicit AuthorizationSet(/* NOT const */ AuthorizationSetBuilder& builder);
83 
84     // Copy constructor.
AuthorizationSet(const AuthorizationSet & set)85     AuthorizationSet(const AuthorizationSet& set)
86         : Serializable(), elems_capacity_(0), indirect_data_(nullptr), indirect_data_size_(0),
87           indirect_data_capacity_(0), error_(OK) {
88         elems_ = nullptr;
89         error_ = set.error_;
90         if (error_ != OK) return;
91         Reinitialize(set.elems_, set.elems_size_);
92     }
93 
94     // Move constructor.
AuthorizationSet(AuthorizationSet && set)95     AuthorizationSet(AuthorizationSet&& set) : Serializable() {
96         MoveFrom(set);
97     }
98 
99     // Copy assignment.
100     AuthorizationSet& operator=(const AuthorizationSet& set) {
101         Reinitialize(set.elems_, set.elems_size_);
102         error_ = set.error_;
103         return *this;
104     }
105 
106     // Move assignment.
107     AuthorizationSet& operator=(AuthorizationSet&& set) {
108         FreeData();
109         MoveFrom(set);
110         return *this;
111     }
112 
113     /**
114      * Clear existing authorization set data
115      */
116     void Clear();
117 
118     /**
119      * Reinitialize an AuthorizationSet as a dynamically-allocated, growable copy of the data in the
120      * provided array (and the data referenced by its embedded pointers, if any).  If the allocation
121      * of the needed storage fails this method will return false and \p is_valid() will return
122      * ALLOCATION_FAILURE.
123      */
124     bool Reinitialize(const keymaster_key_param_t* elems, size_t count);
125 
Reinitialize(const AuthorizationSet & set)126     bool Reinitialize(const AuthorizationSet& set) {
127         return Reinitialize(set.elems_, set.elems_size_);
128     }
129 
Reinitialize(const keymaster_key_param_set_t & set)130     bool Reinitialize(const keymaster_key_param_set_t& set) {
131         return Reinitialize(set.params, set.length);
132     }
133 
134     ~AuthorizationSet();
135 
136     enum Error {
137         OK,
138         ALLOCATION_FAILURE,
139         MALFORMED_DATA,
140     };
141 
is_valid()142     Error is_valid() const { return error_; }
143 
144     /**
145      * Returns the size of the set.
146      */
size()147     size_t size() const { return elems_size_; }
148 
149     /**
150      * Returns true if the set is empty.
151      */
empty()152     bool empty() const { return size() == 0; }
153 
154     /**
155      * Returns the total size of all indirect data referenced by set elements.
156      */
indirect_size()157     size_t indirect_size() const { return indirect_data_size_; }
158 
159     /**
160      * Returns the data in the set, directly. Be careful with this.
161      */
data()162     const keymaster_key_param_t* data() const { return elems_; }
163 
164     /**
165      * Sorts the set
166      */
167     void Sort();
168 
169     /**
170      * Sorts the set and removes duplicates (inadvertently duplicating tags is easy to do with the
171      * AuthorizationSetBuilder).
172      */
173     void Deduplicate();
174 
175     /**
176      * Adds all elements from \p set that are not already present in this AuthorizationSet.  As a
177      * side-effect, if \p set is not null this AuthorizationSet will end up sorted.
178      */
179     void Union(const keymaster_key_param_set_t& set);
180 
181     /**
182      * Removes all elements in \p set from this AuthorizationSet.
183      */
184     void Difference(const keymaster_key_param_set_t& set);
185 
186     /**
187      * Returns the data in a keymaster_key_param_set_t, suitable for returning to C code.  For C
188      * compatibility, the contents are malloced, not new'ed, and so must be freed with free(), or
189      * better yet with keymaster_free_param_set, not delete.  The caller takes ownership.
190      */
191     void CopyToParamSet(keymaster_key_param_set_t* set) const;
192 
193     /**
194      * Returns the offset of the next entry that matches \p tag, starting from the element after \p
195      * begin.  If not found, returns -1.
196      */
197     int find(keymaster_tag_t tag, int begin = -1) const;
198 
199     /**
200      * Removes the entry at the specified index. Returns true if successful, false if the index was
201      * out of bounds.
202      */
203     bool erase(int index);
204 
205     /**
206      * Returns iterator (pointer) to beginning of elems array, to enable STL-style iteration
207      */
begin()208     const keymaster_key_param_t* begin() const { return elems_; }
209 
210     /**
211      * Returns iterator (pointer) one past end of elems array, to enable STL-style iteration
212      */
end()213     const keymaster_key_param_t* end() const { return elems_ + elems_size_; }
214 
215     /**
216      * Returns the nth element of the set.
217      */
218     keymaster_key_param_t& operator[](int n);
219 
220     /**
221      * Returns the nth element of the set.
222      */
223     const keymaster_key_param_t& operator[](int n) const;
224 
225     /**
226      * Returns true if the set contains at least one instance of \p tag
227      */
Contains(keymaster_tag_t tag)228     bool Contains(keymaster_tag_t tag) const {
229         return find(tag) != -1;
230     }
231 
232     /**
233      * Returns the number of \p tag entries.
234      */
235     size_t GetTagCount(keymaster_tag_t tag) const;
236 
237     /**
238      * Returns true if the set contains the specified tag and value.
239      */
240     template <keymaster_tag_t Tag, typename T>
Contains(TypedEnumTag<KM_ENUM_REP,Tag,T> tag,T val)241     bool Contains(TypedEnumTag<KM_ENUM_REP, Tag, T> tag, T val) const {
242         return ContainsEnumValue(tag, val);
243     }
244 
245     /**
246      * Returns true if the set contains the specified tag and value.
247      */
248     template <keymaster_tag_t Tag, typename T>
Contains(TypedEnumTag<KM_ENUM,Tag,T> tag,T val)249     bool Contains(TypedEnumTag<KM_ENUM, Tag, T> tag, T val) const {
250         return ContainsEnumValue(tag, val);
251     }
252 
253     /**
254      * Returns true if the set contains the specified tag and value.
255      */
256     template <keymaster_tag_t Tag>
Contains(TypedTag<KM_UINT,Tag> tag,uint32_t val)257     bool Contains(TypedTag<KM_UINT, Tag> tag, uint32_t val) const {
258         return ContainsIntValue(tag, val);
259     }
260 
261     /**
262      * If the specified integer-typed \p tag exists, places its value in \p val and returns true.
263      * If \p tag is not present, leaves \p val unmodified and returns false.
264      */
265     template <keymaster_tag_t T>
GetTagValue(TypedTag<KM_UINT,T> tag,uint32_t * val)266     inline bool GetTagValue(TypedTag<KM_UINT, T> tag, uint32_t* val) const {
267         return GetTagValueInt(tag, val);
268     }
269 
270     /**
271      * If the specified instance of the specified integer-typed \p tag exists, places its value
272      * in \p val and returns true.  If \p tag is not present, leaves \p val unmodified and returns
273      * false.
274      */
275     template <keymaster_tag_t Tag>
GetTagValue(TypedTag<KM_UINT_REP,Tag> tag,size_t instance,uint32_t * val)276     bool GetTagValue(TypedTag<KM_UINT_REP, Tag> tag, size_t instance, uint32_t* val) const {
277         return GetTagValueIntRep(tag, instance, val);
278     }
279 
280     /**
281      * If the specified long-typed \p tag exists, places its value in \p val and returns true.
282      * If \p tag is not present, leaves \p val unmodified and returns false.
283      */
284     template <keymaster_tag_t T>
GetTagValue(TypedTag<KM_ULONG,T> tag,uint64_t * val)285     inline bool GetTagValue(TypedTag<KM_ULONG, T> tag, uint64_t* val) const {
286         return GetTagValueLong(tag, val);
287     }
288 
289     /**
290      * If the specified instance of the specified integer-typed \p tag exists, places its value
291      * in \p val and returns true.  If \p tag is not present, leaves \p val unmodified and returns
292      * false.
293      */
294     template <keymaster_tag_t Tag>
GetTagValue(TypedTag<KM_ULONG_REP,Tag> tag,size_t instance,uint64_t * val)295     bool GetTagValue(TypedTag<KM_ULONG_REP, Tag> tag, size_t instance, uint64_t* val) const {
296         return GetTagValueLongRep(tag, instance, val);
297     }
298 
299     /**
300      * If the specified enumeration-typed \p tag exists, places its value in \p val and returns
301      * true.  If \p tag is not present, leaves \p val unmodified and returns false.
302      */
303     template <keymaster_tag_t Tag, typename T>
GetTagValue(TypedEnumTag<KM_ENUM,Tag,T> tag,T * val)304     bool GetTagValue(TypedEnumTag<KM_ENUM, Tag, T> tag, T* val) const {
305         return GetTagValueEnum(tag, reinterpret_cast<uint32_t*>(val));
306     }
307 
308     /**
309      * If the specified instance of the specified enumeration-typed \p tag exists, places its value
310      * in \p val and returns true.  If \p tag is not present, leaves \p val unmodified and returns
311      * false.
312      */
313     template <keymaster_tag_t Tag, typename T>
GetTagValue(TypedEnumTag<KM_ENUM_REP,Tag,T> tag,size_t instance,T * val)314     bool GetTagValue(TypedEnumTag<KM_ENUM_REP, Tag, T> tag, size_t instance, T* val) const {
315         return GetTagValueEnumRep(tag, instance, reinterpret_cast<uint32_t*>(val));
316     }
317 
318     /**
319      * If exactly one instance of the specified enumeration-typed \p tag exists, places its value in
320      * \p val and returns true.  If \p tag is not present or if multiple copies are present, leaves
321      * \p val unmodified and returns false.
322      */
323     template <keymaster_tag_t Tag, typename T>
GetTagValue(TypedEnumTag<KM_ENUM_REP,Tag,T> tag,T * val)324     bool GetTagValue(TypedEnumTag<KM_ENUM_REP, Tag, T> tag, T* val) const {
325         if (GetTagCount(tag) != 1)
326             return false;
327         return GetTagValueEnumRep(tag, 0, reinterpret_cast<uint32_t*>(val));
328     }
329 
330     /**
331      * If the specified date-typed \p tag exists, places its value in \p val and returns
332      * true.  If \p tag is not present, leaves \p val unmodified and returns false.
333      */
334     template <keymaster_tag_t Tag>
GetTagValue(TypedTag<KM_UINT_REP,Tag> tag,size_t instance,typename TypedTag<KM_UINT_REP,Tag>::value_type * val)335     bool GetTagValue(TypedTag<KM_UINT_REP, Tag> tag, size_t instance,
336                      typename TypedTag<KM_UINT_REP, Tag>::value_type* val) const {
337         return GetTagValueIntRep(tag, instance, val);
338     }
339 
340     /**
341      * If the specified bytes-typed \p tag exists, places its value in \p val and returns
342      * true.  If \p tag is not present, leaves \p val unmodified and returns false.
343      */
344     template <keymaster_tag_t Tag>
GetTagValue(TypedTag<KM_BYTES,Tag> tag,keymaster_blob_t * val)345     bool GetTagValue(TypedTag<KM_BYTES, Tag> tag, keymaster_blob_t* val) const {
346         return GetTagValueBlob(tag, val);
347     }
348 
349     /**
350      * If the specified bignum-typed \p tag exists, places its value in \p val and returns
351      * true.  If \p tag is not present, leaves \p val unmodified and returns false.
352      */
353     template <keymaster_tag_t Tag>
GetTagValue(TypedTag<KM_BIGNUM,Tag> tag,keymaster_blob_t * val)354     bool GetTagValue(TypedTag<KM_BIGNUM, Tag> tag, keymaster_blob_t* val) const {
355         return GetTagValueBlob(tag, val);
356     }
357 
358     /**
359      * Returns true if the specified tag is present, and therefore has the value 'true'.
360      */
GetTagValue(TypedTag<KM_BOOL,Tag> tag)361     template <keymaster_tag_t Tag> bool GetTagValue(TypedTag<KM_BOOL, Tag> tag) const {
362         return GetTagValueBool(tag);
363     }
364 
365     /**
366      * If the specified \p tag exists, places its value in \p val and returns true.  If \p tag is
367      * not present, leaves \p val unmodified and returns false.
368      */
369     template <keymaster_tag_t Tag, keymaster_tag_type_t Type>
GetTagValue(TypedTag<Type,Tag> tag,typename TagValueType<Type>::value_type * val)370     bool GetTagValue(TypedTag<Type, Tag> tag, typename TagValueType<Type>::value_type* val) const {
371         return GetTagValueLong(tag, val);
372     }
373 
374     bool push_back(keymaster_key_param_t elem);
375 
376     /**
377      * Grow the elements array to ensure it can contain \p count entries.  Preserves any existing
378      * entries.
379      */
380     bool reserve_elems(size_t count);
381 
382     /**
383      * Grow the indirect data array to ensure it can contain \p length bytes.  Preserves any
384      * existing indirect data.
385      */
386     bool reserve_indirect(size_t length);
387 
388     bool push_back(const keymaster_key_param_set_t& set);
389 
390     /**
391      * Append the tag and enumerated value to the set.
392      */
393     template <keymaster_tag_t Tag, keymaster_tag_type_t Type, typename KeymasterEnum>
push_back(TypedEnumTag<Type,Tag,KeymasterEnum> tag,KeymasterEnum val)394     bool push_back(TypedEnumTag<Type, Tag, KeymasterEnum> tag, KeymasterEnum val) {
395         return push_back(Authorization(tag, val));
396     }
397 
398     /**
399      * Append the boolean tag (value "true") to the set.
400      */
push_back(TypedTag<KM_BOOL,Tag> tag)401     template <keymaster_tag_t Tag> bool push_back(TypedTag<KM_BOOL, Tag> tag) {
402         return push_back(Authorization(tag));
403     }
404 
405     /**
406      * Append the tag and byte array to the set.  Copies the array into internal storage; does not
407      * take ownership of the passed-in array.
408      */
409     template <keymaster_tag_t Tag>
push_back(TypedTag<KM_BYTES,Tag> tag,const void * bytes,size_t bytes_len)410     bool push_back(TypedTag<KM_BYTES, Tag> tag, const void* bytes, size_t bytes_len) {
411         return push_back(keymaster_param_blob(tag, static_cast<const uint8_t*>(bytes), bytes_len));
412     }
413 
414     /**
415      * Append the tag and blob to the set.  Copies the blob contents into internal storage; does not
416      * take ownership of the blob's data.
417      */
418     template <keymaster_tag_t Tag>
push_back(TypedTag<KM_BYTES,Tag> tag,const keymaster_blob_t & blob)419     bool push_back(TypedTag<KM_BYTES, Tag> tag, const keymaster_blob_t& blob) {
420         return push_back(tag, blob.data, blob.data_length);
421     }
422 
423     /**
424      * Append the tag and bignum array to the set.  Copies the array into internal storage; does not
425      * take ownership of the passed-in array.
426      */
427     template <keymaster_tag_t Tag>
push_back(TypedTag<KM_BIGNUM,Tag> tag,const void * bytes,size_t bytes_len)428     bool push_back(TypedTag<KM_BIGNUM, Tag> tag, const void* bytes, size_t bytes_len) {
429         return push_back(keymaster_param_blob(tag, static_cast<const uint8_t*>(bytes), bytes_len));
430     }
431 
432     template <keymaster_tag_t Tag, keymaster_tag_type_t Type>
push_back(TypedTag<Type,Tag> tag,typename TypedTag<Type,Tag>::value_type val)433     bool push_back(TypedTag<Type, Tag> tag, typename TypedTag<Type, Tag>::value_type val) {
434         return push_back(Authorization(tag, val));
435     }
436 
437     template <keymaster_tag_t Tag, keymaster_tag_type_t Type>
push_back(TypedTag<Type,Tag> tag,const void * bytes,size_t bytes_len)438     bool push_back(TypedTag<Type, Tag> tag, const void* bytes, size_t bytes_len) {
439         return push_back(Authorization(tag, bytes, bytes_len));
440     }
441 
442     /* Virtual methods from Serializable */
443     size_t SerializedSize() const;
444     uint8_t* Serialize(uint8_t* serialized_set, const uint8_t* end) const;
445     bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end);
446 
447     size_t SerializedSizeOfElements() const;
448 
449   private:
450     void FreeData();
451     void MoveFrom(AuthorizationSet& set);
452 
453     void set_invalid(Error err);
454 
455     static size_t ComputeIndirectDataSize(const keymaster_key_param_t* elems, size_t count);
456     void CopyIndirectData();
457     bool CheckIndirectData();
458 
459     bool DeserializeIndirectData(const uint8_t** buf_ptr, const uint8_t* end);
460     bool DeserializeElementsData(const uint8_t** buf_ptr, const uint8_t* end);
461 
462     bool GetTagValueEnum(keymaster_tag_t tag, uint32_t* val) const;
463     bool GetTagValueEnumRep(keymaster_tag_t tag, size_t instance, uint32_t* val) const;
464     bool GetTagValueInt(keymaster_tag_t tag, uint32_t* val) const;
465     bool GetTagValueIntRep(keymaster_tag_t tag, size_t instance, uint32_t* val) const;
466     bool GetTagValueLong(keymaster_tag_t tag, uint64_t* val) const;
467     bool GetTagValueLongRep(keymaster_tag_t tag, size_t instance, uint64_t* val) const;
468     bool GetTagValueDate(keymaster_tag_t tag, uint64_t* val) const;
469     bool GetTagValueBlob(keymaster_tag_t tag, keymaster_blob_t* val) const;
470     bool GetTagValueBool(keymaster_tag_t tag) const;
471 
472     bool ContainsEnumValue(keymaster_tag_t tag, uint32_t val) const;
473     bool ContainsIntValue(keymaster_tag_t tag, uint32_t val) const;
474 
475     // Define elems_ and elems_size_ as aliases to params and length, respectively.  This is to
476     // avoid using the variables without the trailing underscore in the implementation.
477     keymaster_key_param_t*& elems_ = keymaster_key_param_set_t::params;
478     size_t& elems_size_ = keymaster_key_param_set_t::length;
479 
480     size_t elems_capacity_;
481     uint8_t* indirect_data_;
482     size_t indirect_data_size_;
483     size_t indirect_data_capacity_;
484     Error error_;
485 };
486 
487 class AuthorizationSetBuilder {
488   public:
489     template <typename TagType, typename ValueType>
Authorization(TagType tag,ValueType value)490     AuthorizationSetBuilder& Authorization(TagType tag, ValueType value) {
491         set.push_back(tag, value);
492         return *this;
493     }
494 
495     template <keymaster_tag_t Tag>
Authorization(TypedTag<KM_BOOL,Tag> tag)496     AuthorizationSetBuilder& Authorization(TypedTag<KM_BOOL, Tag> tag) {
497         set.push_back(tag);
498         return *this;
499     }
500 
501     template <keymaster_tag_t Tag>
Authorization(TypedTag<KM_INVALID,Tag> tag)502     AuthorizationSetBuilder& Authorization(TypedTag<KM_INVALID, Tag> tag) {
503         keymaster_key_param_t param;
504         param.tag = tag;
505         set.push_back(param);
506         return *this;
507     }
508 
509     template <keymaster_tag_t Tag>
Authorization(TypedTag<KM_BYTES,Tag> tag,const uint8_t * data,size_t data_length)510     AuthorizationSetBuilder& Authorization(TypedTag<KM_BYTES, Tag> tag, const uint8_t* data,
511                                            size_t data_length) {
512         set.push_back(tag, data, data_length);
513         return *this;
514     }
515 
516     template <keymaster_tag_t Tag>
Authorization(TypedTag<KM_BYTES,Tag> tag,const char * data,size_t data_length)517     AuthorizationSetBuilder& Authorization(TypedTag<KM_BYTES, Tag> tag, const char* data,
518                                            size_t data_length) {
519         return Authorization(tag, reinterpret_cast<const uint8_t*>(data), data_length);
520     }
521 
522     AuthorizationSetBuilder& RsaKey(uint32_t key_size, uint64_t public_exponent);
523     AuthorizationSetBuilder& EcdsaKey(uint32_t key_size);
524     AuthorizationSetBuilder& AesKey(uint32_t key_size);
525     AuthorizationSetBuilder& TripleDesKey(uint32_t key_size);
526     AuthorizationSetBuilder& HmacKey(uint32_t key_size);
527 
528     AuthorizationSetBuilder& RsaSigningKey(uint32_t key_size, uint64_t public_exponent);
529     AuthorizationSetBuilder& RsaEncryptionKey(uint32_t key_size, uint64_t public_exponent);
530     AuthorizationSetBuilder& EcdsaSigningKey(uint32_t key_size);
531     AuthorizationSetBuilder& AesEncryptionKey(uint32_t key_size);
532     AuthorizationSetBuilder& TripleDesEncryptionKey(uint32_t key_size);
533 
534     AuthorizationSetBuilder& SigningKey();
535     AuthorizationSetBuilder& EncryptionKey();
536     AuthorizationSetBuilder& NoDigestOrPadding();
537     AuthorizationSetBuilder& EcbMode();
538 
Digest(keymaster_digest_t digest)539     AuthorizationSetBuilder& Digest(keymaster_digest_t digest) {
540         return Authorization(TAG_DIGEST, digest);
541     }
542 
BlockMode(keymaster_block_mode_t mode)543     AuthorizationSetBuilder& BlockMode(keymaster_block_mode_t mode) {
544         return Authorization(TAG_BLOCK_MODE, mode);
545     }
546 
Padding(keymaster_padding_t padding)547     AuthorizationSetBuilder& Padding(keymaster_padding_t padding) {
548         return Authorization(TAG_PADDING, padding);
549     }
550 
Deduplicate()551     AuthorizationSetBuilder& Deduplicate() {
552         set.Deduplicate();
553         return *this;
554     }
555 
build()556     AuthorizationSet build() const { return set; }
557 
558   private:
559     friend AuthorizationSet;
560     AuthorizationSet set;
561 };
562 
RsaKey(uint32_t key_size,uint64_t public_exponent)563 inline AuthorizationSetBuilder& AuthorizationSetBuilder::RsaKey(uint32_t key_size,
564                                                                 uint64_t public_exponent) {
565     Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA);
566     Authorization(TAG_KEY_SIZE, key_size);
567     Authorization(TAG_RSA_PUBLIC_EXPONENT, public_exponent);
568     return *this;
569 }
570 
EcdsaKey(uint32_t key_size)571 inline AuthorizationSetBuilder& AuthorizationSetBuilder::EcdsaKey(uint32_t key_size) {
572     Authorization(TAG_ALGORITHM, KM_ALGORITHM_EC);
573     Authorization(TAG_KEY_SIZE, key_size);
574     return *this;
575 }
576 
AesKey(uint32_t key_size)577 inline AuthorizationSetBuilder& AuthorizationSetBuilder::AesKey(uint32_t key_size) {
578     Authorization(TAG_ALGORITHM, KM_ALGORITHM_AES);
579     return Authorization(TAG_KEY_SIZE, key_size);
580 }
581 
TripleDesKey(uint32_t key_size)582 inline AuthorizationSetBuilder& AuthorizationSetBuilder::TripleDesKey(uint32_t key_size) {
583     Authorization(TAG_ALGORITHM, KM_ALGORITHM_TRIPLE_DES);
584     return Authorization(TAG_KEY_SIZE, key_size);
585 }
586 
HmacKey(uint32_t key_size)587 inline AuthorizationSetBuilder& AuthorizationSetBuilder::HmacKey(uint32_t key_size) {
588     Authorization(TAG_ALGORITHM, KM_ALGORITHM_HMAC);
589     Authorization(TAG_KEY_SIZE, key_size);
590     return SigningKey();
591 }
592 
RsaSigningKey(uint32_t key_size,uint64_t public_exponent)593 inline AuthorizationSetBuilder& AuthorizationSetBuilder::RsaSigningKey(uint32_t key_size,
594                                                                        uint64_t public_exponent) {
595     RsaKey(key_size, public_exponent);
596     return SigningKey();
597 }
598 
599 inline AuthorizationSetBuilder&
RsaEncryptionKey(uint32_t key_size,uint64_t public_exponent)600 AuthorizationSetBuilder::RsaEncryptionKey(uint32_t key_size, uint64_t public_exponent) {
601     RsaKey(key_size, public_exponent);
602     return EncryptionKey();
603 }
604 
EcdsaSigningKey(uint32_t key_size)605 inline AuthorizationSetBuilder& AuthorizationSetBuilder::EcdsaSigningKey(uint32_t key_size) {
606     EcdsaKey(key_size);
607     return SigningKey();
608 }
609 
AesEncryptionKey(uint32_t key_size)610 inline AuthorizationSetBuilder& AuthorizationSetBuilder::AesEncryptionKey(uint32_t key_size) {
611     AesKey(key_size);
612     return EncryptionKey();
613 }
614 
TripleDesEncryptionKey(uint32_t key_size)615 inline AuthorizationSetBuilder& AuthorizationSetBuilder::TripleDesEncryptionKey(uint32_t key_size) {
616     TripleDesKey(key_size);
617     return EncryptionKey();
618 }
619 
SigningKey()620 inline AuthorizationSetBuilder& AuthorizationSetBuilder::SigningKey() {
621     Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN);
622     return Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY);
623 }
624 
EncryptionKey()625 inline AuthorizationSetBuilder& AuthorizationSetBuilder::EncryptionKey() {
626     Authorization(TAG_PURPOSE, KM_PURPOSE_ENCRYPT);
627     return Authorization(TAG_PURPOSE, KM_PURPOSE_DECRYPT);
628 }
629 
NoDigestOrPadding()630 inline AuthorizationSetBuilder& AuthorizationSetBuilder::NoDigestOrPadding() {
631     Authorization(TAG_DIGEST, KM_DIGEST_NONE);
632     return Authorization(TAG_PADDING, KM_PAD_NONE);
633 }
634 
EcbMode()635 inline AuthorizationSetBuilder& AuthorizationSetBuilder::EcbMode() {
636     return Authorization(TAG_BLOCK_MODE, KM_MODE_ECB);
637 }
638 
639 class AuthProxyIterator {
640     constexpr static size_t invalid = ~size_t(0);
641 public:
AuthProxyIterator()642     AuthProxyIterator()
643         : pos_(invalid), auth_set1_(nullptr), auth_set2_(nullptr) {}
AuthProxyIterator(const AuthorizationSet & auth_set1,const AuthorizationSet & auth_set2)644     AuthProxyIterator(const AuthorizationSet& auth_set1, const AuthorizationSet& auth_set2)
645         : pos_(0), auth_set1_(&auth_set1), auth_set2_(&auth_set2) {}
AuthProxyIterator(const AuthProxyIterator & rhs)646     AuthProxyIterator(const AuthProxyIterator& rhs)
647         : pos_(rhs.pos_), auth_set1_(rhs.auth_set1_), auth_set2_(rhs.auth_set2_) {}
~AuthProxyIterator()648     ~AuthProxyIterator() {};
649     AuthProxyIterator& operator=(const AuthProxyIterator& rhs) {
650         if (this != &rhs) {
651             pos_ = rhs.pos_;
652             auth_set1_ = rhs.auth_set1_;
653             auth_set2_ = rhs.auth_set2_;
654         }
655         return *this;
656     }
657     AuthProxyIterator& operator++() {
658         if (pos_ == invalid) return *this;
659         ++pos_;
660         if (pos_ == (auth_set1_->size() + auth_set2_->size())) {
661             pos_ = invalid;
662         }
663         return *this;
664     }
665     const keymaster_key_param_t& operator*() const {
666         if (pos_ < auth_set1_->size()) {
667             return (*auth_set1_)[pos_];
668         } else {
669             return (*auth_set2_)[pos_ - auth_set1_->size()];
670         }
671     }
672     AuthProxyIterator operator++(int) {
673         AuthProxyIterator dummy(*this);
674         ++(*this);
675         return dummy;
676     }
677     const keymaster_key_param_t* operator->() const {
678         return &(*(*this));
679     }
680 
681     bool operator==(const AuthProxyIterator& rhs) {
682         if (pos_ == rhs.pos_) {
683             return pos_ == invalid ||
684                     (auth_set1_ == rhs.auth_set1_ && auth_set2_ == rhs.auth_set2_);
685         } else return false;
686     }
687     bool operator!=(const AuthProxyIterator& rhs) {
688         return !operator==(rhs);
689     }
690 private:
691     size_t pos_;
692     const AuthorizationSet* auth_set1_;
693     const AuthorizationSet* auth_set2_;
694 };
695 
696 class AuthProxy {
697   public:
AuthProxy(const AuthorizationSet & hw_enforced,const AuthorizationSet & sw_enforced)698     AuthProxy(const AuthorizationSet& hw_enforced, const AuthorizationSet& sw_enforced)
699         : hw_enforced_(hw_enforced), sw_enforced_(sw_enforced) {}
700 
Contains(ARGS &&...args)701     template <typename... ARGS> bool Contains(ARGS&&... args) const {
702         return hw_enforced_.Contains(forward<ARGS>(args)...) ||
703                sw_enforced_.Contains(forward<ARGS>(args)...);
704     }
705 
GetTagValue(ARGS &&...args)706     template <typename... ARGS> bool GetTagValue(ARGS&&... args) const {
707         return hw_enforced_.GetTagValue(forward<ARGS>(args)...) ||
708                sw_enforced_.GetTagValue(forward<ARGS>(args)...);
709     }
710 
begin()711     AuthProxyIterator begin() const {
712         return AuthProxyIterator(hw_enforced_, sw_enforced_);
713     }
714 
end()715     AuthProxyIterator end() const { return AuthProxyIterator(); }
716 
size()717     size_t size() const { return hw_enforced_.size() + sw_enforced_.size(); }
718 
719     keymaster_key_param_t operator[](size_t pos) const {
720         if (pos < hw_enforced_.size()) return hw_enforced_[pos];
721         if ((pos - hw_enforced_.size()) < sw_enforced_.size()) {
722             return sw_enforced_[pos - hw_enforced_.size()];
723         }
724         return {};
725     }
726 
727   private:
728     const AuthorizationSet& hw_enforced_;
729     const AuthorizationSet& sw_enforced_;
730 };
731 
732 }  // namespace keymaster
733 
734 #endif  // SYSTEM_KEYMASTER_KEY_AUTHORIZATION_SET_H_
735