blob: b3c186cc4e0b41d27168c9ac99a13ad32eb97591 [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
Shawn Willden98d9b922014-08-26 08:14:10 -060023#include <keymaster/authorization_set.h>
24#include <keymaster/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)
Shawn Willden62de2662014-08-20 14:14:49 -060035 : Serializable(), 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 Willden2c242002015-02-27 07:01:02 -070039AuthorizationSet::AuthorizationSet(AuthorizationSetBuilder& builder) {
40 elems_ = builder.set.elems_;
41 builder.set.elems_ = NULL;
42
43 elems_size_ = builder.set.elems_size_;
44 builder.set.elems_size_ = 0;
45
46 elems_capacity_ = builder.set.elems_capacity_;
47 builder.set.elems_capacity_ = 0;
48
49 indirect_data_ = builder.set.indirect_data_;
50 builder.set.indirect_data_ = NULL;
51
52 indirect_data_capacity_ = builder.set.indirect_data_capacity_;
53 builder.set.indirect_data_capacity_ = 0;
54
55 indirect_data_size_ = builder.set.indirect_data_size_;
56 builder.set.indirect_data_size_ = 0;
57
58 error_ = builder.set.error_;
59 builder.set.error_ = OK;
60}
61
Shawn Willden8d336ae2014-08-09 15:47:05 -060062AuthorizationSet::~AuthorizationSet() {
63 FreeData();
64}
Shawn Willden58e1a542014-08-08 21:58:29 -060065
Shawn Willden37012132014-08-19 08:15:57 -060066bool AuthorizationSet::reserve_elems(size_t count) {
Shawn Willden437fbd12014-08-20 11:59:49 -060067 if (is_valid() != OK)
68 return false;
69
Shawn Willden37012132014-08-19 08:15:57 -060070 if (count >= elems_capacity_) {
71 keymaster_key_param_t* new_elems = new keymaster_key_param_t[count];
72 if (new_elems == NULL) {
73 set_invalid(ALLOCATION_FAILURE);
74 return false;
75 }
76 memcpy(new_elems, elems_, sizeof(*elems_) * elems_size_);
77 delete[] elems_;
78 elems_ = new_elems;
79 elems_capacity_ = count;
80 }
81 return true;
82}
83
84bool AuthorizationSet::reserve_indirect(size_t length) {
Shawn Willden437fbd12014-08-20 11:59:49 -060085 if (is_valid() != OK)
86 return false;
87
Shawn Willden37012132014-08-19 08:15:57 -060088 if (length > indirect_data_capacity_) {
89 uint8_t* new_data = new uint8_t[length];
90 if (new_data == NULL) {
91 set_invalid(ALLOCATION_FAILURE);
92 return false;
93 }
94 memcpy(new_data, indirect_data_, indirect_data_size_);
95
96 // Fix up the data pointers to point into the new region.
97 for (size_t i = 0; i < elems_size_; ++i) {
98 if (is_blob_tag(elems_[i].tag))
99 elems_[i].blob.data = new_data + (elems_[i].blob.data - indirect_data_);
100 }
101 delete[] indirect_data_;
102 indirect_data_ = new_data;
103 indirect_data_capacity_ = length;
104 }
105 return true;
106}
107
Shawn Willden5ada7b62014-07-29 09:44:17 -0600108bool AuthorizationSet::Reinitialize(const keymaster_key_param_t* elems, const size_t count) {
109 FreeData();
110
Shawn Willdenb58dcde2015-03-02 12:53:13 -0700111 if (elems == NULL || count == 0) {
112 error_ = OK;
113 return true;
114 }
115
Shawn Willden37012132014-08-19 08:15:57 -0600116 if (!reserve_elems(count))
Shawn Willden5ada7b62014-07-29 09:44:17 -0600117 return false;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600118
Shawn Willden37012132014-08-19 08:15:57 -0600119 if (!reserve_indirect(ComputeIndirectDataSize(elems, count)))
120 return false;
121
122 memcpy(elems_, elems, sizeof(keymaster_key_param_t) * count);
123 elems_size_ = count;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600124 CopyIndirectData();
Shawn Willden37012132014-08-19 08:15:57 -0600125 error_ = OK;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600126 return true;
127}
128
Shawn Willden5ada7b62014-07-29 09:44:17 -0600129void AuthorizationSet::set_invalid(Error error) {
Shawn Willden5ada7b62014-07-29 09:44:17 -0600130 FreeData();
Shawn Willden37012132014-08-19 08:15:57 -0600131 error_ = error;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600132}
133
Shawn Willden2c242002015-02-27 07:01:02 -0700134void AuthorizationSet::Deduplicate() {
135 qsort(elems_, elems_size_, sizeof(*elems_),
136 reinterpret_cast<int (*)(const void*, const void*)>(keymaster_param_compare));
137
138 size_t invalid_count = 0;
139 for (size_t i = 1; i < size(); ++i) {
140 if (elems_[i - 1].tag == KM_TAG_INVALID)
141 ++invalid_count;
142 else if (keymaster_param_compare(elems_ + i - 1, elems_ + i) == 0) {
143 // Mark dups as invalid. Note that this "leaks" the data referenced by KM_BYTES and
144 // KM_BIGNUM entries, but those are just pointers into indirect_data_, so it will all
145 // get cleaned up.
146 elems_[i - 1].tag = KM_TAG_INVALID;
147 ++invalid_count;
148 }
149 }
150 if (size() > 0 && elems_[size() - 1].tag == KM_TAG_INVALID)
151 ++invalid_count;
152
153 if (invalid_count == 0)
154 return;
155
156 // Since KM_TAG_INVALID == 0, all of the invalid entries are first.
157 elems_size_ -= invalid_count;
158 memmove(elems_, elems_ + invalid_count, size() * sizeof(*elems_));
159}
160
Shawn Willdencb0d64b2015-01-22 10:23:42 -0700161void AuthorizationSet::CopyToParamSet(keymaster_key_param_set_t* set) const {
162 assert(set);
163
164 set->length = size();
165 set->params =
166 reinterpret_cast<keymaster_key_param_t*>(malloc(sizeof(keymaster_key_param_t) * size()));
167
168 for (size_t i = 0; i < size(); ++i) {
169 const keymaster_key_param_t src = (*this)[i];
170 keymaster_key_param_t& dst(set->params[i]);
171
172 dst = src;
173 keymaster_tag_type_t type = keymaster_tag_get_type(src.tag);
174 if (type == KM_BIGNUM || type == KM_BYTES) {
175 void* tmp = malloc(src.blob.data_length);
176 memcpy(tmp, src.blob.data, src.blob.data_length);
177 dst.blob.data = reinterpret_cast<uint8_t*>(tmp);
178 }
179 }
180}
181
Shawn Willden5ada7b62014-07-29 09:44:17 -0600182int AuthorizationSet::find(keymaster_tag_t tag, int begin) const {
Shawn Willden437fbd12014-08-20 11:59:49 -0600183 if (is_valid() != OK)
184 return -1;
185
Shawn Willden5ada7b62014-07-29 09:44:17 -0600186 int i = ++begin;
Shawn Willden8d336ae2014-08-09 15:47:05 -0600187 while (i < (int)elems_size_ && elems_[i].tag != tag)
188 ++i;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600189 if (i == (int)elems_size_)
190 return -1;
191 else
192 return i;
193}
194
195keymaster_key_param_t empty;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600196keymaster_key_param_t AuthorizationSet::operator[](int at) const {
Shawn Willden437fbd12014-08-20 11:59:49 -0600197 if (is_valid() == OK && at < (int)elems_size_) {
Shawn Willden8d336ae2014-08-09 15:47:05 -0600198 return elems_[at];
Shawn Willden5ada7b62014-07-29 09:44:17 -0600199 }
200 memset(&empty, 0, sizeof(empty));
201 return empty;
202}
203
Shawn Willden37012132014-08-19 08:15:57 -0600204bool AuthorizationSet::push_back(const AuthorizationSet& set) {
Shawn Willden437fbd12014-08-20 11:59:49 -0600205 if (is_valid() != OK)
206 return false;
207
Shawn Willden37012132014-08-19 08:15:57 -0600208 if (!reserve_elems(elems_size_ + set.elems_size_))
209 return false;
210
211 if (!reserve_indirect(indirect_data_size_ + set.indirect_data_size_))
212 return false;
213
214 for (size_t i = 0; i < set.size(); ++i)
215 if (!push_back(set[i]))
Shawn Willden5ada7b62014-07-29 09:44:17 -0600216 return false;
Shawn Willden37012132014-08-19 08:15:57 -0600217
218 return true;
219}
220
221bool AuthorizationSet::push_back(keymaster_key_param_t elem) {
Shawn Willden437fbd12014-08-20 11:59:49 -0600222 if (is_valid() != OK)
223 return false;
224
Shawn Willden37012132014-08-19 08:15:57 -0600225 if (elems_size_ >= elems_capacity_)
226 if (!reserve_elems(elems_capacity_ ? elems_capacity_ * 2 : STARTING_ELEMS_CAPACITY))
227 return false;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600228
229 if (is_blob_tag(elem.tag)) {
Shawn Willden37012132014-08-19 08:15:57 -0600230 if (indirect_data_capacity_ - indirect_data_size_ < elem.blob.data_length)
231 if (!reserve_indirect(2 * (indirect_data_capacity_ + elem.blob.data_length)))
Shawn Willden5ada7b62014-07-29 09:44:17 -0600232 return false;
Shawn Willden58e1a542014-08-08 21:58:29 -0600233
Shawn Willden5ada7b62014-07-29 09:44:17 -0600234 memcpy(indirect_data_ + indirect_data_size_, elem.blob.data, elem.blob.data_length);
Shawn Willden8d336ae2014-08-09 15:47:05 -0600235 elem.blob.data = indirect_data_ + indirect_data_size_;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600236 indirect_data_size_ += elem.blob.data_length;
237 }
238
239 elems_[elems_size_++] = elem;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600240 return true;
241}
242
Shawn Willden8d336ae2014-08-09 15:47:05 -0600243static size_t serialized_size(const keymaster_key_param_t& param) {
244 switch (keymaster_tag_get_type(param.tag)) {
245 case KM_INVALID:
246 default:
247 return sizeof(uint32_t);
248 case KM_ENUM:
249 case KM_ENUM_REP:
250 case KM_INT:
251 case KM_INT_REP:
252 return sizeof(uint32_t) * 2;
253 case KM_LONG:
254 case KM_DATE:
255 return sizeof(uint32_t) + sizeof(uint64_t);
256 case KM_BOOL:
257 return sizeof(uint32_t) + 1;
258 break;
259 case KM_BIGNUM:
260 case KM_BYTES:
261 return sizeof(uint32_t) * 3;
262 }
Shawn Willden58e1a542014-08-08 21:58:29 -0600263}
264
Shawn Willden8d336ae2014-08-09 15:47:05 -0600265static uint8_t* serialize(const keymaster_key_param_t& param, uint8_t* buf, const uint8_t* end,
266 const uint8_t* indirect_base) {
Shawn Willden172f8c92014-08-17 07:50:34 -0600267 buf = append_uint32_to_buf(buf, end, param.tag);
Shawn Willden8d336ae2014-08-09 15:47:05 -0600268 switch (keymaster_tag_get_type(param.tag)) {
269 case KM_INVALID:
270 break;
271 case KM_ENUM:
272 case KM_ENUM_REP:
Shawn Willden172f8c92014-08-17 07:50:34 -0600273 buf = append_uint32_to_buf(buf, end, param.enumerated);
Shawn Willden8d336ae2014-08-09 15:47:05 -0600274 break;
275 case KM_INT:
276 case KM_INT_REP:
Shawn Willden172f8c92014-08-17 07:50:34 -0600277 buf = append_uint32_to_buf(buf, end, param.integer);
Shawn Willden8d336ae2014-08-09 15:47:05 -0600278 break;
279 case KM_LONG:
Shawn Willden172f8c92014-08-17 07:50:34 -0600280 buf = append_uint64_to_buf(buf, end, param.long_integer);
Shawn Willden8d336ae2014-08-09 15:47:05 -0600281 break;
282 case KM_DATE:
Shawn Willden172f8c92014-08-17 07:50:34 -0600283 buf = append_uint64_to_buf(buf, end, param.date_time);
Shawn Willden8d336ae2014-08-09 15:47:05 -0600284 break;
285 case KM_BOOL:
286 if (buf < end)
287 *buf = static_cast<uint8_t>(param.boolean);
288 buf++;
289 break;
290 case KM_BIGNUM:
291 case KM_BYTES:
Shawn Willden172f8c92014-08-17 07:50:34 -0600292 buf = append_uint32_to_buf(buf, end, param.blob.data_length);
293 buf = append_uint32_to_buf(buf, end, param.blob.data - indirect_base);
Shawn Willden8d336ae2014-08-09 15:47:05 -0600294 break;
295 }
296 return buf;
297}
298
Shawn Willden172f8c92014-08-17 07:50:34 -0600299static bool deserialize(keymaster_key_param_t* param, const uint8_t** buf_ptr, const uint8_t* end,
Shawn Willden8d336ae2014-08-09 15:47:05 -0600300 const uint8_t* indirect_base, const uint8_t* indirect_end) {
Shawn Willden172f8c92014-08-17 07:50:34 -0600301 if (!copy_uint32_from_buf(buf_ptr, end, &param->tag))
Shawn Willden8d336ae2014-08-09 15:47:05 -0600302 return false;
Shawn Willden8d336ae2014-08-09 15:47:05 -0600303
304 switch (keymaster_tag_get_type(param->tag)) {
305 default:
306 case KM_INVALID:
307 return false;
308 case KM_ENUM:
309 case KM_ENUM_REP:
Shawn Willden172f8c92014-08-17 07:50:34 -0600310 return copy_uint32_from_buf(buf_ptr, end, &param->enumerated);
Shawn Willden8d336ae2014-08-09 15:47:05 -0600311 case KM_INT:
312 case KM_INT_REP:
Shawn Willden172f8c92014-08-17 07:50:34 -0600313 return copy_uint32_from_buf(buf_ptr, end, &param->integer);
Shawn Willden8d336ae2014-08-09 15:47:05 -0600314 case KM_LONG:
Shawn Willden172f8c92014-08-17 07:50:34 -0600315 return copy_uint64_from_buf(buf_ptr, end, &param->long_integer);
Shawn Willden8d336ae2014-08-09 15:47:05 -0600316 case KM_DATE:
Shawn Willden172f8c92014-08-17 07:50:34 -0600317 return copy_uint64_from_buf(buf_ptr, end, &param->date_time);
Shawn Willden8d336ae2014-08-09 15:47:05 -0600318 break;
319 case KM_BOOL:
Shawn Willden172f8c92014-08-17 07:50:34 -0600320 if (*buf_ptr < end) {
321 param->boolean = static_cast<bool>(**buf_ptr);
322 (*buf_ptr)++;
Shawn Willden8d336ae2014-08-09 15:47:05 -0600323 return true;
324 }
325 return false;
326
327 case KM_BIGNUM:
328 case KM_BYTES: {
Shawn Willden8d336ae2014-08-09 15:47:05 -0600329 uint32_t offset;
Shawn Willden172f8c92014-08-17 07:50:34 -0600330 if (!copy_uint32_from_buf(buf_ptr, end, &param->blob.data_length) ||
331 !copy_uint32_from_buf(buf_ptr, end, &offset))
Shawn Willden8d336ae2014-08-09 15:47:05 -0600332 return false;
333 if (static_cast<ptrdiff_t>(offset) > indirect_end - indirect_base ||
Shawn Willden172f8c92014-08-17 07:50:34 -0600334 static_cast<ptrdiff_t>(offset + param->blob.data_length) > indirect_end - indirect_base)
Shawn Willden8d336ae2014-08-09 15:47:05 -0600335 return false;
Shawn Willden8d336ae2014-08-09 15:47:05 -0600336 param->blob.data = indirect_base + offset;
337 return true;
338 }
339 }
340}
341
342size_t AuthorizationSet::SerializedSizeOfElements() const {
343 size_t size = 0;
344 for (size_t i = 0; i < elems_size_; ++i) {
345 size += serialized_size(elems_[i]);
346 }
347 return size;
348}
349
350size_t AuthorizationSet::SerializedSize() const {
351 return sizeof(uint32_t) + // Size of indirect_data_
352 indirect_data_size_ + // indirect_data_
353 sizeof(uint32_t) + // Number of elems_
354 sizeof(uint32_t) + // Size of elems_
355 SerializedSizeOfElements(); // elems_
356}
357
358uint8_t* AuthorizationSet::Serialize(uint8_t* buf, const uint8_t* end) const {
359 buf = append_size_and_data_to_buf(buf, end, indirect_data_, indirect_data_size_);
Shawn Willden172f8c92014-08-17 07:50:34 -0600360 buf = append_uint32_to_buf(buf, end, elems_size_);
361 buf = append_uint32_to_buf(buf, end, SerializedSizeOfElements());
Shawn Willden8d336ae2014-08-09 15:47:05 -0600362 for (size_t i = 0; i < elems_size_; ++i) {
363 buf = serialize(elems_[i], buf, end, indirect_data_);
364 }
365 return buf;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600366}
367
Shawn Willden37012132014-08-19 08:15:57 -0600368bool AuthorizationSet::DeserializeIndirectData(const uint8_t** buf_ptr, const uint8_t* end) {
Shawn Willdenf2282b32014-08-25 06:49:54 -0600369 UniquePtr<uint8_t[]> indirect_buf;
370 if (!copy_size_and_data_from_buf(buf_ptr, end, &indirect_data_size_, &indirect_buf)) {
Shawn Willden37012132014-08-19 08:15:57 -0600371 set_invalid(MALFORMED_DATA);
372 return false;
373 }
Shawn Willdenf2282b32014-08-25 06:49:54 -0600374 indirect_data_ = indirect_buf.release();
Shawn Willden37012132014-08-19 08:15:57 -0600375 return true;
376}
Shawn Willden5ada7b62014-07-29 09:44:17 -0600377
Shawn Willden37012132014-08-19 08:15:57 -0600378bool AuthorizationSet::DeserializeElementsData(const uint8_t** buf_ptr, const uint8_t* end) {
Shawn Willden8d336ae2014-08-09 15:47:05 -0600379 uint32_t elements_count;
380 uint32_t elements_size;
Shawn Willden37012132014-08-19 08:15:57 -0600381 if (!copy_uint32_from_buf(buf_ptr, end, &elements_count) ||
Shawn Willden172f8c92014-08-17 07:50:34 -0600382 !copy_uint32_from_buf(buf_ptr, end, &elements_size)) {
Shawn Willden58e1a542014-08-08 21:58:29 -0600383 set_invalid(MALFORMED_DATA);
Shawn Willden5ada7b62014-07-29 09:44:17 -0600384 return false;
385 }
386
Shawn Willden834e8072014-08-09 16:38:53 -0600387 // Note that the following validation of elements_count is weak, but it prevents allocation of
388 // elems_ arrays which are clearly too large to be reasonable.
Shawn Willden62de2662014-08-20 14:14:49 -0600389 if (static_cast<ptrdiff_t>(elements_size) > end - *buf_ptr ||
390 elements_count * sizeof(uint32_t) > elements_size) {
Shawn Willden834e8072014-08-09 16:38:53 -0600391 set_invalid(MALFORMED_DATA);
392 return false;
393 }
394
Shawn Willden37012132014-08-19 08:15:57 -0600395 if (!reserve_elems(elements_count))
Shawn Willden5ada7b62014-07-29 09:44:17 -0600396 return false;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600397
Shawn Willden8d336ae2014-08-09 15:47:05 -0600398 uint8_t* indirect_end = indirect_data_ + indirect_data_size_;
Shawn Willden172f8c92014-08-17 07:50:34 -0600399 const uint8_t* elements_end = *buf_ptr + elements_size;
Shawn Willden8d336ae2014-08-09 15:47:05 -0600400 for (size_t i = 0; i < elements_count; ++i) {
Shawn Willden172f8c92014-08-17 07:50:34 -0600401 if (!deserialize(elems_ + i, buf_ptr, elements_end, indirect_data_, indirect_end)) {
Shawn Willden8d336ae2014-08-09 15:47:05 -0600402 set_invalid(MALFORMED_DATA);
403 return false;
404 }
405 }
Shawn Willden37012132014-08-19 08:15:57 -0600406 elems_size_ = elements_count;
407 return true;
408}
Shawn Willden8d336ae2014-08-09 15:47:05 -0600409
Shawn Willden37012132014-08-19 08:15:57 -0600410bool AuthorizationSet::Deserialize(const uint8_t** buf_ptr, const uint8_t* end) {
411 FreeData();
412
413 if (!DeserializeIndirectData(buf_ptr, end) || !DeserializeElementsData(buf_ptr, end))
414 return false;
415
416 if (indirect_data_size_ != ComputeIndirectDataSize(elems_, elems_size_)) {
Shawn Willden58e1a542014-08-08 21:58:29 -0600417 set_invalid(MALFORMED_DATA);
Shawn Willden5ada7b62014-07-29 09:44:17 -0600418 return false;
Shawn Willden58e1a542014-08-08 21:58:29 -0600419 }
Shawn Willden8d336ae2014-08-09 15:47:05 -0600420 return true;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600421}
422
Shawn Willden941d1c42014-12-11 13:57:02 -0700423void AuthorizationSet::Clear() {
Shawn Willden1834d5f2014-12-08 12:41:59 -0700424 memset_s(elems_, 0, elems_size_ * sizeof(keymaster_key_param_t));
425 memset_s(indirect_data_, 0, indirect_data_size_);
Shawn Willden941d1c42014-12-11 13:57:02 -0700426 elems_size_ = 0;
427 indirect_data_size_ = 0;
428}
429
430void AuthorizationSet::FreeData() {
431 Clear();
Shawn Willden58e1a542014-08-08 21:58:29 -0600432
433 delete[] elems_;
434 delete[] indirect_data_;
435
Shawn Willden5ada7b62014-07-29 09:44:17 -0600436 elems_ = NULL;
437 indirect_data_ = NULL;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600438 elems_capacity_ = 0;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600439 indirect_data_capacity_ = 0;
Shawn Willden37012132014-08-19 08:15:57 -0600440 error_ = OK;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600441}
442
443/* static */
444size_t AuthorizationSet::ComputeIndirectDataSize(const keymaster_key_param_t* elems, size_t count) {
445 size_t size = 0;
446 for (size_t i = 0; i < count; ++i) {
447 if (is_blob_tag(elems[i].tag)) {
448 size += elems[i].blob.data_length;
449 }
450 }
451 return size;
452}
453
454void AuthorizationSet::CopyIndirectData() {
Shawn Willden37012132014-08-19 08:15:57 -0600455 memset_s(indirect_data_, 0, indirect_data_capacity_);
Shawn Willden5ada7b62014-07-29 09:44:17 -0600456
457 uint8_t* indirect_data_pos = indirect_data_;
458 for (size_t i = 0; i < elems_size_; ++i) {
Shawn Willden37012132014-08-19 08:15:57 -0600459 assert(indirect_data_pos <= indirect_data_ + indirect_data_capacity_);
Shawn Willden5ada7b62014-07-29 09:44:17 -0600460 if (is_blob_tag(elems_[i].tag)) {
461 memcpy(indirect_data_pos, elems_[i].blob.data, elems_[i].blob.data_length);
462 elems_[i].blob.data = indirect_data_pos;
463 indirect_data_pos += elems_[i].blob.data_length;
464 }
465 }
Shawn Willden37012132014-08-19 08:15:57 -0600466 assert(indirect_data_pos == indirect_data_ + indirect_data_capacity_);
467 indirect_data_size_ = indirect_data_pos - indirect_data_;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600468}
469
Shawn Willden1fa5d592015-01-14 08:34:07 -0700470size_t AuthorizationSet::GetTagCount(keymaster_tag_t tag) const {
471 size_t count = 0;
472 for (int pos = -1; (pos = find(tag, pos)) != -1;)
473 ++count;
474 return count;
475}
476
Shawn Willden5ada7b62014-07-29 09:44:17 -0600477bool AuthorizationSet::GetTagValueEnum(keymaster_tag_t tag, uint32_t* val) const {
478 int pos = find(tag);
479 if (pos == -1) {
480 return false;
481 }
Shawn Willdenebf627f2014-08-12 11:15:29 -0600482 *val = elems_[pos].enumerated;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600483 return true;
484}
485
486bool AuthorizationSet::GetTagValueEnumRep(keymaster_tag_t tag, size_t instance,
487 uint32_t* val) const {
488 size_t count = 0;
489 int pos = -1;
490 while (count <= instance) {
491 pos = find(tag, pos);
492 if (pos == -1) {
493 return false;
494 }
495 ++count;
496 }
Shawn Willdenebf627f2014-08-12 11:15:29 -0600497 *val = elems_[pos].enumerated;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600498 return true;
499}
500
501bool AuthorizationSet::GetTagValueInt(keymaster_tag_t tag, uint32_t* val) const {
502 int pos = find(tag);
503 if (pos == -1) {
504 return false;
505 }
Shawn Willdenebf627f2014-08-12 11:15:29 -0600506 *val = elems_[pos].integer;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600507 return true;
508}
509
510bool AuthorizationSet::GetTagValueIntRep(keymaster_tag_t tag, size_t instance,
511 uint32_t* val) const {
512 size_t count = 0;
513 int pos = -1;
514 while (count <= instance) {
515 pos = find(tag, pos);
516 if (pos == -1) {
517 return false;
518 }
519 ++count;
520 }
Shawn Willdenebf627f2014-08-12 11:15:29 -0600521 *val = elems_[pos].integer;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600522 return true;
523}
524
525bool AuthorizationSet::GetTagValueLong(keymaster_tag_t tag, uint64_t* val) const {
526 int pos = find(tag);
527 if (pos == -1) {
528 return false;
529 }
Shawn Willdenebf627f2014-08-12 11:15:29 -0600530 *val = elems_[pos].long_integer;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600531 return true;
532}
533
534bool AuthorizationSet::GetTagValueDate(keymaster_tag_t tag, uint64_t* val) const {
535 int pos = find(tag);
536 if (pos == -1) {
537 return false;
538 }
Shawn Willdenebf627f2014-08-12 11:15:29 -0600539 *val = elems_[pos].date_time;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600540 return true;
541}
542
543bool AuthorizationSet::GetTagValueBlob(keymaster_tag_t tag, keymaster_blob_t* val) const {
544 int pos = find(tag);
545 if (pos == -1) {
546 return false;
547 }
Shawn Willdenebf627f2014-08-12 11:15:29 -0600548 *val = elems_[pos].blob;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600549 return true;
550}
551
Shawn Willdendfa1c032015-02-07 00:39:01 -0700552bool AuthorizationSet::GetTagValueBool(keymaster_tag_t tag) const {
553 int pos = find(tag);
554 if (pos == -1) {
555 return false;
556 }
557 assert(elems_[pos].boolean);
558 return elems_[pos].boolean;
559}
560
Shawn Willden5ada7b62014-07-29 09:44:17 -0600561} // namespace keymaster