xref: /aosp_15_r20/system/keymaster/android_keymaster/authorization_set.cpp (revision 789431f29546679ab5188a97751fb38e3018d44d)
1*789431f2SAndroid Build Coastguard Worker /*
2*789431f2SAndroid Build Coastguard Worker  * Copyright (C) 2014 The Android Open Source Project
3*789431f2SAndroid Build Coastguard Worker  *
4*789431f2SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*789431f2SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*789431f2SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*789431f2SAndroid Build Coastguard Worker  *
8*789431f2SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*789431f2SAndroid Build Coastguard Worker  *
10*789431f2SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*789431f2SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*789431f2SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*789431f2SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*789431f2SAndroid Build Coastguard Worker  * limitations under the License.
15*789431f2SAndroid Build Coastguard Worker  */
16*789431f2SAndroid Build Coastguard Worker 
17*789431f2SAndroid Build Coastguard Worker #include <keymaster/authorization_set.h>
18*789431f2SAndroid Build Coastguard Worker 
19*789431f2SAndroid Build Coastguard Worker #include <assert.h>
20*789431f2SAndroid Build Coastguard Worker #include <stddef.h>
21*789431f2SAndroid Build Coastguard Worker #include <stdlib.h>
22*789431f2SAndroid Build Coastguard Worker #include <string.h>
23*789431f2SAndroid Build Coastguard Worker 
24*789431f2SAndroid Build Coastguard Worker #include <keymaster/android_keymaster_utils.h>
25*789431f2SAndroid Build Coastguard Worker #include <keymaster/logger.h>
26*789431f2SAndroid Build Coastguard Worker 
27*789431f2SAndroid Build Coastguard Worker namespace keymaster {
28*789431f2SAndroid Build Coastguard Worker 
is_blob_tag(keymaster_tag_t tag)29*789431f2SAndroid Build Coastguard Worker static inline bool is_blob_tag(keymaster_tag_t tag) {
30*789431f2SAndroid Build Coastguard Worker     return (keymaster_tag_get_type(tag) == KM_BYTES || keymaster_tag_get_type(tag) == KM_BIGNUM);
31*789431f2SAndroid Build Coastguard Worker }
32*789431f2SAndroid Build Coastguard Worker 
33*789431f2SAndroid Build Coastguard Worker const size_t STARTING_ELEMS_CAPACITY = 8;
34*789431f2SAndroid Build Coastguard Worker 
AuthorizationSet(AuthorizationSetBuilder & builder)35*789431f2SAndroid Build Coastguard Worker AuthorizationSet::AuthorizationSet(AuthorizationSetBuilder& builder) {
36*789431f2SAndroid Build Coastguard Worker     elems_ = builder.set.elems_;
37*789431f2SAndroid Build Coastguard Worker     builder.set.elems_ = nullptr;
38*789431f2SAndroid Build Coastguard Worker 
39*789431f2SAndroid Build Coastguard Worker     elems_size_ = builder.set.elems_size_;
40*789431f2SAndroid Build Coastguard Worker     builder.set.elems_size_ = 0;
41*789431f2SAndroid Build Coastguard Worker 
42*789431f2SAndroid Build Coastguard Worker     elems_capacity_ = builder.set.elems_capacity_;
43*789431f2SAndroid Build Coastguard Worker     builder.set.elems_capacity_ = 0;
44*789431f2SAndroid Build Coastguard Worker 
45*789431f2SAndroid Build Coastguard Worker     indirect_data_ = builder.set.indirect_data_;
46*789431f2SAndroid Build Coastguard Worker     builder.set.indirect_data_ = nullptr;
47*789431f2SAndroid Build Coastguard Worker 
48*789431f2SAndroid Build Coastguard Worker     indirect_data_capacity_ = builder.set.indirect_data_capacity_;
49*789431f2SAndroid Build Coastguard Worker     builder.set.indirect_data_capacity_ = 0;
50*789431f2SAndroid Build Coastguard Worker 
51*789431f2SAndroid Build Coastguard Worker     indirect_data_size_ = builder.set.indirect_data_size_;
52*789431f2SAndroid Build Coastguard Worker     builder.set.indirect_data_size_ = 0;
53*789431f2SAndroid Build Coastguard Worker 
54*789431f2SAndroid Build Coastguard Worker     error_ = builder.set.error_;
55*789431f2SAndroid Build Coastguard Worker     builder.set.error_ = OK;
56*789431f2SAndroid Build Coastguard Worker }
57*789431f2SAndroid Build Coastguard Worker 
~AuthorizationSet()58*789431f2SAndroid Build Coastguard Worker AuthorizationSet::~AuthorizationSet() {
59*789431f2SAndroid Build Coastguard Worker     FreeData();
60*789431f2SAndroid Build Coastguard Worker }
61*789431f2SAndroid Build Coastguard Worker 
reserve_elems(size_t count)62*789431f2SAndroid Build Coastguard Worker bool AuthorizationSet::reserve_elems(size_t count) {
63*789431f2SAndroid Build Coastguard Worker     if (is_valid() != OK) return false;
64*789431f2SAndroid Build Coastguard Worker 
65*789431f2SAndroid Build Coastguard Worker     if (count > elems_capacity_) {
66*789431f2SAndroid Build Coastguard Worker         keymaster_key_param_t* new_elems = new (std::nothrow) keymaster_key_param_t[count];
67*789431f2SAndroid Build Coastguard Worker         if (new_elems == nullptr) {
68*789431f2SAndroid Build Coastguard Worker             set_invalid(ALLOCATION_FAILURE);
69*789431f2SAndroid Build Coastguard Worker             return false;
70*789431f2SAndroid Build Coastguard Worker         }
71*789431f2SAndroid Build Coastguard Worker         memcpy(new_elems, elems_, sizeof(*elems_) * elems_size_);
72*789431f2SAndroid Build Coastguard Worker         delete[] elems_;
73*789431f2SAndroid Build Coastguard Worker         elems_ = new_elems;
74*789431f2SAndroid Build Coastguard Worker         elems_capacity_ = count;
75*789431f2SAndroid Build Coastguard Worker     }
76*789431f2SAndroid Build Coastguard Worker     return true;
77*789431f2SAndroid Build Coastguard Worker }
78*789431f2SAndroid Build Coastguard Worker 
reserve_indirect(size_t length)79*789431f2SAndroid Build Coastguard Worker bool AuthorizationSet::reserve_indirect(size_t length) {
80*789431f2SAndroid Build Coastguard Worker     if (is_valid() != OK) return false;
81*789431f2SAndroid Build Coastguard Worker 
82*789431f2SAndroid Build Coastguard Worker     if (length > indirect_data_capacity_) {
83*789431f2SAndroid Build Coastguard Worker         uint8_t* new_data = new (std::nothrow) uint8_t[length];
84*789431f2SAndroid Build Coastguard Worker         if (new_data == nullptr) {
85*789431f2SAndroid Build Coastguard Worker             set_invalid(ALLOCATION_FAILURE);
86*789431f2SAndroid Build Coastguard Worker             return false;
87*789431f2SAndroid Build Coastguard Worker         }
88*789431f2SAndroid Build Coastguard Worker         memcpy(new_data, indirect_data_, indirect_data_size_);
89*789431f2SAndroid Build Coastguard Worker 
90*789431f2SAndroid Build Coastguard Worker         // Fix up the data pointers to point into the new region.
91*789431f2SAndroid Build Coastguard Worker         for (size_t i = 0; i < elems_size_; ++i) {
92*789431f2SAndroid Build Coastguard Worker             if (is_blob_tag(elems_[i].tag))
93*789431f2SAndroid Build Coastguard Worker                 elems_[i].blob.data = new_data + (elems_[i].blob.data - indirect_data_);
94*789431f2SAndroid Build Coastguard Worker         }
95*789431f2SAndroid Build Coastguard Worker         delete[] indirect_data_;
96*789431f2SAndroid Build Coastguard Worker         indirect_data_ = new_data;
97*789431f2SAndroid Build Coastguard Worker         indirect_data_capacity_ = length;
98*789431f2SAndroid Build Coastguard Worker     }
99*789431f2SAndroid Build Coastguard Worker     return true;
100*789431f2SAndroid Build Coastguard Worker }
101*789431f2SAndroid Build Coastguard Worker 
MoveFrom(AuthorizationSet & set)102*789431f2SAndroid Build Coastguard Worker void AuthorizationSet::MoveFrom(AuthorizationSet& set) {
103*789431f2SAndroid Build Coastguard Worker     elems_ = set.elems_;
104*789431f2SAndroid Build Coastguard Worker     elems_size_ = set.elems_size_;
105*789431f2SAndroid Build Coastguard Worker     elems_capacity_ = set.elems_capacity_;
106*789431f2SAndroid Build Coastguard Worker     indirect_data_ = set.indirect_data_;
107*789431f2SAndroid Build Coastguard Worker     indirect_data_size_ = set.indirect_data_size_;
108*789431f2SAndroid Build Coastguard Worker     indirect_data_capacity_ = set.indirect_data_capacity_;
109*789431f2SAndroid Build Coastguard Worker     error_ = set.error_;
110*789431f2SAndroid Build Coastguard Worker     set.elems_ = nullptr;
111*789431f2SAndroid Build Coastguard Worker     set.elems_size_ = 0;
112*789431f2SAndroid Build Coastguard Worker     set.elems_capacity_ = 0;
113*789431f2SAndroid Build Coastguard Worker     set.indirect_data_ = nullptr;
114*789431f2SAndroid Build Coastguard Worker     set.indirect_data_size_ = 0;
115*789431f2SAndroid Build Coastguard Worker     set.indirect_data_capacity_ = 0;
116*789431f2SAndroid Build Coastguard Worker     set.error_ = OK;
117*789431f2SAndroid Build Coastguard Worker }
118*789431f2SAndroid Build Coastguard Worker 
Reinitialize(const keymaster_key_param_t * elems,const size_t count)119*789431f2SAndroid Build Coastguard Worker bool AuthorizationSet::Reinitialize(const keymaster_key_param_t* elems, const size_t count) {
120*789431f2SAndroid Build Coastguard Worker     FreeData();
121*789431f2SAndroid Build Coastguard Worker 
122*789431f2SAndroid Build Coastguard Worker     if (elems == nullptr || count == 0) {
123*789431f2SAndroid Build Coastguard Worker         error_ = OK;
124*789431f2SAndroid Build Coastguard Worker         return true;
125*789431f2SAndroid Build Coastguard Worker     }
126*789431f2SAndroid Build Coastguard Worker 
127*789431f2SAndroid Build Coastguard Worker     if (!reserve_elems(count)) return false;
128*789431f2SAndroid Build Coastguard Worker 
129*789431f2SAndroid Build Coastguard Worker     if (!reserve_indirect(ComputeIndirectDataSize(elems, count))) return false;
130*789431f2SAndroid Build Coastguard Worker 
131*789431f2SAndroid Build Coastguard Worker     memcpy(elems_, elems, sizeof(keymaster_key_param_t) * count);
132*789431f2SAndroid Build Coastguard Worker     elems_size_ = count;
133*789431f2SAndroid Build Coastguard Worker     CopyIndirectData();
134*789431f2SAndroid Build Coastguard Worker     error_ = OK;
135*789431f2SAndroid Build Coastguard Worker     return true;
136*789431f2SAndroid Build Coastguard Worker }
137*789431f2SAndroid Build Coastguard Worker 
set_invalid(Error error)138*789431f2SAndroid Build Coastguard Worker void AuthorizationSet::set_invalid(Error error) {
139*789431f2SAndroid Build Coastguard Worker     FreeData();
140*789431f2SAndroid Build Coastguard Worker     error_ = error;
141*789431f2SAndroid Build Coastguard Worker }
142*789431f2SAndroid Build Coastguard Worker 
Sort()143*789431f2SAndroid Build Coastguard Worker void AuthorizationSet::Sort() {
144*789431f2SAndroid Build Coastguard Worker     qsort(elems_, elems_size_, sizeof(*elems_),
145*789431f2SAndroid Build Coastguard Worker           reinterpret_cast<int (*)(const void*, const void*)>(keymaster_param_compare));
146*789431f2SAndroid Build Coastguard Worker }
147*789431f2SAndroid Build Coastguard Worker 
Deduplicate()148*789431f2SAndroid Build Coastguard Worker void AuthorizationSet::Deduplicate() {
149*789431f2SAndroid Build Coastguard Worker     Sort();
150*789431f2SAndroid Build Coastguard Worker 
151*789431f2SAndroid Build Coastguard Worker     size_t invalid_count = 0;
152*789431f2SAndroid Build Coastguard Worker     for (size_t i = 1; i < size(); ++i) {
153*789431f2SAndroid Build Coastguard Worker         if (elems_[i - 1].tag == KM_TAG_INVALID)
154*789431f2SAndroid Build Coastguard Worker             ++invalid_count;
155*789431f2SAndroid Build Coastguard Worker         else if (keymaster_param_compare(elems_ + i - 1, elems_ + i) == 0) {
156*789431f2SAndroid Build Coastguard Worker             // Mark dups as invalid.  Note that this "leaks" the data referenced by KM_BYTES and
157*789431f2SAndroid Build Coastguard Worker             // KM_BIGNUM entries, but those are just pointers into indirect_data_, so it will all
158*789431f2SAndroid Build Coastguard Worker             // get cleaned up.
159*789431f2SAndroid Build Coastguard Worker             elems_[i - 1].tag = KM_TAG_INVALID;
160*789431f2SAndroid Build Coastguard Worker             ++invalid_count;
161*789431f2SAndroid Build Coastguard Worker         }
162*789431f2SAndroid Build Coastguard Worker     }
163*789431f2SAndroid Build Coastguard Worker     if (size() > 0 && elems_[size() - 1].tag == KM_TAG_INVALID) ++invalid_count;
164*789431f2SAndroid Build Coastguard Worker 
165*789431f2SAndroid Build Coastguard Worker     if (invalid_count == 0) return;
166*789431f2SAndroid Build Coastguard Worker 
167*789431f2SAndroid Build Coastguard Worker     Sort();
168*789431f2SAndroid Build Coastguard Worker 
169*789431f2SAndroid Build Coastguard Worker     // Since KM_TAG_INVALID == 0, all of the invalid entries are first.
170*789431f2SAndroid Build Coastguard Worker     elems_size_ -= invalid_count;
171*789431f2SAndroid Build Coastguard Worker     memmove(elems_, elems_ + invalid_count, size() * sizeof(*elems_));
172*789431f2SAndroid Build Coastguard Worker }
173*789431f2SAndroid Build Coastguard Worker 
Difference(const keymaster_key_param_set_t & set)174*789431f2SAndroid Build Coastguard Worker void AuthorizationSet::Difference(const keymaster_key_param_set_t& set) {
175*789431f2SAndroid Build Coastguard Worker     if (set.length == 0) return;
176*789431f2SAndroid Build Coastguard Worker 
177*789431f2SAndroid Build Coastguard Worker     Deduplicate();
178*789431f2SAndroid Build Coastguard Worker 
179*789431f2SAndroid Build Coastguard Worker     for (size_t i = 0; i < set.length; i++) {
180*789431f2SAndroid Build Coastguard Worker         int index = -1;
181*789431f2SAndroid Build Coastguard Worker         do {
182*789431f2SAndroid Build Coastguard Worker             index = find(set.params[i].tag, index);
183*789431f2SAndroid Build Coastguard Worker             if (index != -1 && keymaster_param_compare(&elems_[index], &set.params[i]) == 0) {
184*789431f2SAndroid Build Coastguard Worker                 erase(index);
185*789431f2SAndroid Build Coastguard Worker                 break;
186*789431f2SAndroid Build Coastguard Worker             }
187*789431f2SAndroid Build Coastguard Worker         } while (index != -1);
188*789431f2SAndroid Build Coastguard Worker     }
189*789431f2SAndroid Build Coastguard Worker }
190*789431f2SAndroid Build Coastguard Worker 
CopyToParamSet(keymaster_key_param_set_t * set) const191*789431f2SAndroid Build Coastguard Worker void AuthorizationSet::CopyToParamSet(keymaster_key_param_set_t* set) const {
192*789431f2SAndroid Build Coastguard Worker     assert(set);
193*789431f2SAndroid Build Coastguard Worker 
194*789431f2SAndroid Build Coastguard Worker     set->length = size();
195*789431f2SAndroid Build Coastguard Worker     set->params =
196*789431f2SAndroid Build Coastguard Worker         reinterpret_cast<keymaster_key_param_t*>(malloc(sizeof(keymaster_key_param_t) * size()));
197*789431f2SAndroid Build Coastguard Worker 
198*789431f2SAndroid Build Coastguard Worker     for (size_t i = 0; i < size(); ++i) {
199*789431f2SAndroid Build Coastguard Worker         const keymaster_key_param_t src = (*this)[i];
200*789431f2SAndroid Build Coastguard Worker         keymaster_key_param_t& dst(set->params[i]);
201*789431f2SAndroid Build Coastguard Worker 
202*789431f2SAndroid Build Coastguard Worker         dst = src;
203*789431f2SAndroid Build Coastguard Worker         keymaster_tag_type_t type = keymaster_tag_get_type(src.tag);
204*789431f2SAndroid Build Coastguard Worker         if (type == KM_BIGNUM || type == KM_BYTES) {
205*789431f2SAndroid Build Coastguard Worker             void* tmp = malloc(src.blob.data_length);
206*789431f2SAndroid Build Coastguard Worker             memcpy(tmp, src.blob.data, src.blob.data_length);
207*789431f2SAndroid Build Coastguard Worker             dst.blob.data = reinterpret_cast<uint8_t*>(tmp);
208*789431f2SAndroid Build Coastguard Worker         }
209*789431f2SAndroid Build Coastguard Worker     }
210*789431f2SAndroid Build Coastguard Worker }
211*789431f2SAndroid Build Coastguard Worker 
find(keymaster_tag_t tag,int begin) const212*789431f2SAndroid Build Coastguard Worker int AuthorizationSet::find(keymaster_tag_t tag, int begin) const {
213*789431f2SAndroid Build Coastguard Worker     if (is_valid() != OK) return -1;
214*789431f2SAndroid Build Coastguard Worker 
215*789431f2SAndroid Build Coastguard Worker     int i = ++begin;
216*789431f2SAndroid Build Coastguard Worker     while (i < (int)elems_size_ && elems_[i].tag != tag)
217*789431f2SAndroid Build Coastguard Worker         ++i;
218*789431f2SAndroid Build Coastguard Worker     if (i == (int)elems_size_)
219*789431f2SAndroid Build Coastguard Worker         return -1;
220*789431f2SAndroid Build Coastguard Worker     else
221*789431f2SAndroid Build Coastguard Worker         return i;
222*789431f2SAndroid Build Coastguard Worker }
223*789431f2SAndroid Build Coastguard Worker 
erase(int index)224*789431f2SAndroid Build Coastguard Worker bool AuthorizationSet::erase(int index) {
225*789431f2SAndroid Build Coastguard Worker     if (index < 0 || index >= static_cast<int>(size())) return false;
226*789431f2SAndroid Build Coastguard Worker 
227*789431f2SAndroid Build Coastguard Worker     --elems_size_;
228*789431f2SAndroid Build Coastguard Worker     for (size_t i = index; i < elems_size_; ++i)
229*789431f2SAndroid Build Coastguard Worker         elems_[i] = elems_[i + 1];
230*789431f2SAndroid Build Coastguard Worker     return true;
231*789431f2SAndroid Build Coastguard Worker }
232*789431f2SAndroid Build Coastguard Worker 
233*789431f2SAndroid Build Coastguard Worker keymaster_key_param_t empty_param = {KM_TAG_INVALID, {}};
operator [](int at)234*789431f2SAndroid Build Coastguard Worker keymaster_key_param_t& AuthorizationSet::operator[](int at) {
235*789431f2SAndroid Build Coastguard Worker     if (is_valid() == OK && at < (int)elems_size_) {
236*789431f2SAndroid Build Coastguard Worker         return elems_[at];
237*789431f2SAndroid Build Coastguard Worker     }
238*789431f2SAndroid Build Coastguard Worker     empty_param = {KM_TAG_INVALID, {}};
239*789431f2SAndroid Build Coastguard Worker     return empty_param;
240*789431f2SAndroid Build Coastguard Worker }
241*789431f2SAndroid Build Coastguard Worker 
operator [](int at) const242*789431f2SAndroid Build Coastguard Worker const keymaster_key_param_t& AuthorizationSet::operator[](int at) const {
243*789431f2SAndroid Build Coastguard Worker     if (is_valid() == OK && at < (int)elems_size_) {
244*789431f2SAndroid Build Coastguard Worker         return elems_[at];
245*789431f2SAndroid Build Coastguard Worker     }
246*789431f2SAndroid Build Coastguard Worker     empty_param = {KM_TAG_INVALID, {}};
247*789431f2SAndroid Build Coastguard Worker     return empty_param;
248*789431f2SAndroid Build Coastguard Worker }
249*789431f2SAndroid Build Coastguard Worker 
push_back(const keymaster_key_param_set_t & set)250*789431f2SAndroid Build Coastguard Worker bool AuthorizationSet::push_back(const keymaster_key_param_set_t& set) {
251*789431f2SAndroid Build Coastguard Worker     if (is_valid() != OK) return false;
252*789431f2SAndroid Build Coastguard Worker 
253*789431f2SAndroid Build Coastguard Worker     if (!reserve_elems(elems_size_ + set.length)) return false;
254*789431f2SAndroid Build Coastguard Worker 
255*789431f2SAndroid Build Coastguard Worker     if (!reserve_indirect(indirect_data_size_ + ComputeIndirectDataSize(set.params, set.length)))
256*789431f2SAndroid Build Coastguard Worker         return false;
257*789431f2SAndroid Build Coastguard Worker 
258*789431f2SAndroid Build Coastguard Worker     for (size_t i = 0; i < set.length; ++i)
259*789431f2SAndroid Build Coastguard Worker         if (!push_back(set.params[i])) return false;
260*789431f2SAndroid Build Coastguard Worker 
261*789431f2SAndroid Build Coastguard Worker     return true;
262*789431f2SAndroid Build Coastguard Worker }
263*789431f2SAndroid Build Coastguard Worker 
push_back(keymaster_key_param_t elem)264*789431f2SAndroid Build Coastguard Worker bool AuthorizationSet::push_back(keymaster_key_param_t elem) {
265*789431f2SAndroid Build Coastguard Worker     if (is_valid() != OK) return false;
266*789431f2SAndroid Build Coastguard Worker 
267*789431f2SAndroid Build Coastguard Worker     if (elems_size_ >= elems_capacity_)
268*789431f2SAndroid Build Coastguard Worker         if (!reserve_elems(elems_capacity_ ? elems_capacity_ * 2 : STARTING_ELEMS_CAPACITY))
269*789431f2SAndroid Build Coastguard Worker             return false;
270*789431f2SAndroid Build Coastguard Worker 
271*789431f2SAndroid Build Coastguard Worker     if (is_blob_tag(elem.tag)) {
272*789431f2SAndroid Build Coastguard Worker         if (indirect_data_capacity_ - indirect_data_size_ < elem.blob.data_length)
273*789431f2SAndroid Build Coastguard Worker             if (!reserve_indirect(2 * (indirect_data_capacity_ + elem.blob.data_length)))
274*789431f2SAndroid Build Coastguard Worker                 return false;
275*789431f2SAndroid Build Coastguard Worker 
276*789431f2SAndroid Build Coastguard Worker         memcpy(indirect_data_ + indirect_data_size_, elem.blob.data, elem.blob.data_length);
277*789431f2SAndroid Build Coastguard Worker         elem.blob.data = indirect_data_ + indirect_data_size_;
278*789431f2SAndroid Build Coastguard Worker         indirect_data_size_ += elem.blob.data_length;
279*789431f2SAndroid Build Coastguard Worker     }
280*789431f2SAndroid Build Coastguard Worker 
281*789431f2SAndroid Build Coastguard Worker     elems_[elems_size_++] = elem;
282*789431f2SAndroid Build Coastguard Worker     return true;
283*789431f2SAndroid Build Coastguard Worker }
284*789431f2SAndroid Build Coastguard Worker 
serialized_size(const keymaster_key_param_t & param)285*789431f2SAndroid Build Coastguard Worker static size_t serialized_size(const keymaster_key_param_t& param) {
286*789431f2SAndroid Build Coastguard Worker     switch (keymaster_tag_get_type(param.tag)) {
287*789431f2SAndroid Build Coastguard Worker     case KM_INVALID:
288*789431f2SAndroid Build Coastguard Worker         return sizeof(uint32_t);
289*789431f2SAndroid Build Coastguard Worker     case KM_ENUM:
290*789431f2SAndroid Build Coastguard Worker     case KM_ENUM_REP:
291*789431f2SAndroid Build Coastguard Worker     case KM_UINT:
292*789431f2SAndroid Build Coastguard Worker     case KM_UINT_REP:
293*789431f2SAndroid Build Coastguard Worker         return sizeof(uint32_t) * 2;
294*789431f2SAndroid Build Coastguard Worker     case KM_ULONG:
295*789431f2SAndroid Build Coastguard Worker     case KM_ULONG_REP:
296*789431f2SAndroid Build Coastguard Worker     case KM_DATE:
297*789431f2SAndroid Build Coastguard Worker         return sizeof(uint32_t) + sizeof(uint64_t);
298*789431f2SAndroid Build Coastguard Worker     case KM_BOOL:
299*789431f2SAndroid Build Coastguard Worker         return sizeof(uint32_t) + 1;
300*789431f2SAndroid Build Coastguard Worker     case KM_BIGNUM:
301*789431f2SAndroid Build Coastguard Worker     case KM_BYTES:
302*789431f2SAndroid Build Coastguard Worker         return sizeof(uint32_t) * 3;
303*789431f2SAndroid Build Coastguard Worker     }
304*789431f2SAndroid Build Coastguard Worker 
305*789431f2SAndroid Build Coastguard Worker     return sizeof(uint32_t);
306*789431f2SAndroid Build Coastguard Worker }
307*789431f2SAndroid Build Coastguard Worker 
serialize(const keymaster_key_param_t & param,uint8_t * buf,const uint8_t * end,const uint8_t * indirect_base)308*789431f2SAndroid Build Coastguard Worker static uint8_t* serialize(const keymaster_key_param_t& param, uint8_t* buf, const uint8_t* end,
309*789431f2SAndroid Build Coastguard Worker                           const uint8_t* indirect_base) {
310*789431f2SAndroid Build Coastguard Worker     buf = append_uint32_to_buf(buf, end, param.tag);
311*789431f2SAndroid Build Coastguard Worker     switch (keymaster_tag_get_type(param.tag)) {
312*789431f2SAndroid Build Coastguard Worker     case KM_INVALID:
313*789431f2SAndroid Build Coastguard Worker         break;
314*789431f2SAndroid Build Coastguard Worker     case KM_ENUM:
315*789431f2SAndroid Build Coastguard Worker     case KM_ENUM_REP:
316*789431f2SAndroid Build Coastguard Worker         buf = append_uint32_to_buf(buf, end, param.enumerated);
317*789431f2SAndroid Build Coastguard Worker         break;
318*789431f2SAndroid Build Coastguard Worker     case KM_UINT:
319*789431f2SAndroid Build Coastguard Worker     case KM_UINT_REP:
320*789431f2SAndroid Build Coastguard Worker         buf = append_uint32_to_buf(buf, end, param.integer);
321*789431f2SAndroid Build Coastguard Worker         break;
322*789431f2SAndroid Build Coastguard Worker     case KM_ULONG:
323*789431f2SAndroid Build Coastguard Worker     case KM_ULONG_REP:
324*789431f2SAndroid Build Coastguard Worker         buf = append_uint64_to_buf(buf, end, param.long_integer);
325*789431f2SAndroid Build Coastguard Worker         break;
326*789431f2SAndroid Build Coastguard Worker     case KM_DATE:
327*789431f2SAndroid Build Coastguard Worker         buf = append_uint64_to_buf(buf, end, param.date_time);
328*789431f2SAndroid Build Coastguard Worker         break;
329*789431f2SAndroid Build Coastguard Worker     case KM_BOOL:
330*789431f2SAndroid Build Coastguard Worker         if (buf < end) *buf = static_cast<uint8_t>(param.boolean);
331*789431f2SAndroid Build Coastguard Worker         buf++;
332*789431f2SAndroid Build Coastguard Worker         break;
333*789431f2SAndroid Build Coastguard Worker     case KM_BIGNUM:
334*789431f2SAndroid Build Coastguard Worker     case KM_BYTES:
335*789431f2SAndroid Build Coastguard Worker         buf = append_uint32_to_buf(buf, end, param.blob.data_length);
336*789431f2SAndroid Build Coastguard Worker         buf = append_uint32_to_buf(buf, end, param.blob.data - indirect_base);
337*789431f2SAndroid Build Coastguard Worker         break;
338*789431f2SAndroid Build Coastguard Worker     }
339*789431f2SAndroid Build Coastguard Worker     return buf;
340*789431f2SAndroid Build Coastguard Worker }
341*789431f2SAndroid Build Coastguard Worker 
deserialize(keymaster_key_param_t * param,const uint8_t ** buf_ptr,const uint8_t * end,const uint8_t * indirect_base,const uint8_t * indirect_end)342*789431f2SAndroid Build Coastguard Worker static bool deserialize(keymaster_key_param_t* param, const uint8_t** buf_ptr, const uint8_t* end,
343*789431f2SAndroid Build Coastguard Worker                         const uint8_t* indirect_base, const uint8_t* indirect_end) {
344*789431f2SAndroid Build Coastguard Worker     if (!copy_uint32_from_buf(buf_ptr, end, &param->tag)) return false;
345*789431f2SAndroid Build Coastguard Worker 
346*789431f2SAndroid Build Coastguard Worker     switch (keymaster_tag_get_type(param->tag)) {
347*789431f2SAndroid Build Coastguard Worker     case KM_INVALID:
348*789431f2SAndroid Build Coastguard Worker         return false;
349*789431f2SAndroid Build Coastguard Worker     case KM_ENUM:
350*789431f2SAndroid Build Coastguard Worker     case KM_ENUM_REP:
351*789431f2SAndroid Build Coastguard Worker         return copy_uint32_from_buf(buf_ptr, end, &param->enumerated);
352*789431f2SAndroid Build Coastguard Worker     case KM_UINT:
353*789431f2SAndroid Build Coastguard Worker     case KM_UINT_REP:
354*789431f2SAndroid Build Coastguard Worker         return copy_uint32_from_buf(buf_ptr, end, &param->integer);
355*789431f2SAndroid Build Coastguard Worker     case KM_ULONG:
356*789431f2SAndroid Build Coastguard Worker     case KM_ULONG_REP:
357*789431f2SAndroid Build Coastguard Worker         return copy_uint64_from_buf(buf_ptr, end, &param->long_integer);
358*789431f2SAndroid Build Coastguard Worker     case KM_DATE:
359*789431f2SAndroid Build Coastguard Worker         return copy_uint64_from_buf(buf_ptr, end, &param->date_time);
360*789431f2SAndroid Build Coastguard Worker         break;
361*789431f2SAndroid Build Coastguard Worker     case KM_BOOL:
362*789431f2SAndroid Build Coastguard Worker         if (*buf_ptr < end) {
363*789431f2SAndroid Build Coastguard Worker             uint8_t temp = **buf_ptr;
364*789431f2SAndroid Build Coastguard Worker             // Bools are converted to 0 or 1 when serialized so only accept
365*789431f2SAndroid Build Coastguard Worker             // one of these values when deserializing.
366*789431f2SAndroid Build Coastguard Worker             if (temp <= 1) {
367*789431f2SAndroid Build Coastguard Worker                 param->boolean = static_cast<bool>(temp);
368*789431f2SAndroid Build Coastguard Worker                 (*buf_ptr)++;
369*789431f2SAndroid Build Coastguard Worker                 return true;
370*789431f2SAndroid Build Coastguard Worker             }
371*789431f2SAndroid Build Coastguard Worker         }
372*789431f2SAndroid Build Coastguard Worker         return false;
373*789431f2SAndroid Build Coastguard Worker 
374*789431f2SAndroid Build Coastguard Worker     case KM_BIGNUM:
375*789431f2SAndroid Build Coastguard Worker     case KM_BYTES: {
376*789431f2SAndroid Build Coastguard Worker         uint32_t offset;
377*789431f2SAndroid Build Coastguard Worker         if (!copy_uint32_from_buf(buf_ptr, end, &param->blob.data_length) ||
378*789431f2SAndroid Build Coastguard Worker             !copy_uint32_from_buf(buf_ptr, end, &offset))
379*789431f2SAndroid Build Coastguard Worker             return false;
380*789431f2SAndroid Build Coastguard Worker         if (param->blob.data_length + offset < param->blob.data_length ||  // Overflow check
381*789431f2SAndroid Build Coastguard Worker             static_cast<ptrdiff_t>(offset) > indirect_end - indirect_base ||
382*789431f2SAndroid Build Coastguard Worker             static_cast<ptrdiff_t>(offset + param->blob.data_length) > indirect_end - indirect_base)
383*789431f2SAndroid Build Coastguard Worker             return false;
384*789431f2SAndroid Build Coastguard Worker         param->blob.data = indirect_base + offset;
385*789431f2SAndroid Build Coastguard Worker         return true;
386*789431f2SAndroid Build Coastguard Worker     }
387*789431f2SAndroid Build Coastguard Worker     }
388*789431f2SAndroid Build Coastguard Worker 
389*789431f2SAndroid Build Coastguard Worker     return false;
390*789431f2SAndroid Build Coastguard Worker }
391*789431f2SAndroid Build Coastguard Worker 
SerializedSizeOfElements() const392*789431f2SAndroid Build Coastguard Worker size_t AuthorizationSet::SerializedSizeOfElements() const {
393*789431f2SAndroid Build Coastguard Worker     size_t size = 0;
394*789431f2SAndroid Build Coastguard Worker     for (size_t i = 0; i < elems_size_; ++i) {
395*789431f2SAndroid Build Coastguard Worker         size += serialized_size(elems_[i]);
396*789431f2SAndroid Build Coastguard Worker     }
397*789431f2SAndroid Build Coastguard Worker     return size;
398*789431f2SAndroid Build Coastguard Worker }
399*789431f2SAndroid Build Coastguard Worker 
SerializedSize() const400*789431f2SAndroid Build Coastguard Worker size_t AuthorizationSet::SerializedSize() const {
401*789431f2SAndroid Build Coastguard Worker     return sizeof(uint32_t) +           // Size of indirect_data_
402*789431f2SAndroid Build Coastguard Worker            indirect_data_size_ +        // indirect_data_
403*789431f2SAndroid Build Coastguard Worker            sizeof(uint32_t) +           // Number of elems_
404*789431f2SAndroid Build Coastguard Worker            sizeof(uint32_t) +           // Size of elems_
405*789431f2SAndroid Build Coastguard Worker            SerializedSizeOfElements();  // elems_
406*789431f2SAndroid Build Coastguard Worker }
407*789431f2SAndroid Build Coastguard Worker 
Serialize(uint8_t * buf,const uint8_t * end) const408*789431f2SAndroid Build Coastguard Worker uint8_t* AuthorizationSet::Serialize(uint8_t* buf, const uint8_t* end) const {
409*789431f2SAndroid Build Coastguard Worker     buf = append_size_and_data_to_buf(buf, end, indirect_data_, indirect_data_size_);
410*789431f2SAndroid Build Coastguard Worker     buf = append_uint32_to_buf(buf, end, elems_size_);
411*789431f2SAndroid Build Coastguard Worker     buf = append_uint32_to_buf(buf, end, SerializedSizeOfElements());
412*789431f2SAndroid Build Coastguard Worker     for (size_t i = 0; i < elems_size_; ++i) {
413*789431f2SAndroid Build Coastguard Worker         buf = serialize(elems_[i], buf, end, indirect_data_);
414*789431f2SAndroid Build Coastguard Worker     }
415*789431f2SAndroid Build Coastguard Worker     return buf;
416*789431f2SAndroid Build Coastguard Worker }
417*789431f2SAndroid Build Coastguard Worker 
DeserializeIndirectData(const uint8_t ** buf_ptr,const uint8_t * end)418*789431f2SAndroid Build Coastguard Worker bool AuthorizationSet::DeserializeIndirectData(const uint8_t** buf_ptr, const uint8_t* end) {
419*789431f2SAndroid Build Coastguard Worker     UniquePtr<uint8_t[]> indirect_buf;
420*789431f2SAndroid Build Coastguard Worker     if (!copy_size_and_data_from_buf(buf_ptr, end, &indirect_data_size_, &indirect_buf)) {
421*789431f2SAndroid Build Coastguard Worker         LOG_E("Malformed data found in AuthorizationSet deserialization");
422*789431f2SAndroid Build Coastguard Worker         set_invalid(MALFORMED_DATA);
423*789431f2SAndroid Build Coastguard Worker         return false;
424*789431f2SAndroid Build Coastguard Worker     }
425*789431f2SAndroid Build Coastguard Worker     indirect_data_ = indirect_buf.release();
426*789431f2SAndroid Build Coastguard Worker     return true;
427*789431f2SAndroid Build Coastguard Worker }
428*789431f2SAndroid Build Coastguard Worker 
DeserializeElementsData(const uint8_t ** buf_ptr,const uint8_t * end)429*789431f2SAndroid Build Coastguard Worker bool AuthorizationSet::DeserializeElementsData(const uint8_t** buf_ptr, const uint8_t* end) {
430*789431f2SAndroid Build Coastguard Worker     uint32_t elements_count;
431*789431f2SAndroid Build Coastguard Worker     uint32_t elements_size;
432*789431f2SAndroid Build Coastguard Worker     if (!copy_uint32_from_buf(buf_ptr, end, &elements_count) ||
433*789431f2SAndroid Build Coastguard Worker         !copy_uint32_from_buf(buf_ptr, end, &elements_size)) {
434*789431f2SAndroid Build Coastguard Worker         LOG_E("Malformed data found in AuthorizationSet deserialization");
435*789431f2SAndroid Build Coastguard Worker         set_invalid(MALFORMED_DATA);
436*789431f2SAndroid Build Coastguard Worker         return false;
437*789431f2SAndroid Build Coastguard Worker     }
438*789431f2SAndroid Build Coastguard Worker 
439*789431f2SAndroid Build Coastguard Worker     // Note that the following validation of elements_count is weak, but it prevents allocation of
440*789431f2SAndroid Build Coastguard Worker     // elems_ arrays which are clearly too large to be reasonable.
441*789431f2SAndroid Build Coastguard Worker     size_t elems_refs_size;
442*789431f2SAndroid Build Coastguard Worker     size_t elems_alloc_size;
443*789431f2SAndroid Build Coastguard Worker     bool refs_size_overflow =
444*789431f2SAndroid Build Coastguard Worker         __builtin_mul_overflow(elements_count, sizeof(uint32_t), &elems_refs_size);
445*789431f2SAndroid Build Coastguard Worker     bool alloc_size_overflow =
446*789431f2SAndroid Build Coastguard Worker         __builtin_mul_overflow(elements_count, sizeof(*elems_), &elems_alloc_size);
447*789431f2SAndroid Build Coastguard Worker     /* elements_size must fit in the buffer */
448*789431f2SAndroid Build Coastguard Worker     if (static_cast<ptrdiff_t>(elements_size) > end - *buf_ptr ||
449*789431f2SAndroid Build Coastguard Worker         /* The element refs must all fit within elements_size */
450*789431f2SAndroid Build Coastguard Worker         elems_refs_size > elements_size ||
451*789431f2SAndroid Build Coastguard Worker         /* If our pointer math would overflow, bail */
452*789431f2SAndroid Build Coastguard Worker         refs_size_overflow ||
453*789431f2SAndroid Build Coastguard Worker         /* If the resulting allocation would overflow, bail */
454*789431f2SAndroid Build Coastguard Worker         alloc_size_overflow) {
455*789431f2SAndroid Build Coastguard Worker         LOG_E("Malformed data found in AuthorizationSet deserialization");
456*789431f2SAndroid Build Coastguard Worker         set_invalid(MALFORMED_DATA);
457*789431f2SAndroid Build Coastguard Worker         return false;
458*789431f2SAndroid Build Coastguard Worker     }
459*789431f2SAndroid Build Coastguard Worker 
460*789431f2SAndroid Build Coastguard Worker     if (!reserve_elems(elements_count)) return false;
461*789431f2SAndroid Build Coastguard Worker 
462*789431f2SAndroid Build Coastguard Worker     uint8_t* indirect_end = indirect_data_ + indirect_data_size_;
463*789431f2SAndroid Build Coastguard Worker     const uint8_t* elements_end = *buf_ptr + elements_size;
464*789431f2SAndroid Build Coastguard Worker     for (size_t i = 0; i < elements_count; ++i) {
465*789431f2SAndroid Build Coastguard Worker         if (!deserialize(elems_ + i, buf_ptr, elements_end, indirect_data_, indirect_end)) {
466*789431f2SAndroid Build Coastguard Worker             LOG_E("Malformed data found in AuthorizationSet deserialization");
467*789431f2SAndroid Build Coastguard Worker             set_invalid(MALFORMED_DATA);
468*789431f2SAndroid Build Coastguard Worker             return false;
469*789431f2SAndroid Build Coastguard Worker         }
470*789431f2SAndroid Build Coastguard Worker     }
471*789431f2SAndroid Build Coastguard Worker 
472*789431f2SAndroid Build Coastguard Worker     // Check if all the elements were consumed. If not, something was malformed as the
473*789431f2SAndroid Build Coastguard Worker     // retrieved elements_count and elements_size are not consistent with each other.
474*789431f2SAndroid Build Coastguard Worker     if (*buf_ptr != elements_end) {
475*789431f2SAndroid Build Coastguard Worker         LOG_E("Malformed data found in AuthorizationSet deserialization");
476*789431f2SAndroid Build Coastguard Worker         set_invalid(MALFORMED_DATA);
477*789431f2SAndroid Build Coastguard Worker         return false;
478*789431f2SAndroid Build Coastguard Worker     }
479*789431f2SAndroid Build Coastguard Worker 
480*789431f2SAndroid Build Coastguard Worker     elems_size_ = elements_count;
481*789431f2SAndroid Build Coastguard Worker     return true;
482*789431f2SAndroid Build Coastguard Worker }
483*789431f2SAndroid Build Coastguard Worker 
Deserialize(const uint8_t ** buf_ptr,const uint8_t * end)484*789431f2SAndroid Build Coastguard Worker bool AuthorizationSet::Deserialize(const uint8_t** buf_ptr, const uint8_t* end) {
485*789431f2SAndroid Build Coastguard Worker     FreeData();
486*789431f2SAndroid Build Coastguard Worker 
487*789431f2SAndroid Build Coastguard Worker     if (!DeserializeIndirectData(buf_ptr, end) || !DeserializeElementsData(buf_ptr, end))
488*789431f2SAndroid Build Coastguard Worker         return false;
489*789431f2SAndroid Build Coastguard Worker 
490*789431f2SAndroid Build Coastguard Worker     if (indirect_data_size_ != ComputeIndirectDataSize(elems_, elems_size_)) {
491*789431f2SAndroid Build Coastguard Worker         LOG_E("Malformed data found in AuthorizationSet deserialization");
492*789431f2SAndroid Build Coastguard Worker         set_invalid(MALFORMED_DATA);
493*789431f2SAndroid Build Coastguard Worker         return false;
494*789431f2SAndroid Build Coastguard Worker     }
495*789431f2SAndroid Build Coastguard Worker     return true;
496*789431f2SAndroid Build Coastguard Worker }
497*789431f2SAndroid Build Coastguard Worker 
Clear()498*789431f2SAndroid Build Coastguard Worker void AuthorizationSet::Clear() {
499*789431f2SAndroid Build Coastguard Worker     memset_s(elems_, 0, elems_capacity_ * sizeof(keymaster_key_param_t));
500*789431f2SAndroid Build Coastguard Worker     memset_s(indirect_data_, 0, indirect_data_capacity_);
501*789431f2SAndroid Build Coastguard Worker     elems_size_ = 0;
502*789431f2SAndroid Build Coastguard Worker     indirect_data_size_ = 0;
503*789431f2SAndroid Build Coastguard Worker     error_ = OK;
504*789431f2SAndroid Build Coastguard Worker }
505*789431f2SAndroid Build Coastguard Worker 
FreeData()506*789431f2SAndroid Build Coastguard Worker void AuthorizationSet::FreeData() {
507*789431f2SAndroid Build Coastguard Worker     Clear();
508*789431f2SAndroid Build Coastguard Worker 
509*789431f2SAndroid Build Coastguard Worker     delete[] elems_;
510*789431f2SAndroid Build Coastguard Worker     delete[] indirect_data_;
511*789431f2SAndroid Build Coastguard Worker 
512*789431f2SAndroid Build Coastguard Worker     elems_ = nullptr;
513*789431f2SAndroid Build Coastguard Worker     indirect_data_ = nullptr;
514*789431f2SAndroid Build Coastguard Worker     elems_capacity_ = 0;
515*789431f2SAndroid Build Coastguard Worker     indirect_data_capacity_ = 0;
516*789431f2SAndroid Build Coastguard Worker     error_ = OK;
517*789431f2SAndroid Build Coastguard Worker }
518*789431f2SAndroid Build Coastguard Worker 
519*789431f2SAndroid Build Coastguard Worker /* static */
ComputeIndirectDataSize(const keymaster_key_param_t * elems,size_t count)520*789431f2SAndroid Build Coastguard Worker size_t AuthorizationSet::ComputeIndirectDataSize(const keymaster_key_param_t* elems, size_t count) {
521*789431f2SAndroid Build Coastguard Worker     size_t size = 0;
522*789431f2SAndroid Build Coastguard Worker     for (size_t i = 0; i < count; ++i) {
523*789431f2SAndroid Build Coastguard Worker         if (is_blob_tag(elems[i].tag)) {
524*789431f2SAndroid Build Coastguard Worker             size += elems[i].blob.data_length;
525*789431f2SAndroid Build Coastguard Worker         }
526*789431f2SAndroid Build Coastguard Worker     }
527*789431f2SAndroid Build Coastguard Worker     return size;
528*789431f2SAndroid Build Coastguard Worker }
529*789431f2SAndroid Build Coastguard Worker 
CopyIndirectData()530*789431f2SAndroid Build Coastguard Worker void AuthorizationSet::CopyIndirectData() {
531*789431f2SAndroid Build Coastguard Worker     memset_s(indirect_data_, 0, indirect_data_capacity_);
532*789431f2SAndroid Build Coastguard Worker 
533*789431f2SAndroid Build Coastguard Worker     uint8_t* indirect_data_pos = indirect_data_;
534*789431f2SAndroid Build Coastguard Worker     for (size_t i = 0; i < elems_size_; ++i) {
535*789431f2SAndroid Build Coastguard Worker         assert(indirect_data_pos <= indirect_data_ + indirect_data_capacity_);
536*789431f2SAndroid Build Coastguard Worker         if (is_blob_tag(elems_[i].tag)) {
537*789431f2SAndroid Build Coastguard Worker             memcpy(indirect_data_pos, elems_[i].blob.data, elems_[i].blob.data_length);
538*789431f2SAndroid Build Coastguard Worker             elems_[i].blob.data = indirect_data_pos;
539*789431f2SAndroid Build Coastguard Worker             indirect_data_pos += elems_[i].blob.data_length;
540*789431f2SAndroid Build Coastguard Worker         }
541*789431f2SAndroid Build Coastguard Worker     }
542*789431f2SAndroid Build Coastguard Worker     assert(indirect_data_pos == indirect_data_ + indirect_data_capacity_);
543*789431f2SAndroid Build Coastguard Worker     indirect_data_size_ = indirect_data_pos - indirect_data_;
544*789431f2SAndroid Build Coastguard Worker }
545*789431f2SAndroid Build Coastguard Worker 
GetTagCount(keymaster_tag_t tag) const546*789431f2SAndroid Build Coastguard Worker size_t AuthorizationSet::GetTagCount(keymaster_tag_t tag) const {
547*789431f2SAndroid Build Coastguard Worker     size_t count = 0;
548*789431f2SAndroid Build Coastguard Worker     for (int pos = -1; (pos = find(tag, pos)) != -1;)
549*789431f2SAndroid Build Coastguard Worker         ++count;
550*789431f2SAndroid Build Coastguard Worker     return count;
551*789431f2SAndroid Build Coastguard Worker }
552*789431f2SAndroid Build Coastguard Worker 
GetTagValueEnum(keymaster_tag_t tag,uint32_t * val) const553*789431f2SAndroid Build Coastguard Worker bool AuthorizationSet::GetTagValueEnum(keymaster_tag_t tag, uint32_t* val) const {
554*789431f2SAndroid Build Coastguard Worker     int pos = find(tag);
555*789431f2SAndroid Build Coastguard Worker     if (pos == -1) {
556*789431f2SAndroid Build Coastguard Worker         return false;
557*789431f2SAndroid Build Coastguard Worker     }
558*789431f2SAndroid Build Coastguard Worker     *val = elems_[pos].enumerated;
559*789431f2SAndroid Build Coastguard Worker     return true;
560*789431f2SAndroid Build Coastguard Worker }
561*789431f2SAndroid Build Coastguard Worker 
GetTagValueEnumRep(keymaster_tag_t tag,size_t instance,uint32_t * val) const562*789431f2SAndroid Build Coastguard Worker bool AuthorizationSet::GetTagValueEnumRep(keymaster_tag_t tag, size_t instance,
563*789431f2SAndroid Build Coastguard Worker                                           uint32_t* val) const {
564*789431f2SAndroid Build Coastguard Worker     size_t count = 0;
565*789431f2SAndroid Build Coastguard Worker     int pos = -1;
566*789431f2SAndroid Build Coastguard Worker     while (count <= instance) {
567*789431f2SAndroid Build Coastguard Worker         pos = find(tag, pos);
568*789431f2SAndroid Build Coastguard Worker         if (pos == -1) {
569*789431f2SAndroid Build Coastguard Worker             return false;
570*789431f2SAndroid Build Coastguard Worker         }
571*789431f2SAndroid Build Coastguard Worker         ++count;
572*789431f2SAndroid Build Coastguard Worker     }
573*789431f2SAndroid Build Coastguard Worker     *val = elems_[pos].enumerated;
574*789431f2SAndroid Build Coastguard Worker     return true;
575*789431f2SAndroid Build Coastguard Worker }
576*789431f2SAndroid Build Coastguard Worker 
GetTagValueInt(keymaster_tag_t tag,uint32_t * val) const577*789431f2SAndroid Build Coastguard Worker bool AuthorizationSet::GetTagValueInt(keymaster_tag_t tag, uint32_t* val) const {
578*789431f2SAndroid Build Coastguard Worker     int pos = find(tag);
579*789431f2SAndroid Build Coastguard Worker     if (pos == -1) {
580*789431f2SAndroid Build Coastguard Worker         return false;
581*789431f2SAndroid Build Coastguard Worker     }
582*789431f2SAndroid Build Coastguard Worker     *val = elems_[pos].integer;
583*789431f2SAndroid Build Coastguard Worker     return true;
584*789431f2SAndroid Build Coastguard Worker }
585*789431f2SAndroid Build Coastguard Worker 
GetTagValueIntRep(keymaster_tag_t tag,size_t instance,uint32_t * val) const586*789431f2SAndroid Build Coastguard Worker bool AuthorizationSet::GetTagValueIntRep(keymaster_tag_t tag, size_t instance,
587*789431f2SAndroid Build Coastguard Worker                                          uint32_t* val) const {
588*789431f2SAndroid Build Coastguard Worker     size_t count = 0;
589*789431f2SAndroid Build Coastguard Worker     int pos = -1;
590*789431f2SAndroid Build Coastguard Worker     while (count <= instance) {
591*789431f2SAndroid Build Coastguard Worker         pos = find(tag, pos);
592*789431f2SAndroid Build Coastguard Worker         if (pos == -1) {
593*789431f2SAndroid Build Coastguard Worker             return false;
594*789431f2SAndroid Build Coastguard Worker         }
595*789431f2SAndroid Build Coastguard Worker         ++count;
596*789431f2SAndroid Build Coastguard Worker     }
597*789431f2SAndroid Build Coastguard Worker     *val = elems_[pos].integer;
598*789431f2SAndroid Build Coastguard Worker     return true;
599*789431f2SAndroid Build Coastguard Worker }
600*789431f2SAndroid Build Coastguard Worker 
GetTagValueLong(keymaster_tag_t tag,uint64_t * val) const601*789431f2SAndroid Build Coastguard Worker bool AuthorizationSet::GetTagValueLong(keymaster_tag_t tag, uint64_t* val) const {
602*789431f2SAndroid Build Coastguard Worker     int pos = find(tag);
603*789431f2SAndroid Build Coastguard Worker     if (pos == -1) {
604*789431f2SAndroid Build Coastguard Worker         return false;
605*789431f2SAndroid Build Coastguard Worker     }
606*789431f2SAndroid Build Coastguard Worker     *val = elems_[pos].long_integer;
607*789431f2SAndroid Build Coastguard Worker     return true;
608*789431f2SAndroid Build Coastguard Worker }
609*789431f2SAndroid Build Coastguard Worker 
GetTagValueLongRep(keymaster_tag_t tag,size_t instance,uint64_t * val) const610*789431f2SAndroid Build Coastguard Worker bool AuthorizationSet::GetTagValueLongRep(keymaster_tag_t tag, size_t instance,
611*789431f2SAndroid Build Coastguard Worker                                           uint64_t* val) const {
612*789431f2SAndroid Build Coastguard Worker     size_t count = 0;
613*789431f2SAndroid Build Coastguard Worker     int pos = -1;
614*789431f2SAndroid Build Coastguard Worker     while (count <= instance) {
615*789431f2SAndroid Build Coastguard Worker         pos = find(tag, pos);
616*789431f2SAndroid Build Coastguard Worker         if (pos == -1) {
617*789431f2SAndroid Build Coastguard Worker             return false;
618*789431f2SAndroid Build Coastguard Worker         }
619*789431f2SAndroid Build Coastguard Worker         ++count;
620*789431f2SAndroid Build Coastguard Worker     }
621*789431f2SAndroid Build Coastguard Worker     *val = elems_[pos].long_integer;
622*789431f2SAndroid Build Coastguard Worker     return true;
623*789431f2SAndroid Build Coastguard Worker }
624*789431f2SAndroid Build Coastguard Worker 
GetTagValueDate(keymaster_tag_t tag,uint64_t * val) const625*789431f2SAndroid Build Coastguard Worker bool AuthorizationSet::GetTagValueDate(keymaster_tag_t tag, uint64_t* val) const {
626*789431f2SAndroid Build Coastguard Worker     int pos = find(tag);
627*789431f2SAndroid Build Coastguard Worker     if (pos == -1) {
628*789431f2SAndroid Build Coastguard Worker         return false;
629*789431f2SAndroid Build Coastguard Worker     }
630*789431f2SAndroid Build Coastguard Worker     *val = elems_[pos].date_time;
631*789431f2SAndroid Build Coastguard Worker     return true;
632*789431f2SAndroid Build Coastguard Worker }
633*789431f2SAndroid Build Coastguard Worker 
GetTagValueBlob(keymaster_tag_t tag,keymaster_blob_t * val) const634*789431f2SAndroid Build Coastguard Worker bool AuthorizationSet::GetTagValueBlob(keymaster_tag_t tag, keymaster_blob_t* val) const {
635*789431f2SAndroid Build Coastguard Worker     int pos = find(tag);
636*789431f2SAndroid Build Coastguard Worker     if (pos == -1) {
637*789431f2SAndroid Build Coastguard Worker         return false;
638*789431f2SAndroid Build Coastguard Worker     }
639*789431f2SAndroid Build Coastguard Worker     *val = elems_[pos].blob;
640*789431f2SAndroid Build Coastguard Worker     return true;
641*789431f2SAndroid Build Coastguard Worker }
642*789431f2SAndroid Build Coastguard Worker 
GetTagValueBool(keymaster_tag_t tag) const643*789431f2SAndroid Build Coastguard Worker bool AuthorizationSet::GetTagValueBool(keymaster_tag_t tag) const {
644*789431f2SAndroid Build Coastguard Worker     int pos = find(tag);
645*789431f2SAndroid Build Coastguard Worker     if (pos == -1) {
646*789431f2SAndroid Build Coastguard Worker         return false;
647*789431f2SAndroid Build Coastguard Worker     }
648*789431f2SAndroid Build Coastguard Worker     assert(elems_[pos].boolean);
649*789431f2SAndroid Build Coastguard Worker     return elems_[pos].boolean;
650*789431f2SAndroid Build Coastguard Worker }
651*789431f2SAndroid Build Coastguard Worker 
ContainsEnumValue(keymaster_tag_t tag,uint32_t value) const652*789431f2SAndroid Build Coastguard Worker bool AuthorizationSet::ContainsEnumValue(keymaster_tag_t tag, uint32_t value) const {
653*789431f2SAndroid Build Coastguard Worker     for (auto& entry : *this)
654*789431f2SAndroid Build Coastguard Worker         if (entry.tag == tag && entry.enumerated == value) return true;
655*789431f2SAndroid Build Coastguard Worker     return false;
656*789431f2SAndroid Build Coastguard Worker }
657*789431f2SAndroid Build Coastguard Worker 
ContainsIntValue(keymaster_tag_t tag,uint32_t value) const658*789431f2SAndroid Build Coastguard Worker bool AuthorizationSet::ContainsIntValue(keymaster_tag_t tag, uint32_t value) const {
659*789431f2SAndroid Build Coastguard Worker     for (auto& entry : *this)
660*789431f2SAndroid Build Coastguard Worker         if (entry.tag == tag && entry.integer == value) return true;
661*789431f2SAndroid Build Coastguard Worker     return false;
662*789431f2SAndroid Build Coastguard Worker }
663*789431f2SAndroid Build Coastguard Worker 
664*789431f2SAndroid Build Coastguard Worker }  // namespace keymaster
665