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