1 /*
2 * Copyright (C) 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 #include <keystore/keymaster_types.h>
18
19 #include <assert.h>
20 #include <stddef.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <limits>
24 #include <ostream>
25 #include <istream>
26
27 #include <new>
28
29 namespace keystore {
30
keyParamLess(const KeyParameter & a,const KeyParameter & b)31 inline bool keyParamLess(const KeyParameter& a, const KeyParameter& b) {
32 if (a.tag != b.tag) return a.tag < b.tag;
33 int retval;
34 switch (typeFromTag(a.tag)) {
35 case TagType::INVALID:
36 case TagType::BOOL:
37 return false;
38 case TagType::ENUM:
39 case TagType::ENUM_REP:
40 case TagType::UINT:
41 case TagType::UINT_REP:
42 return a.f.integer < b.f.integer;
43 case TagType::ULONG:
44 case TagType::ULONG_REP:
45 return a.f.longInteger < b.f.longInteger;
46 case TagType::DATE:
47 return a.f.dateTime < b.f.dateTime;
48 case TagType::BIGNUM:
49 case TagType::BYTES:
50 // Handle the empty cases.
51 if (a.blob.size() == 0)
52 return b.blob.size() != 0;
53 if (b.blob.size() == 0) return false;
54
55 retval = memcmp(&a.blob[0], &b.blob[0], std::min(a.blob.size(), b.blob.size()));
56 // if one is the prefix of the other the longer wins
57 if (retval == 0) return a.blob.size() < b.blob.size();
58 // Otherwise a is less if a is less.
59 else return retval < 0;
60 }
61 return false;
62 }
63
keyParamEqual(const KeyParameter & a,const KeyParameter & b)64 inline bool keyParamEqual(const KeyParameter& a, const KeyParameter& b) {
65 if (a.tag != b.tag) return false;
66
67 switch (typeFromTag(a.tag)) {
68 case TagType::INVALID:
69 case TagType::BOOL:
70 return true;
71 case TagType::ENUM:
72 case TagType::ENUM_REP:
73 case TagType::UINT:
74 case TagType::UINT_REP:
75 return a.f.integer == b.f.integer;
76 case TagType::ULONG:
77 case TagType::ULONG_REP:
78 return a.f.longInteger == b.f.longInteger;
79 case TagType::DATE:
80 return a.f.dateTime == b.f.dateTime;
81 case TagType::BIGNUM:
82 case TagType::BYTES:
83 if (a.blob.size() != b.blob.size()) return false;
84 return a.blob.size() == 0 ||
85 memcmp(&a.blob[0], &b.blob[0], a.blob.size()) == 0;
86 }
87 return false;
88 }
89
Sort()90 void AuthorizationSet::Sort() {
91 std::sort(data_.begin(), data_.end(), keyParamLess);
92 }
93
Deduplicate()94 void AuthorizationSet::Deduplicate() {
95 if (data_.empty()) return;
96
97 Sort();
98 std::vector<KeyParameter> result;
99
100 auto curr = data_.begin();
101 auto prev = curr++;
102 for (; curr != data_.end(); ++prev, ++curr) {
103 if (prev->tag == Tag::INVALID) continue;
104
105 if (!keyParamEqual(*prev, *curr)) {
106 result.emplace_back(std::move(*prev));
107 }
108 }
109 result.emplace_back(std::move(*prev));
110
111 std::swap(data_, result);
112 }
113
Union(const AuthorizationSet & other)114 void AuthorizationSet::Union(const AuthorizationSet& other) {
115 data_.insert(data_.end(), other.data_.begin(), other.data_.end());
116 Deduplicate();
117 }
118
Subtract(const AuthorizationSet & other)119 void AuthorizationSet::Subtract(const AuthorizationSet& other) {
120 Deduplicate();
121
122 auto i = other.begin();
123 while (i != other.end()) {
124 int pos = -1;
125 do {
126 pos = find(i->tag, pos);
127 if (pos != -1 && keyParamEqual(*i, data_[pos])) {
128 data_.erase(data_.begin() + pos);
129 break;
130 }
131 } while (pos != -1);
132 ++i;
133 }
134 }
135
find(Tag tag,int begin) const136 int AuthorizationSet::find(Tag tag, int begin) const {
137 auto iter = data_.begin() + (1 + begin);
138
139 while (iter != data_.end() && iter->tag != tag) ++iter;
140
141 if (iter != data_.end()) return iter - data_.begin();
142 return -1;
143 }
144
erase(int index)145 bool AuthorizationSet::erase(int index) {
146 auto pos = data_.begin() + index;
147 if (pos != data_.end()) {
148 data_.erase(pos);
149 return true;
150 }
151 return false;
152 }
153
operator [](int at)154 KeyParameter& AuthorizationSet::operator[](int at) {
155 return data_[at];
156 }
157
operator [](int at) const158 const KeyParameter& AuthorizationSet::operator[](int at) const {
159 return data_[at];
160 }
161
Clear()162 void AuthorizationSet::Clear() {
163 data_.clear();
164 }
165
GetTagCount(Tag tag) const166 size_t AuthorizationSet::GetTagCount(Tag tag) const {
167 size_t count = 0;
168 for (int pos = -1; (pos = find(tag, pos)) != -1;)
169 ++count;
170 return count;
171 }
172
GetEntry(Tag tag) const173 NullOr<const KeyParameter&> AuthorizationSet::GetEntry(Tag tag) const {
174 int pos = find(tag);
175 if (pos == -1) return {};
176 return data_[pos];
177 }
178
179 /**
180 * Persistent format is:
181 * | 32 bit indirect_size |
182 * --------------------------------
183 * | indirect_size bytes of data | this is where the blob data is stored
184 * --------------------------------
185 * | 32 bit element_count | number of entries
186 * | 32 bit elements_size | total bytes used by entries (entries have variable length)
187 * --------------------------------
188 * | elementes_size bytes of data | where the elements are stored
189 */
190
191 /**
192 * Persistent format of blobs and bignums:
193 * | 32 bit tag |
194 * | 32 bit blob_length |
195 * | 32 bit indirect_offset |
196 */
197
198 struct OutStreams {
199 std::ostream& indirect;
200 std::ostream& elements;
201 };
202
serializeParamValue(OutStreams & out,const hidl_vec<uint8_t> & blob)203 OutStreams& serializeParamValue(OutStreams& out, const hidl_vec<uint8_t>& blob) {
204 uint32_t buffer;
205
206 // write blob_length
207 auto blob_length = blob.size();
208 if (blob_length > std::numeric_limits<uint32_t>::max()) {
209 out.elements.setstate(std::ios_base::badbit);
210 return out;
211 }
212 buffer = blob_length;
213 out.elements.write(reinterpret_cast<const char*>(&buffer), sizeof(uint32_t));
214
215 // write indirect_offset
216 auto offset = out.indirect.tellp();
217 if (offset < 0 || offset > std::numeric_limits<uint32_t>::max() ||
218 uint32_t(offset) + uint32_t(blob_length) < uint32_t(offset)) { // overflow check
219 out.elements.setstate(std::ios_base::badbit);
220 return out;
221 }
222 buffer = offset;
223 out.elements.write(reinterpret_cast<const char*>(&buffer), sizeof(uint32_t));
224
225 // write blob to indirect stream
226 if(blob_length)
227 out.indirect.write(reinterpret_cast<const char*>(&blob[0]), blob_length);
228
229 return out;
230 }
231
232 template <typename T>
serializeParamValue(OutStreams & out,const T & value)233 OutStreams& serializeParamValue(OutStreams& out, const T& value) {
234 out.elements.write(reinterpret_cast<const char*>(&value), sizeof(T));
235 return out;
236 }
237
serialize(TAG_INVALID_t &&,OutStreams & out,const KeyParameter &)238 OutStreams& serialize(TAG_INVALID_t&&, OutStreams& out, const KeyParameter&) {
239 // skip invalid entries.
240 return out;
241 }
242 template <typename T>
serialize(T ttag,OutStreams & out,const KeyParameter & param)243 OutStreams& serialize(T ttag, OutStreams& out, const KeyParameter& param) {
244 out.elements.write(reinterpret_cast<const char*>(¶m.tag), sizeof(int32_t));
245 return serializeParamValue(out, accessTagValue(ttag, param));
246 }
247
248 template <typename... T>
249 struct choose_serializer;
250 template <typename... Tags>
251 struct choose_serializer<MetaList<Tags...>> {
serializekeystore::choose_serializer252 static OutStreams& serialize(OutStreams& out, const KeyParameter& param) {
253 return choose_serializer<Tags...>::serialize(out, param);
254 }
255 };
256 template <>
257 struct choose_serializer<> {
serializekeystore::choose_serializer258 static OutStreams& serialize(OutStreams& out, const KeyParameter&) {
259 return out;
260 }
261 };
262 template <TagType tag_type, Tag tag, typename... Tail>
263 struct choose_serializer<TypedTag<tag_type, tag>, Tail...> {
serializekeystore::choose_serializer264 static OutStreams& serialize(OutStreams& out, const KeyParameter& param) {
265 if (param.tag == tag) {
266 return keystore::serialize(TypedTag<tag_type, tag>(), out, param);
267 } else {
268 return choose_serializer<Tail...>::serialize(out, param);
269 }
270 }
271 };
272
serialize(OutStreams & out,const KeyParameter & param)273 OutStreams& serialize(OutStreams& out, const KeyParameter& param) {
274 return choose_serializer<all_tags_t>::serialize(out, param);
275 }
276
serialize(std::ostream & out,const std::vector<KeyParameter> & params)277 std::ostream& serialize(std::ostream& out, const std::vector<KeyParameter>& params) {
278 std::stringstream indirect;
279 std::stringstream elements;
280 OutStreams streams = { indirect, elements };
281 for (const auto& param: params) {
282 serialize(streams, param);
283 }
284 if (indirect.bad() || elements.bad()) {
285 out.setstate(std::ios_base::badbit);
286 return out;
287 }
288 auto pos = indirect.tellp();
289 if (pos < 0 || pos > std::numeric_limits<uint32_t>::max()) {
290 out.setstate(std::ios_base::badbit);
291 return out;
292 }
293 uint32_t indirect_size = pos;
294 pos = elements.tellp();
295 if (pos < 0 || pos > std::numeric_limits<uint32_t>::max()) {
296 out.setstate(std::ios_base::badbit);
297 return out;
298 }
299 uint32_t elements_size = pos;
300 uint32_t element_count = params.size();
301
302 out.write(reinterpret_cast<const char*>(&indirect_size), sizeof(uint32_t));
303
304 pos = out.tellp();
305 if (indirect_size)
306 out << indirect.rdbuf();
307 assert(out.tellp() - pos == indirect_size);
308
309 out.write(reinterpret_cast<const char*>(&element_count), sizeof(uint32_t));
310 out.write(reinterpret_cast<const char*>(&elements_size), sizeof(uint32_t));
311
312 pos = out.tellp();
313 if (elements_size)
314 out << elements.rdbuf();
315 assert(out.tellp() - pos == elements_size);
316
317 return out;
318 }
319
320 struct InStreams {
321 std::istream& indirect;
322 std::istream& elements;
323 };
324
deserializeParamValue(InStreams & in,hidl_vec<uint8_t> * blob)325 InStreams& deserializeParamValue(InStreams& in, hidl_vec<uint8_t>* blob) {
326 uint32_t blob_length = 0;
327 uint32_t offset = 0;
328 in.elements.read(reinterpret_cast<char*>(&blob_length), sizeof(uint32_t));
329 blob->resize(blob_length);
330 in.elements.read(reinterpret_cast<char*>(&offset), sizeof(uint32_t));
331 in.indirect.seekg(offset);
332 in.indirect.read(reinterpret_cast<char*>(&(*blob)[0]), blob->size());
333 return in;
334 }
335
336 template <typename T>
deserializeParamValue(InStreams & in,T * value)337 InStreams& deserializeParamValue(InStreams& in, T* value) {
338 in.elements.read(reinterpret_cast<char*>(value), sizeof(T));
339 return in;
340 }
341
deserialize(TAG_INVALID_t &&,InStreams & in,KeyParameter *)342 InStreams& deserialize(TAG_INVALID_t&&, InStreams& in, KeyParameter*) {
343 // there should be no invalid KeyParamaters but if handle them as zero sized.
344 return in;
345 }
346
347 template <typename T>
deserialize(T && ttag,InStreams & in,KeyParameter * param)348 InStreams& deserialize(T&& ttag, InStreams& in, KeyParameter* param) {
349 return deserializeParamValue(in, &accessTagValue(ttag, *param));
350 }
351
352 template <typename... T>
353 struct choose_deserializer;
354 template <typename... Tags>
355 struct choose_deserializer<MetaList<Tags...>> {
deserializekeystore::choose_deserializer356 static InStreams& deserialize(InStreams& in, KeyParameter* param) {
357 return choose_deserializer<Tags...>::deserialize(in, param);
358 }
359 };
360 template <>
361 struct choose_deserializer<> {
deserializekeystore::choose_deserializer362 static InStreams& deserialize(InStreams& in, KeyParameter*) {
363 // encountered an unknown tag -> fail parsing
364 in.elements.setstate(std::ios_base::badbit);
365 return in;
366 }
367 };
368 template <TagType tag_type, Tag tag, typename... Tail>
369 struct choose_deserializer<TypedTag<tag_type, tag>, Tail...> {
deserializekeystore::choose_deserializer370 static InStreams& deserialize(InStreams& in, KeyParameter* param) {
371 if (param->tag == tag) {
372 return keystore::deserialize(TypedTag<tag_type, tag>(), in, param);
373 } else {
374 return choose_deserializer<Tail...>::deserialize(in, param);
375 }
376 }
377 };
378
deserialize(InStreams & in,KeyParameter * param)379 InStreams& deserialize(InStreams& in, KeyParameter* param) {
380 in.elements.read(reinterpret_cast<char*>(¶m->tag), sizeof(Tag));
381 return choose_deserializer<all_tags_t>::deserialize(in, param);
382 }
383
deserialize(std::istream & in,std::vector<KeyParameter> * params)384 std::istream& deserialize(std::istream& in, std::vector<KeyParameter>* params) {
385 uint32_t indirect_size = 0;
386 in.read(reinterpret_cast<char*>(&indirect_size), sizeof(uint32_t));
387 std::string indirect_buffer(indirect_size, '\0');
388 if (indirect_buffer.size() != indirect_size) {
389 in.setstate(std::ios_base::badbit);
390 return in;
391 }
392 in.read(&indirect_buffer[0], indirect_buffer.size());
393
394 uint32_t element_count = 0;
395 in.read(reinterpret_cast<char*>(&element_count), sizeof(uint32_t));
396 uint32_t elements_size = 0;
397 in.read(reinterpret_cast<char*>(&elements_size), sizeof(uint32_t));
398
399 std::string elements_buffer(elements_size, '\0');
400 if(elements_buffer.size() != elements_size) {
401 in.setstate(std::ios_base::badbit);
402 return in;
403 }
404 in.read(&elements_buffer[0], elements_buffer.size());
405
406 if (in.bad()) return in;
407
408 // TODO write one-shot stream buffer to avoid copying here
409 std::stringstream indirect(indirect_buffer);
410 std::stringstream elements(elements_buffer);
411 InStreams streams = { indirect, elements };
412
413 params->resize(element_count);
414
415 for (uint32_t i = 0; i < element_count; ++i) {
416 deserialize(streams, &(*params)[i]);
417 }
418 return in;
419 }
Serialize(std::ostream * out) const420 void AuthorizationSet::Serialize(std::ostream* out) const {
421 serialize(*out, data_);
422 }
Deserialize(std::istream * in)423 void AuthorizationSet::Deserialize(std::istream* in) {
424 deserialize(*in, &data_);
425 }
426
427 } // namespace keystore
428