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