diff options
Diffstat (limited to 'security/keymint/support/authorization_set.cpp')
-rw-r--r-- | security/keymint/support/authorization_set.cpp | 526 |
1 files changed, 0 insertions, 526 deletions
diff --git a/security/keymint/support/authorization_set.cpp b/security/keymint/support/authorization_set.cpp deleted file mode 100644 index aa9638f256..0000000000 --- a/security/keymint/support/authorization_set.cpp +++ /dev/null @@ -1,526 +0,0 @@ -/* - * Copyright 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <keymint_support/authorization_set.h> - -#include <assert.h> -#include <sstream> - -#include <android-base/logging.h> - -#include <android/hardware/security/keymint/Algorithm.h> -#include <android/hardware/security/keymint/BlockMode.h> -#include <android/hardware/security/keymint/Digest.h> -#include <android/hardware/security/keymint/KeyParameter.h> -#include <android/hardware/security/keymint/KeyPurpose.h> -#include <android/hardware/security/keymint/TagType.h> - -namespace android::hardware::security::keymint { - -void AuthorizationSet::Sort() { - std::sort(data_.begin(), data_.end()); -} - -void AuthorizationSet::Deduplicate() { - if (data_.empty()) return; - - Sort(); - std::vector<KeyParameter> result; - - auto curr = data_.begin(); - auto prev = curr++; - for (; curr != data_.end(); ++prev, ++curr) { - if (prev->tag == Tag::INVALID) continue; - - if (*prev != *curr) { - result.push_back(std::move(*prev)); - } - } - result.push_back(std::move(*prev)); - - std::swap(data_, result); -} - -void AuthorizationSet::Union(const AuthorizationSet& other) { - data_.insert(data_.end(), other.data_.begin(), other.data_.end()); - Deduplicate(); -} - -void AuthorizationSet::Subtract(const AuthorizationSet& other) { - Deduplicate(); - - auto i = other.begin(); - while (i != other.end()) { - int pos = -1; - do { - pos = find(i->tag, pos); - if (pos != -1 && (*i == data_[pos])) { - data_.erase(data_.begin() + pos); - break; - } - } while (pos != -1); - ++i; - } -} - -void AuthorizationSet::Filter(std::function<bool(const KeyParameter&)> doKeep) { - std::vector<KeyParameter> result; - for (auto& param : data_) { - if (doKeep(param)) { - result.push_back(std::move(param)); - } - } - std::swap(data_, result); -} - -KeyParameter& AuthorizationSet::operator[](int at) { - return data_[at]; -} - -const KeyParameter& AuthorizationSet::operator[](int at) const { - return data_[at]; -} - -void AuthorizationSet::Clear() { - data_.clear(); -} - -size_t AuthorizationSet::GetTagCount(Tag tag) const { - size_t count = 0; - for (int pos = -1; (pos = find(tag, pos)) != -1;) ++count; - return count; -} - -int AuthorizationSet::find(Tag tag, int begin) const { - auto iter = data_.begin() + (1 + begin); - - while (iter != data_.end() && iter->tag != tag) ++iter; - - if (iter != data_.end()) return iter - data_.begin(); - return -1; -} - -bool AuthorizationSet::erase(int index) { - auto pos = data_.begin() + index; - if (pos != data_.end()) { - data_.erase(pos); - return true; - } - return false; -} - -NullOr<const KeyParameter&> AuthorizationSet::GetEntry(Tag tag) const { - int pos = find(tag); - if (pos == -1) return {}; - return data_[pos]; -} - -/** - * Persistent format is: - * | 32 bit indirect_size | - * -------------------------------- - * | indirect_size bytes of data | this is where the blob data is stored - * -------------------------------- - * | 32 bit element_count | number of entries - * | 32 bit elements_size | total bytes used by entries (entries have variable length) - * -------------------------------- - * | elementes_size bytes of data | where the elements are stored - */ - -/** - * Persistent format of blobs and bignums: - * | 32 bit tag | - * | 32 bit blob_length | - * | 32 bit indirect_offset | - */ - -struct OutStreams { - std::ostream& indirect; - std::ostream& elements; - size_t skipped; -}; - -OutStreams& serializeParamValue(OutStreams& out, const vector<uint8_t>& blob) { - uint32_t buffer; - - // write blob_length - auto blob_length = blob.size(); - if (blob_length > std::numeric_limits<uint32_t>::max()) { - out.elements.setstate(std::ios_base::badbit); - return out; - } - buffer = blob_length; - out.elements.write(reinterpret_cast<const char*>(&buffer), sizeof(uint32_t)); - - // write indirect_offset - auto offset = out.indirect.tellp(); - if (offset < 0 || offset > std::numeric_limits<uint32_t>::max() || - uint32_t(offset) + uint32_t(blob_length) < uint32_t(offset)) { // overflow check - out.elements.setstate(std::ios_base::badbit); - return out; - } - buffer = offset; - out.elements.write(reinterpret_cast<const char*>(&buffer), sizeof(uint32_t)); - - // write blob to indirect stream - if (blob_length) out.indirect.write(reinterpret_cast<const char*>(&blob[0]), blob_length); - - return out; -} - -template <typename T> -OutStreams& serializeParamValue(OutStreams& out, const T& value) { - out.elements.write(reinterpret_cast<const char*>(&value), sizeof(T)); - return out; -} - -OutStreams& serialize(TAG_INVALID_t&&, OutStreams& out, const KeyParameter&) { - // skip invalid entries. - ++out.skipped; - return out; -} -template <typename T> -OutStreams& serialize(T ttag, OutStreams& out, const KeyParameter& param) { - out.elements.write(reinterpret_cast<const char*>(¶m.tag), sizeof(int32_t)); - return serializeParamValue(out, accessTagValue(ttag, param)); -} - -template <typename... T> -struct choose_serializer; -template <typename... Tags> -struct choose_serializer<MetaList<Tags...>> { - static OutStreams& serialize(OutStreams& out, const KeyParameter& param) { - return choose_serializer<Tags...>::serialize(out, param); - } -}; - -template <> -struct choose_serializer<> { - static OutStreams& serialize(OutStreams& out, const KeyParameter& param) { - LOG(WARNING) << "Trying to serialize unknown tag " << unsigned(param.tag) - << ". Did you forget to add it to all_tags_t?"; - ++out.skipped; - return out; - } -}; - -template <TagType tag_type, Tag tag, typename... Tail> -struct choose_serializer<android::hardware::security::keymint::TypedTag<tag_type, tag>, Tail...> { - static OutStreams& serialize(OutStreams& out, const KeyParameter& param) { - if (param.tag == tag) { - return android::hardware::security::keymint::serialize(TypedTag<tag_type, tag>(), out, - param); - } else { - return choose_serializer<Tail...>::serialize(out, param); - } - } -}; - -OutStreams& serialize(OutStreams& out, const KeyParameter& param) { - return choose_serializer<all_tags_t>::serialize(out, param); -} - -std::ostream& serialize(std::ostream& out, const std::vector<KeyParameter>& params) { - std::stringstream indirect; - std::stringstream elements; - OutStreams streams = {indirect, elements, 0}; - for (const auto& param : params) { - serialize(streams, param); - } - if (indirect.bad() || elements.bad()) { - out.setstate(std::ios_base::badbit); - return out; - } - auto pos = indirect.tellp(); - if (pos < 0 || pos > std::numeric_limits<uint32_t>::max()) { - out.setstate(std::ios_base::badbit); - return out; - } - uint32_t indirect_size = pos; - pos = elements.tellp(); - if (pos < 0 || pos > std::numeric_limits<uint32_t>::max()) { - out.setstate(std::ios_base::badbit); - return out; - } - uint32_t elements_size = pos; - uint32_t element_count = params.size() - streams.skipped; - - out.write(reinterpret_cast<const char*>(&indirect_size), sizeof(uint32_t)); - - pos = out.tellp(); - if (indirect_size) out << indirect.rdbuf(); - assert(out.tellp() - pos == indirect_size); - - out.write(reinterpret_cast<const char*>(&element_count), sizeof(uint32_t)); - out.write(reinterpret_cast<const char*>(&elements_size), sizeof(uint32_t)); - - pos = out.tellp(); - if (elements_size) out << elements.rdbuf(); - assert(out.tellp() - pos == elements_size); - - return out; -} - -struct InStreams { - std::istream& indirect; - std::istream& elements; - size_t invalids; -}; - -InStreams& deserializeParamValue(InStreams& in, vector<uint8_t>* blob) { - uint32_t blob_length = 0; - uint32_t offset = 0; - in.elements.read(reinterpret_cast<char*>(&blob_length), sizeof(uint32_t)); - blob->resize(blob_length); - in.elements.read(reinterpret_cast<char*>(&offset), sizeof(uint32_t)); - in.indirect.seekg(offset); - in.indirect.read(reinterpret_cast<char*>(&(*blob)[0]), blob->size()); - return in; -} - -template <typename T> -InStreams& deserializeParamValue(InStreams& in, T* value) { - in.elements.read(reinterpret_cast<char*>(value), sizeof(T)); - return in; -} - -InStreams& deserialize(TAG_INVALID_t&&, InStreams& in, KeyParameter*) { - // there should be no invalid KeyParameters but if handle them as zero sized. - ++in.invalids; - return in; -} - -template <typename T> -InStreams& deserialize(T&& ttag, InStreams& in, KeyParameter* param) { - return deserializeParamValue(in, &accessTagValue(ttag, *param)); -} - -template <typename... T> -struct choose_deserializer; -template <typename... Tags> -struct choose_deserializer<MetaList<Tags...>> { - static InStreams& deserialize(InStreams& in, KeyParameter* param) { - return choose_deserializer<Tags...>::deserialize(in, param); - } -}; -template <> -struct choose_deserializer<> { - static InStreams& deserialize(InStreams& in, KeyParameter*) { - // encountered an unknown tag -> fail parsing - in.elements.setstate(std::ios_base::badbit); - return in; - } -}; -template <TagType tag_type, Tag tag, typename... Tail> -struct choose_deserializer<TypedTag<tag_type, tag>, Tail...> { - static InStreams& deserialize(InStreams& in, KeyParameter* param) { - if (param->tag == tag) { - return android::hardware::security::keymint::deserialize(TypedTag<tag_type, tag>(), in, - param); - } else { - return choose_deserializer<Tail...>::deserialize(in, param); - } - } -}; - -InStreams& deserialize(InStreams& in, KeyParameter* param) { - in.elements.read(reinterpret_cast<char*>(¶m->tag), sizeof(Tag)); - return choose_deserializer<all_tags_t>::deserialize(in, param); -} - -std::istream& deserialize(std::istream& in, std::vector<KeyParameter>* params) { - uint32_t indirect_size = 0; - in.read(reinterpret_cast<char*>(&indirect_size), sizeof(uint32_t)); - std::string indirect_buffer(indirect_size, '\0'); - if (indirect_buffer.size() != indirect_size) { - in.setstate(std::ios_base::badbit); - return in; - } - in.read(&indirect_buffer[0], indirect_buffer.size()); - - uint32_t element_count = 0; - in.read(reinterpret_cast<char*>(&element_count), sizeof(uint32_t)); - uint32_t elements_size = 0; - in.read(reinterpret_cast<char*>(&elements_size), sizeof(uint32_t)); - - std::string elements_buffer(elements_size, '\0'); - if (elements_buffer.size() != elements_size) { - in.setstate(std::ios_base::badbit); - return in; - } - in.read(&elements_buffer[0], elements_buffer.size()); - - if (in.bad()) return in; - - // TODO write one-shot stream buffer to avoid copying here - std::stringstream indirect(indirect_buffer); - std::stringstream elements(elements_buffer); - InStreams streams = {indirect, elements, 0}; - - params->resize(element_count); - - for (uint32_t i = 0; i < element_count; ++i) { - deserialize(streams, &(*params)[i]); - } - - /* - * There are legacy blobs which have invalid tags in them due to a bug during serialization. - * This makes sure that invalid tags are filtered from the result before it is returned. - */ - if (streams.invalids > 0) { - std::vector<KeyParameter> filtered(element_count - streams.invalids); - auto ifiltered = filtered.begin(); - for (auto& p : *params) { - if (p.tag != Tag::INVALID) { - *ifiltered++ = std::move(p); - } - } - *params = std::move(filtered); - } - return in; -} - -void AuthorizationSet::Serialize(std::ostream* out) const { - serialize(*out, data_); -} - -void AuthorizationSet::Deserialize(std::istream* in) { - deserialize(*in, &data_); -} - -AuthorizationSetBuilder& AuthorizationSetBuilder::RsaKey(uint32_t key_size, - uint64_t public_exponent) { - Authorization(TAG_ALGORITHM, Algorithm::RSA); - Authorization(TAG_KEY_SIZE, key_size); - Authorization(TAG_RSA_PUBLIC_EXPONENT, public_exponent); - return *this; -} - -AuthorizationSetBuilder& AuthorizationSetBuilder::EcdsaKey(uint32_t key_size) { - Authorization(TAG_ALGORITHM, Algorithm::EC); - Authorization(TAG_KEY_SIZE, key_size); - return *this; -} - -AuthorizationSetBuilder& AuthorizationSetBuilder::EcdsaKey(EcCurve curve) { - Authorization(TAG_ALGORITHM, Algorithm::EC); - Authorization(TAG_EC_CURVE, curve); - return *this; -} - -AuthorizationSetBuilder& AuthorizationSetBuilder::AesKey(uint32_t key_size) { - Authorization(TAG_ALGORITHM, Algorithm::AES); - return Authorization(TAG_KEY_SIZE, key_size); -} - -AuthorizationSetBuilder& AuthorizationSetBuilder::TripleDesKey(uint32_t key_size) { - Authorization(TAG_ALGORITHM, Algorithm::TRIPLE_DES); - return Authorization(TAG_KEY_SIZE, key_size); -} - -AuthorizationSetBuilder& AuthorizationSetBuilder::HmacKey(uint32_t key_size) { - Authorization(TAG_ALGORITHM, Algorithm::HMAC); - Authorization(TAG_KEY_SIZE, key_size); - return SigningKey(); -} - -AuthorizationSetBuilder& AuthorizationSetBuilder::RsaSigningKey(uint32_t key_size, - uint64_t public_exponent) { - RsaKey(key_size, public_exponent); - return SigningKey(); -} - -AuthorizationSetBuilder& AuthorizationSetBuilder::RsaEncryptionKey(uint32_t key_size, - uint64_t public_exponent) { - RsaKey(key_size, public_exponent); - return EncryptionKey(); -} - -AuthorizationSetBuilder& AuthorizationSetBuilder::EcdsaSigningKey(uint32_t key_size) { - EcdsaKey(key_size); - return SigningKey(); -} - -AuthorizationSetBuilder& AuthorizationSetBuilder::EcdsaSigningKey(EcCurve curve) { - EcdsaKey(curve); - return SigningKey(); -} - -AuthorizationSetBuilder& AuthorizationSetBuilder::AesEncryptionKey(uint32_t key_size) { - AesKey(key_size); - return EncryptionKey(); -} - -AuthorizationSetBuilder& AuthorizationSetBuilder::TripleDesEncryptionKey(uint32_t key_size) { - TripleDesKey(key_size); - return EncryptionKey(); -} - -AuthorizationSetBuilder& AuthorizationSetBuilder::SigningKey() { - Authorization(TAG_PURPOSE, KeyPurpose::SIGN); - return Authorization(TAG_PURPOSE, KeyPurpose::VERIFY); -} - -AuthorizationSetBuilder& AuthorizationSetBuilder::EncryptionKey() { - Authorization(TAG_PURPOSE, KeyPurpose::ENCRYPT); - return Authorization(TAG_PURPOSE, KeyPurpose::DECRYPT); -} - -AuthorizationSetBuilder& AuthorizationSetBuilder::NoDigestOrPadding() { - Authorization(TAG_DIGEST, Digest::NONE); - return Authorization(TAG_PADDING, PaddingMode::NONE); -} - -AuthorizationSetBuilder& AuthorizationSetBuilder::EcbMode() { - return Authorization(TAG_BLOCK_MODE, BlockMode::ECB); -} - -AuthorizationSetBuilder& AuthorizationSetBuilder::GcmModeMinMacLen(uint32_t minMacLength) { - return BlockMode(BlockMode::GCM) - .Padding(PaddingMode::NONE) - .Authorization(TAG_MIN_MAC_LENGTH, minMacLength); -} - -AuthorizationSetBuilder& AuthorizationSetBuilder::GcmModeMacLen(uint32_t macLength) { - return BlockMode(BlockMode::GCM) - .Padding(PaddingMode::NONE) - .Authorization(TAG_MAC_LENGTH, macLength); -} - -AuthorizationSetBuilder& AuthorizationSetBuilder::BlockMode( - std::initializer_list<android::hardware::security::keymint::BlockMode> blockModes) { - for (auto mode : blockModes) { - push_back(TAG_BLOCK_MODE, mode); - } - return *this; -} - -AuthorizationSetBuilder& AuthorizationSetBuilder::Digest(std::vector<keymint::Digest> digests) { - for (auto digest : digests) { - push_back(TAG_DIGEST, digest); - } - return *this; -} - -AuthorizationSetBuilder& AuthorizationSetBuilder::Padding( - std::initializer_list<PaddingMode> paddingModes) { - for (auto paddingMode : paddingModes) { - push_back(TAG_PADDING, paddingMode); - } - return *this; -} - -} // namespace android::hardware::security::keymint |