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