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