1 /* 2 * Copyright 2017 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 <keymasterV4_0/authorization_set.h> 18 19 #include <assert.h> 20 21 #include <android-base/logging.h> 22 23 namespace android { 24 namespace hardware { 25 namespace keymaster { 26 namespace V4_0 { 27 28 inline bool keyParamLess(const KeyParameter& a, const KeyParameter& b) { 29 if (a.tag != b.tag) return a.tag < b.tag; 30 int retval; 31 switch (typeFromTag(a.tag)) { 32 case TagType::INVALID: 33 case TagType::BOOL: 34 return false; 35 case TagType::ENUM: 36 case TagType::ENUM_REP: 37 case TagType::UINT: 38 case TagType::UINT_REP: 39 return a.f.integer < b.f.integer; 40 case TagType::ULONG: 41 case TagType::ULONG_REP: 42 return a.f.longInteger < b.f.longInteger; 43 case TagType::DATE: 44 return a.f.dateTime < b.f.dateTime; 45 case TagType::BIGNUM: 46 case TagType::BYTES: 47 // Handle the empty cases. 48 if (a.blob.size() == 0) return b.blob.size() != 0; 49 if (b.blob.size() == 0) return false; 50 51 retval = memcmp(&a.blob[0], &b.blob[0], std::min(a.blob.size(), b.blob.size())); 52 // if one is the prefix of the other the longer wins 53 if (retval == 0) return a.blob.size() < b.blob.size(); 54 // Otherwise a is less if a is less. 55 else 56 return retval < 0; 57 } 58 return false; 59 } 60 61 inline bool keyParamEqual(const KeyParameter& a, const KeyParameter& b) { 62 if (a.tag != b.tag) return false; 63 64 switch (typeFromTag(a.tag)) { 65 case TagType::INVALID: 66 case TagType::BOOL: 67 return true; 68 case TagType::ENUM: 69 case TagType::ENUM_REP: 70 case TagType::UINT: 71 case TagType::UINT_REP: 72 return a.f.integer == b.f.integer; 73 case TagType::ULONG: 74 case TagType::ULONG_REP: 75 return a.f.longInteger == b.f.longInteger; 76 case TagType::DATE: 77 return a.f.dateTime == b.f.dateTime; 78 case TagType::BIGNUM: 79 case TagType::BYTES: 80 if (a.blob.size() != b.blob.size()) return false; 81 return a.blob.size() == 0 || memcmp(&a.blob[0], &b.blob[0], a.blob.size()) == 0; 82 } 83 return false; 84 } 85 86 void AuthorizationSet::Sort() { 87 std::sort(data_.begin(), data_.end(), keyParamLess); 88 } 89 90 void AuthorizationSet::Deduplicate() { 91 if (data_.empty()) return; 92 93 Sort(); 94 std::vector<KeyParameter> result; 95 96 auto curr = data_.begin(); 97 auto prev = curr++; 98 for (; curr != data_.end(); ++prev, ++curr) { 99 if (prev->tag == Tag::INVALID) continue; 100 101 if (!keyParamEqual(*prev, *curr)) { 102 result.push_back(std::move(*prev)); 103 } 104 } 105 result.push_back(std::move(*prev)); 106 107 std::swap(data_, result); 108 } 109 110 void AuthorizationSet::Union(const AuthorizationSet& other) { 111 data_.insert(data_.end(), other.data_.begin(), other.data_.end()); 112 Deduplicate(); 113 } 114 115 void AuthorizationSet::Subtract(const AuthorizationSet& other) { 116 Deduplicate(); 117 118 auto i = other.begin(); 119 while (i != other.end()) { 120 int pos = -1; 121 do { 122 pos = find(i->tag, pos); 123 if (pos != -1 && keyParamEqual(*i, data_[pos])) { 124 data_.erase(data_.begin() + pos); 125 break; 126 } 127 } while (pos != -1); 128 ++i; 129 } 130 } 131 132 void AuthorizationSet::Filter(std::function<bool(const KeyParameter&)> doKeep) { 133 std::vector<KeyParameter> result; 134 for (auto& param : data_) { 135 if (doKeep(param)) { 136 result.push_back(std::move(param)); 137 } 138 } 139 std::swap(data_, result); 140 } 141 142 KeyParameter& AuthorizationSet::operator[](int at) { 143 return data_[at]; 144 } 145 146 const KeyParameter& AuthorizationSet::operator[](int at) const { 147 return data_[at]; 148 } 149 150 void AuthorizationSet::Clear() { 151 data_.clear(); 152 } 153 154 size_t AuthorizationSet::GetTagCount(Tag tag) const { 155 size_t count = 0; 156 for (int pos = -1; (pos = find(tag, pos)) != -1;) ++count; 157 return count; 158 } 159 160 int AuthorizationSet::find(Tag tag, int begin) const { 161 auto iter = data_.begin() + (1 + begin); 162 163 while (iter != data_.end() && iter->tag != tag) ++iter; 164 165 if (iter != data_.end()) return iter - data_.begin(); 166 return -1; 167 } 168 169 bool AuthorizationSet::erase(int index) { 170 auto pos = data_.begin() + index; 171 if (pos != data_.end()) { 172 data_.erase(pos); 173 return true; 174 } 175 return false; 176 } 177 178 NullOr<const KeyParameter&> AuthorizationSet::GetEntry(Tag tag) const { 179 int pos = find(tag); 180 if (pos == -1) return {}; 181 return data_[pos]; 182 } 183 184 /** 185 * Persistent format is: 186 * | 32 bit indirect_size | 187 * -------------------------------- 188 * | indirect_size bytes of data | this is where the blob data is stored 189 * -------------------------------- 190 * | 32 bit element_count | number of entries 191 * | 32 bit elements_size | total bytes used by entries (entries have variable length) 192 * -------------------------------- 193 * | elementes_size bytes of data | where the elements are stored 194 */ 195 196 /** 197 * Persistent format of blobs and bignums: 198 * | 32 bit tag | 199 * | 32 bit blob_length | 200 * | 32 bit indirect_offset | 201 */ 202 203 struct OutStreams { 204 std::ostream& indirect; 205 std::ostream& elements; 206 size_t skipped; 207 }; 208 209 OutStreams& serializeParamValue(OutStreams& out, const hidl_vec<uint8_t>& blob) { 210 uint32_t buffer; 211 212 // write blob_length 213 auto blob_length = blob.size(); 214 if (blob_length > std::numeric_limits<uint32_t>::max()) { 215 out.elements.setstate(std::ios_base::badbit); 216 return out; 217 } 218 buffer = blob_length; 219 out.elements.write(reinterpret_cast<const char*>(&buffer), sizeof(uint32_t)); 220 221 // write indirect_offset 222 auto offset = out.indirect.tellp(); 223 if (offset < 0 || offset > std::numeric_limits<uint32_t>::max() || 224 uint32_t(offset) + uint32_t(blob_length) < uint32_t(offset)) { // overflow check 225 out.elements.setstate(std::ios_base::badbit); 226 return out; 227 } 228 buffer = offset; 229 out.elements.write(reinterpret_cast<const char*>(&buffer), sizeof(uint32_t)); 230 231 // write blob to indirect stream 232 if (blob_length) out.indirect.write(reinterpret_cast<const char*>(&blob[0]), blob_length); 233 234 return out; 235 } 236 237 template <typename T> 238 OutStreams& serializeParamValue(OutStreams& out, const T& value) { 239 out.elements.write(reinterpret_cast<const char*>(&value), sizeof(T)); 240 return out; 241 } 242 243 OutStreams& serialize(TAG_INVALID_t&&, OutStreams& out, const KeyParameter&) { 244 // skip invalid entries. 245 ++out.skipped; 246 return out; 247 } 248 template <typename T> 249 OutStreams& serialize(T ttag, OutStreams& out, const KeyParameter& param) { 250 out.elements.write(reinterpret_cast<const char*>(¶m.tag), sizeof(int32_t)); 251 return serializeParamValue(out, accessTagValue(ttag, param)); 252 } 253 254 template <typename... T> 255 struct choose_serializer; 256 template <typename... Tags> 257 struct choose_serializer<MetaList<Tags...>> { 258 static OutStreams& serialize(OutStreams& out, const KeyParameter& param) { 259 return choose_serializer<Tags...>::serialize(out, param); 260 } 261 }; 262 263 template <> 264 struct choose_serializer<> { 265 static OutStreams& serialize(OutStreams& out, const KeyParameter& param) { 266 LOG(WARNING) << "Trying to serialize unknown tag " << unsigned(param.tag) 267 << ". Did you forget to add it to all_tags_t?"; 268 ++out.skipped; 269 return out; 270 } 271 }; 272 273 template <TagType tag_type, Tag tag, typename... Tail> 274 struct choose_serializer<TypedTag<tag_type, tag>, Tail...> { 275 static OutStreams& serialize(OutStreams& out, const KeyParameter& param) { 276 if (param.tag == tag) { 277 return V4_0::serialize(TypedTag<tag_type, tag>(), out, param); 278 } else { 279 return choose_serializer<Tail...>::serialize(out, param); 280 } 281 } 282 }; 283 284 OutStreams& serialize(OutStreams& out, const KeyParameter& param) { 285 return choose_serializer<all_tags_t>::serialize(out, param); 286 } 287 288 std::ostream& serialize(std::ostream& out, const std::vector<KeyParameter>& params) { 289 std::stringstream indirect; 290 std::stringstream elements; 291 OutStreams streams = {indirect, elements, 0}; 292 for (const auto& param : params) { 293 serialize(streams, param); 294 } 295 if (indirect.bad() || elements.bad()) { 296 out.setstate(std::ios_base::badbit); 297 return out; 298 } 299 auto pos = indirect.tellp(); 300 if (pos < 0 || pos > std::numeric_limits<uint32_t>::max()) { 301 out.setstate(std::ios_base::badbit); 302 return out; 303 } 304 uint32_t indirect_size = pos; 305 pos = elements.tellp(); 306 if (pos < 0 || pos > std::numeric_limits<uint32_t>::max()) { 307 out.setstate(std::ios_base::badbit); 308 return out; 309 } 310 uint32_t elements_size = pos; 311 uint32_t element_count = params.size() - streams.skipped; 312 313 out.write(reinterpret_cast<const char*>(&indirect_size), sizeof(uint32_t)); 314 315 pos = out.tellp(); 316 if (indirect_size) out << indirect.rdbuf(); 317 assert(out.tellp() - pos == indirect_size); 318 319 out.write(reinterpret_cast<const char*>(&element_count), sizeof(uint32_t)); 320 out.write(reinterpret_cast<const char*>(&elements_size), sizeof(uint32_t)); 321 322 pos = out.tellp(); 323 if (elements_size) out << elements.rdbuf(); 324 assert(out.tellp() - pos == elements_size); 325 326 return out; 327 } 328 329 struct InStreams { 330 std::istream& indirect; 331 std::istream& elements; 332 size_t invalids; 333 }; 334 335 InStreams& deserializeParamValue(InStreams& in, hidl_vec<uint8_t>* blob) { 336 uint32_t blob_length = 0; 337 uint32_t offset = 0; 338 in.elements.read(reinterpret_cast<char*>(&blob_length), sizeof(uint32_t)); 339 blob->resize(blob_length); 340 in.elements.read(reinterpret_cast<char*>(&offset), sizeof(uint32_t)); 341 in.indirect.seekg(offset); 342 in.indirect.read(reinterpret_cast<char*>(&(*blob)[0]), blob->size()); 343 return in; 344 } 345 346 template <typename T> 347 InStreams& deserializeParamValue(InStreams& in, T* value) { 348 in.elements.read(reinterpret_cast<char*>(value), sizeof(T)); 349 return in; 350 } 351 352 InStreams& deserialize(TAG_INVALID_t&&, InStreams& in, KeyParameter*) { 353 // there should be no invalid KeyParamaters but if handle them as zero sized. 354 ++in.invalids; 355 return in; 356 } 357 358 template <typename T> 359 InStreams& deserialize(T&& ttag, InStreams& in, KeyParameter* param) { 360 return deserializeParamValue(in, &accessTagValue(ttag, *param)); 361 } 362 363 template <typename... T> 364 struct choose_deserializer; 365 template <typename... Tags> 366 struct choose_deserializer<MetaList<Tags...>> { 367 static InStreams& deserialize(InStreams& in, KeyParameter* param) { 368 return choose_deserializer<Tags...>::deserialize(in, param); 369 } 370 }; 371 template <> 372 struct choose_deserializer<> { 373 static InStreams& deserialize(InStreams& in, KeyParameter*) { 374 // encountered an unknown tag -> fail parsing 375 in.elements.setstate(std::ios_base::badbit); 376 return in; 377 } 378 }; 379 template <TagType tag_type, Tag tag, typename... Tail> 380 struct choose_deserializer<TypedTag<tag_type, tag>, Tail...> { 381 static InStreams& deserialize(InStreams& in, KeyParameter* param) { 382 if (param->tag == tag) { 383 return V4_0::deserialize(TypedTag<tag_type, tag>(), in, param); 384 } else { 385 return choose_deserializer<Tail...>::deserialize(in, param); 386 } 387 } 388 }; 389 390 InStreams& deserialize(InStreams& in, KeyParameter* param) { 391 in.elements.read(reinterpret_cast<char*>(¶m->tag), sizeof(Tag)); 392 return choose_deserializer<all_tags_t>::deserialize(in, param); 393 } 394 395 std::istream& deserialize(std::istream& in, std::vector<KeyParameter>* params) { 396 uint32_t indirect_size = 0; 397 in.read(reinterpret_cast<char*>(&indirect_size), sizeof(uint32_t)); 398 std::string indirect_buffer(indirect_size, '\0'); 399 if (indirect_buffer.size() != indirect_size) { 400 in.setstate(std::ios_base::badbit); 401 return in; 402 } 403 in.read(&indirect_buffer[0], indirect_buffer.size()); 404 405 uint32_t element_count = 0; 406 in.read(reinterpret_cast<char*>(&element_count), sizeof(uint32_t)); 407 uint32_t elements_size = 0; 408 in.read(reinterpret_cast<char*>(&elements_size), sizeof(uint32_t)); 409 410 std::string elements_buffer(elements_size, '\0'); 411 if (elements_buffer.size() != elements_size) { 412 in.setstate(std::ios_base::badbit); 413 return in; 414 } 415 in.read(&elements_buffer[0], elements_buffer.size()); 416 417 if (in.bad()) return in; 418 419 // TODO write one-shot stream buffer to avoid copying here 420 std::stringstream indirect(indirect_buffer); 421 std::stringstream elements(elements_buffer); 422 InStreams streams = {indirect, elements, 0}; 423 424 params->resize(element_count); 425 426 for (uint32_t i = 0; i < element_count; ++i) { 427 deserialize(streams, &(*params)[i]); 428 } 429 430 /* 431 * There are legacy blobs which have invalid tags in them due to a bug during serialization. 432 * This makes sure that invalid tags are filtered from the result before it is returned. 433 */ 434 if (streams.invalids > 0) { 435 std::vector<KeyParameter> filtered(element_count - streams.invalids); 436 auto ifiltered = filtered.begin(); 437 for (auto& p : *params) { 438 if (p.tag != Tag::INVALID) { 439 *ifiltered++ = std::move(p); 440 } 441 } 442 *params = std::move(filtered); 443 } 444 return in; 445 } 446 447 void AuthorizationSet::Serialize(std::ostream* out) const { 448 serialize(*out, data_); 449 } 450 451 void AuthorizationSet::Deserialize(std::istream* in) { 452 deserialize(*in, &data_); 453 } 454 455 AuthorizationSetBuilder& AuthorizationSetBuilder::RsaKey(uint32_t key_size, 456 uint64_t public_exponent) { 457 Authorization(TAG_ALGORITHM, Algorithm::RSA); 458 Authorization(TAG_KEY_SIZE, key_size); 459 Authorization(TAG_RSA_PUBLIC_EXPONENT, public_exponent); 460 return *this; 461 } 462 463 AuthorizationSetBuilder& AuthorizationSetBuilder::EcdsaKey(uint32_t key_size) { 464 Authorization(TAG_ALGORITHM, Algorithm::EC); 465 Authorization(TAG_KEY_SIZE, key_size); 466 return *this; 467 } 468 469 AuthorizationSetBuilder& AuthorizationSetBuilder::EcdsaKey(EcCurve curve) { 470 Authorization(TAG_ALGORITHM, Algorithm::EC); 471 Authorization(TAG_EC_CURVE, curve); 472 return *this; 473 } 474 475 AuthorizationSetBuilder& AuthorizationSetBuilder::AesKey(uint32_t key_size) { 476 Authorization(TAG_ALGORITHM, Algorithm::AES); 477 return Authorization(TAG_KEY_SIZE, key_size); 478 } 479 480 AuthorizationSetBuilder& AuthorizationSetBuilder::TripleDesKey(uint32_t key_size) { 481 Authorization(TAG_ALGORITHM, Algorithm::TRIPLE_DES); 482 return Authorization(TAG_KEY_SIZE, key_size); 483 } 484 485 AuthorizationSetBuilder& AuthorizationSetBuilder::HmacKey(uint32_t key_size) { 486 Authorization(TAG_ALGORITHM, Algorithm::HMAC); 487 Authorization(TAG_KEY_SIZE, key_size); 488 return SigningKey(); 489 } 490 491 AuthorizationSetBuilder& AuthorizationSetBuilder::RsaSigningKey(uint32_t key_size, 492 uint64_t public_exponent) { 493 RsaKey(key_size, public_exponent); 494 return SigningKey(); 495 } 496 497 AuthorizationSetBuilder& AuthorizationSetBuilder::RsaEncryptionKey(uint32_t key_size, 498 uint64_t public_exponent) { 499 RsaKey(key_size, public_exponent); 500 return EncryptionKey(); 501 } 502 503 AuthorizationSetBuilder& AuthorizationSetBuilder::EcdsaSigningKey(uint32_t key_size) { 504 EcdsaKey(key_size); 505 return SigningKey(); 506 } 507 508 AuthorizationSetBuilder& AuthorizationSetBuilder::EcdsaSigningKey(EcCurve curve) { 509 EcdsaKey(curve); 510 return SigningKey(); 511 } 512 513 AuthorizationSetBuilder& AuthorizationSetBuilder::AesEncryptionKey(uint32_t key_size) { 514 AesKey(key_size); 515 return EncryptionKey(); 516 } 517 518 AuthorizationSetBuilder& AuthorizationSetBuilder::TripleDesEncryptionKey(uint32_t key_size) { 519 TripleDesKey(key_size); 520 return EncryptionKey(); 521 } 522 523 AuthorizationSetBuilder& AuthorizationSetBuilder::SigningKey() { 524 Authorization(TAG_PURPOSE, KeyPurpose::SIGN); 525 return Authorization(TAG_PURPOSE, KeyPurpose::VERIFY); 526 } 527 528 AuthorizationSetBuilder& AuthorizationSetBuilder::EncryptionKey() { 529 Authorization(TAG_PURPOSE, KeyPurpose::ENCRYPT); 530 return Authorization(TAG_PURPOSE, KeyPurpose::DECRYPT); 531 } 532 533 AuthorizationSetBuilder& AuthorizationSetBuilder::NoDigestOrPadding() { 534 Authorization(TAG_DIGEST, Digest::NONE); 535 return Authorization(TAG_PADDING, PaddingMode::NONE); 536 } 537 538 AuthorizationSetBuilder& AuthorizationSetBuilder::EcbMode() { 539 return Authorization(TAG_BLOCK_MODE, BlockMode::ECB); 540 } 541 542 AuthorizationSetBuilder& AuthorizationSetBuilder::GcmModeMinMacLen(uint32_t minMacLength) { 543 return BlockMode(BlockMode::GCM) 544 .Padding(PaddingMode::NONE) 545 .Authorization(TAG_MIN_MAC_LENGTH, minMacLength); 546 } 547 548 AuthorizationSetBuilder& AuthorizationSetBuilder::GcmModeMacLen(uint32_t macLength) { 549 return BlockMode(BlockMode::GCM) 550 .Padding(PaddingMode::NONE) 551 .Authorization(TAG_MAC_LENGTH, macLength); 552 } 553 554 AuthorizationSetBuilder& AuthorizationSetBuilder::BlockMode( 555 std::initializer_list<V4_0::BlockMode> blockModes) { 556 for (auto mode : blockModes) { 557 push_back(TAG_BLOCK_MODE, mode); 558 } 559 return *this; 560 } 561 562 AuthorizationSetBuilder& AuthorizationSetBuilder::Digest(std::vector<V4_0::Digest> digests) { 563 for (auto digest : digests) { 564 push_back(TAG_DIGEST, digest); 565 } 566 return *this; 567 } 568 569 AuthorizationSetBuilder& AuthorizationSetBuilder::Padding( 570 std::initializer_list<V4_0::PaddingMode> paddingModes) { 571 for (auto paddingMode : paddingModes) { 572 push_back(TAG_PADDING, paddingMode); 573 } 574 return *this; 575 } 576 577 } // namespace V4_0 578 } // namespace keymaster 579 } // namespace hardware 580 } // namespace android 581