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