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, ¶m->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, ¶m->enumerated);
359 case KM_UINT:
360 case KM_UINT_REP:
361 return copy_uint32_from_buf(buf_ptr, end, ¶m->integer);
362 case KM_ULONG:
363 case KM_ULONG_REP:
364 return copy_uint64_from_buf(buf_ptr, end, ¶m->long_integer);
365 case KM_DATE:
366 return copy_uint64_from_buf(buf_ptr, end, ¶m->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, ¶m->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