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) : indirect_data_(nullptr) {
58 elems_ = nullptr;
59 Reinitialize(elems, count);
60 }
61
AuthorizationSet(const keymaster_key_param_set_t & set)62 explicit AuthorizationSet(const keymaster_key_param_set_t& set) : indirect_data_(nullptr) {
63 elems_ = nullptr;
64 Reinitialize(set.params, set.length);
65 }
66
AuthorizationSet(const uint8_t * serialized_set,size_t serialized_size)67 explicit AuthorizationSet(const uint8_t* serialized_set, size_t serialized_size)
68 : indirect_data_(nullptr) {
69 elems_ = nullptr;
70 Deserialize(&serialized_set, serialized_set + serialized_size);
71 }
72
73 /**
74 * Construct an AuthorizationSet from the provided builder. This extracts the data from the
75 * builder, rather than copying it, so after this call the builder is empty.
76 */
77 explicit AuthorizationSet(/* NOT const */ AuthorizationSetBuilder& builder);
78
79 // Copy constructor.
AuthorizationSet(const AuthorizationSet & set)80 AuthorizationSet(const AuthorizationSet& set) : Serializable(), indirect_data_(nullptr) {
81 elems_ = nullptr;
82 error_ = set.error_;
83 if (error_ != OK) return;
84 Reinitialize(set.elems_, set.elems_size_);
85 }
86
87 // Move constructor.
AuthorizationSet(AuthorizationSet && set)88 AuthorizationSet(AuthorizationSet&& set) : Serializable() {
89 MoveFrom(set);
90 }
91
92 // Copy assignment.
93 AuthorizationSet& operator=(const AuthorizationSet& set) {
94 Reinitialize(set.elems_, set.elems_size_);
95 error_ = set.error_;
96 return *this;
97 }
98
99 // Move assignment.
100 AuthorizationSet& operator=(AuthorizationSet&& set) {
101 FreeData();
102 MoveFrom(set);
103 return *this;
104 }
105
106 /**
107 * Clear existing authorization set data
108 */
109 void Clear();
110
111 /**
112 * Reinitialize an AuthorizationSet as a dynamically-allocated, growable copy of the data in the
113 * provided array (and the data referenced by its embedded pointers, if any). If the allocation
114 * of the needed storage fails this method will return false and \p is_valid() will return
115 * ALLOCATION_FAILURE.
116 */
117 bool Reinitialize(const keymaster_key_param_t* elems, size_t count);
118
Reinitialize(const AuthorizationSet & set)119 bool Reinitialize(const AuthorizationSet& set) {
120 return Reinitialize(set.elems_, set.elems_size_);
121 }
122
Reinitialize(const keymaster_key_param_set_t & set)123 bool Reinitialize(const keymaster_key_param_set_t& set) {
124 return Reinitialize(set.params, set.length);
125 }
126
127 ~AuthorizationSet();
128
129 enum Error {
130 OK,
131 ALLOCATION_FAILURE,
132 MALFORMED_DATA,
133 };
134
is_valid()135 Error is_valid() const { return error_; }
136
137 /**
138 * Returns the size of the set.
139 */
size()140 size_t size() const { return elems_size_; }
141
142 /**
143 * Returns true if the set is empty.
144 */
empty()145 bool empty() const { return size() == 0; }
146
147 /**
148 * Returns the total size of all indirect data referenced by set elements.
149 */
indirect_size()150 size_t indirect_size() const { return indirect_data_size_; }
151
152 /**
153 * Returns the data in the set, directly. Be careful with this.
154 */
data()155 const keymaster_key_param_t* data() const { return elems_; }
156
157 /**
158 * Sorts the set
159 */
160 void Sort();
161
162 /**
163 * Sorts the set and removes duplicates (inadvertently duplicating tags is easy to do with the
164 * AuthorizationSetBuilder).
165 */
166 void Deduplicate();
167
168 /**
169 * Adds all elements from \p set that are not already present in this AuthorizationSet. As a
170 * side-effect, if \p set is not null this AuthorizationSet will end up sorted.
171 */
172 void Union(const keymaster_key_param_set_t& set);
173
174 /**
175 * Removes all elements in \p set from this AuthorizationSet.
176 */
177 void Difference(const keymaster_key_param_set_t& set);
178
179 /**
180 * Returns the data in a keymaster_key_param_set_t, suitable for returning to C code. For C
181 * compatibility, the contents are malloced, not new'ed, and so must be freed with free(), or
182 * better yet with keymaster_free_param_set, not delete. The caller takes ownership.
183 */
184 void CopyToParamSet(keymaster_key_param_set_t* set) const;
185
186 /**
187 * Returns the offset of the next entry that matches \p tag, starting from the element after \p
188 * begin. If not found, returns -1.
189 */
190 int find(keymaster_tag_t tag, int begin = -1) const;
191
192 /**
193 * Removes the entry at the specified index. Returns true if successful, false if the index was
194 * out of bounds.
195 */
196 bool erase(int index);
197
198 /**
199 * Returns iterator (pointer) to beginning of elems array, to enable STL-style iteration
200 */
begin()201 const keymaster_key_param_t* begin() const { return elems_; }
202
203 /**
204 * Returns iterator (pointer) one past end of elems array, to enable STL-style iteration
205 */
end()206 const keymaster_key_param_t* end() const { return elems_ + elems_size_; }
207
208 /**
209 * Returns the nth element of the set.
210 */
211 keymaster_key_param_t& operator[](int n);
212
213 /**
214 * Returns the nth element of the set.
215 */
216 const keymaster_key_param_t& operator[](int n) const;
217
218 /**
219 * Returns true if the set contains at least one instance of \p tag
220 */
Contains(keymaster_tag_t tag)221 bool Contains(keymaster_tag_t tag) const {
222 return find(tag) != -1;
223 }
224
225 /**
226 * Returns the number of \p tag entries.
227 */
228 size_t GetTagCount(keymaster_tag_t tag) const;
229
230 /**
231 * Returns true if the set contains the specified tag and value.
232 */
233 template <keymaster_tag_t Tag, typename T>
Contains(TypedEnumTag<KM_ENUM_REP,Tag,T> tag,T val)234 bool Contains(TypedEnumTag<KM_ENUM_REP, Tag, T> tag, T val) const {
235 return ContainsEnumValue(tag, val);
236 }
237
238 /**
239 * Returns true if the set contains the specified tag and value.
240 */
241 template <keymaster_tag_t Tag, typename T>
Contains(TypedEnumTag<KM_ENUM,Tag,T> tag,T val)242 bool Contains(TypedEnumTag<KM_ENUM, Tag, T> tag, T val) const {
243 return ContainsEnumValue(tag, val);
244 }
245
246 /**
247 * Returns true if the set contains the specified tag and value.
248 */
249 template <keymaster_tag_t Tag>
Contains(TypedTag<KM_UINT,Tag> tag,uint32_t val)250 bool Contains(TypedTag<KM_UINT, Tag> tag, uint32_t val) const {
251 return ContainsIntValue(tag, val);
252 }
253
254 /**
255 * If the specified integer-typed \p tag exists, places its value in \p val and returns true.
256 * If \p tag is not present, leaves \p val unmodified and returns false.
257 */
258 template <keymaster_tag_t T>
GetTagValue(TypedTag<KM_UINT,T> tag,uint32_t * val)259 inline bool GetTagValue(TypedTag<KM_UINT, T> tag, uint32_t* val) const {
260 return GetTagValueInt(tag, val);
261 }
262
263 /**
264 * If the specified instance of the specified integer-typed \p tag exists, places its value
265 * in \p val and returns true. If \p tag is not present, leaves \p val unmodified and returns
266 * false.
267 */
268 template <keymaster_tag_t Tag>
GetTagValue(TypedTag<KM_UINT_REP,Tag> tag,size_t instance,uint32_t * val)269 bool GetTagValue(TypedTag<KM_UINT_REP, Tag> tag, size_t instance, uint32_t* val) const {
270 return GetTagValueIntRep(tag, instance, val);
271 }
272
273 /**
274 * If the specified long-typed \p tag exists, places its value in \p val and returns true.
275 * If \p tag is not present, leaves \p val unmodified and returns false.
276 */
277 template <keymaster_tag_t T>
GetTagValue(TypedTag<KM_ULONG,T> tag,uint64_t * val)278 inline bool GetTagValue(TypedTag<KM_ULONG, T> tag, uint64_t* val) const {
279 return GetTagValueLong(tag, val);
280 }
281
282 /**
283 * If the specified instance of the specified integer-typed \p tag exists, places its value
284 * in \p val and returns true. If \p tag is not present, leaves \p val unmodified and returns
285 * false.
286 */
287 template <keymaster_tag_t Tag>
GetTagValue(TypedTag<KM_ULONG_REP,Tag> tag,size_t instance,uint64_t * val)288 bool GetTagValue(TypedTag<KM_ULONG_REP, Tag> tag, size_t instance, uint64_t* val) const {
289 return GetTagValueLongRep(tag, instance, val);
290 }
291
292 /**
293 * If the specified enumeration-typed \p tag exists, places its value in \p val and returns
294 * true. If \p tag is not present, leaves \p val unmodified and returns false.
295 */
296 template <keymaster_tag_t Tag, typename T>
GetTagValue(TypedEnumTag<KM_ENUM,Tag,T> tag,T * val)297 bool GetTagValue(TypedEnumTag<KM_ENUM, Tag, T> tag, T* val) const {
298 return GetTagValueEnum(tag, reinterpret_cast<uint32_t*>(val));
299 }
300
301 /**
302 * If the specified instance of the specified enumeration-typed \p tag exists, places its value
303 * in \p val and returns true. If \p tag is not present, leaves \p val unmodified and returns
304 * false.
305 */
306 template <keymaster_tag_t Tag, typename T>
GetTagValue(TypedEnumTag<KM_ENUM_REP,Tag,T> tag,size_t instance,T * val)307 bool GetTagValue(TypedEnumTag<KM_ENUM_REP, Tag, T> tag, size_t instance, T* val) const {
308 return GetTagValueEnumRep(tag, instance, reinterpret_cast<uint32_t*>(val));
309 }
310
311 /**
312 * If exactly one instance of the specified enumeration-typed \p tag exists, places its value in
313 * \p val and returns true. If \p tag is not present or if multiple copies are present, leaves
314 * \p val unmodified and returns false.
315 */
316 template <keymaster_tag_t Tag, typename T>
GetTagValue(TypedEnumTag<KM_ENUM_REP,Tag,T> tag,T * val)317 bool GetTagValue(TypedEnumTag<KM_ENUM_REP, Tag, T> tag, T* val) const {
318 if (GetTagCount(tag) != 1)
319 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
BlockMode(keymaster_block_mode_t mode)536 AuthorizationSetBuilder& BlockMode(keymaster_block_mode_t mode) {
537 return Authorization(TAG_BLOCK_MODE, mode);
538 }
539
Padding(keymaster_padding_t padding)540 AuthorizationSetBuilder& Padding(keymaster_padding_t padding) {
541 return Authorization(TAG_PADDING, padding);
542 }
543
Deduplicate()544 AuthorizationSetBuilder& Deduplicate() {
545 set.Deduplicate();
546 return *this;
547 }
548
build()549 AuthorizationSet build() const { return set; }
550
551 private:
552 friend AuthorizationSet;
553 AuthorizationSet set;
554 };
555
RsaKey(uint32_t key_size,uint64_t public_exponent)556 inline AuthorizationSetBuilder& AuthorizationSetBuilder::RsaKey(uint32_t key_size,
557 uint64_t public_exponent) {
558 Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA);
559 Authorization(TAG_KEY_SIZE, key_size);
560 Authorization(TAG_RSA_PUBLIC_EXPONENT, public_exponent);
561 return *this;
562 }
563
EcdsaKey(uint32_t key_size)564 inline AuthorizationSetBuilder& AuthorizationSetBuilder::EcdsaKey(uint32_t key_size) {
565 Authorization(TAG_ALGORITHM, KM_ALGORITHM_EC);
566 Authorization(TAG_KEY_SIZE, key_size);
567 return *this;
568 }
569
AesKey(uint32_t key_size)570 inline AuthorizationSetBuilder& AuthorizationSetBuilder::AesKey(uint32_t key_size) {
571 Authorization(TAG_ALGORITHM, KM_ALGORITHM_AES);
572 return Authorization(TAG_KEY_SIZE, key_size);
573 }
574
TripleDesKey(uint32_t key_size)575 inline AuthorizationSetBuilder& AuthorizationSetBuilder::TripleDesKey(uint32_t key_size) {
576 Authorization(TAG_ALGORITHM, KM_ALGORITHM_TRIPLE_DES);
577 return Authorization(TAG_KEY_SIZE, key_size);
578 }
579
HmacKey(uint32_t key_size)580 inline AuthorizationSetBuilder& AuthorizationSetBuilder::HmacKey(uint32_t key_size) {
581 Authorization(TAG_ALGORITHM, KM_ALGORITHM_HMAC);
582 Authorization(TAG_KEY_SIZE, key_size);
583 return SigningKey();
584 }
585
RsaSigningKey(uint32_t key_size,uint64_t public_exponent)586 inline AuthorizationSetBuilder& AuthorizationSetBuilder::RsaSigningKey(uint32_t key_size,
587 uint64_t public_exponent) {
588 RsaKey(key_size, public_exponent);
589 return SigningKey();
590 }
591
592 inline AuthorizationSetBuilder&
RsaEncryptionKey(uint32_t key_size,uint64_t public_exponent)593 AuthorizationSetBuilder::RsaEncryptionKey(uint32_t key_size, uint64_t public_exponent) {
594 RsaKey(key_size, public_exponent);
595 return EncryptionKey();
596 }
597
EcdsaSigningKey(uint32_t key_size)598 inline AuthorizationSetBuilder& AuthorizationSetBuilder::EcdsaSigningKey(uint32_t key_size) {
599 EcdsaKey(key_size);
600 return SigningKey();
601 }
602
AesEncryptionKey(uint32_t key_size)603 inline AuthorizationSetBuilder& AuthorizationSetBuilder::AesEncryptionKey(uint32_t key_size) {
604 AesKey(key_size);
605 return EncryptionKey();
606 }
607
TripleDesEncryptionKey(uint32_t key_size)608 inline AuthorizationSetBuilder& AuthorizationSetBuilder::TripleDesEncryptionKey(uint32_t key_size) {
609 TripleDesKey(key_size);
610 return EncryptionKey();
611 }
612
SigningKey()613 inline AuthorizationSetBuilder& AuthorizationSetBuilder::SigningKey() {
614 Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN);
615 return Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY);
616 }
617
EncryptionKey()618 inline AuthorizationSetBuilder& AuthorizationSetBuilder::EncryptionKey() {
619 Authorization(TAG_PURPOSE, KM_PURPOSE_ENCRYPT);
620 return Authorization(TAG_PURPOSE, KM_PURPOSE_DECRYPT);
621 }
622
NoDigestOrPadding()623 inline AuthorizationSetBuilder& AuthorizationSetBuilder::NoDigestOrPadding() {
624 Authorization(TAG_DIGEST, KM_DIGEST_NONE);
625 return Authorization(TAG_PADDING, KM_PAD_NONE);
626 }
627
EcbMode()628 inline AuthorizationSetBuilder& AuthorizationSetBuilder::EcbMode() {
629 return Authorization(TAG_BLOCK_MODE, KM_MODE_ECB);
630 }
631
632 class AuthProxyIterator {
633 constexpr static size_t invalid = ~size_t(0);
634 public:
AuthProxyIterator()635 AuthProxyIterator()
636 : pos_(invalid), auth_set1_(nullptr), auth_set2_(nullptr) {}
AuthProxyIterator(const AuthorizationSet & auth_set1,const AuthorizationSet & auth_set2)637 AuthProxyIterator(const AuthorizationSet& auth_set1, const AuthorizationSet& auth_set2)
638 : pos_(0), auth_set1_(&auth_set1), auth_set2_(&auth_set2) {}
AuthProxyIterator(const AuthProxyIterator & rhs)639 AuthProxyIterator(const AuthProxyIterator& rhs)
640 : pos_(rhs.pos_), auth_set1_(rhs.auth_set1_), auth_set2_(rhs.auth_set2_) {}
~AuthProxyIterator()641 ~AuthProxyIterator() {};
642 AuthProxyIterator& operator=(const AuthProxyIterator& rhs) {
643 if (this != &rhs) {
644 pos_ = rhs.pos_;
645 auth_set1_ = rhs.auth_set1_;
646 auth_set2_ = rhs.auth_set2_;
647 }
648 return *this;
649 }
650 AuthProxyIterator& operator++() {
651 if (pos_ == invalid) return *this;
652 ++pos_;
653 if (pos_ == (auth_set1_->size() + auth_set2_->size())) {
654 pos_ = invalid;
655 }
656 return *this;
657 }
658 const keymaster_key_param_t& operator*() const {
659 if (pos_ < auth_set1_->size()) {
660 return (*auth_set1_)[pos_];
661 } else {
662 return (*auth_set2_)[pos_ - auth_set1_->size()];
663 }
664 }
665 AuthProxyIterator operator++(int) {
666 AuthProxyIterator dummy(*this);
667 ++(*this);
668 return dummy;
669 }
670 const keymaster_key_param_t* operator->() const {
671 return &(*(*this));
672 }
673
674 bool operator==(const AuthProxyIterator& rhs) {
675 if (pos_ == rhs.pos_) {
676 return pos_ == invalid ||
677 (auth_set1_ == rhs.auth_set1_ && auth_set2_ == rhs.auth_set2_);
678 } else return false;
679 }
680 bool operator!=(const AuthProxyIterator& rhs) {
681 return !operator==(rhs);
682 }
683 private:
684 size_t pos_;
685 const AuthorizationSet* auth_set1_;
686 const AuthorizationSet* auth_set2_;
687 };
688
689 class AuthProxy {
690 public:
AuthProxy(const AuthorizationSet & hw_enforced,const AuthorizationSet & sw_enforced)691 AuthProxy(const AuthorizationSet& hw_enforced, const AuthorizationSet& sw_enforced)
692 : hw_enforced_(hw_enforced), sw_enforced_(sw_enforced) {}
693
Contains(ARGS &&...args)694 template <typename... ARGS> bool Contains(ARGS&&... args) const {
695 return hw_enforced_.Contains(forward<ARGS>(args)...) ||
696 sw_enforced_.Contains(forward<ARGS>(args)...);
697 }
698
GetTagValue(ARGS &&...args)699 template <typename... ARGS> bool GetTagValue(ARGS&&... args) const {
700 return hw_enforced_.GetTagValue(forward<ARGS>(args)...) ||
701 sw_enforced_.GetTagValue(forward<ARGS>(args)...);
702 }
703
begin()704 AuthProxyIterator begin() const {
705 return AuthProxyIterator(hw_enforced_, sw_enforced_);
706 }
707
end()708 AuthProxyIterator end() const { return AuthProxyIterator(); }
709
size()710 size_t size() const { return hw_enforced_.size() + sw_enforced_.size(); }
711
712 keymaster_key_param_t operator[](size_t pos) const {
713 if (pos < hw_enforced_.size()) return hw_enforced_[pos];
714 if ((pos - hw_enforced_.size()) < sw_enforced_.size()) {
715 return sw_enforced_[pos - hw_enforced_.size()];
716 }
717 return {};
718 }
719
720 private:
721 const AuthorizationSet& hw_enforced_;
722 const AuthorizationSet& sw_enforced_;
723 };
724
725 } // namespace keymaster
726
727 #endif // SYSTEM_KEYMASTER_KEY_AUTHORIZATION_SET_H_
728