• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 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 #include <keymaster/authorization_set.h>
18 
19 #include <assert.h>
20 #include <stddef.h>
21 #include <stdlib.h>
22 #include <string.h>
23 
24 #include <keymaster/android_keymaster_utils.h>
25 #include <keymaster/logger.h>
26 
27 namespace keymaster {
28 
is_blob_tag(keymaster_tag_t tag)29 static inline bool is_blob_tag(keymaster_tag_t tag) {
30     return (keymaster_tag_get_type(tag) == KM_BYTES || keymaster_tag_get_type(tag) == KM_BIGNUM);
31 }
32 
33 const size_t STARTING_ELEMS_CAPACITY = 8;
34 
AuthorizationSet(AuthorizationSetBuilder & builder)35 AuthorizationSet::AuthorizationSet(AuthorizationSetBuilder& builder) {
36     elems_ = builder.set.elems_;
37     builder.set.elems_ = nullptr;
38 
39     elems_size_ = builder.set.elems_size_;
40     builder.set.elems_size_ = 0;
41 
42     elems_capacity_ = builder.set.elems_capacity_;
43     builder.set.elems_capacity_ = 0;
44 
45     indirect_data_ = builder.set.indirect_data_;
46     builder.set.indirect_data_ = nullptr;
47 
48     indirect_data_capacity_ = builder.set.indirect_data_capacity_;
49     builder.set.indirect_data_capacity_ = 0;
50 
51     indirect_data_size_ = builder.set.indirect_data_size_;
52     builder.set.indirect_data_size_ = 0;
53 
54     error_ = builder.set.error_;
55     builder.set.error_ = OK;
56 }
57 
~AuthorizationSet()58 AuthorizationSet::~AuthorizationSet() {
59     FreeData();
60 }
61 
reserve_elems(size_t count)62 bool AuthorizationSet::reserve_elems(size_t count) {
63     if (is_valid() != OK) return false;
64 
65     if (count > elems_capacity_) {
66         keymaster_key_param_t* new_elems = new (std::nothrow) keymaster_key_param_t[count];
67         if (new_elems == nullptr) {
68             set_invalid(ALLOCATION_FAILURE);
69             return false;
70         }
71         if (elems_size_ > 0) {
72             memcpy(new_elems, elems_, sizeof(*elems_) * elems_size_);
73         }
74         delete[] elems_;
75         elems_ = new_elems;
76         elems_capacity_ = count;
77     }
78     return true;
79 }
80 
reserve_indirect(size_t length)81 bool AuthorizationSet::reserve_indirect(size_t length) {
82     if (is_valid() != OK) return false;
83 
84     if (length > indirect_data_capacity_) {
85         uint8_t* new_data = new (std::nothrow) uint8_t[length];
86         if (new_data == nullptr) {
87             set_invalid(ALLOCATION_FAILURE);
88             return false;
89         }
90         if (indirect_data_size_ > 0) {
91             memcpy(new_data, indirect_data_, indirect_data_size_);
92         }
93 
94         // Fix up the data pointers to point into the new region.
95         for (size_t i = 0; i < elems_size_; ++i) {
96             if (is_blob_tag(elems_[i].tag))
97                 elems_[i].blob.data = new_data + (elems_[i].blob.data - indirect_data_);
98         }
99         delete[] indirect_data_;
100         indirect_data_ = new_data;
101         indirect_data_capacity_ = length;
102     }
103     return true;
104 }
105 
MoveFrom(AuthorizationSet & set)106 void AuthorizationSet::MoveFrom(AuthorizationSet& set) {
107     elems_ = set.elems_;
108     elems_size_ = set.elems_size_;
109     elems_capacity_ = set.elems_capacity_;
110     indirect_data_ = set.indirect_data_;
111     indirect_data_size_ = set.indirect_data_size_;
112     indirect_data_capacity_ = set.indirect_data_capacity_;
113     error_ = set.error_;
114     set.elems_ = nullptr;
115     set.elems_size_ = 0;
116     set.elems_capacity_ = 0;
117     set.indirect_data_ = nullptr;
118     set.indirect_data_size_ = 0;
119     set.indirect_data_capacity_ = 0;
120     set.error_ = OK;
121 }
122 
Reinitialize(const keymaster_key_param_t * elems,const size_t count)123 bool AuthorizationSet::Reinitialize(const keymaster_key_param_t* elems, const size_t count) {
124     FreeData();
125 
126     if (elems == nullptr || count == 0) {
127         error_ = OK;
128         return true;
129     }
130 
131     if (!reserve_elems(count)) return false;
132 
133     if (!reserve_indirect(ComputeIndirectDataSize(elems, count))) return false;
134 
135     memcpy(elems_, elems, sizeof(keymaster_key_param_t) * count);
136     elems_size_ = count;
137     CopyIndirectData();
138     error_ = OK;
139     return true;
140 }
141 
set_invalid(Error error)142 void AuthorizationSet::set_invalid(Error error) {
143     FreeData();
144     error_ = error;
145 }
146 
Sort()147 void AuthorizationSet::Sort() {
148     qsort(elems_, elems_size_, sizeof(*elems_),
149           reinterpret_cast<int (*)(const void*, const void*)>(keymaster_param_compare));
150 }
151 
Deduplicate()152 void AuthorizationSet::Deduplicate() {
153     Sort();
154 
155     size_t invalid_count = 0;
156     for (size_t i = 1; i < size(); ++i) {
157         if (elems_[i - 1].tag == KM_TAG_INVALID)
158             ++invalid_count;
159         else if (keymaster_param_compare(elems_ + i - 1, elems_ + i) == 0) {
160             // Mark dups as invalid.  Note that this "leaks" the data referenced by KM_BYTES and
161             // KM_BIGNUM entries, but those are just pointers into indirect_data_, so it will all
162             // get cleaned up.
163             elems_[i - 1].tag = KM_TAG_INVALID;
164             ++invalid_count;
165         }
166     }
167     if (size() > 0 && elems_[size() - 1].tag == KM_TAG_INVALID) ++invalid_count;
168 
169     if (invalid_count == 0) return;
170 
171     Sort();
172 
173     // Since KM_TAG_INVALID == 0, all of the invalid entries are first.
174     elems_size_ -= invalid_count;
175     memmove(elems_, elems_ + invalid_count, size() * sizeof(*elems_));
176 }
177 
Difference(const keymaster_key_param_set_t & set)178 void AuthorizationSet::Difference(const keymaster_key_param_set_t& set) {
179     if (set.length == 0) return;
180 
181     Deduplicate();
182 
183     for (size_t i = 0; i < set.length; i++) {
184         int index = -1;
185         do {
186             index = find(set.params[i].tag, index);
187             if (index != -1 && keymaster_param_compare(&elems_[index], &set.params[i]) == 0) {
188                 erase(index);
189                 break;
190             }
191         } while (index != -1);
192     }
193 }
194 
CopyToParamSet(keymaster_key_param_set_t * set) const195 void AuthorizationSet::CopyToParamSet(keymaster_key_param_set_t* set) const {
196     assert(set);
197 
198     set->length = size();
199     set->params =
200         reinterpret_cast<keymaster_key_param_t*>(malloc(sizeof(keymaster_key_param_t) * size()));
201 
202     for (size_t i = 0; i < size(); ++i) {
203         const keymaster_key_param_t src = (*this)[i];
204         keymaster_key_param_t& dst(set->params[i]);
205 
206         dst = src;
207         keymaster_tag_type_t type = keymaster_tag_get_type(src.tag);
208         if (type == KM_BIGNUM || type == KM_BYTES) {
209             void* tmp = malloc(src.blob.data_length);
210             memcpy(tmp, src.blob.data, src.blob.data_length);
211             dst.blob.data = reinterpret_cast<uint8_t*>(tmp);
212         }
213     }
214 }
215 
find(keymaster_tag_t tag,int begin) const216 int AuthorizationSet::find(keymaster_tag_t tag, int begin) const {
217     if (is_valid() != OK) return -1;
218 
219     int i = ++begin;
220     while (i < (int)elems_size_ && elems_[i].tag != tag)
221         ++i;
222     if (i == (int)elems_size_)
223         return -1;
224     else
225         return i;
226 }
227 
erase(int index)228 bool AuthorizationSet::erase(int index) {
229     if (index < 0 || index >= static_cast<int>(size())) return false;
230 
231     --elems_size_;
232     for (size_t i = index; i < elems_size_; ++i)
233         elems_[i] = elems_[i + 1];
234     return true;
235 }
236 
237 keymaster_key_param_t empty_param = {KM_TAG_INVALID, {}};
operator [](int at)238 keymaster_key_param_t& AuthorizationSet::operator[](int at) {
239     if (is_valid() == OK && at < (int)elems_size_) {
240         return elems_[at];
241     }
242     empty_param = {KM_TAG_INVALID, {}};
243     return empty_param;
244 }
245 
operator [](int at) const246 const keymaster_key_param_t& AuthorizationSet::operator[](int at) const {
247     if (is_valid() == OK && at < (int)elems_size_) {
248         return elems_[at];
249     }
250     empty_param = {KM_TAG_INVALID, {}};
251     return empty_param;
252 }
253 
push_back(const keymaster_key_param_set_t & set)254 bool AuthorizationSet::push_back(const keymaster_key_param_set_t& set) {
255     if (is_valid() != OK) return false;
256 
257     if (!reserve_elems(elems_size_ + set.length)) return false;
258 
259     if (!reserve_indirect(indirect_data_size_ + ComputeIndirectDataSize(set.params, set.length)))
260         return false;
261 
262     for (size_t i = 0; i < set.length; ++i)
263         if (!push_back(set.params[i])) return false;
264 
265     return true;
266 }
267 
push_back(keymaster_key_param_t elem)268 bool AuthorizationSet::push_back(keymaster_key_param_t elem) {
269     if (is_valid() != OK) return false;
270 
271     if (elems_size_ >= elems_capacity_)
272         if (!reserve_elems(elems_capacity_ ? elems_capacity_ * 2 : STARTING_ELEMS_CAPACITY))
273             return false;
274 
275     if (is_blob_tag(elem.tag)) {
276         if (indirect_data_capacity_ - indirect_data_size_ < elem.blob.data_length)
277             if (!reserve_indirect(2 * (indirect_data_capacity_ + elem.blob.data_length)))
278                 return false;
279 
280         memcpy(indirect_data_ + indirect_data_size_, elem.blob.data, elem.blob.data_length);
281         elem.blob.data = indirect_data_ + indirect_data_size_;
282         indirect_data_size_ += elem.blob.data_length;
283     }
284 
285     elems_[elems_size_++] = elem;
286     return true;
287 }
288 
serialized_size(const keymaster_key_param_t & param)289 static size_t serialized_size(const keymaster_key_param_t& param) {
290     switch (keymaster_tag_get_type(param.tag)) {
291     case KM_INVALID:
292         return sizeof(uint32_t);
293     case KM_ENUM:
294     case KM_ENUM_REP:
295     case KM_UINT:
296     case KM_UINT_REP:
297         return sizeof(uint32_t) * 2;
298     case KM_ULONG:
299     case KM_ULONG_REP:
300     case KM_DATE:
301         return sizeof(uint32_t) + sizeof(uint64_t);
302     case KM_BOOL:
303         return sizeof(uint32_t) + 1;
304     case KM_BIGNUM:
305     case KM_BYTES:
306         return sizeof(uint32_t) * 3;
307     }
308 
309     return sizeof(uint32_t);
310 }
311 
serialize(const keymaster_key_param_t & param,uint8_t * buf,const uint8_t * end,const uint8_t * indirect_base)312 static uint8_t* serialize(const keymaster_key_param_t& param, uint8_t* buf, const uint8_t* end,
313                           const uint8_t* indirect_base) {
314     buf = append_uint32_to_buf(buf, end, param.tag);
315     switch (keymaster_tag_get_type(param.tag)) {
316     case KM_INVALID:
317         break;
318     case KM_ENUM:
319     case KM_ENUM_REP:
320         buf = append_uint32_to_buf(buf, end, param.enumerated);
321         break;
322     case KM_UINT:
323     case KM_UINT_REP:
324         buf = append_uint32_to_buf(buf, end, param.integer);
325         break;
326     case KM_ULONG:
327     case KM_ULONG_REP:
328         buf = append_uint64_to_buf(buf, end, param.long_integer);
329         break;
330     case KM_DATE:
331         buf = append_uint64_to_buf(buf, end, param.date_time);
332         break;
333     case KM_BOOL:
334         if (buf < end) *buf = static_cast<uint8_t>(param.boolean);
335         buf++;
336         break;
337     case KM_BIGNUM:
338     case KM_BYTES:
339         buf = append_uint32_to_buf(buf, end, param.blob.data_length);
340         buf = append_uint32_to_buf(buf, end, param.blob.data - indirect_base);
341         break;
342     }
343     return buf;
344 }
345 
deserialize(keymaster_key_param_t * param,const uint8_t ** buf_ptr,const uint8_t * end,const uint8_t * indirect_base,const uint8_t * indirect_end)346 static bool deserialize(keymaster_key_param_t* param, const uint8_t** buf_ptr, const uint8_t* end,
347                         const uint8_t* indirect_base, const uint8_t* indirect_end) {
348     if (!copy_uint32_from_buf(buf_ptr, end, &param->tag)) return false;
349 
350     switch (keymaster_tag_get_type(param->tag)) {
351     case KM_INVALID:
352         return false;
353     case KM_ENUM:
354     case KM_ENUM_REP:
355         return copy_uint32_from_buf(buf_ptr, end, &param->enumerated);
356     case KM_UINT:
357     case KM_UINT_REP:
358         return copy_uint32_from_buf(buf_ptr, end, &param->integer);
359     case KM_ULONG:
360     case KM_ULONG_REP:
361         return copy_uint64_from_buf(buf_ptr, end, &param->long_integer);
362     case KM_DATE:
363         return copy_uint64_from_buf(buf_ptr, end, &param->date_time);
364         break;
365     case KM_BOOL:
366         if (*buf_ptr < end) {
367             uint8_t temp = **buf_ptr;
368             // Bools are converted to 0 or 1 when serialized so only accept
369             // one of these values when deserializing.
370             if (temp <= 1) {
371                 param->boolean = static_cast<bool>(temp);
372                 (*buf_ptr)++;
373                 return true;
374             }
375         }
376         return false;
377 
378     case KM_BIGNUM:
379     case KM_BYTES: {
380         uint32_t offset;
381         if (!copy_uint32_from_buf(buf_ptr, end, &param->blob.data_length) ||
382             !copy_uint32_from_buf(buf_ptr, end, &offset))
383             return false;
384         if (param->blob.data_length + offset < param->blob.data_length ||  // Overflow check
385             static_cast<ptrdiff_t>(offset) > indirect_end - indirect_base ||
386             static_cast<ptrdiff_t>(offset + param->blob.data_length) > indirect_end - indirect_base)
387             return false;
388         param->blob.data = indirect_base + offset;
389         return true;
390     }
391     }
392 
393     return false;
394 }
395 
SerializedSizeOfElements() const396 size_t AuthorizationSet::SerializedSizeOfElements() const {
397     size_t size = 0;
398     for (size_t i = 0; i < elems_size_; ++i) {
399         size += serialized_size(elems_[i]);
400     }
401     return size;
402 }
403 
SerializedSize() const404 size_t AuthorizationSet::SerializedSize() const {
405     return sizeof(uint32_t) +           // Size of indirect_data_
406            indirect_data_size_ +        // indirect_data_
407            sizeof(uint32_t) +           // Number of elems_
408            sizeof(uint32_t) +           // Size of elems_
409            SerializedSizeOfElements();  // elems_
410 }
411 
Serialize(uint8_t * buf,const uint8_t * end) const412 uint8_t* AuthorizationSet::Serialize(uint8_t* buf, const uint8_t* end) const {
413     buf = append_size_and_data_to_buf(buf, end, indirect_data_, indirect_data_size_);
414     buf = append_uint32_to_buf(buf, end, elems_size_);
415     buf = append_uint32_to_buf(buf, end, SerializedSizeOfElements());
416     for (size_t i = 0; i < elems_size_; ++i) {
417         buf = serialize(elems_[i], buf, end, indirect_data_);
418     }
419     return buf;
420 }
421 
DeserializeIndirectData(const uint8_t ** buf_ptr,const uint8_t * end)422 bool AuthorizationSet::DeserializeIndirectData(const uint8_t** buf_ptr, const uint8_t* end) {
423     UniquePtr<uint8_t[]> indirect_buf;
424     if (!copy_size_and_data_from_buf(buf_ptr, end, &indirect_data_size_, &indirect_buf)) {
425         LOG_E("Malformed data found in AuthorizationSet deserialization");
426         set_invalid(MALFORMED_DATA);
427         return false;
428     }
429     indirect_data_ = indirect_buf.release();
430     return true;
431 }
432 
DeserializeElementsData(const uint8_t ** buf_ptr,const uint8_t * end)433 bool AuthorizationSet::DeserializeElementsData(const uint8_t** buf_ptr, const uint8_t* end) {
434     uint32_t elements_count;
435     uint32_t elements_size;
436     if (!copy_uint32_from_buf(buf_ptr, end, &elements_count) ||
437         !copy_uint32_from_buf(buf_ptr, end, &elements_size)) {
438         LOG_E("Malformed data found in AuthorizationSet deserialization");
439         set_invalid(MALFORMED_DATA);
440         return false;
441     }
442 
443     // Note that the following validation of elements_count is weak, but it prevents allocation of
444     // elems_ arrays which are clearly too large to be reasonable.
445     size_t elems_refs_size;
446     size_t elems_alloc_size;
447     bool refs_size_overflow =
448         __builtin_mul_overflow(elements_count, sizeof(uint32_t), &elems_refs_size);
449     bool alloc_size_overflow =
450         __builtin_mul_overflow(elements_count, sizeof(*elems_), &elems_alloc_size);
451     /* elements_size must fit in the buffer */
452     if (static_cast<ptrdiff_t>(elements_size) > end - *buf_ptr ||
453         /* The element refs must all fit within elements_size */
454         elems_refs_size > elements_size ||
455         /* If our pointer math would overflow, bail */
456         refs_size_overflow ||
457         /* If the resulting allocation would overflow, bail */
458         alloc_size_overflow) {
459         LOG_E("Malformed data found in AuthorizationSet deserialization");
460         set_invalid(MALFORMED_DATA);
461         return false;
462     }
463 
464     if (!reserve_elems(elements_count)) return false;
465 
466     uint8_t* indirect_end = indirect_data_ + indirect_data_size_;
467     const uint8_t* elements_end = *buf_ptr + elements_size;
468     for (size_t i = 0; i < elements_count; ++i) {
469         if (!deserialize(elems_ + i, buf_ptr, elements_end, indirect_data_, indirect_end)) {
470             LOG_E("Malformed data found in AuthorizationSet deserialization");
471             set_invalid(MALFORMED_DATA);
472             return false;
473         }
474     }
475 
476     // Check if all the elements were consumed. If not, something was malformed as the
477     // retrieved elements_count and elements_size are not consistent with each other.
478     if (*buf_ptr != elements_end) {
479         LOG_E("Malformed data found in AuthorizationSet deserialization");
480         set_invalid(MALFORMED_DATA);
481         return false;
482     }
483 
484     elems_size_ = elements_count;
485     return true;
486 }
487 
Deserialize(const uint8_t ** buf_ptr,const uint8_t * end)488 bool AuthorizationSet::Deserialize(const uint8_t** buf_ptr, const uint8_t* end) {
489     FreeData();
490 
491     if (!DeserializeIndirectData(buf_ptr, end) || !DeserializeElementsData(buf_ptr, end))
492         return false;
493 
494     if (indirect_data_size_ != ComputeIndirectDataSize(elems_, elems_size_)) {
495         LOG_E("Malformed data found in AuthorizationSet deserialization");
496         set_invalid(MALFORMED_DATA);
497         return false;
498     }
499     return true;
500 }
501 
Clear()502 void AuthorizationSet::Clear() {
503     memset_s(elems_, 0, elems_capacity_ * sizeof(keymaster_key_param_t));
504     memset_s(indirect_data_, 0, indirect_data_capacity_);
505     elems_size_ = 0;
506     indirect_data_size_ = 0;
507     error_ = OK;
508 }
509 
FreeData()510 void AuthorizationSet::FreeData() {
511     Clear();
512 
513     delete[] elems_;
514     delete[] indirect_data_;
515 
516     elems_ = nullptr;
517     indirect_data_ = nullptr;
518     elems_capacity_ = 0;
519     indirect_data_capacity_ = 0;
520     error_ = OK;
521 }
522 
523 /* static */
ComputeIndirectDataSize(const keymaster_key_param_t * elems,size_t count)524 size_t AuthorizationSet::ComputeIndirectDataSize(const keymaster_key_param_t* elems, size_t count) {
525     size_t size = 0;
526     for (size_t i = 0; i < count; ++i) {
527         if (is_blob_tag(elems[i].tag)) {
528             size += elems[i].blob.data_length;
529         }
530     }
531     return size;
532 }
533 
CopyIndirectData()534 void AuthorizationSet::CopyIndirectData() {
535     memset_s(indirect_data_, 0, indirect_data_capacity_);
536 
537     uint8_t* indirect_data_pos = indirect_data_;
538     for (size_t i = 0; i < elems_size_; ++i) {
539         assert(indirect_data_pos <= indirect_data_ + indirect_data_capacity_);
540         if (is_blob_tag(elems_[i].tag)) {
541             memcpy(indirect_data_pos, elems_[i].blob.data, elems_[i].blob.data_length);
542             elems_[i].blob.data = indirect_data_pos;
543             indirect_data_pos += elems_[i].blob.data_length;
544         }
545     }
546     assert(indirect_data_pos == indirect_data_ + indirect_data_capacity_);
547     indirect_data_size_ = indirect_data_pos - indirect_data_;
548 }
549 
GetTagCount(keymaster_tag_t tag) const550 size_t AuthorizationSet::GetTagCount(keymaster_tag_t tag) const {
551     size_t count = 0;
552     for (int pos = -1; (pos = find(tag, pos)) != -1;)
553         ++count;
554     return count;
555 }
556 
GetTagValueEnum(keymaster_tag_t tag,uint32_t * val) const557 bool AuthorizationSet::GetTagValueEnum(keymaster_tag_t tag, uint32_t* val) const {
558     int pos = find(tag);
559     if (pos == -1) {
560         return false;
561     }
562     *val = elems_[pos].enumerated;
563     return true;
564 }
565 
GetTagValueEnumRep(keymaster_tag_t tag,size_t instance,uint32_t * val) const566 bool AuthorizationSet::GetTagValueEnumRep(keymaster_tag_t tag, size_t instance,
567                                           uint32_t* val) const {
568     size_t count = 0;
569     int pos = -1;
570     while (count <= instance) {
571         pos = find(tag, pos);
572         if (pos == -1) {
573             return false;
574         }
575         ++count;
576     }
577     *val = elems_[pos].enumerated;
578     return true;
579 }
580 
GetTagValueInt(keymaster_tag_t tag,uint32_t * val) const581 bool AuthorizationSet::GetTagValueInt(keymaster_tag_t tag, uint32_t* val) const {
582     int pos = find(tag);
583     if (pos == -1) {
584         return false;
585     }
586     *val = elems_[pos].integer;
587     return true;
588 }
589 
GetTagValueIntRep(keymaster_tag_t tag,size_t instance,uint32_t * val) const590 bool AuthorizationSet::GetTagValueIntRep(keymaster_tag_t tag, size_t instance,
591                                          uint32_t* val) const {
592     size_t count = 0;
593     int pos = -1;
594     while (count <= instance) {
595         pos = find(tag, pos);
596         if (pos == -1) {
597             return false;
598         }
599         ++count;
600     }
601     *val = elems_[pos].integer;
602     return true;
603 }
604 
GetTagValueLong(keymaster_tag_t tag,uint64_t * val) const605 bool AuthorizationSet::GetTagValueLong(keymaster_tag_t tag, uint64_t* val) const {
606     int pos = find(tag);
607     if (pos == -1) {
608         return false;
609     }
610     *val = elems_[pos].long_integer;
611     return true;
612 }
613 
GetTagValueLongRep(keymaster_tag_t tag,size_t instance,uint64_t * val) const614 bool AuthorizationSet::GetTagValueLongRep(keymaster_tag_t tag, size_t instance,
615                                           uint64_t* val) const {
616     size_t count = 0;
617     int pos = -1;
618     while (count <= instance) {
619         pos = find(tag, pos);
620         if (pos == -1) {
621             return false;
622         }
623         ++count;
624     }
625     *val = elems_[pos].long_integer;
626     return true;
627 }
628 
GetTagValueDate(keymaster_tag_t tag,uint64_t * val) const629 bool AuthorizationSet::GetTagValueDate(keymaster_tag_t tag, uint64_t* val) const {
630     int pos = find(tag);
631     if (pos == -1) {
632         return false;
633     }
634     *val = elems_[pos].date_time;
635     return true;
636 }
637 
GetTagValueBlob(keymaster_tag_t tag,keymaster_blob_t * val) const638 bool AuthorizationSet::GetTagValueBlob(keymaster_tag_t tag, keymaster_blob_t* val) const {
639     int pos = find(tag);
640     if (pos == -1) {
641         return false;
642     }
643     *val = elems_[pos].blob;
644     return true;
645 }
646 
GetTagValueBool(keymaster_tag_t tag) const647 bool AuthorizationSet::GetTagValueBool(keymaster_tag_t tag) const {
648     int pos = find(tag);
649     if (pos == -1) {
650         return false;
651     }
652     assert(elems_[pos].boolean);
653     return elems_[pos].boolean;
654 }
655 
ContainsEnumValue(keymaster_tag_t tag,uint32_t value) const656 bool AuthorizationSet::ContainsEnumValue(keymaster_tag_t tag, uint32_t value) const {
657     for (auto& entry : *this)
658         if (entry.tag == tag && entry.enumerated == value) return true;
659     return false;
660 }
661 
ContainsIntValue(keymaster_tag_t tag,uint32_t value) const662 bool AuthorizationSet::ContainsIntValue(keymaster_tag_t tag, uint32_t value) const {
663     for (auto& entry : *this)
664         if (entry.tag == tag && entry.integer == value) return true;
665     return false;
666 }
667 
668 }  // namespace keymaster
669