• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2017 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 <keymasterV4_0/authorization_set.h>
18 
19 #include <assert.h>
20 
21 #include <android-base/logging.h>
22 
23 namespace android {
24 namespace hardware {
25 namespace keymaster {
26 namespace V4_0 {
27 
keyParamLess(const KeyParameter & a,const KeyParameter & b)28 inline bool keyParamLess(const KeyParameter& a, const KeyParameter& b) {
29     if (a.tag != b.tag) return a.tag < b.tag;
30     int retval;
31     switch (typeFromTag(a.tag)) {
32         case TagType::INVALID:
33         case TagType::BOOL:
34             return false;
35         case TagType::ENUM:
36         case TagType::ENUM_REP:
37         case TagType::UINT:
38         case TagType::UINT_REP:
39             return a.f.integer < b.f.integer;
40         case TagType::ULONG:
41         case TagType::ULONG_REP:
42             return a.f.longInteger < b.f.longInteger;
43         case TagType::DATE:
44             return a.f.dateTime < b.f.dateTime;
45         case TagType::BIGNUM:
46         case TagType::BYTES:
47             // Handle the empty cases.
48             if (a.blob.size() == 0) return b.blob.size() != 0;
49             if (b.blob.size() == 0) return false;
50 
51             retval = memcmp(&a.blob[0], &b.blob[0], std::min(a.blob.size(), b.blob.size()));
52             // if one is the prefix of the other the longer wins
53             if (retval == 0) return a.blob.size() < b.blob.size();
54             // Otherwise a is less if a is less.
55             else
56                 return retval < 0;
57     }
58     return false;
59 }
60 
keyParamEqual(const KeyParameter & a,const KeyParameter & b)61 inline bool keyParamEqual(const KeyParameter& a, const KeyParameter& b) {
62     if (a.tag != b.tag) return false;
63 
64     switch (typeFromTag(a.tag)) {
65         case TagType::INVALID:
66         case TagType::BOOL:
67             return true;
68         case TagType::ENUM:
69         case TagType::ENUM_REP:
70         case TagType::UINT:
71         case TagType::UINT_REP:
72             return a.f.integer == b.f.integer;
73         case TagType::ULONG:
74         case TagType::ULONG_REP:
75             return a.f.longInteger == b.f.longInteger;
76         case TagType::DATE:
77             return a.f.dateTime == b.f.dateTime;
78         case TagType::BIGNUM:
79         case TagType::BYTES:
80             if (a.blob.size() != b.blob.size()) return false;
81             return a.blob.size() == 0 || memcmp(&a.blob[0], &b.blob[0], a.blob.size()) == 0;
82     }
83     return false;
84 }
85 
Sort()86 void AuthorizationSet::Sort() {
87     std::sort(data_.begin(), data_.end(), keyParamLess);
88 }
89 
Deduplicate()90 void AuthorizationSet::Deduplicate() {
91     if (data_.empty()) return;
92 
93     Sort();
94     std::vector<KeyParameter> result;
95 
96     auto curr = data_.begin();
97     auto prev = curr++;
98     for (; curr != data_.end(); ++prev, ++curr) {
99         if (prev->tag == Tag::INVALID) continue;
100 
101         if (!keyParamEqual(*prev, *curr)) {
102             result.push_back(std::move(*prev));
103         }
104     }
105     result.push_back(std::move(*prev));
106 
107     std::swap(data_, result);
108 }
109 
Union(const AuthorizationSet & other)110 void AuthorizationSet::Union(const AuthorizationSet& other) {
111     data_.insert(data_.end(), other.data_.begin(), other.data_.end());
112     Deduplicate();
113 }
114 
Subtract(const AuthorizationSet & other)115 void AuthorizationSet::Subtract(const AuthorizationSet& other) {
116     Deduplicate();
117 
118     auto i = other.begin();
119     while (i != other.end()) {
120         int pos = -1;
121         do {
122             pos = find(i->tag, pos);
123             if (pos != -1 && keyParamEqual(*i, data_[pos])) {
124                 data_.erase(data_.begin() + pos);
125                 break;
126             }
127         } while (pos != -1);
128         ++i;
129     }
130 }
131 
Filter(std::function<bool (const KeyParameter &)> doKeep)132 void AuthorizationSet::Filter(std::function<bool(const KeyParameter&)> doKeep) {
133     std::vector<KeyParameter> result;
134     for (auto& param : data_) {
135         if (doKeep(param)) {
136             result.push_back(std::move(param));
137         }
138     }
139     std::swap(data_, result);
140 }
141 
operator [](int at)142 KeyParameter& AuthorizationSet::operator[](int at) {
143     return data_[at];
144 }
145 
operator [](int at) const146 const KeyParameter& AuthorizationSet::operator[](int at) const {
147     return data_[at];
148 }
149 
Clear()150 void AuthorizationSet::Clear() {
151     data_.clear();
152 }
153 
GetTagCount(Tag tag) const154 size_t AuthorizationSet::GetTagCount(Tag tag) const {
155     size_t count = 0;
156     for (int pos = -1; (pos = find(tag, pos)) != -1;) ++count;
157     return count;
158 }
159 
find(Tag tag,int begin) const160 int AuthorizationSet::find(Tag tag, int begin) const {
161     auto iter = data_.begin() + (1 + begin);
162 
163     while (iter != data_.end() && iter->tag != tag) ++iter;
164 
165     if (iter != data_.end()) return iter - data_.begin();
166     return -1;
167 }
168 
erase(int index)169 bool AuthorizationSet::erase(int index) {
170     auto pos = data_.begin() + index;
171     if (pos != data_.end()) {
172         data_.erase(pos);
173         return true;
174     }
175     return false;
176 }
177 
GetEntry(Tag tag) const178 NullOr<const KeyParameter&> AuthorizationSet::GetEntry(Tag tag) const {
179     int pos = find(tag);
180     if (pos == -1) return {};
181     return data_[pos];
182 }
183 
184 /**
185  * Persistent format is:
186  * | 32 bit indirect_size         |
187  * --------------------------------
188  * | indirect_size bytes of data  | this is where the blob data is stored
189  * --------------------------------
190  * | 32 bit element_count         | number of entries
191  * | 32 bit elements_size         | total bytes used by entries (entries have variable length)
192  * --------------------------------
193  * | elementes_size bytes of data | where the elements are stored
194  */
195 
196 /**
197  * Persistent format of blobs and bignums:
198  * | 32 bit tag             |
199  * | 32 bit blob_length     |
200  * | 32 bit indirect_offset |
201  */
202 
203 struct OutStreams {
204     std::ostream& indirect;
205     std::ostream& elements;
206     size_t skipped;
207 };
208 
serializeParamValue(OutStreams & out,const hidl_vec<uint8_t> & blob)209 OutStreams& serializeParamValue(OutStreams& out, const hidl_vec<uint8_t>& blob) {
210     uint32_t buffer;
211 
212     // write blob_length
213     auto blob_length = blob.size();
214     if (blob_length > std::numeric_limits<uint32_t>::max()) {
215         out.elements.setstate(std::ios_base::badbit);
216         return out;
217     }
218     buffer = blob_length;
219     out.elements.write(reinterpret_cast<const char*>(&buffer), sizeof(uint32_t));
220 
221     // write indirect_offset
222     auto offset = out.indirect.tellp();
223     if (offset < 0 || offset > std::numeric_limits<uint32_t>::max() ||
224         uint32_t(offset) + uint32_t(blob_length) < uint32_t(offset)) {  // overflow check
225         out.elements.setstate(std::ios_base::badbit);
226         return out;
227     }
228     buffer = offset;
229     out.elements.write(reinterpret_cast<const char*>(&buffer), sizeof(uint32_t));
230 
231     // write blob to indirect stream
232     if (blob_length) out.indirect.write(reinterpret_cast<const char*>(&blob[0]), blob_length);
233 
234     return out;
235 }
236 
237 template <typename T>
serializeParamValue(OutStreams & out,const T & value)238 OutStreams& serializeParamValue(OutStreams& out, const T& value) {
239     out.elements.write(reinterpret_cast<const char*>(&value), sizeof(T));
240     return out;
241 }
242 
serialize(TAG_INVALID_t &&,OutStreams & out,const KeyParameter &)243 OutStreams& serialize(TAG_INVALID_t&&, OutStreams& out, const KeyParameter&) {
244     // skip invalid entries.
245     ++out.skipped;
246     return out;
247 }
248 template <typename T>
serialize(T ttag,OutStreams & out,const KeyParameter & param)249 OutStreams& serialize(T ttag, OutStreams& out, const KeyParameter& param) {
250     out.elements.write(reinterpret_cast<const char*>(&param.tag), sizeof(int32_t));
251     return serializeParamValue(out, accessTagValue(ttag, param));
252 }
253 
254 template <typename... T>
255 struct choose_serializer;
256 template <typename... Tags>
257 struct choose_serializer<MetaList<Tags...>> {
serializeandroid::hardware::keymaster::V4_0::choose_serializer258     static OutStreams& serialize(OutStreams& out, const KeyParameter& param) {
259         return choose_serializer<Tags...>::serialize(out, param);
260     }
261 };
262 
263 template <>
264 struct choose_serializer<> {
serializeandroid::hardware::keymaster::V4_0::choose_serializer265     static OutStreams& serialize(OutStreams& out, const KeyParameter& param) {
266         LOG(WARNING) << "Trying to serialize unknown tag " << unsigned(param.tag)
267                      << ". Did you forget to add it to all_tags_t?";
268         ++out.skipped;
269         return out;
270     }
271 };
272 
273 template <TagType tag_type, Tag tag, typename... Tail>
274 struct choose_serializer<TypedTag<tag_type, tag>, Tail...> {
serializeandroid::hardware::keymaster::V4_0::choose_serializer275     static OutStreams& serialize(OutStreams& out, const KeyParameter& param) {
276         if (param.tag == tag) {
277             return V4_0::serialize(TypedTag<tag_type, tag>(), out, param);
278         } else {
279             return choose_serializer<Tail...>::serialize(out, param);
280         }
281     }
282 };
283 
serialize(OutStreams & out,const KeyParameter & param)284 OutStreams& serialize(OutStreams& out, const KeyParameter& param) {
285     return choose_serializer<all_tags_t>::serialize(out, param);
286 }
287 
serialize(std::ostream & out,const std::vector<KeyParameter> & params)288 std::ostream& serialize(std::ostream& out, const std::vector<KeyParameter>& params) {
289     std::stringstream indirect;
290     std::stringstream elements;
291     OutStreams streams = {indirect, elements, 0};
292     for (const auto& param : params) {
293         serialize(streams, param);
294     }
295     if (indirect.bad() || elements.bad()) {
296         out.setstate(std::ios_base::badbit);
297         return out;
298     }
299     auto pos = indirect.tellp();
300     if (pos < 0 || pos > std::numeric_limits<uint32_t>::max()) {
301         out.setstate(std::ios_base::badbit);
302         return out;
303     }
304     uint32_t indirect_size = pos;
305     pos = elements.tellp();
306     if (pos < 0 || pos > std::numeric_limits<uint32_t>::max()) {
307         out.setstate(std::ios_base::badbit);
308         return out;
309     }
310     uint32_t elements_size = pos;
311     uint32_t element_count = params.size() - streams.skipped;
312 
313     out.write(reinterpret_cast<const char*>(&indirect_size), sizeof(uint32_t));
314 
315     pos = out.tellp();
316     if (indirect_size) out << indirect.rdbuf();
317     assert(out.tellp() - pos == indirect_size);
318 
319     out.write(reinterpret_cast<const char*>(&element_count), sizeof(uint32_t));
320     out.write(reinterpret_cast<const char*>(&elements_size), sizeof(uint32_t));
321 
322     pos = out.tellp();
323     if (elements_size) out << elements.rdbuf();
324     assert(out.tellp() - pos == elements_size);
325 
326     return out;
327 }
328 
329 struct InStreams {
330     std::istream& indirect;
331     std::istream& elements;
332     size_t invalids;
333 };
334 
deserializeParamValue(InStreams & in,hidl_vec<uint8_t> * blob)335 InStreams& deserializeParamValue(InStreams& in, hidl_vec<uint8_t>* blob) {
336     uint32_t blob_length = 0;
337     uint32_t offset = 0;
338     in.elements.read(reinterpret_cast<char*>(&blob_length), sizeof(uint32_t));
339     blob->resize(blob_length);
340     in.elements.read(reinterpret_cast<char*>(&offset), sizeof(uint32_t));
341     in.indirect.seekg(offset);
342     in.indirect.read(reinterpret_cast<char*>(&(*blob)[0]), blob->size());
343     return in;
344 }
345 
346 template <typename T>
deserializeParamValue(InStreams & in,T * value)347 InStreams& deserializeParamValue(InStreams& in, T* value) {
348     in.elements.read(reinterpret_cast<char*>(value), sizeof(T));
349     return in;
350 }
351 
deserialize(TAG_INVALID_t &&,InStreams & in,KeyParameter *)352 InStreams& deserialize(TAG_INVALID_t&&, InStreams& in, KeyParameter*) {
353     // there should be no invalid KeyParamaters but if handle them as zero sized.
354     ++in.invalids;
355     return in;
356 }
357 
358 template <typename T>
deserialize(T && ttag,InStreams & in,KeyParameter * param)359 InStreams& deserialize(T&& ttag, InStreams& in, KeyParameter* param) {
360     return deserializeParamValue(in, &accessTagValue(ttag, *param));
361 }
362 
363 template <typename... T>
364 struct choose_deserializer;
365 template <typename... Tags>
366 struct choose_deserializer<MetaList<Tags...>> {
deserializeandroid::hardware::keymaster::V4_0::choose_deserializer367     static InStreams& deserialize(InStreams& in, KeyParameter* param) {
368         return choose_deserializer<Tags...>::deserialize(in, param);
369     }
370 };
371 template <>
372 struct choose_deserializer<> {
deserializeandroid::hardware::keymaster::V4_0::choose_deserializer373     static InStreams& deserialize(InStreams& in, KeyParameter*) {
374         // encountered an unknown tag -> fail parsing
375         in.elements.setstate(std::ios_base::badbit);
376         return in;
377     }
378 };
379 template <TagType tag_type, Tag tag, typename... Tail>
380 struct choose_deserializer<TypedTag<tag_type, tag>, Tail...> {
deserializeandroid::hardware::keymaster::V4_0::choose_deserializer381     static InStreams& deserialize(InStreams& in, KeyParameter* param) {
382         if (param->tag == tag) {
383             return V4_0::deserialize(TypedTag<tag_type, tag>(), in, param);
384         } else {
385             return choose_deserializer<Tail...>::deserialize(in, param);
386         }
387     }
388 };
389 
deserialize(InStreams & in,KeyParameter * param)390 InStreams& deserialize(InStreams& in, KeyParameter* param) {
391     in.elements.read(reinterpret_cast<char*>(&param->tag), sizeof(Tag));
392     return choose_deserializer<all_tags_t>::deserialize(in, param);
393 }
394 
deserialize(std::istream & in,std::vector<KeyParameter> * params)395 std::istream& deserialize(std::istream& in, std::vector<KeyParameter>* params) {
396     uint32_t indirect_size = 0;
397     in.read(reinterpret_cast<char*>(&indirect_size), sizeof(uint32_t));
398     std::string indirect_buffer(indirect_size, '\0');
399     if (indirect_buffer.size() != indirect_size) {
400         in.setstate(std::ios_base::badbit);
401         return in;
402     }
403     in.read(&indirect_buffer[0], indirect_buffer.size());
404 
405     uint32_t element_count = 0;
406     in.read(reinterpret_cast<char*>(&element_count), sizeof(uint32_t));
407     uint32_t elements_size = 0;
408     in.read(reinterpret_cast<char*>(&elements_size), sizeof(uint32_t));
409 
410     std::string elements_buffer(elements_size, '\0');
411     if (elements_buffer.size() != elements_size) {
412         in.setstate(std::ios_base::badbit);
413         return in;
414     }
415     in.read(&elements_buffer[0], elements_buffer.size());
416 
417     if (in.bad()) return in;
418 
419     // TODO write one-shot stream buffer to avoid copying here
420     std::stringstream indirect(indirect_buffer);
421     std::stringstream elements(elements_buffer);
422     InStreams streams = {indirect, elements, 0};
423 
424     params->resize(element_count);
425 
426     for (uint32_t i = 0; i < element_count; ++i) {
427         deserialize(streams, &(*params)[i]);
428     }
429 
430     /*
431      * There are legacy blobs which have invalid tags in them due to a bug during serialization.
432      * This makes sure that invalid tags are filtered from the result before it is returned.
433      */
434     if (streams.invalids > 0) {
435         std::vector<KeyParameter> filtered(element_count - streams.invalids);
436         auto ifiltered = filtered.begin();
437         for (auto& p : *params) {
438             if (p.tag != Tag::INVALID) {
439                 *ifiltered++ = std::move(p);
440             }
441         }
442         *params = std::move(filtered);
443     }
444     return in;
445 }
446 
Serialize(std::ostream * out) const447 void AuthorizationSet::Serialize(std::ostream* out) const {
448     serialize(*out, data_);
449 }
450 
Deserialize(std::istream * in)451 void AuthorizationSet::Deserialize(std::istream* in) {
452     deserialize(*in, &data_);
453 }
454 
RsaKey(uint32_t key_size,uint64_t public_exponent)455 AuthorizationSetBuilder& AuthorizationSetBuilder::RsaKey(uint32_t key_size,
456                                                          uint64_t public_exponent) {
457     Authorization(TAG_ALGORITHM, Algorithm::RSA);
458     Authorization(TAG_KEY_SIZE, key_size);
459     Authorization(TAG_RSA_PUBLIC_EXPONENT, public_exponent);
460     return *this;
461 }
462 
EcdsaKey(uint32_t key_size)463 AuthorizationSetBuilder& AuthorizationSetBuilder::EcdsaKey(uint32_t key_size) {
464     Authorization(TAG_ALGORITHM, Algorithm::EC);
465     Authorization(TAG_KEY_SIZE, key_size);
466     return *this;
467 }
468 
EcdsaKey(EcCurve curve)469 AuthorizationSetBuilder& AuthorizationSetBuilder::EcdsaKey(EcCurve curve) {
470     Authorization(TAG_ALGORITHM, Algorithm::EC);
471     Authorization(TAG_EC_CURVE, curve);
472     return *this;
473 }
474 
AesKey(uint32_t key_size)475 AuthorizationSetBuilder& AuthorizationSetBuilder::AesKey(uint32_t key_size) {
476     Authorization(TAG_ALGORITHM, Algorithm::AES);
477     return Authorization(TAG_KEY_SIZE, key_size);
478 }
479 
TripleDesKey(uint32_t key_size)480 AuthorizationSetBuilder& AuthorizationSetBuilder::TripleDesKey(uint32_t key_size) {
481     Authorization(TAG_ALGORITHM, Algorithm::TRIPLE_DES);
482     return Authorization(TAG_KEY_SIZE, key_size);
483 }
484 
HmacKey(uint32_t key_size)485 AuthorizationSetBuilder& AuthorizationSetBuilder::HmacKey(uint32_t key_size) {
486     Authorization(TAG_ALGORITHM, Algorithm::HMAC);
487     Authorization(TAG_KEY_SIZE, key_size);
488     return SigningKey();
489 }
490 
RsaSigningKey(uint32_t key_size,uint64_t public_exponent)491 AuthorizationSetBuilder& AuthorizationSetBuilder::RsaSigningKey(uint32_t key_size,
492                                                                 uint64_t public_exponent) {
493     RsaKey(key_size, public_exponent);
494     return SigningKey();
495 }
496 
RsaEncryptionKey(uint32_t key_size,uint64_t public_exponent)497 AuthorizationSetBuilder& AuthorizationSetBuilder::RsaEncryptionKey(uint32_t key_size,
498                                                                    uint64_t public_exponent) {
499     RsaKey(key_size, public_exponent);
500     return EncryptionKey();
501 }
502 
EcdsaSigningKey(uint32_t key_size)503 AuthorizationSetBuilder& AuthorizationSetBuilder::EcdsaSigningKey(uint32_t key_size) {
504     EcdsaKey(key_size);
505     return SigningKey();
506 }
507 
EcdsaSigningKey(EcCurve curve)508 AuthorizationSetBuilder& AuthorizationSetBuilder::EcdsaSigningKey(EcCurve curve) {
509     EcdsaKey(curve);
510     return SigningKey();
511 }
512 
AesEncryptionKey(uint32_t key_size)513 AuthorizationSetBuilder& AuthorizationSetBuilder::AesEncryptionKey(uint32_t key_size) {
514     AesKey(key_size);
515     return EncryptionKey();
516 }
517 
TripleDesEncryptionKey(uint32_t key_size)518 AuthorizationSetBuilder& AuthorizationSetBuilder::TripleDesEncryptionKey(uint32_t key_size) {
519     TripleDesKey(key_size);
520     return EncryptionKey();
521 }
522 
SigningKey()523 AuthorizationSetBuilder& AuthorizationSetBuilder::SigningKey() {
524     Authorization(TAG_PURPOSE, KeyPurpose::SIGN);
525     return Authorization(TAG_PURPOSE, KeyPurpose::VERIFY);
526 }
527 
EncryptionKey()528 AuthorizationSetBuilder& AuthorizationSetBuilder::EncryptionKey() {
529     Authorization(TAG_PURPOSE, KeyPurpose::ENCRYPT);
530     return Authorization(TAG_PURPOSE, KeyPurpose::DECRYPT);
531 }
532 
NoDigestOrPadding()533 AuthorizationSetBuilder& AuthorizationSetBuilder::NoDigestOrPadding() {
534     Authorization(TAG_DIGEST, Digest::NONE);
535     return Authorization(TAG_PADDING, PaddingMode::NONE);
536 }
537 
EcbMode()538 AuthorizationSetBuilder& AuthorizationSetBuilder::EcbMode() {
539     return Authorization(TAG_BLOCK_MODE, BlockMode::ECB);
540 }
541 
GcmModeMinMacLen(uint32_t minMacLength)542 AuthorizationSetBuilder& AuthorizationSetBuilder::GcmModeMinMacLen(uint32_t minMacLength) {
543     return BlockMode(BlockMode::GCM)
544         .Padding(PaddingMode::NONE)
545         .Authorization(TAG_MIN_MAC_LENGTH, minMacLength);
546 }
547 
GcmModeMacLen(uint32_t macLength)548 AuthorizationSetBuilder& AuthorizationSetBuilder::GcmModeMacLen(uint32_t macLength) {
549     return BlockMode(BlockMode::GCM)
550         .Padding(PaddingMode::NONE)
551         .Authorization(TAG_MAC_LENGTH, macLength);
552 }
553 
BlockMode(std::initializer_list<V4_0::BlockMode> blockModes)554 AuthorizationSetBuilder& AuthorizationSetBuilder::BlockMode(
555     std::initializer_list<V4_0::BlockMode> blockModes) {
556     for (auto mode : blockModes) {
557         push_back(TAG_BLOCK_MODE, mode);
558     }
559     return *this;
560 }
561 
Digest(std::vector<V4_0::Digest> digests)562 AuthorizationSetBuilder& AuthorizationSetBuilder::Digest(std::vector<V4_0::Digest> digests) {
563     for (auto digest : digests) {
564         push_back(TAG_DIGEST, digest);
565     }
566     return *this;
567 }
568 
Padding(std::initializer_list<V4_0::PaddingMode> paddingModes)569 AuthorizationSetBuilder& AuthorizationSetBuilder::Padding(
570     std::initializer_list<V4_0::PaddingMode> paddingModes) {
571     for (auto paddingMode : paddingModes) {
572         push_back(TAG_PADDING, paddingMode);
573     }
574     return *this;
575 }
576 
577 }  // namespace V4_0
578 }  // namespace keymaster
579 }  // namespace hardware
580 }  // namespace android
581