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