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 <stdlib.h> 18 #include <string.h> 19 #include <stddef.h> 20 21 #include <assert.h> 22 23 #include <keymaster/authorization_set.h> 24 #include <keymaster/google_keymaster_utils.h> 25 26 namespace keymaster { 27 28 static 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 32 const size_t STARTING_ELEMS_CAPACITY = 8; 33 34 AuthorizationSet::AuthorizationSet(const AuthorizationSet& set) 35 : Serializable(), elems_(NULL), indirect_data_(NULL) { 36 Reinitialize(set.elems_, set.elems_size_); 37 } 38 39 AuthorizationSet::~AuthorizationSet() { 40 FreeData(); 41 } 42 43 bool AuthorizationSet::reserve_elems(size_t count) { 44 if (is_valid() != OK) 45 return false; 46 47 if (count >= elems_capacity_) { 48 keymaster_key_param_t* new_elems = new keymaster_key_param_t[count]; 49 if (new_elems == NULL) { 50 set_invalid(ALLOCATION_FAILURE); 51 return false; 52 } 53 memcpy(new_elems, elems_, sizeof(*elems_) * elems_size_); 54 delete[] elems_; 55 elems_ = new_elems; 56 elems_capacity_ = count; 57 } 58 return true; 59 } 60 61 bool AuthorizationSet::reserve_indirect(size_t length) { 62 if (is_valid() != OK) 63 return false; 64 65 if (length > indirect_data_capacity_) { 66 uint8_t* new_data = new uint8_t[length]; 67 if (new_data == NULL) { 68 set_invalid(ALLOCATION_FAILURE); 69 return false; 70 } 71 memcpy(new_data, indirect_data_, indirect_data_size_); 72 73 // Fix up the data pointers to point into the new region. 74 for (size_t i = 0; i < elems_size_; ++i) { 75 if (is_blob_tag(elems_[i].tag)) 76 elems_[i].blob.data = new_data + (elems_[i].blob.data - indirect_data_); 77 } 78 delete[] indirect_data_; 79 indirect_data_ = new_data; 80 indirect_data_capacity_ = length; 81 } 82 return true; 83 } 84 85 bool AuthorizationSet::Reinitialize(const keymaster_key_param_t* elems, const size_t count) { 86 FreeData(); 87 88 if (!reserve_elems(count)) 89 return false; 90 91 if (!reserve_indirect(ComputeIndirectDataSize(elems, count))) 92 return false; 93 94 memcpy(elems_, elems, sizeof(keymaster_key_param_t) * count); 95 elems_size_ = count; 96 CopyIndirectData(); 97 error_ = OK; 98 return true; 99 } 100 101 void AuthorizationSet::set_invalid(Error error) { 102 FreeData(); 103 error_ = error; 104 } 105 106 int AuthorizationSet::find(keymaster_tag_t tag, int begin) const { 107 if (is_valid() != OK) 108 return -1; 109 110 int i = ++begin; 111 while (i < (int)elems_size_ && elems_[i].tag != tag) 112 ++i; 113 if (i == (int)elems_size_) 114 return -1; 115 else 116 return i; 117 } 118 119 keymaster_key_param_t empty; 120 keymaster_key_param_t AuthorizationSet::operator[](int at) const { 121 if (is_valid() == OK && at < (int)elems_size_) { 122 return elems_[at]; 123 } 124 memset(&empty, 0, sizeof(empty)); 125 return empty; 126 } 127 128 template <typename T> int comparator(const T& a, const T& b) { 129 if (a < b) 130 return -1; 131 else if (a > b) 132 return 1; 133 else 134 return 0; 135 } 136 137 static int param_comparator(const void* a, const void* b) { 138 const keymaster_key_param_t* lhs = static_cast<const keymaster_key_param_t*>(a); 139 const keymaster_key_param_t* rhs = static_cast<const keymaster_key_param_t*>(b); 140 141 if (lhs->tag < rhs->tag) 142 return -1; 143 else if (lhs->tag > rhs->tag) 144 return 1; 145 else 146 switch (keymaster_tag_get_type(lhs->tag)) { 147 default: 148 case KM_INVALID: 149 return 0; 150 case KM_ENUM: 151 case KM_ENUM_REP: 152 return comparator(lhs->enumerated, rhs->enumerated); 153 case KM_INT: 154 case KM_INT_REP: 155 return comparator(lhs->integer, rhs->integer); 156 case KM_LONG: 157 return comparator(lhs->long_integer, rhs->long_integer); 158 case KM_DATE: 159 return comparator(lhs->date_time, rhs->date_time); 160 case KM_BOOL: 161 return comparator(lhs->boolean, rhs->boolean); 162 case KM_BIGNUM: 163 case KM_BYTES: { 164 size_t min_len = lhs->blob.data_length; 165 if (rhs->blob.data_length < min_len) 166 min_len = rhs->blob.data_length; 167 168 if (lhs->blob.data_length == rhs->blob.data_length && min_len > 0) 169 return memcmp(lhs->blob.data, rhs->blob.data, min_len); 170 int cmp_result = memcmp(lhs->blob.data, rhs->blob.data, min_len); 171 if (cmp_result == 0) { 172 // The blobs are equal up to the length of the shortest (which may have length 0), 173 // so the shorter is less, the longer is greater and if they have the same length 174 // they're identical. 175 return comparator(lhs->blob.data_length, rhs->blob.data_length); 176 } 177 return cmp_result; 178 } break; 179 } 180 } 181 182 bool AuthorizationSet::push_back(const AuthorizationSet& set) { 183 if (is_valid() != OK) 184 return false; 185 186 if (!reserve_elems(elems_size_ + set.elems_size_)) 187 return false; 188 189 if (!reserve_indirect(indirect_data_size_ + set.indirect_data_size_)) 190 return false; 191 192 for (size_t i = 0; i < set.size(); ++i) 193 if (!push_back(set[i])) 194 return false; 195 196 return true; 197 } 198 199 bool AuthorizationSet::push_back(keymaster_key_param_t elem) { 200 if (is_valid() != OK) 201 return false; 202 203 if (elems_size_ >= elems_capacity_) 204 if (!reserve_elems(elems_capacity_ ? elems_capacity_ * 2 : STARTING_ELEMS_CAPACITY)) 205 return false; 206 207 if (is_blob_tag(elem.tag)) { 208 if (indirect_data_capacity_ - indirect_data_size_ < elem.blob.data_length) 209 if (!reserve_indirect(2 * (indirect_data_capacity_ + elem.blob.data_length))) 210 return false; 211 212 memcpy(indirect_data_ + indirect_data_size_, elem.blob.data, elem.blob.data_length); 213 elem.blob.data = indirect_data_ + indirect_data_size_; 214 indirect_data_size_ += elem.blob.data_length; 215 } 216 217 elems_[elems_size_++] = elem; 218 return true; 219 } 220 221 static size_t serialized_size(const keymaster_key_param_t& param) { 222 switch (keymaster_tag_get_type(param.tag)) { 223 case KM_INVALID: 224 default: 225 return sizeof(uint32_t); 226 case KM_ENUM: 227 case KM_ENUM_REP: 228 case KM_INT: 229 case KM_INT_REP: 230 return sizeof(uint32_t) * 2; 231 case KM_LONG: 232 case KM_DATE: 233 return sizeof(uint32_t) + sizeof(uint64_t); 234 case KM_BOOL: 235 return sizeof(uint32_t) + 1; 236 break; 237 case KM_BIGNUM: 238 case KM_BYTES: 239 return sizeof(uint32_t) * 3; 240 } 241 } 242 243 static uint8_t* serialize(const keymaster_key_param_t& param, uint8_t* buf, const uint8_t* end, 244 const uint8_t* indirect_base) { 245 buf = append_uint32_to_buf(buf, end, param.tag); 246 switch (keymaster_tag_get_type(param.tag)) { 247 case KM_INVALID: 248 break; 249 case KM_ENUM: 250 case KM_ENUM_REP: 251 buf = append_uint32_to_buf(buf, end, param.enumerated); 252 break; 253 case KM_INT: 254 case KM_INT_REP: 255 buf = append_uint32_to_buf(buf, end, param.integer); 256 break; 257 case KM_LONG: 258 buf = append_uint64_to_buf(buf, end, param.long_integer); 259 break; 260 case KM_DATE: 261 buf = append_uint64_to_buf(buf, end, param.date_time); 262 break; 263 case KM_BOOL: 264 if (buf < end) 265 *buf = static_cast<uint8_t>(param.boolean); 266 buf++; 267 break; 268 case KM_BIGNUM: 269 case KM_BYTES: 270 buf = append_uint32_to_buf(buf, end, param.blob.data_length); 271 buf = append_uint32_to_buf(buf, end, param.blob.data - indirect_base); 272 break; 273 } 274 return buf; 275 } 276 277 static bool deserialize(keymaster_key_param_t* param, const uint8_t** buf_ptr, const uint8_t* end, 278 const uint8_t* indirect_base, const uint8_t* indirect_end) { 279 if (!copy_uint32_from_buf(buf_ptr, end, ¶m->tag)) 280 return false; 281 282 switch (keymaster_tag_get_type(param->tag)) { 283 default: 284 case KM_INVALID: 285 return false; 286 case KM_ENUM: 287 case KM_ENUM_REP: 288 return copy_uint32_from_buf(buf_ptr, end, ¶m->enumerated); 289 case KM_INT: 290 case KM_INT_REP: 291 return copy_uint32_from_buf(buf_ptr, end, ¶m->integer); 292 case KM_LONG: 293 return copy_uint64_from_buf(buf_ptr, end, ¶m->long_integer); 294 case KM_DATE: 295 return copy_uint64_from_buf(buf_ptr, end, ¶m->date_time); 296 break; 297 case KM_BOOL: 298 if (*buf_ptr < end) { 299 param->boolean = static_cast<bool>(**buf_ptr); 300 (*buf_ptr)++; 301 return true; 302 } 303 return false; 304 305 case KM_BIGNUM: 306 case KM_BYTES: { 307 uint32_t offset; 308 if (!copy_uint32_from_buf(buf_ptr, end, ¶m->blob.data_length) || 309 !copy_uint32_from_buf(buf_ptr, end, &offset)) 310 return false; 311 if (static_cast<ptrdiff_t>(offset) > indirect_end - indirect_base || 312 static_cast<ptrdiff_t>(offset + param->blob.data_length) > indirect_end - indirect_base) 313 return false; 314 param->blob.data = indirect_base + offset; 315 return true; 316 } 317 } 318 } 319 320 size_t AuthorizationSet::SerializedSizeOfElements() const { 321 size_t size = 0; 322 for (size_t i = 0; i < elems_size_; ++i) { 323 size += serialized_size(elems_[i]); 324 } 325 return size; 326 } 327 328 size_t AuthorizationSet::SerializedSize() const { 329 return sizeof(uint32_t) + // Size of indirect_data_ 330 indirect_data_size_ + // indirect_data_ 331 sizeof(uint32_t) + // Number of elems_ 332 sizeof(uint32_t) + // Size of elems_ 333 SerializedSizeOfElements(); // elems_ 334 } 335 336 uint8_t* AuthorizationSet::Serialize(uint8_t* buf, const uint8_t* end) const { 337 buf = append_size_and_data_to_buf(buf, end, indirect_data_, indirect_data_size_); 338 buf = append_uint32_to_buf(buf, end, elems_size_); 339 buf = append_uint32_to_buf(buf, end, SerializedSizeOfElements()); 340 for (size_t i = 0; i < elems_size_; ++i) { 341 buf = serialize(elems_[i], buf, end, indirect_data_); 342 } 343 return buf; 344 } 345 346 bool AuthorizationSet::DeserializeIndirectData(const uint8_t** buf_ptr, const uint8_t* end) { 347 UniquePtr<uint8_t[]> indirect_buf; 348 if (!copy_size_and_data_from_buf(buf_ptr, end, &indirect_data_size_, &indirect_buf)) { 349 set_invalid(MALFORMED_DATA); 350 return false; 351 } 352 indirect_data_ = indirect_buf.release(); 353 return true; 354 } 355 356 bool AuthorizationSet::DeserializeElementsData(const uint8_t** buf_ptr, const uint8_t* end) { 357 uint32_t elements_count; 358 uint32_t elements_size; 359 if (!copy_uint32_from_buf(buf_ptr, end, &elements_count) || 360 !copy_uint32_from_buf(buf_ptr, end, &elements_size)) { 361 set_invalid(MALFORMED_DATA); 362 return false; 363 } 364 365 // Note that the following validation of elements_count is weak, but it prevents allocation of 366 // elems_ arrays which are clearly too large to be reasonable. 367 if (static_cast<ptrdiff_t>(elements_size) > end - *buf_ptr || 368 elements_count * sizeof(uint32_t) > elements_size) { 369 set_invalid(MALFORMED_DATA); 370 return false; 371 } 372 373 if (!reserve_elems(elements_count)) 374 return false; 375 376 uint8_t* indirect_end = indirect_data_ + indirect_data_size_; 377 const uint8_t* elements_end = *buf_ptr + elements_size; 378 for (size_t i = 0; i < elements_count; ++i) { 379 if (!deserialize(elems_ + i, buf_ptr, elements_end, indirect_data_, indirect_end)) { 380 set_invalid(MALFORMED_DATA); 381 return false; 382 } 383 } 384 elems_size_ = elements_count; 385 return true; 386 } 387 388 bool AuthorizationSet::Deserialize(const uint8_t** buf_ptr, const uint8_t* end) { 389 FreeData(); 390 391 if (!DeserializeIndirectData(buf_ptr, end) || !DeserializeElementsData(buf_ptr, end)) 392 return false; 393 394 if (indirect_data_size_ != ComputeIndirectDataSize(elems_, elems_size_)) { 395 set_invalid(MALFORMED_DATA); 396 return false; 397 } 398 return true; 399 } 400 401 void AuthorizationSet::FreeData() { 402 if (elems_ != NULL) 403 memset_s(elems_, 0, elems_size_ * sizeof(keymaster_key_param_t)); 404 if (indirect_data_ != NULL) 405 memset_s(indirect_data_, 0, indirect_data_size_); 406 407 delete[] elems_; 408 delete[] indirect_data_; 409 410 elems_ = NULL; 411 indirect_data_ = NULL; 412 elems_size_ = 0; 413 elems_capacity_ = 0; 414 indirect_data_size_ = 0; 415 indirect_data_capacity_ = 0; 416 error_ = OK; 417 } 418 419 /* static */ 420 size_t AuthorizationSet::ComputeIndirectDataSize(const keymaster_key_param_t* elems, size_t count) { 421 size_t size = 0; 422 for (size_t i = 0; i < count; ++i) { 423 if (is_blob_tag(elems[i].tag)) { 424 size += elems[i].blob.data_length; 425 } 426 } 427 return size; 428 } 429 430 void AuthorizationSet::CopyIndirectData() { 431 memset_s(indirect_data_, 0, indirect_data_capacity_); 432 433 uint8_t* indirect_data_pos = indirect_data_; 434 for (size_t i = 0; i < elems_size_; ++i) { 435 assert(indirect_data_pos <= indirect_data_ + indirect_data_capacity_); 436 if (is_blob_tag(elems_[i].tag)) { 437 memcpy(indirect_data_pos, elems_[i].blob.data, elems_[i].blob.data_length); 438 elems_[i].blob.data = indirect_data_pos; 439 indirect_data_pos += elems_[i].blob.data_length; 440 } 441 } 442 assert(indirect_data_pos == indirect_data_ + indirect_data_capacity_); 443 indirect_data_size_ = indirect_data_pos - indirect_data_; 444 } 445 446 bool AuthorizationSet::GetTagValueEnum(keymaster_tag_t tag, uint32_t* val) const { 447 int pos = find(tag); 448 if (pos == -1) { 449 return false; 450 } 451 *val = elems_[pos].enumerated; 452 return true; 453 } 454 455 bool AuthorizationSet::GetTagValueEnumRep(keymaster_tag_t tag, size_t instance, 456 uint32_t* val) const { 457 size_t count = 0; 458 int pos = -1; 459 while (count <= instance) { 460 pos = find(tag, pos); 461 if (pos == -1) { 462 return false; 463 } 464 ++count; 465 } 466 *val = elems_[pos].enumerated; 467 return true; 468 } 469 470 bool AuthorizationSet::GetTagValueInt(keymaster_tag_t tag, uint32_t* val) const { 471 int pos = find(tag); 472 if (pos == -1) { 473 return false; 474 } 475 *val = elems_[pos].integer; 476 return true; 477 } 478 479 bool AuthorizationSet::GetTagValueIntRep(keymaster_tag_t tag, size_t instance, 480 uint32_t* val) const { 481 size_t count = 0; 482 int pos = -1; 483 while (count <= instance) { 484 pos = find(tag, pos); 485 if (pos == -1) { 486 return false; 487 } 488 ++count; 489 } 490 *val = elems_[pos].integer; 491 return true; 492 } 493 494 bool AuthorizationSet::GetTagValueLong(keymaster_tag_t tag, uint64_t* val) const { 495 int pos = find(tag); 496 if (pos == -1) { 497 return false; 498 } 499 *val = elems_[pos].long_integer; 500 return true; 501 } 502 503 bool AuthorizationSet::GetTagValueDate(keymaster_tag_t tag, uint64_t* val) const { 504 int pos = find(tag); 505 if (pos == -1) { 506 return false; 507 } 508 *val = elems_[pos].date_time; 509 return true; 510 } 511 512 bool AuthorizationSet::GetTagValueBlob(keymaster_tag_t tag, keymaster_blob_t* val) const { 513 int pos = find(tag); 514 if (pos == -1) { 515 return false; 516 } 517 *val = elems_[pos].blob; 518 return true; 519 } 520 521 } // namespace keymaster 522