1 /*
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 <keymaster/authorization_set.h>
18
19 #include <assert.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <stddef.h>
23
24 #include <new>
25
26 #include <keymaster/android_keymaster_utils.h>
27 #include <keymaster/logger.h>
28
29 namespace keymaster {
30
is_blob_tag(keymaster_tag_t tag)31 static inline bool is_blob_tag(keymaster_tag_t tag) {
32 return (keymaster_tag_get_type(tag) == KM_BYTES || keymaster_tag_get_type(tag) == KM_BIGNUM);
33 }
34
35 const size_t STARTING_ELEMS_CAPACITY = 8;
36
AuthorizationSet(AuthorizationSetBuilder & builder)37 AuthorizationSet::AuthorizationSet(AuthorizationSetBuilder& builder) {
38 elems_ = builder.set.elems_;
39 builder.set.elems_ = NULL;
40
41 elems_size_ = builder.set.elems_size_;
42 builder.set.elems_size_ = 0;
43
44 elems_capacity_ = builder.set.elems_capacity_;
45 builder.set.elems_capacity_ = 0;
46
47 indirect_data_ = builder.set.indirect_data_;
48 builder.set.indirect_data_ = NULL;
49
50 indirect_data_capacity_ = builder.set.indirect_data_capacity_;
51 builder.set.indirect_data_capacity_ = 0;
52
53 indirect_data_size_ = builder.set.indirect_data_size_;
54 builder.set.indirect_data_size_ = 0;
55
56 error_ = builder.set.error_;
57 builder.set.error_ = OK;
58 }
59
~AuthorizationSet()60 AuthorizationSet::~AuthorizationSet() {
61 FreeData();
62 }
63
reserve_elems(size_t count)64 bool AuthorizationSet::reserve_elems(size_t count) {
65 if (is_valid() != OK)
66 return false;
67
68 if (count >= elems_capacity_) {
69 keymaster_key_param_t* new_elems = new (std::nothrow) keymaster_key_param_t[count];
70 if (new_elems == NULL) {
71 set_invalid(ALLOCATION_FAILURE);
72 return false;
73 }
74 memcpy(new_elems, elems_, sizeof(*elems_) * elems_size_);
75 delete[] elems_;
76 elems_ = new_elems;
77 elems_capacity_ = count;
78 }
79 return true;
80 }
81
reserve_indirect(size_t length)82 bool AuthorizationSet::reserve_indirect(size_t length) {
83 if (is_valid() != OK)
84 return false;
85
86 if (length > indirect_data_capacity_) {
87 uint8_t* new_data = new (std::nothrow) uint8_t[length];
88 if (new_data == NULL) {
89 set_invalid(ALLOCATION_FAILURE);
90 return false;
91 }
92 memcpy(new_data, indirect_data_, indirect_data_size_);
93
94 // Fix up the data pointers to point into the new region.
95 for (size_t i = 0; i < elems_size_; ++i) {
96 if (is_blob_tag(elems_[i].tag))
97 elems_[i].blob.data = new_data + (elems_[i].blob.data - indirect_data_);
98 }
99 delete[] indirect_data_;
100 indirect_data_ = new_data;
101 indirect_data_capacity_ = length;
102 }
103 return true;
104 }
105
Reinitialize(const keymaster_key_param_t * elems,const size_t count)106 bool AuthorizationSet::Reinitialize(const keymaster_key_param_t* elems, const size_t count) {
107 FreeData();
108
109 if (elems == NULL || count == 0) {
110 error_ = OK;
111 return true;
112 }
113
114 if (!reserve_elems(count))
115 return false;
116
117 if (!reserve_indirect(ComputeIndirectDataSize(elems, count)))
118 return false;
119
120 memcpy(elems_, elems, sizeof(keymaster_key_param_t) * count);
121 elems_size_ = count;
122 CopyIndirectData();
123 error_ = OK;
124 return true;
125 }
126
set_invalid(Error error)127 void AuthorizationSet::set_invalid(Error error) {
128 FreeData();
129 error_ = error;
130 }
131
Deduplicate()132 void AuthorizationSet::Deduplicate() {
133 qsort(elems_, elems_size_, sizeof(*elems_),
134 reinterpret_cast<int (*)(const void*, const void*)>(keymaster_param_compare));
135
136 size_t invalid_count = 0;
137 for (size_t i = 1; i < size(); ++i) {
138 if (elems_[i - 1].tag == KM_TAG_INVALID)
139 ++invalid_count;
140 else if (keymaster_param_compare(elems_ + i - 1, elems_ + i) == 0) {
141 // Mark dups as invalid. Note that this "leaks" the data referenced by KM_BYTES and
142 // KM_BIGNUM entries, but those are just pointers into indirect_data_, so it will all
143 // get cleaned up.
144 elems_[i - 1].tag = KM_TAG_INVALID;
145 ++invalid_count;
146 }
147 }
148 if (size() > 0 && elems_[size() - 1].tag == KM_TAG_INVALID)
149 ++invalid_count;
150
151 if (invalid_count == 0)
152 return;
153
154 // Since KM_TAG_INVALID == 0, all of the invalid entries are first.
155 elems_size_ -= invalid_count;
156 memmove(elems_, elems_ + invalid_count, size() * sizeof(*elems_));
157 }
158
CopyToParamSet(keymaster_key_param_set_t * set) const159 void AuthorizationSet::CopyToParamSet(keymaster_key_param_set_t* set) const {
160 assert(set);
161
162 set->length = size();
163 set->params =
164 reinterpret_cast<keymaster_key_param_t*>(malloc(sizeof(keymaster_key_param_t) * size()));
165
166 for (size_t i = 0; i < size(); ++i) {
167 const keymaster_key_param_t src = (*this)[i];
168 keymaster_key_param_t& dst(set->params[i]);
169
170 dst = src;
171 keymaster_tag_type_t type = keymaster_tag_get_type(src.tag);
172 if (type == KM_BIGNUM || type == KM_BYTES) {
173 void* tmp = malloc(src.blob.data_length);
174 memcpy(tmp, src.blob.data, src.blob.data_length);
175 dst.blob.data = reinterpret_cast<uint8_t*>(tmp);
176 }
177 }
178 }
179
find(keymaster_tag_t tag,int begin) const180 int AuthorizationSet::find(keymaster_tag_t tag, int begin) const {
181 if (is_valid() != OK)
182 return -1;
183
184 int i = ++begin;
185 while (i < (int)elems_size_ && elems_[i].tag != tag)
186 ++i;
187 if (i == (int)elems_size_)
188 return -1;
189 else
190 return i;
191 }
192
193 keymaster_key_param_t empty;
operator [](int at)194 keymaster_key_param_t& AuthorizationSet::operator[](int at) {
195 if (is_valid() == OK && at < (int)elems_size_) {
196 return elems_[at];
197 }
198 memset(&empty, 0, sizeof(empty));
199 return empty;
200 }
201
202
operator [](int at) const203 keymaster_key_param_t AuthorizationSet::operator[](int at) const {
204 if (is_valid() == OK && at < (int)elems_size_) {
205 return elems_[at];
206 }
207 memset(&empty, 0, sizeof(empty));
208 return empty;
209 }
210
push_back(const keymaster_key_param_set_t & set)211 bool AuthorizationSet::push_back(const keymaster_key_param_set_t& set) {
212 if (is_valid() != OK)
213 return false;
214
215 if (!reserve_elems(elems_size_ + set.length))
216 return false;
217
218 if (!reserve_indirect(indirect_data_size_ + ComputeIndirectDataSize(set.params, set.length)))
219 return false;
220
221 for (size_t i = 0; i < set.length; ++i)
222 if (!push_back(set.params[i]))
223 return false;
224
225 return true;
226 }
227
push_back(keymaster_key_param_t elem)228 bool AuthorizationSet::push_back(keymaster_key_param_t elem) {
229 if (is_valid() != OK)
230 return false;
231
232 if (elems_size_ >= elems_capacity_)
233 if (!reserve_elems(elems_capacity_ ? elems_capacity_ * 2 : STARTING_ELEMS_CAPACITY))
234 return false;
235
236 if (is_blob_tag(elem.tag)) {
237 if (indirect_data_capacity_ - indirect_data_size_ < elem.blob.data_length)
238 if (!reserve_indirect(2 * (indirect_data_capacity_ + elem.blob.data_length)))
239 return false;
240
241 memcpy(indirect_data_ + indirect_data_size_, elem.blob.data, elem.blob.data_length);
242 elem.blob.data = indirect_data_ + indirect_data_size_;
243 indirect_data_size_ += elem.blob.data_length;
244 }
245
246 elems_[elems_size_++] = elem;
247 return true;
248 }
249
serialized_size(const keymaster_key_param_t & param)250 static size_t serialized_size(const keymaster_key_param_t& param) {
251 switch (keymaster_tag_get_type(param.tag)) {
252 case KM_INVALID:
253 return sizeof(uint32_t);
254 case KM_ENUM:
255 case KM_ENUM_REP:
256 case KM_UINT:
257 case KM_UINT_REP:
258 return sizeof(uint32_t) * 2;
259 case KM_ULONG:
260 case KM_ULONG_REP:
261 case KM_DATE:
262 return sizeof(uint32_t) + sizeof(uint64_t);
263 case KM_BOOL:
264 return sizeof(uint32_t) + 1;
265 case KM_BIGNUM:
266 case KM_BYTES:
267 return sizeof(uint32_t) * 3;
268 }
269
270 return sizeof(uint32_t);
271 }
272
serialize(const keymaster_key_param_t & param,uint8_t * buf,const uint8_t * end,const uint8_t * indirect_base)273 static uint8_t* serialize(const keymaster_key_param_t& param, uint8_t* buf, const uint8_t* end,
274 const uint8_t* indirect_base) {
275 buf = append_uint32_to_buf(buf, end, param.tag);
276 switch (keymaster_tag_get_type(param.tag)) {
277 case KM_INVALID:
278 break;
279 case KM_ENUM:
280 case KM_ENUM_REP:
281 buf = append_uint32_to_buf(buf, end, param.enumerated);
282 break;
283 case KM_UINT:
284 case KM_UINT_REP:
285 buf = append_uint32_to_buf(buf, end, param.integer);
286 break;
287 case KM_ULONG:
288 case KM_ULONG_REP:
289 buf = append_uint64_to_buf(buf, end, param.long_integer);
290 break;
291 case KM_DATE:
292 buf = append_uint64_to_buf(buf, end, param.date_time);
293 break;
294 case KM_BOOL:
295 if (buf < end)
296 *buf = static_cast<uint8_t>(param.boolean);
297 buf++;
298 break;
299 case KM_BIGNUM:
300 case KM_BYTES:
301 buf = append_uint32_to_buf(buf, end, param.blob.data_length);
302 buf = append_uint32_to_buf(buf, end, param.blob.data - indirect_base);
303 break;
304 }
305 return buf;
306 }
307
deserialize(keymaster_key_param_t * param,const uint8_t ** buf_ptr,const uint8_t * end,const uint8_t * indirect_base,const uint8_t * indirect_end)308 static bool deserialize(keymaster_key_param_t* param, const uint8_t** buf_ptr, const uint8_t* end,
309 const uint8_t* indirect_base, const uint8_t* indirect_end) {
310 if (!copy_uint32_from_buf(buf_ptr, end, ¶m->tag))
311 return false;
312
313 switch (keymaster_tag_get_type(param->tag)) {
314 case KM_INVALID:
315 return false;
316 case KM_ENUM:
317 case KM_ENUM_REP:
318 return copy_uint32_from_buf(buf_ptr, end, ¶m->enumerated);
319 case KM_UINT:
320 case KM_UINT_REP:
321 return copy_uint32_from_buf(buf_ptr, end, ¶m->integer);
322 case KM_ULONG:
323 case KM_ULONG_REP:
324 return copy_uint64_from_buf(buf_ptr, end, ¶m->long_integer);
325 case KM_DATE:
326 return copy_uint64_from_buf(buf_ptr, end, ¶m->date_time);
327 break;
328 case KM_BOOL:
329 if (*buf_ptr < end) {
330 param->boolean = static_cast<bool>(**buf_ptr);
331 (*buf_ptr)++;
332 return true;
333 }
334 return false;
335
336 case KM_BIGNUM:
337 case KM_BYTES: {
338 uint32_t offset;
339 if (!copy_uint32_from_buf(buf_ptr, end, ¶m->blob.data_length) ||
340 !copy_uint32_from_buf(buf_ptr, end, &offset))
341 return false;
342 if (param->blob.data_length + offset < param->blob.data_length || // Overflow check
343 static_cast<ptrdiff_t>(offset) > indirect_end - indirect_base ||
344 static_cast<ptrdiff_t>(offset + param->blob.data_length) > indirect_end - indirect_base)
345 return false;
346 param->blob.data = indirect_base + offset;
347 return true;
348 }
349 }
350
351 return false;
352 }
353
SerializedSizeOfElements() const354 size_t AuthorizationSet::SerializedSizeOfElements() const {
355 size_t size = 0;
356 for (size_t i = 0; i < elems_size_; ++i) {
357 size += serialized_size(elems_[i]);
358 }
359 return size;
360 }
361
SerializedSize() const362 size_t AuthorizationSet::SerializedSize() const {
363 return sizeof(uint32_t) + // Size of indirect_data_
364 indirect_data_size_ + // indirect_data_
365 sizeof(uint32_t) + // Number of elems_
366 sizeof(uint32_t) + // Size of elems_
367 SerializedSizeOfElements(); // elems_
368 }
369
Serialize(uint8_t * buf,const uint8_t * end) const370 uint8_t* AuthorizationSet::Serialize(uint8_t* buf, const uint8_t* end) const {
371 buf = append_size_and_data_to_buf(buf, end, indirect_data_, indirect_data_size_);
372 buf = append_uint32_to_buf(buf, end, elems_size_);
373 buf = append_uint32_to_buf(buf, end, SerializedSizeOfElements());
374 for (size_t i = 0; i < elems_size_; ++i) {
375 buf = serialize(elems_[i], buf, end, indirect_data_);
376 }
377 return buf;
378 }
379
DeserializeIndirectData(const uint8_t ** buf_ptr,const uint8_t * end)380 bool AuthorizationSet::DeserializeIndirectData(const uint8_t** buf_ptr, const uint8_t* end) {
381 UniquePtr<uint8_t[]> indirect_buf;
382 if (!copy_size_and_data_from_buf(buf_ptr, end, &indirect_data_size_, &indirect_buf)) {
383 LOG_E("Malformed data found in AuthorizationSet deserialization", 0);
384 set_invalid(MALFORMED_DATA);
385 return false;
386 }
387 indirect_data_ = indirect_buf.release();
388 return true;
389 }
390
DeserializeElementsData(const uint8_t ** buf_ptr,const uint8_t * end)391 bool AuthorizationSet::DeserializeElementsData(const uint8_t** buf_ptr, const uint8_t* end) {
392 uint32_t elements_count;
393 uint32_t elements_size;
394 if (!copy_uint32_from_buf(buf_ptr, end, &elements_count) ||
395 !copy_uint32_from_buf(buf_ptr, end, &elements_size)) {
396 LOG_E("Malformed data found in AuthorizationSet deserialization", 0);
397 set_invalid(MALFORMED_DATA);
398 return false;
399 }
400
401 // Note that the following validation of elements_count is weak, but it prevents allocation of
402 // elems_ arrays which are clearly too large to be reasonable.
403 if (static_cast<ptrdiff_t>(elements_size) > end - *buf_ptr ||
404 elements_count * sizeof(uint32_t) > elements_size ||
405 *buf_ptr + (elements_count * sizeof(*elems_)) < *buf_ptr) {
406 LOG_E("Malformed data found in AuthorizationSet deserialization", 0);
407 set_invalid(MALFORMED_DATA);
408 return false;
409 }
410
411 if (!reserve_elems(elements_count))
412 return false;
413
414 uint8_t* indirect_end = indirect_data_ + indirect_data_size_;
415 const uint8_t* elements_end = *buf_ptr + elements_size;
416 for (size_t i = 0; i < elements_count; ++i) {
417 if (!deserialize(elems_ + i, buf_ptr, elements_end, indirect_data_, indirect_end)) {
418 LOG_E("Malformed data found in AuthorizationSet deserialization", 0);
419 set_invalid(MALFORMED_DATA);
420 return false;
421 }
422 }
423 elems_size_ = elements_count;
424 return true;
425 }
426
Deserialize(const uint8_t ** buf_ptr,const uint8_t * end)427 bool AuthorizationSet::Deserialize(const uint8_t** buf_ptr, const uint8_t* end) {
428 FreeData();
429
430 if (!DeserializeIndirectData(buf_ptr, end) || !DeserializeElementsData(buf_ptr, end))
431 return false;
432
433 if (indirect_data_size_ != ComputeIndirectDataSize(elems_, elems_size_)) {
434 LOG_E("Malformed data found in AuthorizationSet deserialization", 0);
435 set_invalid(MALFORMED_DATA);
436 return false;
437 }
438 return true;
439 }
440
Clear()441 void AuthorizationSet::Clear() {
442 memset_s(elems_, 0, elems_size_ * sizeof(keymaster_key_param_t));
443 memset_s(indirect_data_, 0, indirect_data_size_);
444 elems_size_ = 0;
445 indirect_data_size_ = 0;
446 }
447
FreeData()448 void AuthorizationSet::FreeData() {
449 Clear();
450
451 delete[] elems_;
452 delete[] indirect_data_;
453
454 elems_ = NULL;
455 indirect_data_ = NULL;
456 elems_capacity_ = 0;
457 indirect_data_capacity_ = 0;
458 error_ = OK;
459 }
460
461 /* static */
ComputeIndirectDataSize(const keymaster_key_param_t * elems,size_t count)462 size_t AuthorizationSet::ComputeIndirectDataSize(const keymaster_key_param_t* elems, size_t count) {
463 size_t size = 0;
464 for (size_t i = 0; i < count; ++i) {
465 if (is_blob_tag(elems[i].tag)) {
466 size += elems[i].blob.data_length;
467 }
468 }
469 return size;
470 }
471
CopyIndirectData()472 void AuthorizationSet::CopyIndirectData() {
473 memset_s(indirect_data_, 0, indirect_data_capacity_);
474
475 uint8_t* indirect_data_pos = indirect_data_;
476 for (size_t i = 0; i < elems_size_; ++i) {
477 assert(indirect_data_pos <= indirect_data_ + indirect_data_capacity_);
478 if (is_blob_tag(elems_[i].tag)) {
479 memcpy(indirect_data_pos, elems_[i].blob.data, elems_[i].blob.data_length);
480 elems_[i].blob.data = indirect_data_pos;
481 indirect_data_pos += elems_[i].blob.data_length;
482 }
483 }
484 assert(indirect_data_pos == indirect_data_ + indirect_data_capacity_);
485 indirect_data_size_ = indirect_data_pos - indirect_data_;
486 }
487
GetTagCount(keymaster_tag_t tag) const488 size_t AuthorizationSet::GetTagCount(keymaster_tag_t tag) const {
489 size_t count = 0;
490 for (int pos = -1; (pos = find(tag, pos)) != -1;)
491 ++count;
492 return count;
493 }
494
GetTagValueEnum(keymaster_tag_t tag,uint32_t * val) const495 bool AuthorizationSet::GetTagValueEnum(keymaster_tag_t tag, uint32_t* val) const {
496 int pos = find(tag);
497 if (pos == -1) {
498 return false;
499 }
500 *val = elems_[pos].enumerated;
501 return true;
502 }
503
GetTagValueEnumRep(keymaster_tag_t tag,size_t instance,uint32_t * val) const504 bool AuthorizationSet::GetTagValueEnumRep(keymaster_tag_t tag, size_t instance,
505 uint32_t* val) const {
506 size_t count = 0;
507 int pos = -1;
508 while (count <= instance) {
509 pos = find(tag, pos);
510 if (pos == -1) {
511 return false;
512 }
513 ++count;
514 }
515 *val = elems_[pos].enumerated;
516 return true;
517 }
518
GetTagValueInt(keymaster_tag_t tag,uint32_t * val) const519 bool AuthorizationSet::GetTagValueInt(keymaster_tag_t tag, uint32_t* val) const {
520 int pos = find(tag);
521 if (pos == -1) {
522 return false;
523 }
524 *val = elems_[pos].integer;
525 return true;
526 }
527
GetTagValueIntRep(keymaster_tag_t tag,size_t instance,uint32_t * val) const528 bool AuthorizationSet::GetTagValueIntRep(keymaster_tag_t tag, size_t instance,
529 uint32_t* val) const {
530 size_t count = 0;
531 int pos = -1;
532 while (count <= instance) {
533 pos = find(tag, pos);
534 if (pos == -1) {
535 return false;
536 }
537 ++count;
538 }
539 *val = elems_[pos].integer;
540 return true;
541 }
542
GetTagValueLong(keymaster_tag_t tag,uint64_t * val) const543 bool AuthorizationSet::GetTagValueLong(keymaster_tag_t tag, uint64_t* val) const {
544 int pos = find(tag);
545 if (pos == -1) {
546 return false;
547 }
548 *val = elems_[pos].long_integer;
549 return true;
550 }
551
GetTagValueLongRep(keymaster_tag_t tag,size_t instance,uint64_t * val) const552 bool AuthorizationSet::GetTagValueLongRep(keymaster_tag_t tag, size_t instance,
553 uint64_t* val) const {
554 size_t count = 0;
555 int pos = -1;
556 while (count <= instance) {
557 pos = find(tag, pos);
558 if (pos == -1) {
559 return false;
560 }
561 ++count;
562 }
563 *val = elems_[pos].long_integer;
564 return true;
565 }
566
GetTagValueDate(keymaster_tag_t tag,uint64_t * val) const567 bool AuthorizationSet::GetTagValueDate(keymaster_tag_t tag, uint64_t* val) const {
568 int pos = find(tag);
569 if (pos == -1) {
570 return false;
571 }
572 *val = elems_[pos].date_time;
573 return true;
574 }
575
GetTagValueBlob(keymaster_tag_t tag,keymaster_blob_t * val) const576 bool AuthorizationSet::GetTagValueBlob(keymaster_tag_t tag, keymaster_blob_t* val) const {
577 int pos = find(tag);
578 if (pos == -1) {
579 return false;
580 }
581 *val = elems_[pos].blob;
582 return true;
583 }
584
GetTagValueBool(keymaster_tag_t tag) const585 bool AuthorizationSet::GetTagValueBool(keymaster_tag_t tag) const {
586 int pos = find(tag);
587 if (pos == -1) {
588 return false;
589 }
590 assert(elems_[pos].boolean);
591 return elems_[pos].boolean;
592 }
593
ContainsEnumValue(keymaster_tag_t tag,uint32_t value) const594 bool AuthorizationSet::ContainsEnumValue(keymaster_tag_t tag, uint32_t value) const {
595 for (auto& entry : *this)
596 if (entry.tag == tag && entry.enumerated == value)
597 return true;
598 return false;
599 }
600
601 } // namespace keymaster
602