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, ¶m->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, ¶m->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, ¶m->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, ¶m->long_integer);
358*789431f2SAndroid Build Coastguard Worker case KM_DATE:
359*789431f2SAndroid Build Coastguard Worker return copy_uint64_from_buf(buf_ptr, end, ¶m->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, ¶m->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