blob: 61bfa6a58dcc84cefe067a69d97c3910b4502bd8 [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"
24
25namespace keymaster {
26
27static inline bool is_blob_tag(keymaster_tag_t tag) {
28 return (keymaster_tag_get_type(tag) == KM_BYTES || keymaster_tag_get_type(tag) == KM_BIGNUM);
29}
30
31const size_t STARTING_ELEMS_CAPACITY = 8;
32
Shawn Willden58e1a542014-08-08 21:58:29 -060033AuthorizationSet::AuthorizationSet(const AuthorizationSet& set)
34 : elems_(NULL), indirect_data_(NULL) {
35 elems_ = new keymaster_key_param_t[set.elems_size_];
36 if (elems_ == NULL) {
37 error_ = ALLOCATION_FAILURE;
38 return;
39 }
40 memcpy(elems_, set.elems_, set.elems_size_ * sizeof(keymaster_key_param_t));
41 elems_size_ = set.elems_size_;
42 elems_capacity_ = elems_size_;
43
44 if (set.indirect_data_ == NULL) {
45 indirect_data_ = NULL;
46 indirect_data_size_ = 0;
47 indirect_data_capacity_ = 0;
48 } else {
49 indirect_data_ = new uint8_t[set.indirect_data_size_];
50 if (indirect_data_ == NULL) {
51 error_ = ALLOCATION_FAILURE;
52 return;
53 }
54 memcpy(indirect_data_, set.indirect_data_, set.indirect_data_size_);
Shawn Willden8d336ae2014-08-09 15:47:05 -060055 for (size_t i = 0; i < elems_size_; ++i) {
56 if (is_blob_tag(elems_[i].tag))
57 elems_[i].blob.data = indirect_data_ + (elems_[i].blob.data - set.indirect_data_);
58 }
59
Shawn Willden58e1a542014-08-08 21:58:29 -060060 indirect_data_size_ = set.indirect_data_size_;
61 indirect_data_capacity_ = indirect_data_size_;
62 }
63 error_ = OK;
Shawn Willden5ada7b62014-07-29 09:44:17 -060064}
65
Shawn Willden8d336ae2014-08-09 15:47:05 -060066AuthorizationSet::~AuthorizationSet() {
67 FreeData();
68}
Shawn Willden58e1a542014-08-08 21:58:29 -060069
Shawn Willden5ada7b62014-07-29 09:44:17 -060070bool AuthorizationSet::Reinitialize(const keymaster_key_param_t* elems, const size_t count) {
71 FreeData();
72
73 elems_size_ = count;
74 elems_capacity_ = count;
75 indirect_data_size_ = ComputeIndirectDataSize(elems, count);
76 indirect_data_capacity_ = indirect_data_size_;
Shawn Willden58e1a542014-08-08 21:58:29 -060077 error_ = OK;
Shawn Willden5ada7b62014-07-29 09:44:17 -060078
79 indirect_data_ = new uint8_t[indirect_data_size_];
80 elems_ = new keymaster_key_param_t[elems_size_];
81 if (indirect_data_ == NULL || elems_ == NULL) {
82 set_invalid(ALLOCATION_FAILURE);
83 return false;
84 }
Shawn Willden5ada7b62014-07-29 09:44:17 -060085
86 memcpy(elems_, elems, sizeof(keymaster_key_param_t) * elems_size_);
87 CopyIndirectData();
Shawn Willden5ada7b62014-07-29 09:44:17 -060088 return true;
89}
90
Shawn Willden5ada7b62014-07-29 09:44:17 -060091void AuthorizationSet::set_invalid(Error error) {
92 error_ = error;
93 FreeData();
94}
95
96int AuthorizationSet::find(keymaster_tag_t tag, int begin) const {
97 int i = ++begin;
Shawn Willden8d336ae2014-08-09 15:47:05 -060098 while (i < (int)elems_size_ && elems_[i].tag != tag)
99 ++i;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600100 if (i == (int)elems_size_)
101 return -1;
102 else
103 return i;
104}
105
106keymaster_key_param_t empty;
107
108keymaster_key_param_t AuthorizationSet::operator[](int at) const {
109 if (at < (int)elems_size_) {
Shawn Willden8d336ae2014-08-09 15:47:05 -0600110 return elems_[at];
Shawn Willden5ada7b62014-07-29 09:44:17 -0600111 }
112 memset(&empty, 0, sizeof(empty));
113 return empty;
114}
115
116bool AuthorizationSet::push_back(keymaster_key_param_t elem) {
117 if (elems_size_ >= elems_capacity_) {
Shawn Willden58e1a542014-08-08 21:58:29 -0600118 size_t new_capacity = elems_capacity_ ? elems_capacity_ * 2 : STARTING_ELEMS_CAPACITY;
119 keymaster_key_param_t* new_elems = new keymaster_key_param_t[new_capacity];
120 if (new_elems == NULL) {
121 set_invalid(ALLOCATION_FAILURE);
Shawn Willden5ada7b62014-07-29 09:44:17 -0600122 return false;
123 }
Shawn Willden58e1a542014-08-08 21:58:29 -0600124 memcpy(new_elems, elems_, sizeof(*elems_) * elems_size_);
125 delete[] elems_;
126 elems_ = new_elems;
127 elems_capacity_ = new_capacity;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600128 }
129
130 if (is_blob_tag(elem.tag)) {
131 if (indirect_data_capacity_ - indirect_data_size_ < elem.blob.data_length) {
Shawn Willden58e1a542014-08-08 21:58:29 -0600132 size_t new_capacity = 2 * (indirect_data_capacity_ + elem.blob.data_length);
133 uint8_t* new_data = new uint8_t[new_capacity];
134 if (new_data == false) {
135 set_invalid(ALLOCATION_FAILURE);
Shawn Willden5ada7b62014-07-29 09:44:17 -0600136 return false;
137 }
Shawn Willden58e1a542014-08-08 21:58:29 -0600138 memcpy(new_data, indirect_data_, indirect_data_size_);
Shawn Willden8d336ae2014-08-09 15:47:05 -0600139 // Fix up the data pointers to point into the new region.
140 for (size_t i = 0; i < elems_size_; ++i) {
141 if (is_blob_tag(elems_[i].tag))
142 elems_[i].blob.data = new_data + (elems_[i].blob.data - indirect_data_);
143 }
Shawn Willden58e1a542014-08-08 21:58:29 -0600144 delete[] indirect_data_;
145 indirect_data_ = new_data;
146 indirect_data_capacity_ = new_capacity;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600147 }
Shawn Willden58e1a542014-08-08 21:58:29 -0600148
Shawn Willden5ada7b62014-07-29 09:44:17 -0600149 memcpy(indirect_data_ + indirect_data_size_, elem.blob.data, elem.blob.data_length);
Shawn Willden8d336ae2014-08-09 15:47:05 -0600150 elem.blob.data = indirect_data_ + indirect_data_size_;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600151 indirect_data_size_ += elem.blob.data_length;
152 }
153
154 elems_[elems_size_++] = elem;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600155 return true;
156}
157
Shawn Willden8d336ae2014-08-09 15:47:05 -0600158static size_t serialized_size(const keymaster_key_param_t& param) {
159 switch (keymaster_tag_get_type(param.tag)) {
160 case KM_INVALID:
161 default:
162 return sizeof(uint32_t);
163 case KM_ENUM:
164 case KM_ENUM_REP:
165 case KM_INT:
166 case KM_INT_REP:
167 return sizeof(uint32_t) * 2;
168 case KM_LONG:
169 case KM_DATE:
170 return sizeof(uint32_t) + sizeof(uint64_t);
171 case KM_BOOL:
172 return sizeof(uint32_t) + 1;
173 break;
174 case KM_BIGNUM:
175 case KM_BYTES:
176 return sizeof(uint32_t) * 3;
177 }
Shawn Willden58e1a542014-08-08 21:58:29 -0600178}
179
Shawn Willden8d336ae2014-08-09 15:47:05 -0600180static uint8_t* serialize(const keymaster_key_param_t& param, uint8_t* buf, const uint8_t* end,
181 const uint8_t* indirect_base) {
182 buf = append_to_buf(buf, end, static_cast<uint32_t>(param.tag));
183 switch (keymaster_tag_get_type(param.tag)) {
184 case KM_INVALID:
185 break;
186 case KM_ENUM:
187 case KM_ENUM_REP:
188 buf = append_to_buf(buf, end, param.enumerated);
189 break;
190 case KM_INT:
191 case KM_INT_REP:
192 buf = append_to_buf(buf, end, param.integer);
193 break;
194 case KM_LONG:
195 buf = append_to_buf(buf, end, param.long_integer);
196 break;
197 case KM_DATE:
198 buf = append_to_buf(buf, end, param.date_time);
199 break;
200 case KM_BOOL:
201 if (buf < end)
202 *buf = static_cast<uint8_t>(param.boolean);
203 buf++;
204 break;
205 case KM_BIGNUM:
206 case KM_BYTES:
207 buf = append_to_buf(buf, end, static_cast<uint32_t>(param.blob.data_length));
208 buf = append_to_buf(buf, end, static_cast<uint32_t>(param.blob.data - indirect_base));
209 break;
210 }
211 return buf;
212}
213
214static bool deserialize(keymaster_key_param_t* param, const uint8_t** buf, const uint8_t* end,
215 const uint8_t* indirect_base, const uint8_t* indirect_end) {
216 uint32_t tag_val;
217 if (!copy_from_buf(buf, end, &tag_val))
218 return false;
219 param->tag = static_cast<keymaster_tag_t>(tag_val);
220
221 switch (keymaster_tag_get_type(param->tag)) {
222 default:
223 case KM_INVALID:
224 return false;
225 case KM_ENUM:
226 case KM_ENUM_REP:
227 return copy_from_buf(buf, end, &param->enumerated);
228 case KM_INT:
229 case KM_INT_REP:
230 return copy_from_buf(buf, end, &param->integer);
231 case KM_LONG:
232 return copy_from_buf(buf, end, &param->long_integer);
233 case KM_DATE:
234 return copy_from_buf(buf, end, &param->date_time);
235 break;
236 case KM_BOOL:
237 if (*buf < end) {
238 param->boolean = static_cast<bool>(**buf);
239 (*buf)++;
240 return true;
241 }
242 return false;
243
244 case KM_BIGNUM:
245 case KM_BYTES: {
246 uint32_t length;
247 uint32_t offset;
248 if (!copy_from_buf(buf, end, &length) || !copy_from_buf(buf, end, &offset))
249 return false;
250 if (static_cast<ptrdiff_t>(offset) > indirect_end - indirect_base ||
251 static_cast<ptrdiff_t>(offset + length) > indirect_end - indirect_base)
252 return false;
253 param->blob.data_length = length;
254 param->blob.data = indirect_base + offset;
255 return true;
256 }
257 }
258}
259
260size_t AuthorizationSet::SerializedSizeOfElements() const {
261 size_t size = 0;
262 for (size_t i = 0; i < elems_size_; ++i) {
263 size += serialized_size(elems_[i]);
264 }
265 return size;
266}
267
268size_t AuthorizationSet::SerializedSize() const {
269 return sizeof(uint32_t) + // Size of indirect_data_
270 indirect_data_size_ + // indirect_data_
271 sizeof(uint32_t) + // Number of elems_
272 sizeof(uint32_t) + // Size of elems_
273 SerializedSizeOfElements(); // elems_
274}
275
276uint8_t* AuthorizationSet::Serialize(uint8_t* buf, const uint8_t* end) const {
277 buf = append_size_and_data_to_buf(buf, end, indirect_data_, indirect_data_size_);
278 buf = append_to_buf(buf, end, static_cast<uint32_t>(elems_size_));
279 buf = append_to_buf(buf, end, static_cast<uint32_t>(SerializedSizeOfElements()));
280 for (size_t i = 0; i < elems_size_; ++i) {
281 buf = serialize(elems_[i], buf, end, indirect_data_);
282 }
283 return buf;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600284}
285
Shawn Willden58e1a542014-08-08 21:58:29 -0600286bool AuthorizationSet::Deserialize(const uint8_t** buf, const uint8_t* end) {
Shawn Willden5ada7b62014-07-29 09:44:17 -0600287 FreeData();
288
Shawn Willden8d336ae2014-08-09 15:47:05 -0600289 uint32_t elements_count;
290 uint32_t elements_size;
291 if (!copy_size_and_data_from_buf(buf, end, &indirect_data_size_, &indirect_data_) ||
292 !copy_from_buf(buf, end, &elements_count) || !copy_from_buf(buf, end, &elements_size)) {
Shawn Willden58e1a542014-08-08 21:58:29 -0600293 set_invalid(MALFORMED_DATA);
Shawn Willden5ada7b62014-07-29 09:44:17 -0600294 return false;
295 }
296
Shawn Willden8d336ae2014-08-09 15:47:05 -0600297 elems_ = new keymaster_key_param_t[elements_count];
Shawn Willden5ada7b62014-07-29 09:44:17 -0600298 if (elems_ == NULL) {
299 set_invalid(ALLOCATION_FAILURE);
300 return false;
301 }
Shawn Willden5ada7b62014-07-29 09:44:17 -0600302
Shawn Willden8d336ae2014-08-09 15:47:05 -0600303 uint8_t* indirect_end = indirect_data_ + indirect_data_size_;
304 const uint8_t* elements_end = *buf + elements_size;
305 for (size_t i = 0; i < elements_count; ++i) {
306 if (!deserialize(elems_ + i, buf, elements_end, indirect_data_, indirect_end)) {
307 set_invalid(MALFORMED_DATA);
308 return false;
309 }
310 }
311
312 if (indirect_data_size_ != ComputeIndirectDataSize(elems_, elements_count)) {
Shawn Willden58e1a542014-08-08 21:58:29 -0600313 set_invalid(MALFORMED_DATA);
Shawn Willden5ada7b62014-07-29 09:44:17 -0600314 return false;
Shawn Willden58e1a542014-08-08 21:58:29 -0600315 }
Shawn Willden5ada7b62014-07-29 09:44:17 -0600316
Shawn Willden8d336ae2014-08-09 15:47:05 -0600317 elems_size_ = elements_count;
318 elems_capacity_ = elements_count;
319 indirect_data_capacity_ = indirect_data_size_;
Shawn Willden58e1a542014-08-08 21:58:29 -0600320 error_ = OK;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600321
Shawn Willden8d336ae2014-08-09 15:47:05 -0600322 return true;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600323}
324
325void AuthorizationSet::FreeData() {
Shawn Willden58e1a542014-08-08 21:58:29 -0600326 if (elems_ != NULL)
327 memset(elems_, 0, elems_size_ * sizeof(keymaster_key_param_t));
328 if (indirect_data_ != NULL)
329 memset(indirect_data_, 0, indirect_data_size_);
330
331 delete[] elems_;
332 delete[] indirect_data_;
333
Shawn Willden5ada7b62014-07-29 09:44:17 -0600334 elems_ = NULL;
335 indirect_data_ = NULL;
336 elems_size_ = 0;
337 elems_capacity_ = 0;
338 indirect_data_size_ = 0;
339 indirect_data_capacity_ = 0;
340}
341
342/* static */
343size_t AuthorizationSet::ComputeIndirectDataSize(const keymaster_key_param_t* elems, size_t count) {
344 size_t size = 0;
345 for (size_t i = 0; i < count; ++i) {
346 if (is_blob_tag(elems[i].tag)) {
347 size += elems[i].blob.data_length;
348 }
349 }
350 return size;
351}
352
353void AuthorizationSet::CopyIndirectData() {
354 memset(indirect_data_, 0, indirect_data_size_);
355
356 uint8_t* indirect_data_pos = indirect_data_;
357 for (size_t i = 0; i < elems_size_; ++i) {
358 assert(indirect_data_pos <= indirect_data_ + indirect_data_size_);
359 if (is_blob_tag(elems_[i].tag)) {
360 memcpy(indirect_data_pos, elems_[i].blob.data, elems_[i].blob.data_length);
361 elems_[i].blob.data = indirect_data_pos;
362 indirect_data_pos += elems_[i].blob.data_length;
363 }
364 }
365 assert(indirect_data_pos == indirect_data_ + indirect_data_size_);
366}
367
Shawn Willden5ada7b62014-07-29 09:44:17 -0600368bool AuthorizationSet::GetTagValueEnum(keymaster_tag_t tag, uint32_t* val) const {
369 int pos = find(tag);
370 if (pos == -1) {
371 return false;
372 }
373 *val = (*this)[pos].enumerated;
374 return true;
375}
376
377bool AuthorizationSet::GetTagValueEnumRep(keymaster_tag_t tag, size_t instance,
378 uint32_t* val) const {
379 size_t count = 0;
380 int pos = -1;
381 while (count <= instance) {
382 pos = find(tag, pos);
383 if (pos == -1) {
384 return false;
385 }
386 ++count;
387 }
388 *val = (*this)[pos].enumerated;
389 return true;
390}
391
392bool AuthorizationSet::GetTagValueInt(keymaster_tag_t tag, uint32_t* val) const {
393 int pos = find(tag);
394 if (pos == -1) {
395 return false;
396 }
397 *val = (*this)[pos].integer;
398 return true;
399}
400
401bool AuthorizationSet::GetTagValueIntRep(keymaster_tag_t tag, size_t instance,
402 uint32_t* val) const {
403 size_t count = 0;
404 int pos = -1;
405 while (count <= instance) {
406 pos = find(tag, pos);
407 if (pos == -1) {
408 return false;
409 }
410 ++count;
411 }
412 *val = (*this)[pos].integer;
413 return true;
414}
415
416bool AuthorizationSet::GetTagValueLong(keymaster_tag_t tag, uint64_t* val) const {
417 int pos = find(tag);
418 if (pos == -1) {
419 return false;
420 }
421 *val = (*this)[pos].long_integer;
422 return true;
423}
424
425bool AuthorizationSet::GetTagValueDate(keymaster_tag_t tag, uint64_t* val) const {
426 int pos = find(tag);
427 if (pos == -1) {
428 return false;
429 }
430 *val = (*this)[pos].date_time;
431 return true;
432}
433
434bool AuthorizationSet::GetTagValueBlob(keymaster_tag_t tag, keymaster_blob_t* val) const {
435 int pos = find(tag);
436 if (pos == -1) {
437 return false;
438 }
439 *val = (*this)[pos].blob;
440 return true;
441}
442
443} // namespace keymaster