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