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