Loading security/keymint/support/authorization_set.cpp +0 −273 Original line number Diff line number Diff line Loading @@ -118,279 +118,6 @@ NullOr<const KeyParameter&> AuthorizationSet::GetEntry(Tag tag) const { 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); Loading security/keymint/support/include/keymint_support/authorization_set.h +2 −6 Original line number Diff line number Diff line Loading @@ -32,9 +32,8 @@ using std::vector; class AuthorizationSetBuilder; /** * An ordered collection of KeyParameters. It provides memory ownership and some convenient * functionality for sorting, deduplicating, joining, and subtracting sets of KeyParameters. * For serialization, wrap the backing store of this structure in a vector<KeyParameter>. * A collection of KeyParameters. It provides memory ownership and some convenient functionality for * sorting, deduplicating, joining, and subtracting sets of KeyParameters. */ class AuthorizationSet { public: Loading Loading @@ -219,9 +218,6 @@ class AuthorizationSet { return result; } void Serialize(std::ostream* out) const; void Deserialize(std::istream* in); private: NullOr<const KeyParameter&> GetEntry(Tag tag) const; Loading Loading
security/keymint/support/authorization_set.cpp +0 −273 Original line number Diff line number Diff line Loading @@ -118,279 +118,6 @@ NullOr<const KeyParameter&> AuthorizationSet::GetEntry(Tag tag) const { 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); Loading
security/keymint/support/include/keymint_support/authorization_set.h +2 −6 Original line number Diff line number Diff line Loading @@ -32,9 +32,8 @@ using std::vector; class AuthorizationSetBuilder; /** * An ordered collection of KeyParameters. It provides memory ownership and some convenient * functionality for sorting, deduplicating, joining, and subtracting sets of KeyParameters. * For serialization, wrap the backing store of this structure in a vector<KeyParameter>. * A collection of KeyParameters. It provides memory ownership and some convenient functionality for * sorting, deduplicating, joining, and subtracting sets of KeyParameters. */ class AuthorizationSet { public: Loading Loading @@ -219,9 +218,6 @@ class AuthorizationSet { return result; } void Serialize(std::ostream* out) const; void Deserialize(std::istream* in); private: NullOr<const KeyParameter&> GetEntry(Tag tag) const; Loading