blob: 2b65ee15e903ea9194e9aec3764d753e667d3d73 [file] [log] [blame]
Shawn Willden5ada7b62014-07-29 09:44:17 -06001/*
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 <stdlib.h>
18#include <string.h>
19#include <stddef.h>
20
21#include <assert.h>
22
23#include "authorization_set.h"
Shawn Willden74aff352014-08-11 14:08:31 -060024#include "google_keymaster_utils.h"
Shawn Willden5ada7b62014-07-29 09:44:17 -060025
26namespace keymaster {
27
28static inline bool is_blob_tag(keymaster_tag_t tag) {
29 return (keymaster_tag_get_type(tag) == KM_BYTES || keymaster_tag_get_type(tag) == KM_BIGNUM);
30}
31
32const size_t STARTING_ELEMS_CAPACITY = 8;
33
Shawn Willden58e1a542014-08-08 21:58:29 -060034AuthorizationSet::AuthorizationSet(const AuthorizationSet& set)
35 : elems_(NULL), indirect_data_(NULL) {
Shawn Willden76364712014-08-11 17:48:04 -060036 Reinitialize(set.elems_, set.elems_size_);
Shawn Willden5ada7b62014-07-29 09:44:17 -060037}
38
Shawn Willden8d336ae2014-08-09 15:47:05 -060039AuthorizationSet::~AuthorizationSet() {
40 FreeData();
41}
Shawn Willden58e1a542014-08-08 21:58:29 -060042
Shawn Willden37012132014-08-19 08:15:57 -060043bool AuthorizationSet::reserve_elems(size_t count) {
44 if (count >= elems_capacity_) {
45 keymaster_key_param_t* new_elems = new keymaster_key_param_t[count];
46 if (new_elems == NULL) {
47 set_invalid(ALLOCATION_FAILURE);
48 return false;
49 }
50 memcpy(new_elems, elems_, sizeof(*elems_) * elems_size_);
51 delete[] elems_;
52 elems_ = new_elems;
53 elems_capacity_ = count;
54 }
55 return true;
56}
57
58bool AuthorizationSet::reserve_indirect(size_t length) {
59 if (length > indirect_data_capacity_) {
60 uint8_t* new_data = new uint8_t[length];
61 if (new_data == NULL) {
62 set_invalid(ALLOCATION_FAILURE);
63 return false;
64 }
65 memcpy(new_data, indirect_data_, indirect_data_size_);
66
67 // Fix up the data pointers to point into the new region.
68 for (size_t i = 0; i < elems_size_; ++i) {
69 if (is_blob_tag(elems_[i].tag))
70 elems_[i].blob.data = new_data + (elems_[i].blob.data - indirect_data_);
71 }
72 delete[] indirect_data_;
73 indirect_data_ = new_data;
74 indirect_data_capacity_ = length;
75 }
76 return true;
77}
78
Shawn Willden5ada7b62014-07-29 09:44:17 -060079bool AuthorizationSet::Reinitialize(const keymaster_key_param_t* elems, const size_t count) {
80 FreeData();
81
Shawn Willden37012132014-08-19 08:15:57 -060082 if (!reserve_elems(count))
Shawn Willden5ada7b62014-07-29 09:44:17 -060083 return false;
Shawn Willden5ada7b62014-07-29 09:44:17 -060084
Shawn Willden37012132014-08-19 08:15:57 -060085 if (!reserve_indirect(ComputeIndirectDataSize(elems, count)))
86 return false;
87
88 memcpy(elems_, elems, sizeof(keymaster_key_param_t) * count);
89 elems_size_ = count;
Shawn Willden5ada7b62014-07-29 09:44:17 -060090 CopyIndirectData();
Shawn Willden37012132014-08-19 08:15:57 -060091 error_ = OK;
Shawn Willden5ada7b62014-07-29 09:44:17 -060092 return true;
93}
94
Shawn Willden5ada7b62014-07-29 09:44:17 -060095void AuthorizationSet::set_invalid(Error error) {
Shawn Willden5ada7b62014-07-29 09:44:17 -060096 FreeData();
Shawn Willden37012132014-08-19 08:15:57 -060097 error_ = error;
Shawn Willden5ada7b62014-07-29 09:44:17 -060098}
99
100int AuthorizationSet::find(keymaster_tag_t tag, int begin) const {
101 int i = ++begin;
Shawn Willden8d336ae2014-08-09 15:47:05 -0600102 while (i < (int)elems_size_ && elems_[i].tag != tag)
103 ++i;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600104 if (i == (int)elems_size_)
105 return -1;
106 else
107 return i;
108}
109
110keymaster_key_param_t empty;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600111keymaster_key_param_t AuthorizationSet::operator[](int at) const {
112 if (at < (int)elems_size_) {
Shawn Willden8d336ae2014-08-09 15:47:05 -0600113 return elems_[at];
Shawn Willden5ada7b62014-07-29 09:44:17 -0600114 }
115 memset(&empty, 0, sizeof(empty));
116 return empty;
117}
118
Shawn Willden76364712014-08-11 17:48:04 -0600119template <typename T> int comparator(const T& a, const T& b) {
120 if (a < b)
121 return -1;
122 else if (a > b)
123 return 1;
124 else
125 return 0;
126}
127
128static int param_comparator(const void* a, const void* b) {
129 const keymaster_key_param_t* lhs = static_cast<const keymaster_key_param_t*>(a);
130 const keymaster_key_param_t* rhs = static_cast<const keymaster_key_param_t*>(b);
131
132 if (lhs->tag < rhs->tag)
133 return -1;
134 else if (lhs->tag > rhs->tag)
135 return 1;
136 else
137 switch (keymaster_tag_get_type(lhs->tag)) {
138 default:
139 case KM_INVALID:
140 return 0;
141 case KM_ENUM:
142 case KM_ENUM_REP:
143 return comparator(lhs->enumerated, rhs->enumerated);
144 case KM_INT:
145 case KM_INT_REP:
146 return comparator(lhs->integer, rhs->integer);
147 case KM_LONG:
148 return comparator(lhs->long_integer, rhs->long_integer);
149 case KM_DATE:
150 return comparator(lhs->date_time, rhs->date_time);
151 case KM_BOOL:
152 return comparator(lhs->boolean, rhs->boolean);
153 case KM_BIGNUM:
154 case KM_BYTES: {
155 size_t min_len = lhs->blob.data_length;
156 if (rhs->blob.data_length < min_len)
157 min_len = rhs->blob.data_length;
158
159 if (lhs->blob.data_length == rhs->blob.data_length && min_len > 0)
160 return memcmp(lhs->blob.data, rhs->blob.data, min_len);
161 int cmp_result = memcmp(lhs->blob.data, rhs->blob.data, min_len);
162 if (cmp_result == 0) {
163 // The blobs are equal up to the length of the shortest (which may have length 0),
164 // so the shorter is less, the longer is greater and if they have the same length
165 // they're identical.
166 return comparator(lhs->blob.data_length, rhs->blob.data_length);
167 }
168 return cmp_result;
169 } break;
170 }
171}
172
Shawn Willden37012132014-08-19 08:15:57 -0600173bool AuthorizationSet::push_back(const AuthorizationSet& set) {
174 if (!reserve_elems(elems_size_ + set.elems_size_))
175 return false;
176
177 if (!reserve_indirect(indirect_data_size_ + set.indirect_data_size_))
178 return false;
179
180 for (size_t i = 0; i < set.size(); ++i)
181 if (!push_back(set[i]))
Shawn Willden5ada7b62014-07-29 09:44:17 -0600182 return false;
Shawn Willden37012132014-08-19 08:15:57 -0600183
184 return true;
185}
186
187bool AuthorizationSet::push_back(keymaster_key_param_t elem) {
188 if (elems_size_ >= elems_capacity_)
189 if (!reserve_elems(elems_capacity_ ? elems_capacity_ * 2 : STARTING_ELEMS_CAPACITY))
190 return false;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600191
192 if (is_blob_tag(elem.tag)) {
Shawn Willden37012132014-08-19 08:15:57 -0600193 if (indirect_data_capacity_ - indirect_data_size_ < elem.blob.data_length)
194 if (!reserve_indirect(2 * (indirect_data_capacity_ + elem.blob.data_length)))
Shawn Willden5ada7b62014-07-29 09:44:17 -0600195 return false;
Shawn Willden58e1a542014-08-08 21:58:29 -0600196
Shawn Willden5ada7b62014-07-29 09:44:17 -0600197 memcpy(indirect_data_ + indirect_data_size_, elem.blob.data, elem.blob.data_length);
Shawn Willden8d336ae2014-08-09 15:47:05 -0600198 elem.blob.data = indirect_data_ + indirect_data_size_;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600199 indirect_data_size_ += elem.blob.data_length;
200 }
201
202 elems_[elems_size_++] = elem;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600203 return true;
204}
205
Shawn Willden8d336ae2014-08-09 15:47:05 -0600206static size_t serialized_size(const keymaster_key_param_t& param) {
207 switch (keymaster_tag_get_type(param.tag)) {
208 case KM_INVALID:
209 default:
210 return sizeof(uint32_t);
211 case KM_ENUM:
212 case KM_ENUM_REP:
213 case KM_INT:
214 case KM_INT_REP:
215 return sizeof(uint32_t) * 2;
216 case KM_LONG:
217 case KM_DATE:
218 return sizeof(uint32_t) + sizeof(uint64_t);
219 case KM_BOOL:
220 return sizeof(uint32_t) + 1;
221 break;
222 case KM_BIGNUM:
223 case KM_BYTES:
224 return sizeof(uint32_t) * 3;
225 }
Shawn Willden58e1a542014-08-08 21:58:29 -0600226}
227
Shawn Willden8d336ae2014-08-09 15:47:05 -0600228static uint8_t* serialize(const keymaster_key_param_t& param, uint8_t* buf, const uint8_t* end,
229 const uint8_t* indirect_base) {
Shawn Willden172f8c92014-08-17 07:50:34 -0600230 buf = append_uint32_to_buf(buf, end, param.tag);
Shawn Willden8d336ae2014-08-09 15:47:05 -0600231 switch (keymaster_tag_get_type(param.tag)) {
232 case KM_INVALID:
233 break;
234 case KM_ENUM:
235 case KM_ENUM_REP:
Shawn Willden172f8c92014-08-17 07:50:34 -0600236 buf = append_uint32_to_buf(buf, end, param.enumerated);
Shawn Willden8d336ae2014-08-09 15:47:05 -0600237 break;
238 case KM_INT:
239 case KM_INT_REP:
Shawn Willden172f8c92014-08-17 07:50:34 -0600240 buf = append_uint32_to_buf(buf, end, param.integer);
Shawn Willden8d336ae2014-08-09 15:47:05 -0600241 break;
242 case KM_LONG:
Shawn Willden172f8c92014-08-17 07:50:34 -0600243 buf = append_uint64_to_buf(buf, end, param.long_integer);
Shawn Willden8d336ae2014-08-09 15:47:05 -0600244 break;
245 case KM_DATE:
Shawn Willden172f8c92014-08-17 07:50:34 -0600246 buf = append_uint64_to_buf(buf, end, param.date_time);
Shawn Willden8d336ae2014-08-09 15:47:05 -0600247 break;
248 case KM_BOOL:
249 if (buf < end)
250 *buf = static_cast<uint8_t>(param.boolean);
251 buf++;
252 break;
253 case KM_BIGNUM:
254 case KM_BYTES:
Shawn Willden172f8c92014-08-17 07:50:34 -0600255 buf = append_uint32_to_buf(buf, end, param.blob.data_length);
256 buf = append_uint32_to_buf(buf, end, param.blob.data - indirect_base);
Shawn Willden8d336ae2014-08-09 15:47:05 -0600257 break;
258 }
259 return buf;
260}
261
Shawn Willden172f8c92014-08-17 07:50:34 -0600262static bool deserialize(keymaster_key_param_t* param, const uint8_t** buf_ptr, const uint8_t* end,
Shawn Willden8d336ae2014-08-09 15:47:05 -0600263 const uint8_t* indirect_base, const uint8_t* indirect_end) {
Shawn Willden172f8c92014-08-17 07:50:34 -0600264 if (!copy_uint32_from_buf(buf_ptr, end, &param->tag))
Shawn Willden8d336ae2014-08-09 15:47:05 -0600265 return false;
Shawn Willden8d336ae2014-08-09 15:47:05 -0600266
267 switch (keymaster_tag_get_type(param->tag)) {
268 default:
269 case KM_INVALID:
270 return false;
271 case KM_ENUM:
272 case KM_ENUM_REP:
Shawn Willden172f8c92014-08-17 07:50:34 -0600273 return copy_uint32_from_buf(buf_ptr, end, &param->enumerated);
Shawn Willden8d336ae2014-08-09 15:47:05 -0600274 case KM_INT:
275 case KM_INT_REP:
Shawn Willden172f8c92014-08-17 07:50:34 -0600276 return copy_uint32_from_buf(buf_ptr, end, &param->integer);
Shawn Willden8d336ae2014-08-09 15:47:05 -0600277 case KM_LONG:
Shawn Willden172f8c92014-08-17 07:50:34 -0600278 return copy_uint64_from_buf(buf_ptr, end, &param->long_integer);
Shawn Willden8d336ae2014-08-09 15:47:05 -0600279 case KM_DATE:
Shawn Willden172f8c92014-08-17 07:50:34 -0600280 return copy_uint64_from_buf(buf_ptr, end, &param->date_time);
Shawn Willden8d336ae2014-08-09 15:47:05 -0600281 break;
282 case KM_BOOL:
Shawn Willden172f8c92014-08-17 07:50:34 -0600283 if (*buf_ptr < end) {
284 param->boolean = static_cast<bool>(**buf_ptr);
285 (*buf_ptr)++;
Shawn Willden8d336ae2014-08-09 15:47:05 -0600286 return true;
287 }
288 return false;
289
290 case KM_BIGNUM:
291 case KM_BYTES: {
Shawn Willden8d336ae2014-08-09 15:47:05 -0600292 uint32_t offset;
Shawn Willden172f8c92014-08-17 07:50:34 -0600293 if (!copy_uint32_from_buf(buf_ptr, end, &param->blob.data_length) ||
294 !copy_uint32_from_buf(buf_ptr, end, &offset))
Shawn Willden8d336ae2014-08-09 15:47:05 -0600295 return false;
296 if (static_cast<ptrdiff_t>(offset) > indirect_end - indirect_base ||
Shawn Willden172f8c92014-08-17 07:50:34 -0600297 static_cast<ptrdiff_t>(offset + param->blob.data_length) > indirect_end - indirect_base)
Shawn Willden8d336ae2014-08-09 15:47:05 -0600298 return false;
Shawn Willden8d336ae2014-08-09 15:47:05 -0600299 param->blob.data = indirect_base + offset;
300 return true;
301 }
302 }
303}
304
305size_t AuthorizationSet::SerializedSizeOfElements() const {
306 size_t size = 0;
307 for (size_t i = 0; i < elems_size_; ++i) {
308 size += serialized_size(elems_[i]);
309 }
310 return size;
311}
312
313size_t AuthorizationSet::SerializedSize() const {
314 return sizeof(uint32_t) + // Size of indirect_data_
315 indirect_data_size_ + // indirect_data_
316 sizeof(uint32_t) + // Number of elems_
317 sizeof(uint32_t) + // Size of elems_
318 SerializedSizeOfElements(); // elems_
319}
320
321uint8_t* AuthorizationSet::Serialize(uint8_t* buf, const uint8_t* end) const {
322 buf = append_size_and_data_to_buf(buf, end, indirect_data_, indirect_data_size_);
Shawn Willden172f8c92014-08-17 07:50:34 -0600323 buf = append_uint32_to_buf(buf, end, elems_size_);
324 buf = append_uint32_to_buf(buf, end, SerializedSizeOfElements());
Shawn Willden8d336ae2014-08-09 15:47:05 -0600325 for (size_t i = 0; i < elems_size_; ++i) {
326 buf = serialize(elems_[i], buf, end, indirect_data_);
327 }
328 return buf;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600329}
330
Shawn Willden37012132014-08-19 08:15:57 -0600331bool AuthorizationSet::DeserializeIndirectData(const uint8_t** buf_ptr, const uint8_t* end) {
332 if (!copy_size_and_data_from_buf(buf_ptr, end, &indirect_data_size_, &indirect_data_)) {
333 set_invalid(MALFORMED_DATA);
334 return false;
335 }
336 return true;
337}
Shawn Willden5ada7b62014-07-29 09:44:17 -0600338
Shawn Willden37012132014-08-19 08:15:57 -0600339bool AuthorizationSet::DeserializeElementsData(const uint8_t** buf_ptr, const uint8_t* end) {
Shawn Willden8d336ae2014-08-09 15:47:05 -0600340 uint32_t elements_count;
341 uint32_t elements_size;
Shawn Willden37012132014-08-19 08:15:57 -0600342 if (!copy_uint32_from_buf(buf_ptr, end, &elements_count) ||
Shawn Willden172f8c92014-08-17 07:50:34 -0600343 !copy_uint32_from_buf(buf_ptr, end, &elements_size)) {
Shawn Willden58e1a542014-08-08 21:58:29 -0600344 set_invalid(MALFORMED_DATA);
Shawn Willden5ada7b62014-07-29 09:44:17 -0600345 return false;
346 }
347
Shawn Willden834e8072014-08-09 16:38:53 -0600348 // Note that the following validation of elements_count is weak, but it prevents allocation of
349 // elems_ arrays which are clearly too large to be reasonable.
Shawn Willden172f8c92014-08-17 07:50:34 -0600350 if (elements_size > end - *buf_ptr || elements_count * sizeof(uint32_t) > elements_size) {
Shawn Willden834e8072014-08-09 16:38:53 -0600351 set_invalid(MALFORMED_DATA);
352 return false;
353 }
354
Shawn Willden37012132014-08-19 08:15:57 -0600355 if (!reserve_elems(elements_count))
Shawn Willden5ada7b62014-07-29 09:44:17 -0600356 return false;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600357
Shawn Willden8d336ae2014-08-09 15:47:05 -0600358 uint8_t* indirect_end = indirect_data_ + indirect_data_size_;
Shawn Willden172f8c92014-08-17 07:50:34 -0600359 const uint8_t* elements_end = *buf_ptr + elements_size;
Shawn Willden8d336ae2014-08-09 15:47:05 -0600360 for (size_t i = 0; i < elements_count; ++i) {
Shawn Willden172f8c92014-08-17 07:50:34 -0600361 if (!deserialize(elems_ + i, buf_ptr, elements_end, indirect_data_, indirect_end)) {
Shawn Willden8d336ae2014-08-09 15:47:05 -0600362 set_invalid(MALFORMED_DATA);
363 return false;
364 }
365 }
Shawn Willden37012132014-08-19 08:15:57 -0600366 elems_size_ = elements_count;
367 return true;
368}
Shawn Willden8d336ae2014-08-09 15:47:05 -0600369
Shawn Willden37012132014-08-19 08:15:57 -0600370bool AuthorizationSet::Deserialize(const uint8_t** buf_ptr, const uint8_t* end) {
371 FreeData();
372
373 if (!DeserializeIndirectData(buf_ptr, end) || !DeserializeElementsData(buf_ptr, end))
374 return false;
375
376 if (indirect_data_size_ != ComputeIndirectDataSize(elems_, elems_size_)) {
Shawn Willden58e1a542014-08-08 21:58:29 -0600377 set_invalid(MALFORMED_DATA);
Shawn Willden5ada7b62014-07-29 09:44:17 -0600378 return false;
Shawn Willden58e1a542014-08-08 21:58:29 -0600379 }
Shawn Willden8d336ae2014-08-09 15:47:05 -0600380 return true;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600381}
382
383void AuthorizationSet::FreeData() {
Shawn Willden58e1a542014-08-08 21:58:29 -0600384 if (elems_ != NULL)
Shawn Willden74aff352014-08-11 14:08:31 -0600385 memset_s(elems_, 0, elems_size_ * sizeof(keymaster_key_param_t));
Shawn Willden58e1a542014-08-08 21:58:29 -0600386 if (indirect_data_ != NULL)
Shawn Willden74aff352014-08-11 14:08:31 -0600387 memset_s(indirect_data_, 0, indirect_data_size_);
Shawn Willden58e1a542014-08-08 21:58:29 -0600388
389 delete[] elems_;
390 delete[] indirect_data_;
391
Shawn Willden5ada7b62014-07-29 09:44:17 -0600392 elems_ = NULL;
393 indirect_data_ = NULL;
394 elems_size_ = 0;
395 elems_capacity_ = 0;
396 indirect_data_size_ = 0;
397 indirect_data_capacity_ = 0;
Shawn Willden37012132014-08-19 08:15:57 -0600398 error_ = OK;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600399}
400
401/* static */
402size_t AuthorizationSet::ComputeIndirectDataSize(const keymaster_key_param_t* elems, size_t count) {
403 size_t size = 0;
404 for (size_t i = 0; i < count; ++i) {
405 if (is_blob_tag(elems[i].tag)) {
406 size += elems[i].blob.data_length;
407 }
408 }
409 return size;
410}
411
412void AuthorizationSet::CopyIndirectData() {
Shawn Willden37012132014-08-19 08:15:57 -0600413 memset_s(indirect_data_, 0, indirect_data_capacity_);
Shawn Willden5ada7b62014-07-29 09:44:17 -0600414
415 uint8_t* indirect_data_pos = indirect_data_;
416 for (size_t i = 0; i < elems_size_; ++i) {
Shawn Willden37012132014-08-19 08:15:57 -0600417 assert(indirect_data_pos <= indirect_data_ + indirect_data_capacity_);
Shawn Willden5ada7b62014-07-29 09:44:17 -0600418 if (is_blob_tag(elems_[i].tag)) {
419 memcpy(indirect_data_pos, elems_[i].blob.data, elems_[i].blob.data_length);
420 elems_[i].blob.data = indirect_data_pos;
421 indirect_data_pos += elems_[i].blob.data_length;
422 }
423 }
Shawn Willden37012132014-08-19 08:15:57 -0600424 assert(indirect_data_pos == indirect_data_ + indirect_data_capacity_);
425 indirect_data_size_ = indirect_data_pos - indirect_data_;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600426}
427
Shawn Willden5ada7b62014-07-29 09:44:17 -0600428bool AuthorizationSet::GetTagValueEnum(keymaster_tag_t tag, uint32_t* val) const {
429 int pos = find(tag);
430 if (pos == -1) {
431 return false;
432 }
Shawn Willdenebf627f2014-08-12 11:15:29 -0600433 *val = elems_[pos].enumerated;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600434 return true;
435}
436
437bool AuthorizationSet::GetTagValueEnumRep(keymaster_tag_t tag, size_t instance,
438 uint32_t* val) const {
439 size_t count = 0;
440 int pos = -1;
441 while (count <= instance) {
442 pos = find(tag, pos);
443 if (pos == -1) {
444 return false;
445 }
446 ++count;
447 }
Shawn Willdenebf627f2014-08-12 11:15:29 -0600448 *val = elems_[pos].enumerated;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600449 return true;
450}
451
452bool AuthorizationSet::GetTagValueInt(keymaster_tag_t tag, uint32_t* val) const {
453 int pos = find(tag);
454 if (pos == -1) {
455 return false;
456 }
Shawn Willdenebf627f2014-08-12 11:15:29 -0600457 *val = elems_[pos].integer;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600458 return true;
459}
460
461bool AuthorizationSet::GetTagValueIntRep(keymaster_tag_t tag, size_t instance,
462 uint32_t* val) const {
463 size_t count = 0;
464 int pos = -1;
465 while (count <= instance) {
466 pos = find(tag, pos);
467 if (pos == -1) {
468 return false;
469 }
470 ++count;
471 }
Shawn Willdenebf627f2014-08-12 11:15:29 -0600472 *val = elems_[pos].integer;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600473 return true;
474}
475
476bool AuthorizationSet::GetTagValueLong(keymaster_tag_t tag, uint64_t* val) const {
477 int pos = find(tag);
478 if (pos == -1) {
479 return false;
480 }
Shawn Willdenebf627f2014-08-12 11:15:29 -0600481 *val = elems_[pos].long_integer;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600482 return true;
483}
484
485bool AuthorizationSet::GetTagValueDate(keymaster_tag_t tag, uint64_t* val) const {
486 int pos = find(tag);
487 if (pos == -1) {
488 return false;
489 }
Shawn Willdenebf627f2014-08-12 11:15:29 -0600490 *val = elems_[pos].date_time;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600491 return true;
492}
493
494bool AuthorizationSet::GetTagValueBlob(keymaster_tag_t tag, keymaster_blob_t* val) const {
495 int pos = find(tag);
496 if (pos == -1) {
497 return false;
498 }
Shawn Willdenebf627f2014-08-12 11:15:29 -0600499 *val = elems_[pos].blob;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600500 return true;
501}
502
503} // namespace keymaster