• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 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 #pragma once
18 
19 #include "keymaster_tags.h"
20 #include <vector>
21 
22 namespace keymaster::ng {
23 
24 class AuthorizationSetBuilder;
25 
26 /**
27  * An ordered collection of KeyParameters. It provides memory ownership and some convenient
28  * functionality for sorting, deduplicating, joining, and subtracting sets of KeyParameters.
29  * For serialization, wrap the backing store of this structure in a hidl_vec<KeyParameter>.
30  */
31 class AuthorizationSet {
32   public:
33     /**
34      * Construct an empty, dynamically-allocated, growable AuthorizationSet.
35      */
AuthorizationSet()36     AuthorizationSet(){};
37 
38     // Copy constructor.
AuthorizationSet(const AuthorizationSet & other)39     AuthorizationSet(const AuthorizationSet& other) : data_(other.data_) {}
40 
41     // Move constructor.
AuthorizationSet(AuthorizationSet && other)42     AuthorizationSet(AuthorizationSet&& other) : data_(std::move(other.data_)) {}
43 
44     // Constructor from hidl_vec<KeyParameter>
AuthorizationSet(const hidl_vec<KeyParameter> & other)45     explicit AuthorizationSet(const hidl_vec<KeyParameter>& other) { *this = other; }
46 
47     // Copy assignment.
48     AuthorizationSet& operator=(const AuthorizationSet& other) {
49         if (this == &other) return *this;
50         data_ = other.data_;
51         return *this;
52     }
53 
54     // Move assignment.
55     AuthorizationSet& operator=(AuthorizationSet&& other) {
56         data_ = std::move(other.data_);
57         return *this;
58     }
59 
60     AuthorizationSet& operator=(const hidl_vec<KeyParameter>& other) {
61         if (other.size() > 0) {
62             data_.resize(other.size());
63             for (size_t i = 0; i < data_.size(); ++i) {
64                 /* This makes a deep copy even of embedded blobs.
65                  * See assignment operator/copy constructor of hidl_vec.*/
66                 data_[i] = other[i];
67             }
68         }
69         return *this;
70     }
71 
72     /**
73      * Clear existing authorization set data
74      */
75     void Clear();
76 
77     ~AuthorizationSet() = default;
78 
79     /**
80      * Returns the size of the set.
81      */
size()82     size_t size() const { return data_.size(); }
83 
84     /**
85      * Returns true if the set is empty.
86      */
empty()87     bool empty() const { return size() == 0; }
88 
89     /**
90      * Returns the data in the set, directly. Be careful with this.
91      */
data()92     const KeyParameter* data() const { return data_.data(); }
93 
94     /**
95      * Sorts the set
96      */
97     void Sort();
98 
99     /**
100      * Sorts the set and removes duplicates (inadvertently duplicating tags is easy to do with the
101      * AuthorizationSetBuilder).
102      */
103     void Deduplicate();
104 
105     /**
106      * Adds all elements from \p set that are not already present in this AuthorizationSet.  As a
107      * side-effect, if \p set is not null this AuthorizationSet will end up sorted.
108      */
109     void Union(const AuthorizationSet& set);
110 
111     /**
112      * Removes all elements in \p set from this AuthorizationSet.
113      */
114     void Subtract(const AuthorizationSet& set);
115 
116     /**
117      * Returns the offset of the next entry that matches \p tag, starting from the element after \p
118      * begin.  If not found, returns -1.
119      */
120     int find(Tag tag, int begin = -1) const;
121 
122     /**
123      * Removes the entry at the specified index. Returns true if successful, false if the index was
124      * out of bounds.
125      */
126     bool erase(int index);
127 
128     /**
129      * Returns iterator (pointer) to beginning of elems array, to enable STL-style iteration
130      */
begin()131     std::vector<KeyParameter>::const_iterator begin() const { return data_.begin(); }
132 
133     /**
134      * Returns iterator (pointer) one past end of elems array, to enable STL-style iteration
135      */
end()136     std::vector<KeyParameter>::const_iterator end() const { return data_.end(); }
137 
138     /**
139      * Returns the nth element of the set.
140      * Like for std::vector::operator[] there is no range check performed. Use of out of range
141      * indices is undefined.
142      */
143     KeyParameter& operator[](int n);
144 
145     /**
146      * Returns the nth element of the set.
147      * Like for std::vector::operator[] there is no range check performed. Use of out of range
148      * indices is undefined.
149      */
150     const KeyParameter& operator[](int n) const;
151 
152     /**
153      * Returns true if the set contains at least one instance of \p tag
154      */
Contains(Tag tag)155     bool Contains(Tag tag) const { return find(tag) != -1; }
156 
157     template <TagType tag_type, Tag tag, typename ValueT>
Contains(TypedTag<tag_type,tag> ttag,const ValueT & value)158     bool Contains(TypedTag<tag_type, tag> ttag, const ValueT& value) const {
159         for (const auto& param : data_) {
160             auto entry = authorizationValue(ttag, param);
161             if (entry.isOk() && entry.value() == value) return true;
162         }
163         return false;
164     }
165     /**
166      * Returns the number of \p tag entries.
167      */
168     size_t GetTagCount(Tag tag) const;
169 
170     template <typename T>
GetTagValue(T tag)171     inline NullOr<const typename TypedTag2ValueType<T>::type&> GetTagValue(T tag) const {
172         auto entry = GetEntry(tag);
173         if (entry.isOk()) return authorizationValue(tag, entry.value());
174         return {};
175     }
176 
push_back(const KeyParameter & param)177     void push_back(const KeyParameter& param) { data_.push_back(param); }
push_back(KeyParameter && param)178     void push_back(KeyParameter&& param) { data_.push_back(std::move(param)); }
179 
180     /**
181      * Append the tag and enumerated value to the set.
182      * "val" may be exactly one parameter unless a boolean parameter is added.
183      * In this case "val" is omitted. This condition is checked at compile time by Authorization()
184      */
push_back(TypedTagT tag,Value &&...val)185     template <typename TypedTagT, typename... Value> void push_back(TypedTagT tag, Value&&... val) {
186         push_back(Authorization(tag, std::forward<Value>(val)...));
187     }
188 
append(Iterator begin,Iterator end)189     template <typename Iterator> void append(Iterator begin, Iterator end) {
190         while (begin != end) {
191             push_back(*begin);
192             ++begin;
193         }
194     }
195 
hidl_data()196     hidl_vec<KeyParameter> hidl_data() const {
197         hidl_vec<KeyParameter> result;
198         result.setToExternal(const_cast<KeyParameter*>(data()), size());
199         return result;
200     }
201 
202     void Serialize(std::ostream* out) const;
203     void Deserialize(std::istream* in);
204 
205   private:
206     NullOr<const KeyParameter&> GetEntry(Tag tag) const;
207 
208     std::vector<KeyParameter> data_;
209 };
210 
211 class AuthorizationSetBuilder : public AuthorizationSet {
212   public:
213     template <typename TagType, typename... ValueType>
Authorization(TagType ttag,ValueType &&...value)214     AuthorizationSetBuilder& Authorization(TagType ttag, ValueType&&... value) {
215         push_back(ttag, std::forward<ValueType>(value)...);
216         return *this;
217     }
218 
219     template <Tag tag>
Authorization(TypedTag<TagType::BYTES,tag> ttag,const uint8_t * data,size_t data_length)220     AuthorizationSetBuilder& Authorization(TypedTag<TagType::BYTES, tag> ttag, const uint8_t* data,
221                                            size_t data_length) {
222         hidl_vec<uint8_t> new_blob;
223         new_blob.setToExternal(const_cast<uint8_t*>(data), data_length);
224         push_back(ttag, std::move(new_blob));
225         return *this;
226     }
227 
228     template <Tag tag>
Authorization(TypedTag<TagType::BYTES,tag> ttag,const char * data,size_t data_length)229     AuthorizationSetBuilder& Authorization(TypedTag<TagType::BYTES, tag> ttag, const char* data,
230                                            size_t data_length) {
231         return Authorization(ttag, reinterpret_cast<const uint8_t*>(data), data_length);
232     }
233 
234     AuthorizationSetBuilder& RsaKey(uint32_t key_size, uint64_t public_exponent);
235     AuthorizationSetBuilder& EcdsaKey(uint32_t key_size);
236     AuthorizationSetBuilder& AesKey(uint32_t key_size);
237     AuthorizationSetBuilder& HmacKey(uint32_t key_size);
238 
239     AuthorizationSetBuilder& RsaSigningKey(uint32_t key_size, uint64_t public_exponent);
240     AuthorizationSetBuilder& RsaEncryptionKey(uint32_t key_size, uint64_t public_exponent);
241     AuthorizationSetBuilder& EcdsaSigningKey(uint32_t key_size);
242     AuthorizationSetBuilder& AesEncryptionKey(uint32_t key_size);
243 
244     AuthorizationSetBuilder& SigningKey();
245     AuthorizationSetBuilder& EncryptionKey();
246     AuthorizationSetBuilder& NoDigestOrPadding();
247     AuthorizationSetBuilder& EcbMode();
248 
Digest(Digest digest)249     AuthorizationSetBuilder& Digest(Digest digest) { return Authorization(TAG_DIGEST, digest); }
250 
Padding(PaddingMode padding)251     AuthorizationSetBuilder& Padding(PaddingMode padding) {
252         return Authorization(TAG_PADDING, padding);
253     }
254 };
255 
RsaKey(uint32_t key_size,uint64_t public_exponent)256 inline AuthorizationSetBuilder& AuthorizationSetBuilder::RsaKey(uint32_t key_size,
257                                                                 uint64_t public_exponent) {
258     Authorization(TAG_ALGORITHM, Algorithm::RSA);
259     Authorization(TAG_KEY_SIZE, key_size);
260     Authorization(TAG_RSA_PUBLIC_EXPONENT, public_exponent);
261     return *this;
262 }
263 
EcdsaKey(uint32_t key_size)264 inline AuthorizationSetBuilder& AuthorizationSetBuilder::EcdsaKey(uint32_t key_size) {
265     Authorization(TAG_ALGORITHM, Algorithm::EC);
266     Authorization(TAG_KEY_SIZE, key_size);
267     return *this;
268 }
269 
AesKey(uint32_t key_size)270 inline AuthorizationSetBuilder& AuthorizationSetBuilder::AesKey(uint32_t key_size) {
271     Authorization(TAG_ALGORITHM, Algorithm::AES);
272     return Authorization(TAG_KEY_SIZE, key_size);
273 }
274 
HmacKey(uint32_t key_size)275 inline AuthorizationSetBuilder& AuthorizationSetBuilder::HmacKey(uint32_t key_size) {
276     Authorization(TAG_ALGORITHM, Algorithm::HMAC);
277     Authorization(TAG_KEY_SIZE, key_size);
278     return SigningKey();
279 }
280 
RsaSigningKey(uint32_t key_size,uint64_t public_exponent)281 inline AuthorizationSetBuilder& AuthorizationSetBuilder::RsaSigningKey(uint32_t key_size,
282                                                                        uint64_t public_exponent) {
283     RsaKey(key_size, public_exponent);
284     return SigningKey();
285 }
286 
287 inline AuthorizationSetBuilder&
RsaEncryptionKey(uint32_t key_size,uint64_t public_exponent)288 AuthorizationSetBuilder::RsaEncryptionKey(uint32_t key_size, uint64_t public_exponent) {
289     RsaKey(key_size, public_exponent);
290     return EncryptionKey();
291 }
292 
EcdsaSigningKey(uint32_t key_size)293 inline AuthorizationSetBuilder& AuthorizationSetBuilder::EcdsaSigningKey(uint32_t key_size) {
294     EcdsaKey(key_size);
295     return SigningKey();
296 }
297 
AesEncryptionKey(uint32_t key_size)298 inline AuthorizationSetBuilder& AuthorizationSetBuilder::AesEncryptionKey(uint32_t key_size) {
299     AesKey(key_size);
300     return EncryptionKey();
301 }
302 
SigningKey()303 inline AuthorizationSetBuilder& AuthorizationSetBuilder::SigningKey() {
304     Authorization(TAG_PURPOSE, KeyPurpose::SIGN);
305     return Authorization(TAG_PURPOSE, KeyPurpose::VERIFY);
306 }
307 
EncryptionKey()308 inline AuthorizationSetBuilder& AuthorizationSetBuilder::EncryptionKey() {
309     Authorization(TAG_PURPOSE, KeyPurpose::ENCRYPT);
310     return Authorization(TAG_PURPOSE, KeyPurpose::DECRYPT);
311 }
312 
NoDigestOrPadding()313 inline AuthorizationSetBuilder& AuthorizationSetBuilder::NoDigestOrPadding() {
314     Authorization(TAG_DIGEST, Digest::NONE);
315     return Authorization(TAG_PADDING, PaddingMode::NONE);
316 }
317 
EcbMode()318 inline AuthorizationSetBuilder& AuthorizationSetBuilder::EcbMode() {
319     return Authorization(TAG_BLOCK_MODE, BlockMode::ECB);
320 }
321 
322 }  // namespace keymaster::ng
323