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