/* * Copyright 2017 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. */ #ifndef HARDWARE_INTERFACES_KEYMASTER_30_VTS_FUNCTIONAL_AUTHORIZATION_SET_H_ #define HARDWARE_INTERFACES_KEYMASTER_30_VTS_FUNCTIONAL_AUTHORIZATION_SET_H_ #include "keymaster_tags.h" #include #include namespace android { namespace hardware { namespace keymaster { namespace V3_0 { 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 hidl_vec. */ class AuthorizationSet { public: typedef KeyParameter value_type; /** * Construct an empty, dynamically-allocated, growable AuthorizationSet. */ AuthorizationSet(){}; // Copy constructor. AuthorizationSet(const AuthorizationSet& other) : data_(other.data_) {} // Move constructor. AuthorizationSet(AuthorizationSet&& other) : data_(std::move(other.data_)) {} // Constructor from hidl_vec AuthorizationSet(const hidl_vec& other) { *this = other; } // Copy assignment. AuthorizationSet& operator=(const AuthorizationSet& other) { data_ = other.data_; return *this; } // Move assignment. AuthorizationSet& operator=(AuthorizationSet&& other) { data_ = std::move(other.data_); return *this; } AuthorizationSet& operator=(const hidl_vec& other) { if (other.size() > 0) { data_.resize(other.size()); for (size_t i = 0; i < data_.size(); ++i) { /* This makes a deep copy even of embedded blobs. * See assignment operator/copy constructor of hidl_vec.*/ data_[i] = other[i]; } } return *this; } /** * Clear existing authorization set data */ void Clear(); ~AuthorizationSet() = default; /** * Returns the size of the set. */ size_t size() const { return data_.size(); } /** * Returns true if the set is empty. */ bool empty() const { return size() == 0; } /** * Returns the data in the set, directly. Be careful with this. */ const KeyParameter* data() const { return data_.data(); } /** * Sorts the set */ void Sort(); /** * Sorts the set and removes duplicates (inadvertently duplicating tags is easy to do with the * AuthorizationSetBuilder). */ void Deduplicate(); /** * Adds all elements from \p set that are not already present in this AuthorizationSet. As a * side-effect, if \p set is not null this AuthorizationSet will end up sorted. */ void Union(const AuthorizationSet& set); /** * Removes all elements in \p set from this AuthorizationSet. */ void Subtract(const AuthorizationSet& set); /** * Returns the offset of the next entry that matches \p tag, starting from the element after \p * begin. If not found, returns -1. */ int find(Tag tag, int begin = -1) const; /** * Removes the entry at the specified index. Returns true if successful, false if the index was * out of bounds. */ bool erase(int index); /** * Returns iterator (pointer) to beginning of elems array, to enable STL-style iteration */ std::vector::const_iterator begin() const { return data_.begin(); } /** * Returns iterator (pointer) one past end of elems array, to enable STL-style iteration */ std::vector::const_iterator end() const { return data_.end(); } /** * Returns the nth element of the set. * Like for std::vector::operator[] there is no range check performed. Use of out of range * indices is undefined. */ KeyParameter& operator[](int n); /** * Returns the nth element of the set. * Like for std::vector::operator[] there is no range check performed. Use of out of range * indices is undefined. */ const KeyParameter& operator[](int n) const; /** * Returns true if the set contains at least one instance of \p tag */ bool Contains(Tag tag) const { return find(tag) != -1; } template bool Contains(T tag) const { return find(tag) != -1; } template bool Contains(TypedTag ttag, const ValueT& value) const { for (const auto& param : data_) { auto entry = authorizationValue(ttag, param); if (entry.isOk() && static_cast(entry.value()) == value) return true; } return false; } /** * Returns the number of \p tag entries. */ size_t GetTagCount(Tag tag) const; template inline NullOr::type&> GetTagValue(T tag) const { auto entry = GetEntry(tag); if (entry.isOk()) return authorizationValue(tag, entry.value()); return {}; } void push_back(const KeyParameter& param) { data_.push_back(param); } void push_back(KeyParameter&& param) { data_.push_back(std::move(param)); } void push_back(const AuthorizationSet& set) { for (auto& entry : set) { push_back(entry); } } void push_back(AuthorizationSet&& set) { move(set.begin(), set.end()); set.Clear(); } template void push_back(TypedTag ttag, const uint8_t* data, size_t data_length) { hidl_vec new_blob; new_blob.setToExternal(const_cast(data), data_length); push_back(ttag, new_blob); } /** * Append the tag and enumerated value to the set. * "val" may be exactly one parameter unless a boolean parameter is added. * In this case "val" is omitted. This condition is checked at compile time by Authorization() */ template void push_back(TypedTagT tag, Value&&... val) { push_back(Authorization(tag, std::forward(val)...)); } template void push_back(Iterator begin, Iterator end) { while (begin != end) { push_back(*begin); ++begin; } } template void move(Iterator begin, Iterator end) { std::move(begin, end, std::back_inserter(data_)); } hidl_vec hidl_data() const { hidl_vec result(begin(), end()); return result; } void Serialize(std::ostream* out) const; void Deserialize(std::istream* in); private: NullOr GetEntry(Tag tag) const; std::vector data_; }; class AuthorizationSetBuilder : public AuthorizationSet { public: template AuthorizationSetBuilder& Authorization(TagType ttag, ValueType&&... value) { push_back(ttag, std::forward(value)...); return *this; } template AuthorizationSetBuilder& Authorization(TypedTag ttag, const uint8_t* data, size_t data_length) { hidl_vec new_blob; new_blob.setToExternal(const_cast(data), data_length); push_back(ttag, new_blob); return *this; } template AuthorizationSetBuilder& Authorization(TypedTag ttag, const char* data, size_t data_length) { return Authorization(ttag, reinterpret_cast(data), data_length); } template AuthorizationSetBuilder& Authorization(TypedTag ttag, char* data, size_t data_length) { return Authorization(ttag, reinterpret_cast(data), data_length); } AuthorizationSetBuilder& Authorizations(AuthorizationSet&& set); AuthorizationSetBuilder& Authorizations(const AuthorizationSet& set); AuthorizationSetBuilder& RsaKey(uint32_t key_size, uint64_t public_exponent); AuthorizationSetBuilder& EcdsaKey(uint32_t key_size); AuthorizationSetBuilder& EcdsaKey(EcCurve curve); AuthorizationSetBuilder& AesKey(uint32_t key_size); AuthorizationSetBuilder& HmacKey(uint32_t key_size); AuthorizationSetBuilder& RsaSigningKey(uint32_t key_size, uint64_t public_exponent); AuthorizationSetBuilder& RsaEncryptionKey(uint32_t key_size, uint64_t public_exponent); AuthorizationSetBuilder& EcdsaSigningKey(uint32_t key_size); AuthorizationSetBuilder& EcdsaSigningKey(EcCurve curve); AuthorizationSetBuilder& AesEncryptionKey(uint32_t key_size); AuthorizationSetBuilder& SigningKey(); AuthorizationSetBuilder& EncryptionKey(); AuthorizationSetBuilder& NoDigestOrPadding(); AuthorizationSetBuilder& EcbMode(); AuthorizationSetBuilder& BlockMode(std::initializer_list block_modes); AuthorizationSetBuilder& Digest(std::initializer_list digests); AuthorizationSetBuilder& Padding(std::initializer_list padding_modes); // The following forwarding templates enable BlockMode,Digest and Padding to be called with a // variable number of arguments; no need to wrap them in braces to make them an initalizer_list. template AuthorizationSetBuilder& BlockMode(T&&... a) { return BlockMode({std::forward(a)...}); } template AuthorizationSetBuilder& Digest(T&&... a) { return Digest({std::forward(a)...}); } template AuthorizationSetBuilder& Padding(T&&... a) { return Padding({std::forward(a)...}); } }; inline AuthorizationSetBuilder& AuthorizationSetBuilder::Authorizations(AuthorizationSet&& set) { move(set.begin(), set.end()); set.Clear(); return *this; } inline AuthorizationSetBuilder& AuthorizationSetBuilder::Authorizations(const AuthorizationSet& set) { push_back(set.begin(), set.end()); return *this; } inline 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; } inline AuthorizationSetBuilder& AuthorizationSetBuilder::EcdsaKey(uint32_t key_size) { Authorization(TAG_ALGORITHM, Algorithm::EC); Authorization(TAG_KEY_SIZE, key_size); return *this; } inline AuthorizationSetBuilder& AuthorizationSetBuilder::EcdsaKey(EcCurve curve) { Authorization(TAG_ALGORITHM, Algorithm::EC); Authorization(TAG_EC_CURVE, curve); return *this; } inline AuthorizationSetBuilder& AuthorizationSetBuilder::AesKey(uint32_t key_size) { Authorization(TAG_ALGORITHM, Algorithm::AES); return Authorization(TAG_KEY_SIZE, key_size); } inline AuthorizationSetBuilder& AuthorizationSetBuilder::HmacKey(uint32_t key_size) { Authorization(TAG_ALGORITHM, Algorithm::HMAC); Authorization(TAG_KEY_SIZE, key_size); return SigningKey(); } inline AuthorizationSetBuilder& AuthorizationSetBuilder::RsaSigningKey(uint32_t key_size, uint64_t public_exponent) { RsaKey(key_size, public_exponent); return SigningKey(); } inline AuthorizationSetBuilder& AuthorizationSetBuilder::RsaEncryptionKey(uint32_t key_size, uint64_t public_exponent) { RsaKey(key_size, public_exponent); return EncryptionKey(); } inline AuthorizationSetBuilder& AuthorizationSetBuilder::EcdsaSigningKey(uint32_t key_size) { EcdsaKey(key_size); return SigningKey(); } inline AuthorizationSetBuilder& AuthorizationSetBuilder::EcdsaSigningKey(EcCurve curve) { EcdsaKey(curve); return SigningKey(); } inline AuthorizationSetBuilder& AuthorizationSetBuilder::AesEncryptionKey(uint32_t key_size) { AesKey(key_size); return EncryptionKey(); } inline AuthorizationSetBuilder& AuthorizationSetBuilder::SigningKey() { Authorization(TAG_PURPOSE, KeyPurpose::SIGN); return Authorization(TAG_PURPOSE, KeyPurpose::VERIFY); } inline AuthorizationSetBuilder& AuthorizationSetBuilder::EncryptionKey() { Authorization(TAG_PURPOSE, KeyPurpose::ENCRYPT); return Authorization(TAG_PURPOSE, KeyPurpose::DECRYPT); } inline AuthorizationSetBuilder& AuthorizationSetBuilder::NoDigestOrPadding() { Authorization(TAG_DIGEST, Digest::NONE); return Authorization(TAG_PADDING, PaddingMode::NONE); } inline AuthorizationSetBuilder& AuthorizationSetBuilder::EcbMode() { return BlockMode(BlockMode::ECB); } inline AuthorizationSetBuilder& AuthorizationSetBuilder::BlockMode(std::initializer_list block_modes) { for (auto block_mode : block_modes) { Authorization(TAG_BLOCK_MODE, block_mode); } return *this; } inline AuthorizationSetBuilder& AuthorizationSetBuilder::Digest(std::initializer_list digests) { for (auto digest : digests) { Authorization(TAG_DIGEST, digest); } return *this; } inline AuthorizationSetBuilder& AuthorizationSetBuilder::Padding(std::initializer_list padding_modes) { for (auto padding : padding_modes) { Authorization(TAG_PADDING, padding); } return *this; } } // namespace V3_0 } // namespace keymaster } // namespace hardware } // namespace android #endif // HARDWARE_INTERFACES_KEYMASTER_30_VTS_FUNCTIONAL_AUTHORIZATION_SET_H_