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