blob: d147ef349dd4af260471e3f7c8749b037cf2c2d0 [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 Willden834e8072014-08-09 16:38:53 -0600297 // Note that the following validation of elements_count is weak, but it prevents allocation of
298 // elems_ arrays which are clearly too large to be reasonable.
299 if (elements_size > end - *buf || elements_count * sizeof(uint32_t) > elements_size) {
300 set_invalid(MALFORMED_DATA);
301 return false;
302 }
303
Shawn Willden8d336ae2014-08-09 15:47:05 -0600304 elems_ = new keymaster_key_param_t[elements_count];
Shawn Willden5ada7b62014-07-29 09:44:17 -0600305 if (elems_ == NULL) {
306 set_invalid(ALLOCATION_FAILURE);
307 return false;
308 }
Shawn Willden5ada7b62014-07-29 09:44:17 -0600309
Shawn Willden8d336ae2014-08-09 15:47:05 -0600310 uint8_t* indirect_end = indirect_data_ + indirect_data_size_;
311 const uint8_t* elements_end = *buf + elements_size;
312 for (size_t i = 0; i < elements_count; ++i) {
313 if (!deserialize(elems_ + i, buf, elements_end, indirect_data_, indirect_end)) {
314 set_invalid(MALFORMED_DATA);
315 return false;
316 }
317 }
318
319 if (indirect_data_size_ != ComputeIndirectDataSize(elems_, elements_count)) {
Shawn Willden58e1a542014-08-08 21:58:29 -0600320 set_invalid(MALFORMED_DATA);
Shawn Willden5ada7b62014-07-29 09:44:17 -0600321 return false;
Shawn Willden58e1a542014-08-08 21:58:29 -0600322 }
Shawn Willden5ada7b62014-07-29 09:44:17 -0600323
Shawn Willden8d336ae2014-08-09 15:47:05 -0600324 elems_size_ = elements_count;
325 elems_capacity_ = elements_count;
326 indirect_data_capacity_ = indirect_data_size_;
Shawn Willden58e1a542014-08-08 21:58:29 -0600327 error_ = OK;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600328
Shawn Willden8d336ae2014-08-09 15:47:05 -0600329 return true;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600330}
331
332void AuthorizationSet::FreeData() {
Shawn Willden58e1a542014-08-08 21:58:29 -0600333 if (elems_ != NULL)
334 memset(elems_, 0, elems_size_ * sizeof(keymaster_key_param_t));
335 if (indirect_data_ != NULL)
336 memset(indirect_data_, 0, indirect_data_size_);
337
338 delete[] elems_;
339 delete[] indirect_data_;
340
Shawn Willden5ada7b62014-07-29 09:44:17 -0600341 elems_ = NULL;
342 indirect_data_ = NULL;
343 elems_size_ = 0;
344 elems_capacity_ = 0;
345 indirect_data_size_ = 0;
346 indirect_data_capacity_ = 0;
347}
348
349/* static */
350size_t AuthorizationSet::ComputeIndirectDataSize(const keymaster_key_param_t* elems, size_t count) {
351 size_t size = 0;
352 for (size_t i = 0; i < count; ++i) {
353 if (is_blob_tag(elems[i].tag)) {
354 size += elems[i].blob.data_length;
355 }
356 }
357 return size;
358}
359
360void AuthorizationSet::CopyIndirectData() {
361 memset(indirect_data_, 0, indirect_data_size_);
362
363 uint8_t* indirect_data_pos = indirect_data_;
364 for (size_t i = 0; i < elems_size_; ++i) {
365 assert(indirect_data_pos <= indirect_data_ + indirect_data_size_);
366 if (is_blob_tag(elems_[i].tag)) {
367 memcpy(indirect_data_pos, elems_[i].blob.data, elems_[i].blob.data_length);
368 elems_[i].blob.data = indirect_data_pos;
369 indirect_data_pos += elems_[i].blob.data_length;
370 }
371 }
372 assert(indirect_data_pos == indirect_data_ + indirect_data_size_);
373}
374
Shawn Willden5ada7b62014-07-29 09:44:17 -0600375bool AuthorizationSet::GetTagValueEnum(keymaster_tag_t tag, uint32_t* val) const {
376 int pos = find(tag);
377 if (pos == -1) {
378 return false;
379 }
380 *val = (*this)[pos].enumerated;
381 return true;
382}
383
384bool AuthorizationSet::GetTagValueEnumRep(keymaster_tag_t tag, size_t instance,
385 uint32_t* val) const {
386 size_t count = 0;
387 int pos = -1;
388 while (count <= instance) {
389 pos = find(tag, pos);
390 if (pos == -1) {
391 return false;
392 }
393 ++count;
394 }
395 *val = (*this)[pos].enumerated;
396 return true;
397}
398
399bool AuthorizationSet::GetTagValueInt(keymaster_tag_t tag, uint32_t* val) const {
400 int pos = find(tag);
401 if (pos == -1) {
402 return false;
403 }
404 *val = (*this)[pos].integer;
405 return true;
406}
407
408bool AuthorizationSet::GetTagValueIntRep(keymaster_tag_t tag, size_t instance,
409 uint32_t* val) const {
410 size_t count = 0;
411 int pos = -1;
412 while (count <= instance) {
413 pos = find(tag, pos);
414 if (pos == -1) {
415 return false;
416 }
417 ++count;
418 }
419 *val = (*this)[pos].integer;
420 return true;
421}
422
423bool AuthorizationSet::GetTagValueLong(keymaster_tag_t tag, uint64_t* val) const {
424 int pos = find(tag);
425 if (pos == -1) {
426 return false;
427 }
428 *val = (*this)[pos].long_integer;
429 return true;
430}
431
432bool AuthorizationSet::GetTagValueDate(keymaster_tag_t tag, uint64_t* val) const {
433 int pos = find(tag);
434 if (pos == -1) {
435 return false;
436 }
437 *val = (*this)[pos].date_time;
438 return true;
439}
440
441bool AuthorizationSet::GetTagValueBlob(keymaster_tag_t tag, keymaster_blob_t* val) const {
442 int pos = find(tag);
443 if (pos == -1) {
444 return false;
445 }
446 *val = (*this)[pos].blob;
447 return true;
448}
449
450} // namespace keymaster