blob: 1fb9d8286e3940f3a2a09e8c4552491cfb27ae13 [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) {
36 elems_ = new keymaster_key_param_t[set.elems_size_];
37 if (elems_ == NULL) {
38 error_ = ALLOCATION_FAILURE;
39 return;
40 }
41 memcpy(elems_, set.elems_, set.elems_size_ * sizeof(keymaster_key_param_t));
42 elems_size_ = set.elems_size_;
43 elems_capacity_ = elems_size_;
44
45 if (set.indirect_data_ == NULL) {
46 indirect_data_ = NULL;
47 indirect_data_size_ = 0;
48 indirect_data_capacity_ = 0;
49 } else {
50 indirect_data_ = new uint8_t[set.indirect_data_size_];
51 if (indirect_data_ == NULL) {
52 error_ = ALLOCATION_FAILURE;
53 return;
54 }
55 memcpy(indirect_data_, set.indirect_data_, set.indirect_data_size_);
Shawn Willden8d336ae2014-08-09 15:47:05 -060056 for (size_t i = 0; i < elems_size_; ++i) {
57 if (is_blob_tag(elems_[i].tag))
58 elems_[i].blob.data = indirect_data_ + (elems_[i].blob.data - set.indirect_data_);
59 }
60
Shawn Willden58e1a542014-08-08 21:58:29 -060061 indirect_data_size_ = set.indirect_data_size_;
62 indirect_data_capacity_ = indirect_data_size_;
63 }
64 error_ = OK;
Shawn Willden5ada7b62014-07-29 09:44:17 -060065}
66
Shawn Willden8d336ae2014-08-09 15:47:05 -060067AuthorizationSet::~AuthorizationSet() {
68 FreeData();
69}
Shawn Willden58e1a542014-08-08 21:58:29 -060070
Shawn Willden5ada7b62014-07-29 09:44:17 -060071bool AuthorizationSet::Reinitialize(const keymaster_key_param_t* elems, const size_t count) {
72 FreeData();
73
74 elems_size_ = count;
75 elems_capacity_ = count;
76 indirect_data_size_ = ComputeIndirectDataSize(elems, count);
77 indirect_data_capacity_ = indirect_data_size_;
Shawn Willden58e1a542014-08-08 21:58:29 -060078 error_ = OK;
Shawn Willden5ada7b62014-07-29 09:44:17 -060079
80 indirect_data_ = new uint8_t[indirect_data_size_];
81 elems_ = new keymaster_key_param_t[elems_size_];
82 if (indirect_data_ == NULL || elems_ == NULL) {
83 set_invalid(ALLOCATION_FAILURE);
84 return false;
85 }
Shawn Willden5ada7b62014-07-29 09:44:17 -060086
87 memcpy(elems_, elems, sizeof(keymaster_key_param_t) * elems_size_);
88 CopyIndirectData();
Shawn Willden5ada7b62014-07-29 09:44:17 -060089 return true;
90}
91
Shawn Willden5ada7b62014-07-29 09:44:17 -060092void AuthorizationSet::set_invalid(Error error) {
93 error_ = error;
94 FreeData();
95}
96
97int AuthorizationSet::find(keymaster_tag_t tag, int begin) const {
98 int i = ++begin;
Shawn Willden8d336ae2014-08-09 15:47:05 -060099 while (i < (int)elems_size_ && elems_[i].tag != tag)
100 ++i;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600101 if (i == (int)elems_size_)
102 return -1;
103 else
104 return i;
105}
106
107keymaster_key_param_t empty;
108
109keymaster_key_param_t AuthorizationSet::operator[](int at) const {
110 if (at < (int)elems_size_) {
Shawn Willden8d336ae2014-08-09 15:47:05 -0600111 return elems_[at];
Shawn Willden5ada7b62014-07-29 09:44:17 -0600112 }
113 memset(&empty, 0, sizeof(empty));
114 return empty;
115}
116
117bool AuthorizationSet::push_back(keymaster_key_param_t elem) {
118 if (elems_size_ >= elems_capacity_) {
Shawn Willden58e1a542014-08-08 21:58:29 -0600119 size_t new_capacity = elems_capacity_ ? elems_capacity_ * 2 : STARTING_ELEMS_CAPACITY;
120 keymaster_key_param_t* new_elems = new keymaster_key_param_t[new_capacity];
121 if (new_elems == NULL) {
122 set_invalid(ALLOCATION_FAILURE);
Shawn Willden5ada7b62014-07-29 09:44:17 -0600123 return false;
124 }
Shawn Willden58e1a542014-08-08 21:58:29 -0600125 memcpy(new_elems, elems_, sizeof(*elems_) * elems_size_);
126 delete[] elems_;
127 elems_ = new_elems;
128 elems_capacity_ = new_capacity;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600129 }
130
131 if (is_blob_tag(elem.tag)) {
132 if (indirect_data_capacity_ - indirect_data_size_ < elem.blob.data_length) {
Shawn Willden58e1a542014-08-08 21:58:29 -0600133 size_t new_capacity = 2 * (indirect_data_capacity_ + elem.blob.data_length);
134 uint8_t* new_data = new uint8_t[new_capacity];
135 if (new_data == false) {
136 set_invalid(ALLOCATION_FAILURE);
Shawn Willden5ada7b62014-07-29 09:44:17 -0600137 return false;
138 }
Shawn Willden58e1a542014-08-08 21:58:29 -0600139 memcpy(new_data, indirect_data_, indirect_data_size_);
Shawn Willden8d336ae2014-08-09 15:47:05 -0600140 // Fix up the data pointers to point into the new region.
141 for (size_t i = 0; i < elems_size_; ++i) {
142 if (is_blob_tag(elems_[i].tag))
143 elems_[i].blob.data = new_data + (elems_[i].blob.data - indirect_data_);
144 }
Shawn Willden58e1a542014-08-08 21:58:29 -0600145 delete[] indirect_data_;
146 indirect_data_ = new_data;
147 indirect_data_capacity_ = new_capacity;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600148 }
Shawn Willden58e1a542014-08-08 21:58:29 -0600149
Shawn Willden5ada7b62014-07-29 09:44:17 -0600150 memcpy(indirect_data_ + indirect_data_size_, elem.blob.data, elem.blob.data_length);
Shawn Willden8d336ae2014-08-09 15:47:05 -0600151 elem.blob.data = indirect_data_ + indirect_data_size_;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600152 indirect_data_size_ += elem.blob.data_length;
153 }
154
155 elems_[elems_size_++] = elem;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600156 return true;
157}
158
Shawn Willden8d336ae2014-08-09 15:47:05 -0600159static size_t serialized_size(const keymaster_key_param_t& param) {
160 switch (keymaster_tag_get_type(param.tag)) {
161 case KM_INVALID:
162 default:
163 return sizeof(uint32_t);
164 case KM_ENUM:
165 case KM_ENUM_REP:
166 case KM_INT:
167 case KM_INT_REP:
168 return sizeof(uint32_t) * 2;
169 case KM_LONG:
170 case KM_DATE:
171 return sizeof(uint32_t) + sizeof(uint64_t);
172 case KM_BOOL:
173 return sizeof(uint32_t) + 1;
174 break;
175 case KM_BIGNUM:
176 case KM_BYTES:
177 return sizeof(uint32_t) * 3;
178 }
Shawn Willden58e1a542014-08-08 21:58:29 -0600179}
180
Shawn Willden8d336ae2014-08-09 15:47:05 -0600181static uint8_t* serialize(const keymaster_key_param_t& param, uint8_t* buf, const uint8_t* end,
182 const uint8_t* indirect_base) {
183 buf = append_to_buf(buf, end, static_cast<uint32_t>(param.tag));
184 switch (keymaster_tag_get_type(param.tag)) {
185 case KM_INVALID:
186 break;
187 case KM_ENUM:
188 case KM_ENUM_REP:
189 buf = append_to_buf(buf, end, param.enumerated);
190 break;
191 case KM_INT:
192 case KM_INT_REP:
193 buf = append_to_buf(buf, end, param.integer);
194 break;
195 case KM_LONG:
196 buf = append_to_buf(buf, end, param.long_integer);
197 break;
198 case KM_DATE:
199 buf = append_to_buf(buf, end, param.date_time);
200 break;
201 case KM_BOOL:
202 if (buf < end)
203 *buf = static_cast<uint8_t>(param.boolean);
204 buf++;
205 break;
206 case KM_BIGNUM:
207 case KM_BYTES:
208 buf = append_to_buf(buf, end, static_cast<uint32_t>(param.blob.data_length));
209 buf = append_to_buf(buf, end, static_cast<uint32_t>(param.blob.data - indirect_base));
210 break;
211 }
212 return buf;
213}
214
215static bool deserialize(keymaster_key_param_t* param, const uint8_t** buf, const uint8_t* end,
216 const uint8_t* indirect_base, const uint8_t* indirect_end) {
217 uint32_t tag_val;
218 if (!copy_from_buf(buf, end, &tag_val))
219 return false;
220 param->tag = static_cast<keymaster_tag_t>(tag_val);
221
222 switch (keymaster_tag_get_type(param->tag)) {
223 default:
224 case KM_INVALID:
225 return false;
226 case KM_ENUM:
227 case KM_ENUM_REP:
228 return copy_from_buf(buf, end, &param->enumerated);
229 case KM_INT:
230 case KM_INT_REP:
231 return copy_from_buf(buf, end, &param->integer);
232 case KM_LONG:
233 return copy_from_buf(buf, end, &param->long_integer);
234 case KM_DATE:
235 return copy_from_buf(buf, end, &param->date_time);
236 break;
237 case KM_BOOL:
238 if (*buf < end) {
239 param->boolean = static_cast<bool>(**buf);
240 (*buf)++;
241 return true;
242 }
243 return false;
244
245 case KM_BIGNUM:
246 case KM_BYTES: {
247 uint32_t length;
248 uint32_t offset;
249 if (!copy_from_buf(buf, end, &length) || !copy_from_buf(buf, end, &offset))
250 return false;
251 if (static_cast<ptrdiff_t>(offset) > indirect_end - indirect_base ||
252 static_cast<ptrdiff_t>(offset + length) > indirect_end - indirect_base)
253 return false;
254 param->blob.data_length = length;
255 param->blob.data = indirect_base + offset;
256 return true;
257 }
258 }
259}
260
261size_t AuthorizationSet::SerializedSizeOfElements() const {
262 size_t size = 0;
263 for (size_t i = 0; i < elems_size_; ++i) {
264 size += serialized_size(elems_[i]);
265 }
266 return size;
267}
268
269size_t AuthorizationSet::SerializedSize() const {
270 return sizeof(uint32_t) + // Size of indirect_data_
271 indirect_data_size_ + // indirect_data_
272 sizeof(uint32_t) + // Number of elems_
273 sizeof(uint32_t) + // Size of elems_
274 SerializedSizeOfElements(); // elems_
275}
276
277uint8_t* AuthorizationSet::Serialize(uint8_t* buf, const uint8_t* end) const {
278 buf = append_size_and_data_to_buf(buf, end, indirect_data_, indirect_data_size_);
279 buf = append_to_buf(buf, end, static_cast<uint32_t>(elems_size_));
280 buf = append_to_buf(buf, end, static_cast<uint32_t>(SerializedSizeOfElements()));
281 for (size_t i = 0; i < elems_size_; ++i) {
282 buf = serialize(elems_[i], buf, end, indirect_data_);
283 }
284 return buf;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600285}
286
Shawn Willden58e1a542014-08-08 21:58:29 -0600287bool AuthorizationSet::Deserialize(const uint8_t** buf, const uint8_t* end) {
Shawn Willden5ada7b62014-07-29 09:44:17 -0600288 FreeData();
289
Shawn Willden8d336ae2014-08-09 15:47:05 -0600290 uint32_t elements_count;
291 uint32_t elements_size;
292 if (!copy_size_and_data_from_buf(buf, end, &indirect_data_size_, &indirect_data_) ||
293 !copy_from_buf(buf, end, &elements_count) || !copy_from_buf(buf, end, &elements_size)) {
Shawn Willden58e1a542014-08-08 21:58:29 -0600294 set_invalid(MALFORMED_DATA);
Shawn Willden5ada7b62014-07-29 09:44:17 -0600295 return false;
296 }
297
Shawn Willden834e8072014-08-09 16:38:53 -0600298 // Note that the following validation of elements_count is weak, but it prevents allocation of
299 // elems_ arrays which are clearly too large to be reasonable.
300 if (elements_size > end - *buf || elements_count * sizeof(uint32_t) > elements_size) {
301 set_invalid(MALFORMED_DATA);
302 return false;
303 }
304
Shawn Willden8d336ae2014-08-09 15:47:05 -0600305 elems_ = new keymaster_key_param_t[elements_count];
Shawn Willden5ada7b62014-07-29 09:44:17 -0600306 if (elems_ == NULL) {
307 set_invalid(ALLOCATION_FAILURE);
308 return false;
309 }
Shawn Willden5ada7b62014-07-29 09:44:17 -0600310
Shawn Willden8d336ae2014-08-09 15:47:05 -0600311 uint8_t* indirect_end = indirect_data_ + indirect_data_size_;
312 const uint8_t* elements_end = *buf + elements_size;
313 for (size_t i = 0; i < elements_count; ++i) {
314 if (!deserialize(elems_ + i, buf, elements_end, indirect_data_, indirect_end)) {
315 set_invalid(MALFORMED_DATA);
316 return false;
317 }
318 }
319
320 if (indirect_data_size_ != ComputeIndirectDataSize(elems_, elements_count)) {
Shawn Willden58e1a542014-08-08 21:58:29 -0600321 set_invalid(MALFORMED_DATA);
Shawn Willden5ada7b62014-07-29 09:44:17 -0600322 return false;
Shawn Willden58e1a542014-08-08 21:58:29 -0600323 }
Shawn Willden5ada7b62014-07-29 09:44:17 -0600324
Shawn Willden8d336ae2014-08-09 15:47:05 -0600325 elems_size_ = elements_count;
326 elems_capacity_ = elements_count;
327 indirect_data_capacity_ = indirect_data_size_;
Shawn Willden58e1a542014-08-08 21:58:29 -0600328 error_ = OK;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600329
Shawn Willden8d336ae2014-08-09 15:47:05 -0600330 return true;
Shawn Willden5ada7b62014-07-29 09:44:17 -0600331}
332
333void AuthorizationSet::FreeData() {
Shawn Willden58e1a542014-08-08 21:58:29 -0600334 if (elems_ != NULL)
Shawn Willden74aff352014-08-11 14:08:31 -0600335 memset_s(elems_, 0, elems_size_ * sizeof(keymaster_key_param_t));
Shawn Willden58e1a542014-08-08 21:58:29 -0600336 if (indirect_data_ != NULL)
Shawn Willden74aff352014-08-11 14:08:31 -0600337 memset_s(indirect_data_, 0, indirect_data_size_);
Shawn Willden58e1a542014-08-08 21:58:29 -0600338
339 delete[] elems_;
340 delete[] indirect_data_;
341
Shawn Willden5ada7b62014-07-29 09:44:17 -0600342 elems_ = NULL;
343 indirect_data_ = NULL;
344 elems_size_ = 0;
345 elems_capacity_ = 0;
346 indirect_data_size_ = 0;
347 indirect_data_capacity_ = 0;
348}
349
350/* static */
351size_t AuthorizationSet::ComputeIndirectDataSize(const keymaster_key_param_t* elems, size_t count) {
352 size_t size = 0;
353 for (size_t i = 0; i < count; ++i) {
354 if (is_blob_tag(elems[i].tag)) {
355 size += elems[i].blob.data_length;
356 }
357 }
358 return size;
359}
360
361void AuthorizationSet::CopyIndirectData() {
362 memset(indirect_data_, 0, indirect_data_size_);
363
364 uint8_t* indirect_data_pos = indirect_data_;
365 for (size_t i = 0; i < elems_size_; ++i) {
366 assert(indirect_data_pos <= indirect_data_ + indirect_data_size_);
367 if (is_blob_tag(elems_[i].tag)) {
368 memcpy(indirect_data_pos, elems_[i].blob.data, elems_[i].blob.data_length);
369 elems_[i].blob.data = indirect_data_pos;
370 indirect_data_pos += elems_[i].blob.data_length;
371 }
372 }
373 assert(indirect_data_pos == indirect_data_ + indirect_data_size_);
374}
375
Shawn Willden5ada7b62014-07-29 09:44:17 -0600376bool AuthorizationSet::GetTagValueEnum(keymaster_tag_t tag, uint32_t* val) const {
377 int pos = find(tag);
378 if (pos == -1) {
379 return false;
380 }
381 *val = (*this)[pos].enumerated;
382 return true;
383}
384
385bool AuthorizationSet::GetTagValueEnumRep(keymaster_tag_t tag, size_t instance,
386 uint32_t* val) const {
387 size_t count = 0;
388 int pos = -1;
389 while (count <= instance) {
390 pos = find(tag, pos);
391 if (pos == -1) {
392 return false;
393 }
394 ++count;
395 }
396 *val = (*this)[pos].enumerated;
397 return true;
398}
399
400bool AuthorizationSet::GetTagValueInt(keymaster_tag_t tag, uint32_t* val) const {
401 int pos = find(tag);
402 if (pos == -1) {
403 return false;
404 }
405 *val = (*this)[pos].integer;
406 return true;
407}
408
409bool AuthorizationSet::GetTagValueIntRep(keymaster_tag_t tag, size_t instance,
410 uint32_t* val) const {
411 size_t count = 0;
412 int pos = -1;
413 while (count <= instance) {
414 pos = find(tag, pos);
415 if (pos == -1) {
416 return false;
417 }
418 ++count;
419 }
420 *val = (*this)[pos].integer;
421 return true;
422}
423
424bool AuthorizationSet::GetTagValueLong(keymaster_tag_t tag, uint64_t* val) const {
425 int pos = find(tag);
426 if (pos == -1) {
427 return false;
428 }
429 *val = (*this)[pos].long_integer;
430 return true;
431}
432
433bool AuthorizationSet::GetTagValueDate(keymaster_tag_t tag, uint64_t* val) const {
434 int pos = find(tag);
435 if (pos == -1) {
436 return false;
437 }
438 *val = (*this)[pos].date_time;
439 return true;
440}
441
442bool AuthorizationSet::GetTagValueBlob(keymaster_tag_t tag, keymaster_blob_t* val) const {
443 int pos = find(tag);
444 if (pos == -1) {
445 return false;
446 }
447 *val = (*this)[pos].blob;
448 return true;
449}
450
451} // namespace keymaster