authorization_set.cpp revision 2c242009007a38b5c8003137fb8ba5a1fdb73b70
15ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden/*
25ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden * Copyright (C) 2014 The Android Open Source Project
35ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden *
45ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden * Licensed under the Apache License, Version 2.0 (the "License");
55ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden * you may not use this file except in compliance with the License.
65ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden * You may obtain a copy of the License at
75ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden *
85ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden *      http://www.apache.org/licenses/LICENSE-2.0
95ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden *
105ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden * Unless required by applicable law or agreed to in writing, software
115ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden * distributed under the License is distributed on an "AS IS" BASIS,
125ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden * See the License for the specific language governing permissions and
145ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden * limitations under the License.
155ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden */
165ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
175ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden#include <stdlib.h>
185ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden#include <string.h>
195ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden#include <stddef.h>
205ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
215ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden#include <assert.h>
225ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
2398d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden#include <keymaster/authorization_set.h>
2498d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden#include <keymaster/google_keymaster_utils.h>
255ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
265ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willdennamespace keymaster {
275ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
285ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willdenstatic inline bool is_blob_tag(keymaster_tag_t tag) {
295ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    return (keymaster_tag_get_type(tag) == KM_BYTES || keymaster_tag_get_type(tag) == KM_BIGNUM);
305ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden}
315ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
325ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willdenconst size_t STARTING_ELEMS_CAPACITY = 8;
335ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
3458e1a5486219a1be9264d4e863a9dd3e393906c3Shawn WilldenAuthorizationSet::AuthorizationSet(const AuthorizationSet& set)
3562de26672193373972f2ce968b51cf8335f118f9Shawn Willden    : Serializable(), elems_(NULL), indirect_data_(NULL) {
367636471bd1c553ac179f0dddc17133491d0e1fafShawn Willden    Reinitialize(set.elems_, set.elems_size_);
375ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden}
385ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
392c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn WilldenAuthorizationSet::AuthorizationSet(AuthorizationSetBuilder& builder) {
402c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    elems_ = builder.set.elems_;
412c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    builder.set.elems_ = NULL;
422c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden
432c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    elems_size_ = builder.set.elems_size_;
442c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    builder.set.elems_size_ = 0;
452c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden
462c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    elems_capacity_ = builder.set.elems_capacity_;
472c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    builder.set.elems_capacity_ = 0;
482c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden
492c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    indirect_data_ = builder.set.indirect_data_;
502c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    builder.set.indirect_data_ = NULL;
512c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden
522c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    indirect_data_capacity_ = builder.set.indirect_data_capacity_;
532c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    builder.set.indirect_data_capacity_ = 0;
542c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden
552c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    indirect_data_size_ = builder.set.indirect_data_size_;
562c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    builder.set.indirect_data_size_ = 0;
572c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden
582c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    error_ = builder.set.error_;
592c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    builder.set.error_ = OK;
602c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden}
612c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden
628d336ae10df66da4c0433f17c2d42e85baea32c5Shawn WilldenAuthorizationSet::~AuthorizationSet() {
638d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    FreeData();
648d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden}
6558e1a5486219a1be9264d4e863a9dd3e393906c3Shawn Willden
66370121346777e13437c275fbe7a975d899cc325cShawn Willdenbool AuthorizationSet::reserve_elems(size_t count) {
67437fbd195e7de57b7dc0c449c04458bd90ef50deShawn Willden    if (is_valid() != OK)
68437fbd195e7de57b7dc0c449c04458bd90ef50deShawn Willden        return false;
69437fbd195e7de57b7dc0c449c04458bd90ef50deShawn Willden
70370121346777e13437c275fbe7a975d899cc325cShawn Willden    if (count >= elems_capacity_) {
71370121346777e13437c275fbe7a975d899cc325cShawn Willden        keymaster_key_param_t* new_elems = new keymaster_key_param_t[count];
72370121346777e13437c275fbe7a975d899cc325cShawn Willden        if (new_elems == NULL) {
73370121346777e13437c275fbe7a975d899cc325cShawn Willden            set_invalid(ALLOCATION_FAILURE);
74370121346777e13437c275fbe7a975d899cc325cShawn Willden            return false;
75370121346777e13437c275fbe7a975d899cc325cShawn Willden        }
76370121346777e13437c275fbe7a975d899cc325cShawn Willden        memcpy(new_elems, elems_, sizeof(*elems_) * elems_size_);
77370121346777e13437c275fbe7a975d899cc325cShawn Willden        delete[] elems_;
78370121346777e13437c275fbe7a975d899cc325cShawn Willden        elems_ = new_elems;
79370121346777e13437c275fbe7a975d899cc325cShawn Willden        elems_capacity_ = count;
80370121346777e13437c275fbe7a975d899cc325cShawn Willden    }
81370121346777e13437c275fbe7a975d899cc325cShawn Willden    return true;
82370121346777e13437c275fbe7a975d899cc325cShawn Willden}
83370121346777e13437c275fbe7a975d899cc325cShawn Willden
84370121346777e13437c275fbe7a975d899cc325cShawn Willdenbool AuthorizationSet::reserve_indirect(size_t length) {
85437fbd195e7de57b7dc0c449c04458bd90ef50deShawn Willden    if (is_valid() != OK)
86437fbd195e7de57b7dc0c449c04458bd90ef50deShawn Willden        return false;
87437fbd195e7de57b7dc0c449c04458bd90ef50deShawn Willden
88370121346777e13437c275fbe7a975d899cc325cShawn Willden    if (length > indirect_data_capacity_) {
89370121346777e13437c275fbe7a975d899cc325cShawn Willden        uint8_t* new_data = new uint8_t[length];
90370121346777e13437c275fbe7a975d899cc325cShawn Willden        if (new_data == NULL) {
91370121346777e13437c275fbe7a975d899cc325cShawn Willden            set_invalid(ALLOCATION_FAILURE);
92370121346777e13437c275fbe7a975d899cc325cShawn Willden            return false;
93370121346777e13437c275fbe7a975d899cc325cShawn Willden        }
94370121346777e13437c275fbe7a975d899cc325cShawn Willden        memcpy(new_data, indirect_data_, indirect_data_size_);
95370121346777e13437c275fbe7a975d899cc325cShawn Willden
96370121346777e13437c275fbe7a975d899cc325cShawn Willden        // Fix up the data pointers to point into the new region.
97370121346777e13437c275fbe7a975d899cc325cShawn Willden        for (size_t i = 0; i < elems_size_; ++i) {
98370121346777e13437c275fbe7a975d899cc325cShawn Willden            if (is_blob_tag(elems_[i].tag))
99370121346777e13437c275fbe7a975d899cc325cShawn Willden                elems_[i].blob.data = new_data + (elems_[i].blob.data - indirect_data_);
100370121346777e13437c275fbe7a975d899cc325cShawn Willden        }
101370121346777e13437c275fbe7a975d899cc325cShawn Willden        delete[] indirect_data_;
102370121346777e13437c275fbe7a975d899cc325cShawn Willden        indirect_data_ = new_data;
103370121346777e13437c275fbe7a975d899cc325cShawn Willden        indirect_data_capacity_ = length;
104370121346777e13437c275fbe7a975d899cc325cShawn Willden    }
105370121346777e13437c275fbe7a975d899cc325cShawn Willden    return true;
106370121346777e13437c275fbe7a975d899cc325cShawn Willden}
107370121346777e13437c275fbe7a975d899cc325cShawn Willden
1085ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willdenbool AuthorizationSet::Reinitialize(const keymaster_key_param_t* elems, const size_t count) {
1095ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    FreeData();
1105ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
111370121346777e13437c275fbe7a975d899cc325cShawn Willden    if (!reserve_elems(count))
112370121346777e13437c275fbe7a975d899cc325cShawn Willden        return false;
1135ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
114370121346777e13437c275fbe7a975d899cc325cShawn Willden    if (!reserve_indirect(ComputeIndirectDataSize(elems, count)))
1155ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden        return false;
1165ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
117370121346777e13437c275fbe7a975d899cc325cShawn Willden    memcpy(elems_, elems, sizeof(keymaster_key_param_t) * count);
118370121346777e13437c275fbe7a975d899cc325cShawn Willden    elems_size_ = count;
1195ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    CopyIndirectData();
120370121346777e13437c275fbe7a975d899cc325cShawn Willden    error_ = OK;
1215ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    return true;
1225ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden}
1235ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
1245ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willdenvoid AuthorizationSet::set_invalid(Error error) {
1255ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    FreeData();
126370121346777e13437c275fbe7a975d899cc325cShawn Willden    error_ = error;
1275ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden}
1285ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
1292c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willdenvoid AuthorizationSet::Deduplicate() {
1302c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    qsort(elems_, elems_size_, sizeof(*elems_),
1312c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden          reinterpret_cast<int (*)(const void*, const void*)>(keymaster_param_compare));
1322c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden
1332c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    size_t invalid_count = 0;
1342c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    for (size_t i = 1; i < size(); ++i) {
1352c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden        if (elems_[i - 1].tag == KM_TAG_INVALID)
1362c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden            ++invalid_count;
1372c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden        else if (keymaster_param_compare(elems_ + i - 1, elems_ + i) == 0) {
1382c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden            // Mark dups as invalid.  Note that this "leaks" the data referenced by KM_BYTES and
1392c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden            // KM_BIGNUM entries, but those are just pointers into indirect_data_, so it will all
1402c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden            // get cleaned up.
1412c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden            elems_[i - 1].tag = KM_TAG_INVALID;
1422c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden            ++invalid_count;
1432c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden        }
1442c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    }
1452c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    if (size() > 0 && elems_[size() - 1].tag == KM_TAG_INVALID)
1462c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden        ++invalid_count;
1472c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden
1482c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    if (invalid_count == 0)
1492c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden        return;
1502c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden
1512c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    // Since KM_TAG_INVALID == 0, all of the invalid entries are first.
1522c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    elems_size_ -= invalid_count;
1532c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    memmove(elems_, elems_ + invalid_count, size() * sizeof(*elems_));
1542c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden}
1552c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden
156cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willdenvoid AuthorizationSet::CopyToParamSet(keymaster_key_param_set_t* set) const {
157cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden    assert(set);
158cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden
159cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden    set->length = size();
160cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden    set->params =
161cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden        reinterpret_cast<keymaster_key_param_t*>(malloc(sizeof(keymaster_key_param_t) * size()));
162cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden
163cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden    for (size_t i = 0; i < size(); ++i) {
164cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden        const keymaster_key_param_t src = (*this)[i];
165cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden        keymaster_key_param_t& dst(set->params[i]);
166cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden
167cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden        dst = src;
168cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden        keymaster_tag_type_t type = keymaster_tag_get_type(src.tag);
169cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden        if (type == KM_BIGNUM || type == KM_BYTES) {
170cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden            void* tmp = malloc(src.blob.data_length);
171cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden            memcpy(tmp, src.blob.data, src.blob.data_length);
172cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden            dst.blob.data = reinterpret_cast<uint8_t*>(tmp);
173cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden        }
174cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden    }
175cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden}
176cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden
1775ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willdenint AuthorizationSet::find(keymaster_tag_t tag, int begin) const {
178437fbd195e7de57b7dc0c449c04458bd90ef50deShawn Willden    if (is_valid() != OK)
179437fbd195e7de57b7dc0c449c04458bd90ef50deShawn Willden        return -1;
180437fbd195e7de57b7dc0c449c04458bd90ef50deShawn Willden
1815ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    int i = ++begin;
1828d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    while (i < (int)elems_size_ && elems_[i].tag != tag)
1838d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden        ++i;
1845ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    if (i == (int)elems_size_)
1855ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden        return -1;
1865ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    else
1875ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden        return i;
1885ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden}
1895ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
1905ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willdenkeymaster_key_param_t empty;
1915ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willdenkeymaster_key_param_t AuthorizationSet::operator[](int at) const {
192437fbd195e7de57b7dc0c449c04458bd90ef50deShawn Willden    if (is_valid() == OK && at < (int)elems_size_) {
1938d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden        return elems_[at];
1945ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    }
1955ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    memset(&empty, 0, sizeof(empty));
1965ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    return empty;
1975ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden}
1985ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
199370121346777e13437c275fbe7a975d899cc325cShawn Willdenbool AuthorizationSet::push_back(const AuthorizationSet& set) {
200437fbd195e7de57b7dc0c449c04458bd90ef50deShawn Willden    if (is_valid() != OK)
201437fbd195e7de57b7dc0c449c04458bd90ef50deShawn Willden        return false;
202437fbd195e7de57b7dc0c449c04458bd90ef50deShawn Willden
203370121346777e13437c275fbe7a975d899cc325cShawn Willden    if (!reserve_elems(elems_size_ + set.elems_size_))
204370121346777e13437c275fbe7a975d899cc325cShawn Willden        return false;
205370121346777e13437c275fbe7a975d899cc325cShawn Willden
206370121346777e13437c275fbe7a975d899cc325cShawn Willden    if (!reserve_indirect(indirect_data_size_ + set.indirect_data_size_))
207370121346777e13437c275fbe7a975d899cc325cShawn Willden        return false;
208370121346777e13437c275fbe7a975d899cc325cShawn Willden
209370121346777e13437c275fbe7a975d899cc325cShawn Willden    for (size_t i = 0; i < set.size(); ++i)
210370121346777e13437c275fbe7a975d899cc325cShawn Willden        if (!push_back(set[i]))
211370121346777e13437c275fbe7a975d899cc325cShawn Willden            return false;
212370121346777e13437c275fbe7a975d899cc325cShawn Willden
213370121346777e13437c275fbe7a975d899cc325cShawn Willden    return true;
214370121346777e13437c275fbe7a975d899cc325cShawn Willden}
215370121346777e13437c275fbe7a975d899cc325cShawn Willden
2165ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willdenbool AuthorizationSet::push_back(keymaster_key_param_t elem) {
217437fbd195e7de57b7dc0c449c04458bd90ef50deShawn Willden    if (is_valid() != OK)
218437fbd195e7de57b7dc0c449c04458bd90ef50deShawn Willden        return false;
219437fbd195e7de57b7dc0c449c04458bd90ef50deShawn Willden
220370121346777e13437c275fbe7a975d899cc325cShawn Willden    if (elems_size_ >= elems_capacity_)
221370121346777e13437c275fbe7a975d899cc325cShawn Willden        if (!reserve_elems(elems_capacity_ ? elems_capacity_ * 2 : STARTING_ELEMS_CAPACITY))
2225ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden            return false;
2235ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
2245ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    if (is_blob_tag(elem.tag)) {
225370121346777e13437c275fbe7a975d899cc325cShawn Willden        if (indirect_data_capacity_ - indirect_data_size_ < elem.blob.data_length)
226370121346777e13437c275fbe7a975d899cc325cShawn Willden            if (!reserve_indirect(2 * (indirect_data_capacity_ + elem.blob.data_length)))
2275ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden                return false;
22858e1a5486219a1be9264d4e863a9dd3e393906c3Shawn Willden
2295ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden        memcpy(indirect_data_ + indirect_data_size_, elem.blob.data, elem.blob.data_length);
2308d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden        elem.blob.data = indirect_data_ + indirect_data_size_;
2315ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden        indirect_data_size_ += elem.blob.data_length;
2325ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    }
2335ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
2345ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    elems_[elems_size_++] = elem;
2355ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    return true;
2365ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden}
2375ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
2388d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willdenstatic size_t serialized_size(const keymaster_key_param_t& param) {
2398d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    switch (keymaster_tag_get_type(param.tag)) {
2408d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    case KM_INVALID:
2418d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    default:
2428d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden        return sizeof(uint32_t);
2438d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    case KM_ENUM:
2448d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    case KM_ENUM_REP:
2458d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    case KM_INT:
2468d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    case KM_INT_REP:
2478d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden        return sizeof(uint32_t) * 2;
2488d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    case KM_LONG:
2498d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    case KM_DATE:
2508d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden        return sizeof(uint32_t) + sizeof(uint64_t);
2518d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    case KM_BOOL:
2528d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden        return sizeof(uint32_t) + 1;
2538d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden        break;
2548d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    case KM_BIGNUM:
2558d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    case KM_BYTES:
2568d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden        return sizeof(uint32_t) * 3;
2578d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    }
2588d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden}
2598d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden
2608d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willdenstatic uint8_t* serialize(const keymaster_key_param_t& param, uint8_t* buf, const uint8_t* end,
2618d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden                          const uint8_t* indirect_base) {
262172f8c9be706e27f43022063bbc7f4b0177583acShawn Willden    buf = append_uint32_to_buf(buf, end, param.tag);
2638d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    switch (keymaster_tag_get_type(param.tag)) {
2648d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    case KM_INVALID:
2658d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden        break;
2668d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    case KM_ENUM:
2678d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    case KM_ENUM_REP:
268172f8c9be706e27f43022063bbc7f4b0177583acShawn Willden        buf = append_uint32_to_buf(buf, end, param.enumerated);
2698d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden        break;
2708d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    case KM_INT:
2718d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    case KM_INT_REP:
272172f8c9be706e27f43022063bbc7f4b0177583acShawn Willden        buf = append_uint32_to_buf(buf, end, param.integer);
2738d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden        break;
2748d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    case KM_LONG:
275172f8c9be706e27f43022063bbc7f4b0177583acShawn Willden        buf = append_uint64_to_buf(buf, end, param.long_integer);
2768d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden        break;
2778d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    case KM_DATE:
278172f8c9be706e27f43022063bbc7f4b0177583acShawn Willden        buf = append_uint64_to_buf(buf, end, param.date_time);
2798d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden        break;
2808d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    case KM_BOOL:
2818d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden        if (buf < end)
2828d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden            *buf = static_cast<uint8_t>(param.boolean);
2838d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden        buf++;
2848d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden        break;
2858d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    case KM_BIGNUM:
2868d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    case KM_BYTES:
287172f8c9be706e27f43022063bbc7f4b0177583acShawn Willden        buf = append_uint32_to_buf(buf, end, param.blob.data_length);
288172f8c9be706e27f43022063bbc7f4b0177583acShawn Willden        buf = append_uint32_to_buf(buf, end, param.blob.data - indirect_base);
2898d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden        break;
2908d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    }
2918d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    return buf;
2928d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden}
2938d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden
294172f8c9be706e27f43022063bbc7f4b0177583acShawn Willdenstatic bool deserialize(keymaster_key_param_t* param, const uint8_t** buf_ptr, const uint8_t* end,
2958d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden                        const uint8_t* indirect_base, const uint8_t* indirect_end) {
296172f8c9be706e27f43022063bbc7f4b0177583acShawn Willden    if (!copy_uint32_from_buf(buf_ptr, end, &param->tag))
2978d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden        return false;
2988d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden
2998d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    switch (keymaster_tag_get_type(param->tag)) {
3008d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    default:
3018d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    case KM_INVALID:
3028d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden        return false;
3038d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    case KM_ENUM:
3048d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    case KM_ENUM_REP:
305172f8c9be706e27f43022063bbc7f4b0177583acShawn Willden        return copy_uint32_from_buf(buf_ptr, end, &param->enumerated);
3068d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    case KM_INT:
3078d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    case KM_INT_REP:
308172f8c9be706e27f43022063bbc7f4b0177583acShawn Willden        return copy_uint32_from_buf(buf_ptr, end, &param->integer);
3098d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    case KM_LONG:
310172f8c9be706e27f43022063bbc7f4b0177583acShawn Willden        return copy_uint64_from_buf(buf_ptr, end, &param->long_integer);
3118d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    case KM_DATE:
312172f8c9be706e27f43022063bbc7f4b0177583acShawn Willden        return copy_uint64_from_buf(buf_ptr, end, &param->date_time);
3138d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden        break;
3148d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    case KM_BOOL:
315172f8c9be706e27f43022063bbc7f4b0177583acShawn Willden        if (*buf_ptr < end) {
316172f8c9be706e27f43022063bbc7f4b0177583acShawn Willden            param->boolean = static_cast<bool>(**buf_ptr);
317172f8c9be706e27f43022063bbc7f4b0177583acShawn Willden            (*buf_ptr)++;
3188d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden            return true;
3198d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden        }
3208d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden        return false;
3218d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden
3228d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    case KM_BIGNUM:
3238d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    case KM_BYTES: {
3248d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden        uint32_t offset;
325172f8c9be706e27f43022063bbc7f4b0177583acShawn Willden        if (!copy_uint32_from_buf(buf_ptr, end, &param->blob.data_length) ||
326172f8c9be706e27f43022063bbc7f4b0177583acShawn Willden            !copy_uint32_from_buf(buf_ptr, end, &offset))
3278d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden            return false;
3288d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden        if (static_cast<ptrdiff_t>(offset) > indirect_end - indirect_base ||
329172f8c9be706e27f43022063bbc7f4b0177583acShawn Willden            static_cast<ptrdiff_t>(offset + param->blob.data_length) > indirect_end - indirect_base)
3308d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden            return false;
3318d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden        param->blob.data = indirect_base + offset;
3328d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden        return true;
3338d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    }
3348d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    }
3358d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden}
3368d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden
3378d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willdensize_t AuthorizationSet::SerializedSizeOfElements() const {
3388d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    size_t size = 0;
3398d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    for (size_t i = 0; i < elems_size_; ++i) {
3408d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden        size += serialized_size(elems_[i]);
3418d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    }
3428d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    return size;
3438d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden}
3448d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden
34558e1a5486219a1be9264d4e863a9dd3e393906c3Shawn Willdensize_t AuthorizationSet::SerializedSize() const {
3468d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    return sizeof(uint32_t) +           // Size of indirect_data_
3478d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden           indirect_data_size_ +        // indirect_data_
3488d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden           sizeof(uint32_t) +           // Number of elems_
3498d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden           sizeof(uint32_t) +           // Size of elems_
3508d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden           SerializedSizeOfElements();  // elems_
3515ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden}
3525ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
3538d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willdenuint8_t* AuthorizationSet::Serialize(uint8_t* buf, const uint8_t* end) const {
3548d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    buf = append_size_and_data_to_buf(buf, end, indirect_data_, indirect_data_size_);
355172f8c9be706e27f43022063bbc7f4b0177583acShawn Willden    buf = append_uint32_to_buf(buf, end, elems_size_);
356172f8c9be706e27f43022063bbc7f4b0177583acShawn Willden    buf = append_uint32_to_buf(buf, end, SerializedSizeOfElements());
3578d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    for (size_t i = 0; i < elems_size_; ++i) {
3588d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden        buf = serialize(elems_[i], buf, end, indirect_data_);
3598d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    }
3608d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    return buf;
3615ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden}
3625ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
363370121346777e13437c275fbe7a975d899cc325cShawn Willdenbool AuthorizationSet::DeserializeIndirectData(const uint8_t** buf_ptr, const uint8_t* end) {
364f2282b3c6690ccfaa7878886f01693ef4f0b3bedShawn Willden    UniquePtr<uint8_t[]> indirect_buf;
365f2282b3c6690ccfaa7878886f01693ef4f0b3bedShawn Willden    if (!copy_size_and_data_from_buf(buf_ptr, end, &indirect_data_size_, &indirect_buf)) {
366370121346777e13437c275fbe7a975d899cc325cShawn Willden        set_invalid(MALFORMED_DATA);
367370121346777e13437c275fbe7a975d899cc325cShawn Willden        return false;
368370121346777e13437c275fbe7a975d899cc325cShawn Willden    }
369f2282b3c6690ccfaa7878886f01693ef4f0b3bedShawn Willden    indirect_data_ = indirect_buf.release();
370370121346777e13437c275fbe7a975d899cc325cShawn Willden    return true;
371370121346777e13437c275fbe7a975d899cc325cShawn Willden}
3725ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
373370121346777e13437c275fbe7a975d899cc325cShawn Willdenbool AuthorizationSet::DeserializeElementsData(const uint8_t** buf_ptr, const uint8_t* end) {
3748d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    uint32_t elements_count;
3758d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    uint32_t elements_size;
376370121346777e13437c275fbe7a975d899cc325cShawn Willden    if (!copy_uint32_from_buf(buf_ptr, end, &elements_count) ||
377172f8c9be706e27f43022063bbc7f4b0177583acShawn Willden        !copy_uint32_from_buf(buf_ptr, end, &elements_size)) {
37858e1a5486219a1be9264d4e863a9dd3e393906c3Shawn Willden        set_invalid(MALFORMED_DATA);
3795ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden        return false;
3805ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    }
3815ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
382834e80747cbb960f8a4028c5c8604bf5218ecdb9Shawn Willden    // Note that the following validation of elements_count is weak, but it prevents allocation of
383834e80747cbb960f8a4028c5c8604bf5218ecdb9Shawn Willden    // elems_ arrays which are clearly too large to be reasonable.
38462de26672193373972f2ce968b51cf8335f118f9Shawn Willden    if (static_cast<ptrdiff_t>(elements_size) > end - *buf_ptr ||
38562de26672193373972f2ce968b51cf8335f118f9Shawn Willden        elements_count * sizeof(uint32_t) > elements_size) {
386834e80747cbb960f8a4028c5c8604bf5218ecdb9Shawn Willden        set_invalid(MALFORMED_DATA);
387834e80747cbb960f8a4028c5c8604bf5218ecdb9Shawn Willden        return false;
388834e80747cbb960f8a4028c5c8604bf5218ecdb9Shawn Willden    }
389834e80747cbb960f8a4028c5c8604bf5218ecdb9Shawn Willden
390370121346777e13437c275fbe7a975d899cc325cShawn Willden    if (!reserve_elems(elements_count))
3915ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden        return false;
3925ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
3938d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    uint8_t* indirect_end = indirect_data_ + indirect_data_size_;
394172f8c9be706e27f43022063bbc7f4b0177583acShawn Willden    const uint8_t* elements_end = *buf_ptr + elements_size;
3958d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    for (size_t i = 0; i < elements_count; ++i) {
396172f8c9be706e27f43022063bbc7f4b0177583acShawn Willden        if (!deserialize(elems_ + i, buf_ptr, elements_end, indirect_data_, indirect_end)) {
3978d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden            set_invalid(MALFORMED_DATA);
3988d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden            return false;
3998d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden        }
40058e1a5486219a1be9264d4e863a9dd3e393906c3Shawn Willden    }
401370121346777e13437c275fbe7a975d899cc325cShawn Willden    elems_size_ = elements_count;
402370121346777e13437c275fbe7a975d899cc325cShawn Willden    return true;
403370121346777e13437c275fbe7a975d899cc325cShawn Willden}
4045ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
405370121346777e13437c275fbe7a975d899cc325cShawn Willdenbool AuthorizationSet::Deserialize(const uint8_t** buf_ptr, const uint8_t* end) {
406370121346777e13437c275fbe7a975d899cc325cShawn Willden    FreeData();
407370121346777e13437c275fbe7a975d899cc325cShawn Willden
408370121346777e13437c275fbe7a975d899cc325cShawn Willden    if (!DeserializeIndirectData(buf_ptr, end) || !DeserializeElementsData(buf_ptr, end))
409370121346777e13437c275fbe7a975d899cc325cShawn Willden        return false;
410370121346777e13437c275fbe7a975d899cc325cShawn Willden
411370121346777e13437c275fbe7a975d899cc325cShawn Willden    if (indirect_data_size_ != ComputeIndirectDataSize(elems_, elems_size_)) {
4128d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden        set_invalid(MALFORMED_DATA);
4135ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden        return false;
4145ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    }
4158d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    return true;
4165ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden}
4175ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
418941d1c4ad4422a796d90010191c11aef0580295eShawn Willdenvoid AuthorizationSet::Clear() {
4191834d5f82a7ad5884c184fd22c702ac9d915af45Shawn Willden    memset_s(elems_, 0, elems_size_ * sizeof(keymaster_key_param_t));
4201834d5f82a7ad5884c184fd22c702ac9d915af45Shawn Willden    memset_s(indirect_data_, 0, indirect_data_size_);
421941d1c4ad4422a796d90010191c11aef0580295eShawn Willden    elems_size_ = 0;
422941d1c4ad4422a796d90010191c11aef0580295eShawn Willden    indirect_data_size_ = 0;
423941d1c4ad4422a796d90010191c11aef0580295eShawn Willden}
424941d1c4ad4422a796d90010191c11aef0580295eShawn Willden
425941d1c4ad4422a796d90010191c11aef0580295eShawn Willdenvoid AuthorizationSet::FreeData() {
426941d1c4ad4422a796d90010191c11aef0580295eShawn Willden    Clear();
42758e1a5486219a1be9264d4e863a9dd3e393906c3Shawn Willden
42858e1a5486219a1be9264d4e863a9dd3e393906c3Shawn Willden    delete[] elems_;
42958e1a5486219a1be9264d4e863a9dd3e393906c3Shawn Willden    delete[] indirect_data_;
43058e1a5486219a1be9264d4e863a9dd3e393906c3Shawn Willden
4315ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    elems_ = NULL;
4325ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    indirect_data_ = NULL;
4335ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    elems_capacity_ = 0;
4345ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    indirect_data_capacity_ = 0;
435370121346777e13437c275fbe7a975d899cc325cShawn Willden    error_ = OK;
4365ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden}
4375ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
4385ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden/* static */
4395ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willdensize_t AuthorizationSet::ComputeIndirectDataSize(const keymaster_key_param_t* elems, size_t count) {
4405ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    size_t size = 0;
4415ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    for (size_t i = 0; i < count; ++i) {
4425ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden        if (is_blob_tag(elems[i].tag)) {
4435ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden            size += elems[i].blob.data_length;
4445ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden        }
4455ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    }
4465ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    return size;
4475ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden}
4485ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
4495ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willdenvoid AuthorizationSet::CopyIndirectData() {
450370121346777e13437c275fbe7a975d899cc325cShawn Willden    memset_s(indirect_data_, 0, indirect_data_capacity_);
4515ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
4525ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    uint8_t* indirect_data_pos = indirect_data_;
4535ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    for (size_t i = 0; i < elems_size_; ++i) {
454370121346777e13437c275fbe7a975d899cc325cShawn Willden        assert(indirect_data_pos <= indirect_data_ + indirect_data_capacity_);
4555ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden        if (is_blob_tag(elems_[i].tag)) {
4565ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden            memcpy(indirect_data_pos, elems_[i].blob.data, elems_[i].blob.data_length);
4575ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden            elems_[i].blob.data = indirect_data_pos;
4585ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden            indirect_data_pos += elems_[i].blob.data_length;
4595ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden        }
4605ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    }
461370121346777e13437c275fbe7a975d899cc325cShawn Willden    assert(indirect_data_pos == indirect_data_ + indirect_data_capacity_);
462370121346777e13437c275fbe7a975d899cc325cShawn Willden    indirect_data_size_ = indirect_data_pos - indirect_data_;
4635ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden}
4645ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
4651fa5d591fe6807665092753a5628d8d470888da4Shawn Willdensize_t AuthorizationSet::GetTagCount(keymaster_tag_t tag) const {
4661fa5d591fe6807665092753a5628d8d470888da4Shawn Willden    size_t count = 0;
4671fa5d591fe6807665092753a5628d8d470888da4Shawn Willden    for (int pos = -1; (pos = find(tag, pos)) != -1;)
4681fa5d591fe6807665092753a5628d8d470888da4Shawn Willden        ++count;
4691fa5d591fe6807665092753a5628d8d470888da4Shawn Willden    return count;
4701fa5d591fe6807665092753a5628d8d470888da4Shawn Willden}
4711fa5d591fe6807665092753a5628d8d470888da4Shawn Willden
4725ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willdenbool AuthorizationSet::GetTagValueEnum(keymaster_tag_t tag, uint32_t* val) const {
4735ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    int pos = find(tag);
4745ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    if (pos == -1) {
4755ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden        return false;
4765ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    }
477ebf627f0b50c0979e6cf53668464297703371ebaShawn Willden    *val = elems_[pos].enumerated;
4785ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    return true;
4795ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden}
4805ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
4815ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willdenbool AuthorizationSet::GetTagValueEnumRep(keymaster_tag_t tag, size_t instance,
4825ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden                                          uint32_t* val) const {
4835ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    size_t count = 0;
4845ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    int pos = -1;
4855ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    while (count <= instance) {
4865ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden        pos = find(tag, pos);
4875ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden        if (pos == -1) {
4885ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden            return false;
4895ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden        }
4905ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden        ++count;
4915ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    }
492ebf627f0b50c0979e6cf53668464297703371ebaShawn Willden    *val = elems_[pos].enumerated;
4935ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    return true;
4945ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden}
4955ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
4965ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willdenbool AuthorizationSet::GetTagValueInt(keymaster_tag_t tag, uint32_t* val) const {
4975ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    int pos = find(tag);
4985ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    if (pos == -1) {
4995ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden        return false;
5005ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    }
501ebf627f0b50c0979e6cf53668464297703371ebaShawn Willden    *val = elems_[pos].integer;
5025ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    return true;
5035ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden}
5045ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
5055ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willdenbool AuthorizationSet::GetTagValueIntRep(keymaster_tag_t tag, size_t instance,
5065ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden                                         uint32_t* val) const {
5075ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    size_t count = 0;
5085ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    int pos = -1;
5095ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    while (count <= instance) {
5105ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden        pos = find(tag, pos);
5115ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden        if (pos == -1) {
5125ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden            return false;
5135ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden        }
5145ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden        ++count;
5155ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    }
516ebf627f0b50c0979e6cf53668464297703371ebaShawn Willden    *val = elems_[pos].integer;
5175ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    return true;
5185ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden}
5195ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
5205ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willdenbool AuthorizationSet::GetTagValueLong(keymaster_tag_t tag, uint64_t* val) const {
5215ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    int pos = find(tag);
5225ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    if (pos == -1) {
5235ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden        return false;
5245ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    }
525ebf627f0b50c0979e6cf53668464297703371ebaShawn Willden    *val = elems_[pos].long_integer;
5265ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    return true;
5275ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden}
5285ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
5295ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willdenbool AuthorizationSet::GetTagValueDate(keymaster_tag_t tag, uint64_t* val) const {
5305ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    int pos = find(tag);
5315ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    if (pos == -1) {
5325ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden        return false;
5335ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    }
534ebf627f0b50c0979e6cf53668464297703371ebaShawn Willden    *val = elems_[pos].date_time;
5355ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    return true;
5365ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden}
5375ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
5385ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willdenbool AuthorizationSet::GetTagValueBlob(keymaster_tag_t tag, keymaster_blob_t* val) const {
5395ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    int pos = find(tag);
5405ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    if (pos == -1) {
5415ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden        return false;
5425ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    }
543ebf627f0b50c0979e6cf53668464297703371ebaShawn Willden    *val = elems_[pos].blob;
5445ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    return true;
5455ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden}
5465ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
547dfa1c030e941cba4e66b362854d84b19298353c9Shawn Willdenbool AuthorizationSet::GetTagValueBool(keymaster_tag_t tag) const {
548dfa1c030e941cba4e66b362854d84b19298353c9Shawn Willden    int pos = find(tag);
549dfa1c030e941cba4e66b362854d84b19298353c9Shawn Willden    if (pos == -1) {
550dfa1c030e941cba4e66b362854d84b19298353c9Shawn Willden        return false;
551dfa1c030e941cba4e66b362854d84b19298353c9Shawn Willden    }
552dfa1c030e941cba4e66b362854d84b19298353c9Shawn Willden    assert(elems_[pos].boolean);
553dfa1c030e941cba4e66b362854d84b19298353c9Shawn Willden    return elems_[pos].boolean;
554dfa1c030e941cba4e66b362854d84b19298353c9Shawn Willden}
555dfa1c030e941cba4e66b362854d84b19298353c9Shawn Willden
5565ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden}  // namespace keymaster
557