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