15ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden/*
25ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden * Copyright 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
17b10f3b26af1e3b382d9ef361b3eb5279d16a9c05Shawn Willden#ifndef SYSTEM_KEYMASTER_AUTHORIZATION_SET_H_
18b10f3b26af1e3b382d9ef361b3eb5279d16a9c05Shawn Willden#define SYSTEM_KEYMASTER_AUTHORIZATION_SET_H_
195ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
20f38a002624126ca837865826f948edc9100d6e8aJanis Danisevskis#include <keymaster/UniquePtr.h>
215ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
22b9d584d3dacc8041e5502cd0d036e21895eb6dc6Shawn Willden#include <hardware/keymaster_defs.h>
2398d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden#include <keymaster/keymaster_tags.h>
2498d9b92547a9a7553b99e3e941a4175926f95b62Shawn Willden#include <keymaster/serializable.h>
255ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
265ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willdennamespace keymaster {
275ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
282c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willdenclass AuthorizationSetBuilder;
292c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden
305ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden/**
31bf0679a97499f92abc664179ddb8c1e3974f5c85Shawn Willden * An extension of the keymaster_key_param_set_t struct, which provides serialization memory
32bf0679a97499f92abc664179ddb8c1e3974f5c85Shawn Willden * management and methods for easy manipulation and construction.
335ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden */
34bf0679a97499f92abc664179ddb8c1e3974f5c85Shawn Willdenclass AuthorizationSet : public Serializable, public keymaster_key_param_set_t {
355ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden  public:
365ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    /**
375ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     * Construct an empty, dynamically-allocated, growable AuthorizationSet.  Does not actually
385ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     * allocate any storage until elements are added, so there is no cost to creating an
395ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     * AuthorizationSet with this constructor and then reinitializing it to point at pre-allocated
405ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     * buffers, with \p Reinitialize.
415ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     */
425ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    AuthorizationSet()
43bf0679a97499f92abc664179ddb8c1e3974f5c85Shawn Willden        : elems_capacity_(0), indirect_data_(NULL), indirect_data_size_(0),
44bf0679a97499f92abc664179ddb8c1e3974f5c85Shawn Willden          indirect_data_capacity_(0), error_(OK) {
45bf0679a97499f92abc664179ddb8c1e3974f5c85Shawn Willden        elems_ = nullptr;
46bf0679a97499f92abc664179ddb8c1e3974f5c85Shawn Willden        elems_size_ = 0;
47bf0679a97499f92abc664179ddb8c1e3974f5c85Shawn Willden    }
485ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
495ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    /**
505ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     * Construct an AuthorizationSet from the provided array.  The AuthorizationSet copies the data
515ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     * from the provided array (and the data referenced by its embedded pointers, if any) into
525ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     * dynamically-allocated storage.  If allocation of the needed storage fails, \p is_valid() will
535ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     * return ALLOCATION_FAILURE. It is the responsibility of the caller to check before using the
545ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     * set, if allocations might fail.
555ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     */
56bf0679a97499f92abc664179ddb8c1e3974f5c85Shawn Willden    AuthorizationSet(const keymaster_key_param_t* elems, size_t count) : indirect_data_(nullptr) {
57bf0679a97499f92abc664179ddb8c1e3974f5c85Shawn Willden        elems_ = nullptr;
585ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden        Reinitialize(elems, count);
595ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    }
605ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
61bf0679a97499f92abc664179ddb8c1e3974f5c85Shawn Willden    explicit AuthorizationSet(const keymaster_key_param_set_t& set) : indirect_data_(nullptr) {
62bf0679a97499f92abc664179ddb8c1e3974f5c85Shawn Willden        elems_ = nullptr;
63cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden        Reinitialize(set.params, set.length);
64cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden    }
65cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden
66bf0679a97499f92abc664179ddb8c1e3974f5c85Shawn Willden    explicit AuthorizationSet(const uint8_t* serialized_set, size_t serialized_size)
67bf0679a97499f92abc664179ddb8c1e3974f5c85Shawn Willden        : indirect_data_(nullptr) {
68bf0679a97499f92abc664179ddb8c1e3974f5c85Shawn Willden        elems_ = nullptr;
6958e1a5486219a1be9264d4e863a9dd3e393906c3Shawn Willden        Deserialize(&serialized_set, serialized_set + serialized_size);
705ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    }
715ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
722c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    /**
732c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden     * Construct an AuthorizationSet from the provided builder.  This extracts the data from the
742c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden     * builder, rather than copying it, so after this call the builder is empty.
752c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden     */
76bf0679a97499f92abc664179ddb8c1e3974f5c85Shawn Willden    explicit AuthorizationSet(/* NOT const */ AuthorizationSetBuilder& builder);
772c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden
7858e1a5486219a1be9264d4e863a9dd3e393906c3Shawn Willden    // Copy constructor.
79bf0679a97499f92abc664179ddb8c1e3974f5c85Shawn Willden    AuthorizationSet(const AuthorizationSet& set) : Serializable(), indirect_data_(nullptr) {
80bf0679a97499f92abc664179ddb8c1e3974f5c85Shawn Willden        elems_ = nullptr;
8143786c8ca4e9034b5aa1528b52f9eaaa7551b05fPaul Crowley        error_ = set.error_;
82856761d5b01da66c09dbc6cb339b5345bfe0a945Janis Danisevskis        if (error_ != OK) return;
83856761d5b01da66c09dbc6cb339b5345bfe0a945Janis Danisevskis        Reinitialize(set.elems_, set.elems_size_);
8443786c8ca4e9034b5aa1528b52f9eaaa7551b05fPaul Crowley    }
8543786c8ca4e9034b5aa1528b52f9eaaa7551b05fPaul Crowley
8643786c8ca4e9034b5aa1528b52f9eaaa7551b05fPaul Crowley    // Move constructor.
8743786c8ca4e9034b5aa1528b52f9eaaa7551b05fPaul Crowley    AuthorizationSet(AuthorizationSet&& set) : Serializable() {
8843786c8ca4e9034b5aa1528b52f9eaaa7551b05fPaul Crowley        MoveFrom(set);
8943786c8ca4e9034b5aa1528b52f9eaaa7551b05fPaul Crowley    }
9043786c8ca4e9034b5aa1528b52f9eaaa7551b05fPaul Crowley
9143786c8ca4e9034b5aa1528b52f9eaaa7551b05fPaul Crowley    // Copy assignment.
9243786c8ca4e9034b5aa1528b52f9eaaa7551b05fPaul Crowley    AuthorizationSet& operator=(const AuthorizationSet& set) {
9343786c8ca4e9034b5aa1528b52f9eaaa7551b05fPaul Crowley        Reinitialize(set.elems_, set.elems_size_);
9443786c8ca4e9034b5aa1528b52f9eaaa7551b05fPaul Crowley        error_ = set.error_;
9543786c8ca4e9034b5aa1528b52f9eaaa7551b05fPaul Crowley        return *this;
9643786c8ca4e9034b5aa1528b52f9eaaa7551b05fPaul Crowley    }
9743786c8ca4e9034b5aa1528b52f9eaaa7551b05fPaul Crowley
9843786c8ca4e9034b5aa1528b52f9eaaa7551b05fPaul Crowley    // Move assignment.
9943786c8ca4e9034b5aa1528b52f9eaaa7551b05fPaul Crowley    AuthorizationSet& operator=(AuthorizationSet&& set) {
10043786c8ca4e9034b5aa1528b52f9eaaa7551b05fPaul Crowley        FreeData();
10143786c8ca4e9034b5aa1528b52f9eaaa7551b05fPaul Crowley        MoveFrom(set);
10243786c8ca4e9034b5aa1528b52f9eaaa7551b05fPaul Crowley        return *this;
103bf0679a97499f92abc664179ddb8c1e3974f5c85Shawn Willden    }
10458e1a5486219a1be9264d4e863a9dd3e393906c3Shawn Willden
1055ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    /**
106941d1c4ad4422a796d90010191c11aef0580295eShawn Willden     * Clear existing authorization set data
107941d1c4ad4422a796d90010191c11aef0580295eShawn Willden     */
108941d1c4ad4422a796d90010191c11aef0580295eShawn Willden    void Clear();
109941d1c4ad4422a796d90010191c11aef0580295eShawn Willden
110941d1c4ad4422a796d90010191c11aef0580295eShawn Willden    /**
1115ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     * Reinitialize an AuthorizationSet as a dynamically-allocated, growable copy of the data in the
1125ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     * provided array (and the data referenced by its embedded pointers, if any).  If the allocation
1135ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     * of the needed storage fails this method will return false and \p is_valid() will return
1145ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     * ALLOCATION_FAILURE.
1155ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     */
1165ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    bool Reinitialize(const keymaster_key_param_t* elems, size_t count);
1175ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
1187636471bd1c553ac179f0dddc17133491d0e1fafShawn Willden    bool Reinitialize(const AuthorizationSet& set) {
1197636471bd1c553ac179f0dddc17133491d0e1fafShawn Willden        return Reinitialize(set.elems_, set.elems_size_);
1207636471bd1c553ac179f0dddc17133491d0e1fafShawn Willden    }
1217636471bd1c553ac179f0dddc17133491d0e1fafShawn Willden
122bf0679a97499f92abc664179ddb8c1e3974f5c85Shawn Willden    bool Reinitialize(const keymaster_key_param_set_t& set) {
123bf0679a97499f92abc664179ddb8c1e3974f5c85Shawn Willden        return Reinitialize(set.params, set.length);
124bf0679a97499f92abc664179ddb8c1e3974f5c85Shawn Willden    }
125bf0679a97499f92abc664179ddb8c1e3974f5c85Shawn Willden
12658e1a5486219a1be9264d4e863a9dd3e393906c3Shawn Willden    ~AuthorizationSet();
1275ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
1285ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    enum Error {
12958e1a5486219a1be9264d4e863a9dd3e393906c3Shawn Willden        OK,
1305ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden        ALLOCATION_FAILURE,
1315ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden        MALFORMED_DATA,
1325ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    };
1335ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
134172f8c9be706e27f43022063bbc7f4b0177583acShawn Willden    Error is_valid() const { return error_; }
1355ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
1365ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    /**
1375ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     * Returns the size of the set.
1385ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     */
139172f8c9be706e27f43022063bbc7f4b0177583acShawn Willden    size_t size() const { return elems_size_; }
1407636471bd1c553ac179f0dddc17133491d0e1fafShawn Willden
1417636471bd1c553ac179f0dddc17133491d0e1fafShawn Willden    /**
142cb647fec03f71929fd316d2b8f0750f7b24824f3Shawn Willden     * Returns true if the set is empty.
143cb647fec03f71929fd316d2b8f0750f7b24824f3Shawn Willden     */
144cb647fec03f71929fd316d2b8f0750f7b24824f3Shawn Willden    bool empty() const { return size() == 0; }
145cb647fec03f71929fd316d2b8f0750f7b24824f3Shawn Willden
146cb647fec03f71929fd316d2b8f0750f7b24824f3Shawn Willden    /**
147370121346777e13437c275fbe7a975d899cc325cShawn Willden     * Returns the total size of all indirect data referenced by set elements.
148370121346777e13437c275fbe7a975d899cc325cShawn Willden     */
149370121346777e13437c275fbe7a975d899cc325cShawn Willden    size_t indirect_size() const { return indirect_data_size_; }
150370121346777e13437c275fbe7a975d899cc325cShawn Willden
151370121346777e13437c275fbe7a975d899cc325cShawn Willden    /**
1527636471bd1c553ac179f0dddc17133491d0e1fafShawn Willden     * Returns the data in the set, directly. Be careful with this.
1537636471bd1c553ac179f0dddc17133491d0e1fafShawn Willden     */
154be4a2a3e70ada1ee026eaffb7163211161396215Shawn Willden    const keymaster_key_param_t* data() const { return elems_; }
155cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden
156cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden    /**
157f21afff128ac22479c49bdda84f13335ae17d009Shawn Willden     * Sorts the set
158f21afff128ac22479c49bdda84f13335ae17d009Shawn Willden     */
159f21afff128ac22479c49bdda84f13335ae17d009Shawn Willden    void Sort();
160f21afff128ac22479c49bdda84f13335ae17d009Shawn Willden
161f21afff128ac22479c49bdda84f13335ae17d009Shawn Willden    /**
1622c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden     * Sorts the set and removes duplicates (inadvertently duplicating tags is easy to do with the
1632c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden     * AuthorizationSetBuilder).
1642c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden     */
1652c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    void Deduplicate();
1662c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden
1672c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    /**
168391a367df2352bed7e70885493421892a1cdaffcTucker Sylvestro     * Adds all elements from \p set that are not already present in this AuthorizationSet.  As a
169391a367df2352bed7e70885493421892a1cdaffcTucker Sylvestro     * side-effect, if \p set is not null this AuthorizationSet will end up sorted.
170391a367df2352bed7e70885493421892a1cdaffcTucker Sylvestro     */
171391a367df2352bed7e70885493421892a1cdaffcTucker Sylvestro    void Union(const keymaster_key_param_set_t& set);
172391a367df2352bed7e70885493421892a1cdaffcTucker Sylvestro
173391a367df2352bed7e70885493421892a1cdaffcTucker Sylvestro    /**
174391a367df2352bed7e70885493421892a1cdaffcTucker Sylvestro     * Removes all elements in \p set from this AuthorizationSet.
175391a367df2352bed7e70885493421892a1cdaffcTucker Sylvestro     */
176391a367df2352bed7e70885493421892a1cdaffcTucker Sylvestro    void Difference(const keymaster_key_param_set_t& set);
177391a367df2352bed7e70885493421892a1cdaffcTucker Sylvestro
178391a367df2352bed7e70885493421892a1cdaffcTucker Sylvestro    /**
179cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden     * Returns the data in a keymaster_key_param_set_t, suitable for returning to C code.  For C
180056ec1531752b6e8491269661581036a95c5d3e5Shawn Willden     * compatibility, the contents are malloced, not new'ed, and so must be freed with free(), or
181056ec1531752b6e8491269661581036a95c5d3e5Shawn Willden     * better yet with keymaster_free_param_set, not delete.  The caller takes ownership.
182cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden     */
183cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden    void CopyToParamSet(keymaster_key_param_set_t* set) const;
1845ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
1855ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    /**
1865ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     * Returns the offset of the next entry that matches \p tag, starting from the element after \p
1875ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     * begin.  If not found, returns -1.
1885ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     */
1895ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    int find(keymaster_tag_t tag, int begin = -1) const;
1905ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
1915ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    /**
192cb647fec03f71929fd316d2b8f0750f7b24824f3Shawn Willden     * Removes the entry at the specified index. Returns true if successful, false if the index was
193cb647fec03f71929fd316d2b8f0750f7b24824f3Shawn Willden     * out of bounds.
194cb647fec03f71929fd316d2b8f0750f7b24824f3Shawn Willden     */
195c15af1910d8f451341d0068b5533816ace5defecShawn Willden    bool erase(int index);
196cb647fec03f71929fd316d2b8f0750f7b24824f3Shawn Willden
197cb647fec03f71929fd316d2b8f0750f7b24824f3Shawn Willden    /**
1983e35dbcecbc5ae9de32be2c437c08a9faa940d5bShawn Willden     * Returns iterator (pointer) to beginning of elems array, to enable STL-style iteration
1993e35dbcecbc5ae9de32be2c437c08a9faa940d5bShawn Willden     */
2003e35dbcecbc5ae9de32be2c437c08a9faa940d5bShawn Willden    const keymaster_key_param_t* begin() const { return elems_; }
2013e35dbcecbc5ae9de32be2c437c08a9faa940d5bShawn Willden
2023e35dbcecbc5ae9de32be2c437c08a9faa940d5bShawn Willden    /**
2033e35dbcecbc5ae9de32be2c437c08a9faa940d5bShawn Willden     * Returns iterator (pointer) one past end of elems array, to enable STL-style iteration
2043e35dbcecbc5ae9de32be2c437c08a9faa940d5bShawn Willden     */
2053e35dbcecbc5ae9de32be2c437c08a9faa940d5bShawn Willden    const keymaster_key_param_t* end() const { return elems_ + elems_size_; }
2063e35dbcecbc5ae9de32be2c437c08a9faa940d5bShawn Willden
2073e35dbcecbc5ae9de32be2c437c08a9faa940d5bShawn Willden    /**
2085ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     * Returns the nth element of the set.
2095ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     */
210d599b15c0693950bdc72fb867872044fdc484ef5Shawn Willden    keymaster_key_param_t& operator[](int n);
211d599b15c0693950bdc72fb867872044fdc484ef5Shawn Willden
212d599b15c0693950bdc72fb867872044fdc484ef5Shawn Willden    /**
213d599b15c0693950bdc72fb867872044fdc484ef5Shawn Willden     * Returns the nth element of the set.
214d599b15c0693950bdc72fb867872044fdc484ef5Shawn Willden     */
2155ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    keymaster_key_param_t operator[](int n) const;
2165ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
2175ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    /**
2183609584c328ea66f95478dded394ad4697779450Shawn Willden     * Returns true if the set contains at least one instance of \p tag
2193609584c328ea66f95478dded394ad4697779450Shawn Willden     */
2203609584c328ea66f95478dded394ad4697779450Shawn Willden    bool Contains(keymaster_tag_t tag) const {
2213609584c328ea66f95478dded394ad4697779450Shawn Willden        return find(tag) != -1;
2223609584c328ea66f95478dded394ad4697779450Shawn Willden    }
2233609584c328ea66f95478dded394ad4697779450Shawn Willden
2243609584c328ea66f95478dded394ad4697779450Shawn Willden    /**
2251fa5d591fe6807665092753a5628d8d470888da4Shawn Willden     * Returns the number of \p tag entries.
2261fa5d591fe6807665092753a5628d8d470888da4Shawn Willden     */
2271fa5d591fe6807665092753a5628d8d470888da4Shawn Willden    size_t GetTagCount(keymaster_tag_t tag) const;
2281fa5d591fe6807665092753a5628d8d470888da4Shawn Willden
2291fa5d591fe6807665092753a5628d8d470888da4Shawn Willden    /**
230edb7994f7d5764fcf06188dc005743f4209deb0fShawn Willden     * Returns true if the set contains the specified tag and value.
231edb7994f7d5764fcf06188dc005743f4209deb0fShawn Willden     */
232edb7994f7d5764fcf06188dc005743f4209deb0fShawn Willden    template <keymaster_tag_t Tag, typename T>
233edb7994f7d5764fcf06188dc005743f4209deb0fShawn Willden    bool Contains(TypedEnumTag<KM_ENUM_REP, Tag, T> tag, T val) const {
234edb7994f7d5764fcf06188dc005743f4209deb0fShawn Willden        return ContainsEnumValue(tag, val);
235edb7994f7d5764fcf06188dc005743f4209deb0fShawn Willden    }
236edb7994f7d5764fcf06188dc005743f4209deb0fShawn Willden
237edb7994f7d5764fcf06188dc005743f4209deb0fShawn Willden    /**
238226746bfb5f79857145d5f3ebdfd6f49b6c114acShawn Willden     * Returns true if the set contains the specified tag and value.
239226746bfb5f79857145d5f3ebdfd6f49b6c114acShawn Willden     */
240226746bfb5f79857145d5f3ebdfd6f49b6c114acShawn Willden    template <keymaster_tag_t Tag, typename T>
241226746bfb5f79857145d5f3ebdfd6f49b6c114acShawn Willden    bool Contains(TypedEnumTag<KM_ENUM, Tag, T> tag, T val) const {
242226746bfb5f79857145d5f3ebdfd6f49b6c114acShawn Willden        return ContainsEnumValue(tag, val);
243226746bfb5f79857145d5f3ebdfd6f49b6c114acShawn Willden    }
244226746bfb5f79857145d5f3ebdfd6f49b6c114acShawn Willden
245226746bfb5f79857145d5f3ebdfd6f49b6c114acShawn Willden    /**
246ba0d5d01bde427b7d7a22cec84cd9304c00b4e14Shawn Willden     * Returns true if the set contains the specified tag and value.
247ba0d5d01bde427b7d7a22cec84cd9304c00b4e14Shawn Willden     */
248ba0d5d01bde427b7d7a22cec84cd9304c00b4e14Shawn Willden    template <keymaster_tag_t Tag>
249ba0d5d01bde427b7d7a22cec84cd9304c00b4e14Shawn Willden    bool Contains(TypedTag<KM_UINT, Tag> tag, uint32_t val) const {
250ba0d5d01bde427b7d7a22cec84cd9304c00b4e14Shawn Willden        return ContainsIntValue(tag, val);
251ba0d5d01bde427b7d7a22cec84cd9304c00b4e14Shawn Willden    }
252ba0d5d01bde427b7d7a22cec84cd9304c00b4e14Shawn Willden
253ba0d5d01bde427b7d7a22cec84cd9304c00b4e14Shawn Willden    /**
2545ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     * If the specified integer-typed \p tag exists, places its value in \p val and returns true.
2555ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     * If \p tag is not present, leaves \p val unmodified and returns false.
2565ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     */
2575ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    template <keymaster_tag_t T>
258c3ac84f04c4d6d74fa36abfd1cc2e5ac763a8af3Shawn Willden    inline bool GetTagValue(TypedTag<KM_UINT, T> tag, uint32_t* val) const {
2595ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden        return GetTagValueInt(tag, val);
2605ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    }
2615ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
2625ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    /**
2635ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     * If the specified instance of the specified integer-typed \p tag exists, places its value
2645ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     * in \p val and returns true.  If \p tag is not present, leaves \p val unmodified and returns
2655ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     * false.
2665ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     */
2675ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    template <keymaster_tag_t Tag>
268c3ac84f04c4d6d74fa36abfd1cc2e5ac763a8af3Shawn Willden    bool GetTagValue(TypedTag<KM_UINT_REP, Tag> tag, size_t instance, uint32_t* val) const {
2695ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden        return GetTagValueIntRep(tag, instance, val);
2705ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    }
2715ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
2725ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    /**
2735ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     * If the specified long-typed \p tag exists, places its value in \p val and returns true.
2745ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     * If \p tag is not present, leaves \p val unmodified and returns false.
2755ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     */
2765ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    template <keymaster_tag_t T>
277c3ac84f04c4d6d74fa36abfd1cc2e5ac763a8af3Shawn Willden    inline bool GetTagValue(TypedTag<KM_ULONG, T> tag, uint64_t* val) const {
2785ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden        return GetTagValueLong(tag, val);
2795ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    }
2805ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
2815ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    /**
282eb63b9799eadcaa6ef206f8b804d7432e0dab14aShawn Willden     * If the specified instance of the specified integer-typed \p tag exists, places its value
283eb63b9799eadcaa6ef206f8b804d7432e0dab14aShawn Willden     * in \p val and returns true.  If \p tag is not present, leaves \p val unmodified and returns
284eb63b9799eadcaa6ef206f8b804d7432e0dab14aShawn Willden     * false.
285eb63b9799eadcaa6ef206f8b804d7432e0dab14aShawn Willden     */
286eb63b9799eadcaa6ef206f8b804d7432e0dab14aShawn Willden    template <keymaster_tag_t Tag>
287c3ac84f04c4d6d74fa36abfd1cc2e5ac763a8af3Shawn Willden    bool GetTagValue(TypedTag<KM_ULONG_REP, Tag> tag, size_t instance, uint64_t* val) const {
288eb63b9799eadcaa6ef206f8b804d7432e0dab14aShawn Willden        return GetTagValueLongRep(tag, instance, val);
289eb63b9799eadcaa6ef206f8b804d7432e0dab14aShawn Willden    }
290eb63b9799eadcaa6ef206f8b804d7432e0dab14aShawn Willden
291eb63b9799eadcaa6ef206f8b804d7432e0dab14aShawn Willden    /**
2925ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     * If the specified enumeration-typed \p tag exists, places its value in \p val and returns
2935ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     * true.  If \p tag is not present, leaves \p val unmodified and returns false.
2945ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     */
2955ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    template <keymaster_tag_t Tag, typename T>
2965ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    bool GetTagValue(TypedEnumTag<KM_ENUM, Tag, T> tag, T* val) const {
2975ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden        return GetTagValueEnum(tag, reinterpret_cast<uint32_t*>(val));
2985ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    }
2995ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
3005ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    /**
3015ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     * If the specified instance of the specified enumeration-typed \p tag exists, places its value
3025ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     * in \p val and returns true.  If \p tag is not present, leaves \p val unmodified and returns
3035ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     * false.
3045ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     */
3055ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    template <keymaster_tag_t Tag, typename T>
3065ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    bool GetTagValue(TypedEnumTag<KM_ENUM_REP, Tag, T> tag, size_t instance, T* val) const {
3075ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden        return GetTagValueEnumRep(tag, instance, reinterpret_cast<uint32_t*>(val));
3085ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    }
3095ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
3105ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    /**
311d9d7acff7c43f52ebd038eb77afd67d597844b35Shawn Willden     * If exactly one instance of the specified enumeration-typed \p tag exists, places its value in
312d9d7acff7c43f52ebd038eb77afd67d597844b35Shawn Willden     * \p val and returns true.  If \p tag is not present or if multiple copies are present, leaves
313d9d7acff7c43f52ebd038eb77afd67d597844b35Shawn Willden     * \p val unmodified and returns false.
314d9d7acff7c43f52ebd038eb77afd67d597844b35Shawn Willden     */
315d9d7acff7c43f52ebd038eb77afd67d597844b35Shawn Willden    template <keymaster_tag_t Tag, typename T>
316d9d7acff7c43f52ebd038eb77afd67d597844b35Shawn Willden    bool GetTagValue(TypedEnumTag<KM_ENUM_REP, Tag, T> tag, T* val) const {
317d9d7acff7c43f52ebd038eb77afd67d597844b35Shawn Willden        if (GetTagCount(tag) != 1)
318d9d7acff7c43f52ebd038eb77afd67d597844b35Shawn Willden            return false;
319d9d7acff7c43f52ebd038eb77afd67d597844b35Shawn Willden        return GetTagValueEnumRep(tag, 0, reinterpret_cast<uint32_t*>(val));
320d9d7acff7c43f52ebd038eb77afd67d597844b35Shawn Willden    }
321d9d7acff7c43f52ebd038eb77afd67d597844b35Shawn Willden
322d9d7acff7c43f52ebd038eb77afd67d597844b35Shawn Willden    /**
3235ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     * If the specified date-typed \p tag exists, places its value in \p val and returns
3245ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     * true.  If \p tag is not present, leaves \p val unmodified and returns false.
3255ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     */
3265ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    template <keymaster_tag_t Tag>
327c3ac84f04c4d6d74fa36abfd1cc2e5ac763a8af3Shawn Willden    bool GetTagValue(TypedTag<KM_UINT_REP, Tag> tag, size_t instance,
328c3ac84f04c4d6d74fa36abfd1cc2e5ac763a8af3Shawn Willden                     typename TypedTag<KM_UINT_REP, Tag>::value_type* val) const {
3295ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden        return GetTagValueIntRep(tag, instance, val);
3305ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    }
3315ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
3325ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    /**
3335ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     * If the specified bytes-typed \p tag exists, places its value in \p val and returns
3345ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     * true.  If \p tag is not present, leaves \p val unmodified and returns false.
3355ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     */
3365ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    template <keymaster_tag_t Tag>
3375ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    bool GetTagValue(TypedTag<KM_BYTES, Tag> tag, keymaster_blob_t* val) const {
3385ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden        return GetTagValueBlob(tag, val);
3395ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    }
3405ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
3415ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    /**
3425ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     * If the specified bignum-typed \p tag exists, places its value in \p val and returns
3435ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     * true.  If \p tag is not present, leaves \p val unmodified and returns false.
3445ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     */
3455ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    template <keymaster_tag_t Tag>
3465ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    bool GetTagValue(TypedTag<KM_BIGNUM, Tag> tag, keymaster_blob_t* val) const {
34728e41475a2559824a0f3f2c850ed92a65c586f95Shawn Willden        return GetTagValueBlob(tag, val);
3485ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    }
3495ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
3505ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    /**
351dfa1c030e941cba4e66b362854d84b19298353c9Shawn Willden     * Returns true if the specified tag is present, and therefore has the value 'true'.
352dfa1c030e941cba4e66b362854d84b19298353c9Shawn Willden     */
3532c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    template <keymaster_tag_t Tag> bool GetTagValue(TypedTag<KM_BOOL, Tag> tag) const {
354dfa1c030e941cba4e66b362854d84b19298353c9Shawn Willden        return GetTagValueBool(tag);
355dfa1c030e941cba4e66b362854d84b19298353c9Shawn Willden    }
356dfa1c030e941cba4e66b362854d84b19298353c9Shawn Willden
357dfa1c030e941cba4e66b362854d84b19298353c9Shawn Willden    /**
3585ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     * If the specified \p tag exists, places its value in \p val and returns true.  If \p tag is
3595ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     * not present, leaves \p val unmodified and returns false.
3605ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden     */
3615ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    template <keymaster_tag_t Tag, keymaster_tag_type_t Type>
3625ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    bool GetTagValue(TypedTag<Type, Tag> tag, typename TagValueType<Type>::value_type* val) const {
3635ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden        return GetTagValueLong(tag, val);
3645ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    }
3655ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
3665ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    bool push_back(keymaster_key_param_t elem);
3675ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
368370121346777e13437c275fbe7a975d899cc325cShawn Willden    /**
369370121346777e13437c275fbe7a975d899cc325cShawn Willden     * Grow the elements array to ensure it can contain \p count entries.  Preserves any existing
370370121346777e13437c275fbe7a975d899cc325cShawn Willden     * entries.
371370121346777e13437c275fbe7a975d899cc325cShawn Willden     */
372370121346777e13437c275fbe7a975d899cc325cShawn Willden    bool reserve_elems(size_t count);
373370121346777e13437c275fbe7a975d899cc325cShawn Willden
374370121346777e13437c275fbe7a975d899cc325cShawn Willden    /**
375370121346777e13437c275fbe7a975d899cc325cShawn Willden     * Grow the indirect data array to ensure it can contain \p length bytes.  Preserves any
376370121346777e13437c275fbe7a975d899cc325cShawn Willden     * existing indirect data.
377370121346777e13437c275fbe7a975d899cc325cShawn Willden     */
378370121346777e13437c275fbe7a975d899cc325cShawn Willden    bool reserve_indirect(size_t length);
379370121346777e13437c275fbe7a975d899cc325cShawn Willden
380b5508298cdb1d42eaf8c81aa8a6ac2cbfdeef3c7Shawn Willden    bool push_back(const keymaster_key_param_set_t& set);
381370121346777e13437c275fbe7a975d899cc325cShawn Willden
382cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden    /**
383cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden     * Append the tag and enumerated value to the set.
384cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden     */
3855ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    template <keymaster_tag_t Tag, keymaster_tag_type_t Type, typename KeymasterEnum>
3865ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    bool push_back(TypedEnumTag<Type, Tag, KeymasterEnum> tag, KeymasterEnum val) {
3875ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden        return push_back(Authorization(tag, val));
3885ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    }
3895ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
390cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden    /**
391cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden     * Append the boolean tag (value "true") to the set.
392cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden     */
3935ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    template <keymaster_tag_t Tag> bool push_back(TypedTag<KM_BOOL, Tag> tag) {
3945ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden        return push_back(Authorization(tag));
3955ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    }
3965ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
397cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden    /**
398cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden     * Append the tag and byte array to the set.  Copies the array into internal storage; does not
399cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden     * take ownership of the passed-in array.
400cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden     */
4017636471bd1c553ac179f0dddc17133491d0e1fafShawn Willden    template <keymaster_tag_t Tag>
4027636471bd1c553ac179f0dddc17133491d0e1fafShawn Willden    bool push_back(TypedTag<KM_BYTES, Tag> tag, const void* bytes, size_t bytes_len) {
4037636471bd1c553ac179f0dddc17133491d0e1fafShawn Willden        return push_back(keymaster_param_blob(tag, static_cast<const uint8_t*>(bytes), bytes_len));
4047636471bd1c553ac179f0dddc17133491d0e1fafShawn Willden    }
4057636471bd1c553ac179f0dddc17133491d0e1fafShawn Willden
406cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden    /**
407cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden     * Append the tag and blob to the set.  Copies the blob contents into internal storage; does not
408cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden     * take ownership of the blob's data.
409cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden     */
410cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden    template <keymaster_tag_t Tag>
411cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden    bool push_back(TypedTag<KM_BYTES, Tag> tag, const keymaster_blob_t& blob) {
412cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden        return push_back(tag, blob.data, blob.data_length);
413cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden    }
414cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden
415cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden    /**
416cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden     * Append the tag and bignum array to the set.  Copies the array into internal storage; does not
417cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden     * take ownership of the passed-in array.
418cb0d64b02d0df2b9eb692c5b0ea5c36db1000e9aShawn Willden     */
4197636471bd1c553ac179f0dddc17133491d0e1fafShawn Willden    template <keymaster_tag_t Tag>
4207636471bd1c553ac179f0dddc17133491d0e1fafShawn Willden    bool push_back(TypedTag<KM_BIGNUM, Tag> tag, const void* bytes, size_t bytes_len) {
4217636471bd1c553ac179f0dddc17133491d0e1fafShawn Willden        return push_back(keymaster_param_blob(tag, static_cast<const uint8_t*>(bytes), bytes_len));
4227636471bd1c553ac179f0dddc17133491d0e1fafShawn Willden    }
4237636471bd1c553ac179f0dddc17133491d0e1fafShawn Willden
4245ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    template <keymaster_tag_t Tag, keymaster_tag_type_t Type>
4255ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    bool push_back(TypedTag<Type, Tag> tag, typename TypedTag<Type, Tag>::value_type val) {
4265ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden        return push_back(Authorization(tag, val));
4275ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    }
4285ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
4295ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    template <keymaster_tag_t Tag, keymaster_tag_type_t Type>
4305ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    bool push_back(TypedTag<Type, Tag> tag, const void* bytes, size_t bytes_len) {
4315ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden        return push_back(Authorization(tag, bytes, bytes_len));
4325ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    }
4335ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
43458e1a5486219a1be9264d4e863a9dd3e393906c3Shawn Willden    /* Virtual methods from Serializable */
43558e1a5486219a1be9264d4e863a9dd3e393906c3Shawn Willden    size_t SerializedSize() const;
43658e1a5486219a1be9264d4e863a9dd3e393906c3Shawn Willden    uint8_t* Serialize(uint8_t* serialized_set, const uint8_t* end) const;
437172f8c9be706e27f43022063bbc7f4b0177583acShawn Willden    bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end);
4385ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
4398d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    size_t SerializedSizeOfElements() const;
4408d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden
4415ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden  private:
4425ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    void FreeData();
44343786c8ca4e9034b5aa1528b52f9eaaa7551b05fPaul Crowley    void MoveFrom(AuthorizationSet& set);
44443786c8ca4e9034b5aa1528b52f9eaaa7551b05fPaul Crowley
4455ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    void set_invalid(Error err);
4465ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
4475ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    static size_t ComputeIndirectDataSize(const keymaster_key_param_t* elems, size_t count);
4485ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    void CopyIndirectData();
4498d336ae10df66da4c0433f17c2d42e85baea32c5Shawn Willden    bool CheckIndirectData();
4505ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
451370121346777e13437c275fbe7a975d899cc325cShawn Willden    bool DeserializeIndirectData(const uint8_t** buf_ptr, const uint8_t* end);
452370121346777e13437c275fbe7a975d899cc325cShawn Willden    bool DeserializeElementsData(const uint8_t** buf_ptr, const uint8_t* end);
453370121346777e13437c275fbe7a975d899cc325cShawn Willden
4545ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    bool GetTagValueEnum(keymaster_tag_t tag, uint32_t* val) const;
4555ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    bool GetTagValueEnumRep(keymaster_tag_t tag, size_t instance, uint32_t* val) const;
4565ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    bool GetTagValueInt(keymaster_tag_t tag, uint32_t* val) const;
4575ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    bool GetTagValueIntRep(keymaster_tag_t tag, size_t instance, uint32_t* val) const;
4585ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    bool GetTagValueLong(keymaster_tag_t tag, uint64_t* val) const;
459eb63b9799eadcaa6ef206f8b804d7432e0dab14aShawn Willden    bool GetTagValueLongRep(keymaster_tag_t tag, size_t instance, uint64_t* val) const;
4605ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    bool GetTagValueDate(keymaster_tag_t tag, uint64_t* val) const;
4615ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    bool GetTagValueBlob(keymaster_tag_t tag, keymaster_blob_t* val) const;
462dfa1c030e941cba4e66b362854d84b19298353c9Shawn Willden    bool GetTagValueBool(keymaster_tag_t tag) const;
4635ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
464edb7994f7d5764fcf06188dc005743f4209deb0fShawn Willden    bool ContainsEnumValue(keymaster_tag_t tag, uint32_t val) const;
465ba0d5d01bde427b7d7a22cec84cd9304c00b4e14Shawn Willden    bool ContainsIntValue(keymaster_tag_t tag, uint32_t val) const;
466edb7994f7d5764fcf06188dc005743f4209deb0fShawn Willden
46743786c8ca4e9034b5aa1528b52f9eaaa7551b05fPaul Crowley    // Define elems_ and elems_size_ as aliases to params and length, respectively.  This is to
468bf0679a97499f92abc664179ddb8c1e3974f5c85Shawn Willden    // avoid using the variables without the trailing underscore in the implementation.
469bf0679a97499f92abc664179ddb8c1e3974f5c85Shawn Willden    keymaster_key_param_t*& elems_ = keymaster_key_param_set_t::params;
470bf0679a97499f92abc664179ddb8c1e3974f5c85Shawn Willden    size_t& elems_size_ = keymaster_key_param_set_t::length;
471bf0679a97499f92abc664179ddb8c1e3974f5c85Shawn Willden
4725ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    size_t elems_capacity_;
4735ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    uint8_t* indirect_data_;
4745ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    size_t indirect_data_size_;
4755ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    size_t indirect_data_capacity_;
4765ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden    Error error_;
4775ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden};
4785ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
4792c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willdenclass AuthorizationSetBuilder {
4802c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden  public:
4812c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    template <typename TagType, typename ValueType>
4822c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    AuthorizationSetBuilder& Authorization(TagType tag, ValueType value) {
4832c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden        set.push_back(tag, value);
4842c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden        return *this;
4852c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    }
4862c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden
4872c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    template <keymaster_tag_t Tag>
4882c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    AuthorizationSetBuilder& Authorization(TypedTag<KM_BOOL, Tag> tag) {
4892c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden        set.push_back(tag);
4902c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden        return *this;
4912c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    }
4922c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden
4932c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    template <keymaster_tag_t Tag>
4942c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    AuthorizationSetBuilder& Authorization(TypedTag<KM_INVALID, Tag> tag) {
4952c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden        keymaster_key_param_t param;
4962c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden        param.tag = tag;
4972c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden        set.push_back(param);
4982c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden        return *this;
4992c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    }
5002c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden
5012c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    template <keymaster_tag_t Tag>
5022c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    AuthorizationSetBuilder& Authorization(TypedTag<KM_BYTES, Tag> tag, const uint8_t* data,
5032c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden                                           size_t data_length) {
5042c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden        set.push_back(tag, data, data_length);
5052c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden        return *this;
5062c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    }
5072c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden
5082c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    template <keymaster_tag_t Tag>
5092c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    AuthorizationSetBuilder& Authorization(TypedTag<KM_BYTES, Tag> tag, const char* data,
5102c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden                                           size_t data_length) {
5112c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden        return Authorization(tag, reinterpret_cast<const uint8_t*>(data), data_length);
5122c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    }
5132c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden
5142c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    AuthorizationSetBuilder& RsaKey(uint32_t key_size, uint64_t public_exponent);
5152c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    AuthorizationSetBuilder& EcdsaKey(uint32_t key_size);
5162c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    AuthorizationSetBuilder& AesKey(uint32_t key_size);
517af533990df2265e48d01b187a8e86eefa04d1be3Shawn Willden    AuthorizationSetBuilder& HmacKey(uint32_t key_size);
5182c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden
519af533990df2265e48d01b187a8e86eefa04d1be3Shawn Willden    AuthorizationSetBuilder& RsaSigningKey(uint32_t key_size, uint64_t public_exponent);
520af533990df2265e48d01b187a8e86eefa04d1be3Shawn Willden    AuthorizationSetBuilder& RsaEncryptionKey(uint32_t key_size, uint64_t public_exponent);
521af533990df2265e48d01b187a8e86eefa04d1be3Shawn Willden    AuthorizationSetBuilder& EcdsaSigningKey(uint32_t key_size);
5222c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    AuthorizationSetBuilder& AesEncryptionKey(uint32_t key_size);
523af533990df2265e48d01b187a8e86eefa04d1be3Shawn Willden
5242c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    AuthorizationSetBuilder& SigningKey();
5252c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    AuthorizationSetBuilder& EncryptionKey();
5262c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    AuthorizationSetBuilder& NoDigestOrPadding();
527c47c88f1a9ec3fce5e8116b9b5572b58783f56d0Shawn Willden    AuthorizationSetBuilder& EcbMode();
5282c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden
529af533990df2265e48d01b187a8e86eefa04d1be3Shawn Willden    AuthorizationSetBuilder& Digest(keymaster_digest_t digest) {
530af533990df2265e48d01b187a8e86eefa04d1be3Shawn Willden        return Authorization(TAG_DIGEST, digest);
531af533990df2265e48d01b187a8e86eefa04d1be3Shawn Willden    }
532af533990df2265e48d01b187a8e86eefa04d1be3Shawn Willden
533af533990df2265e48d01b187a8e86eefa04d1be3Shawn Willden    AuthorizationSetBuilder& Padding(keymaster_padding_t padding) {
534af533990df2265e48d01b187a8e86eefa04d1be3Shawn Willden        return Authorization(TAG_PADDING, padding);
535af533990df2265e48d01b187a8e86eefa04d1be3Shawn Willden    }
536af533990df2265e48d01b187a8e86eefa04d1be3Shawn Willden
5372c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    AuthorizationSetBuilder& Deduplicate() {
5382c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden        set.Deduplicate();
5392c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden        return *this;
5402c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    }
5412c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden
5422c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    AuthorizationSet build() const { return set; }
5432c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden
5442c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden  private:
5452c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    friend AuthorizationSet;
5462c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    AuthorizationSet set;
5472c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden};
5482c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden
5492c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willdeninline AuthorizationSetBuilder& AuthorizationSetBuilder::RsaKey(uint32_t key_size,
5502c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden                                                                uint64_t public_exponent) {
5512c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    Authorization(TAG_ALGORITHM, KM_ALGORITHM_RSA);
5522c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    Authorization(TAG_KEY_SIZE, key_size);
5532c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    Authorization(TAG_RSA_PUBLIC_EXPONENT, public_exponent);
5542c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    return *this;
5552c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden}
5562c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden
5572c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willdeninline AuthorizationSetBuilder& AuthorizationSetBuilder::EcdsaKey(uint32_t key_size) {
5589c65b2bd1978a918b52a459596dafc7dde992416Shawn Willden    Authorization(TAG_ALGORITHM, KM_ALGORITHM_EC);
5592c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    Authorization(TAG_KEY_SIZE, key_size);
5602c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    return *this;
5612c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden}
5622c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden
5632c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willdeninline AuthorizationSetBuilder& AuthorizationSetBuilder::AesKey(uint32_t key_size) {
5642c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    Authorization(TAG_ALGORITHM, KM_ALGORITHM_AES);
5652c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    return Authorization(TAG_KEY_SIZE, key_size);
5662c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden}
5672c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden
568af533990df2265e48d01b187a8e86eefa04d1be3Shawn Willdeninline AuthorizationSetBuilder& AuthorizationSetBuilder::HmacKey(uint32_t key_size) {
5692c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    Authorization(TAG_ALGORITHM, KM_ALGORITHM_HMAC);
5702c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    Authorization(TAG_KEY_SIZE, key_size);
571af533990df2265e48d01b187a8e86eefa04d1be3Shawn Willden    return SigningKey();
5722c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden}
5732c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden
574af533990df2265e48d01b187a8e86eefa04d1be3Shawn Willdeninline AuthorizationSetBuilder& AuthorizationSetBuilder::RsaSigningKey(uint32_t key_size,
575af533990df2265e48d01b187a8e86eefa04d1be3Shawn Willden                                                                       uint64_t public_exponent) {
5762c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    RsaKey(key_size, public_exponent);
577af533990df2265e48d01b187a8e86eefa04d1be3Shawn Willden    return SigningKey();
5782c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden}
5792c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden
5802c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willdeninline AuthorizationSetBuilder&
581af533990df2265e48d01b187a8e86eefa04d1be3Shawn WilldenAuthorizationSetBuilder::RsaEncryptionKey(uint32_t key_size, uint64_t public_exponent) {
5822c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    RsaKey(key_size, public_exponent);
583af533990df2265e48d01b187a8e86eefa04d1be3Shawn Willden    return EncryptionKey();
5842c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden}
5852c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden
586af533990df2265e48d01b187a8e86eefa04d1be3Shawn Willdeninline AuthorizationSetBuilder& AuthorizationSetBuilder::EcdsaSigningKey(uint32_t key_size) {
5872c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    EcdsaKey(key_size);
588af533990df2265e48d01b187a8e86eefa04d1be3Shawn Willden    return SigningKey();
5892c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden}
5902c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden
5912c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willdeninline AuthorizationSetBuilder& AuthorizationSetBuilder::AesEncryptionKey(uint32_t key_size) {
5922c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    AesKey(key_size);
5932c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    return EncryptionKey();
5942c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden}
5952c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden
5962c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willdeninline AuthorizationSetBuilder& AuthorizationSetBuilder::SigningKey() {
5972c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    Authorization(TAG_PURPOSE, KM_PURPOSE_SIGN);
5982c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    return Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY);
5992c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden}
6002c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden
6012c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willdeninline AuthorizationSetBuilder& AuthorizationSetBuilder::EncryptionKey() {
6022c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    Authorization(TAG_PURPOSE, KM_PURPOSE_ENCRYPT);
6032c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    return Authorization(TAG_PURPOSE, KM_PURPOSE_DECRYPT);
6042c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden}
6052c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden
6062c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willdeninline AuthorizationSetBuilder& AuthorizationSetBuilder::NoDigestOrPadding() {
6072c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    Authorization(TAG_DIGEST, KM_DIGEST_NONE);
6082c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden    return Authorization(TAG_PADDING, KM_PAD_NONE);
6092c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden}
6102c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden
611c47c88f1a9ec3fce5e8116b9b5572b58783f56d0Shawn Willdeninline AuthorizationSetBuilder& AuthorizationSetBuilder::EcbMode() {
612c47c88f1a9ec3fce5e8116b9b5572b58783f56d0Shawn Willden    return Authorization(TAG_BLOCK_MODE, KM_MODE_ECB);
6132c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden}
6142c242009007a38b5c8003137fb8ba5a1fdb73b70Shawn Willden
6155ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden}  // namespace keymaster
6165ada7b6c525d2bfd5b556a698ccb11db23e052bbShawn Willden
617b10f3b26af1e3b382d9ef361b3eb5279d16a9c05Shawn Willden#endif  // SYSTEM_KEYMASTER_KEY_AUTHORIZATION_SET_H_
618