blob: 94ee73d10f71b777cb728cf52429e33502bbaf0e [file] [log] [blame]
/*
* Copyright 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef EXTERNAL_KEYMASTER_AUTHORIZATION_SET_H_
#define EXTERNAL_KEYMASTER_AUTHORIZATION_SET_H_
#include <hardware/keymaster_defs.h>
#include <UniquePtr.h>
#include "keymaster_tags.h"
#include "serializable.h"
namespace keymaster {
/**
* A container that manages a set of keymaster_key_param_t objects, providing serialization,
* de-serialization and accessors.
*/
class AuthorizationSet : public Serializable {
public:
~AuthorizationSet();
/**
* Construct an empty, dynamically-allocated, growable AuthorizationSet. Does not actually
* allocate any storage until elements are added, so there is no cost to creating an
* AuthorizationSet with this constructor and then reinitializing it to point at pre-allocated
* buffers, with \p Reinitialize.
*/
AuthorizationSet()
: elems_(NULL), elems_size_(0), elems_capacity_(0), indirect_data_(NULL),
indirect_data_size_(0), indirect_data_capacity_(0), owns_data_(true),
error_(OK_GROWABLE) {}
/**
* Construct an AuthorizationSet from the provided array. The AuthorizationSet copies the data
* from the provided array (and the data referenced by its embedded pointers, if any) into
* dynamically-allocated storage. If allocation of the needed storage fails, \p is_valid() will
* return ALLOCATION_FAILURE. It is the responsibility of the caller to check before using the
* set, if allocations might fail.
*/
AuthorizationSet(const keymaster_key_param_t* elems, size_t count) : owns_data_(false) {
Reinitialize(elems, count);
}
/**
* Construct an AuthorizationSet which accesses serialized data IN PLACE. \p serialized_set
* must point to a buffer full of data produced by Serialize() and must exist as long as the
* AuthorizationSet exists. The input isn't strongly validated, but it is thoroughly
* bounds-checked. The caller must check is_valid() to verify there were no bounds checking
* errors before using the set.
*/
AuthorizationSet(uint8_t* serialized_set, size_t length);
/**
* Construct an empty, growable AuthorizationSet in the provided storage. \p push_back() will
* add an element into the element array, copying any indirect data into the indirect data
* buffer provided.
*/
AuthorizationSet(keymaster_key_param_t* elems_array, size_t elems_buf_count,
uint8_t* indirect_data_buf, size_t indirect_data_buf_size)
: owns_data_(false) {
Reinitialize(elems_array, elems_buf_count, indirect_data_buf, indirect_data_buf_size);
}
/**
* Reinitialize an AuthorizationSet as a dynamically-allocated, growable copy of the data in the
* provided array (and the data referenced by its embedded pointers, if any). If the allocation
* of the needed storage fails this method will return false and \p is_valid() will return
* ALLOCATION_FAILURE.
*/
bool Reinitialize(const keymaster_key_param_t* elems, size_t count);
/**
* Reinitialize an AuthorizationSet as an empty, growable set in the provided storage.
*/
void Reinitialize(keymaster_key_param_t* elems_array, size_t elems_buf_count,
uint8_t* indirect_data_buf, size_t indirect_data_buf_size);
enum Error {
OK_FULL, /* Set is valid, but cannot accept additional elements */
OK_GROWABLE, /* Set is valid, and can accept additional data */
ALLOCATION_FAILURE,
BOUNDS_CHECKING_FAILURE,
MALFORMED_DATA,
};
Error is_valid() const { return error_; }
/**
* Returns the size of the set.
*/
size_t size() const { return elems_size_; }
/**
* Returns the offset of the next entry that matches \p tag, starting from the element after \p
* begin. If not found, returns -1.
*/
int find(keymaster_tag_t tag, int begin = -1) const;
/**
* Returns the nth element of the set.
*/
keymaster_key_param_t operator[](int n) const;
/**
* If the specified integer-typed \p tag exists, places its value in \p val and returns true.
* If \p tag is not present, leaves \p val unmodified and returns false.
*/
template <keymaster_tag_t T>
inline bool GetTagValue(TypedTag<KM_INT, T> tag, uint32_t* val) const {
return GetTagValueInt(tag, val);
}
/**
* If the specified instance of the specified integer-typed \p tag exists, places its value
* in \p val and returns true. If \p tag is not present, leaves \p val unmodified and returns
* false.
*/
template <keymaster_tag_t Tag>
bool GetTagValue(TypedTag<KM_INT_REP, Tag> tag, size_t instance, uint32_t* val) const {
return GetTagValueIntRep(tag, instance, val);
}
/**
* If the specified long-typed \p tag exists, places its value in \p val and returns true.
* If \p tag is not present, leaves \p val unmodified and returns false.
*/
template <keymaster_tag_t T>
inline bool GetTagValue(TypedTag<KM_LONG, T> tag, uint64_t* val) const {
return GetTagValueLong(tag, val);
}
/**
* If the specified enumeration-typed \p tag exists, places its value in \p val and returns
* true. If \p tag is not present, leaves \p val unmodified and returns false.
*/
template <keymaster_tag_t Tag, typename T>
bool GetTagValue(TypedEnumTag<KM_ENUM, Tag, T> tag, T* val) const {
return GetTagValueEnum(tag, reinterpret_cast<uint32_t*>(val));
}
/**
* If the specified instance of the specified enumeration-typed \p tag exists, places its value
* in \p val and returns true. If \p tag is not present, leaves \p val unmodified and returns
* false.
*/
template <keymaster_tag_t Tag, typename T>
bool GetTagValue(TypedEnumTag<KM_ENUM_REP, Tag, T> tag, size_t instance, T* val) const {
return GetTagValueEnumRep(tag, instance, reinterpret_cast<uint32_t*>(val));
}
/**
* If the specified date-typed \p tag exists, places its value in \p val and returns
* true. If \p tag is not present, leaves \p val unmodified and returns false.
*/
template <keymaster_tag_t Tag>
bool GetTagValue(TypedTag<KM_INT_REP, Tag> tag, size_t instance,
typename TypedTag<KM_INT_REP, Tag>::value_type* val) const {
return GetTagValueIntRep(tag, instance, val);
}
/**
* If the specified bytes-typed \p tag exists, places its value in \p val and returns
* true. If \p tag is not present, leaves \p val unmodified and returns false.
*/
template <keymaster_tag_t Tag>
bool GetTagValue(TypedTag<KM_BYTES, Tag> tag, keymaster_blob_t* val) const {
return GetTagValueBlob(tag, val);
}
/**
* If the specified bignum-typed \p tag exists, places its value in \p val and returns
* true. If \p tag is not present, leaves \p val unmodified and returns false.
*/
template <keymaster_tag_t Tag>
bool GetTagValue(TypedTag<KM_BIGNUM, Tag> tag, keymaster_blob_t* val) const {
return GetTagValueDate(tag, val);
}
/**
* If the specified \p tag exists, places its value in \p val and returns true. If \p tag is
* not present, leaves \p val unmodified and returns false.
*/
template <keymaster_tag_t Tag, keymaster_tag_type_t Type>
bool GetTagValue(TypedTag<Type, Tag> tag, typename TagValueType<Type>::value_type* val) const {
return GetTagValueLong(tag, val);
}
bool push_back(keymaster_key_param_t elem);
template <keymaster_tag_t Tag, keymaster_tag_type_t Type, typename KeymasterEnum>
bool push_back(TypedEnumTag<Type, Tag, KeymasterEnum> tag, KeymasterEnum val) {
return push_back(Authorization(tag, val));
}
template <keymaster_tag_t Tag> bool push_back(TypedTag<KM_BOOL, Tag> tag) {
return push_back(Authorization(tag));
}
template <keymaster_tag_t Tag, keymaster_tag_type_t Type>
bool push_back(TypedTag<Type, Tag> tag, typename TypedTag<Type, Tag>::value_type val) {
return push_back(Authorization(tag, val));
}
template <keymaster_tag_t Tag, keymaster_tag_type_t Type>
bool push_back(TypedTag<Type, Tag> tag, const void* bytes, size_t bytes_len) {
return push_back(Authorization(tag, bytes, bytes_len));
}
/**
* Returns the size of the buffer needed for serializing this set.
*/
size_t SerializedSize() const {
return sizeof(uint32_t) * 2 + sizeof(*elems_) * elems_size_ + indirect_data_size_;
}
/**
* Writes the serialized set into \p serialized_set, which must be at least \p SerializedSize()
* bytes in length. Returns buf, advandeced by the bytes written.
*/
uint8_t* Serialize(uint8_t* serialized_set) const;
bool DeserializeInPlace(uint8_t** buf, const uint8_t* end);
bool DeserializeToCopy(const uint8_t** buf, const uint8_t* end);
private:
void FreeData();
void set_invalid(Error err);
static size_t ComputeIndirectDataSize(const keymaster_key_param_t* elems, size_t count);
static void ConvertPointersToOffsets(keymaster_key_param_t* elems, size_t count,
const uint8_t* indirect_base);
void CopyIndirectData();
bool CheckIndirectDataOffsets();
bool GetTagValueEnum(keymaster_tag_t tag, uint32_t* val) const;
bool GetTagValueEnumRep(keymaster_tag_t tag, size_t instance, uint32_t* val) const;
bool GetTagValueInt(keymaster_tag_t tag, uint32_t* val) const;
bool GetTagValueIntRep(keymaster_tag_t tag, size_t instance, uint32_t* val) const;
bool GetTagValueLong(keymaster_tag_t tag, uint64_t* val) const;
bool GetTagValueDate(keymaster_tag_t tag, uint64_t* val) const;
bool GetTagValueBlob(keymaster_tag_t tag, keymaster_blob_t* val) const;
keymaster_key_param_t* elems_;
size_t elems_size_;
size_t elems_capacity_;
uint8_t* indirect_data_;
size_t indirect_data_size_;
size_t indirect_data_capacity_;
bool owns_data_;
Error error_;
};
const keymaster_key_param_t* find(keymaster_tag_t tag, const AuthorizationSet& set1,
const AuthorizationSet& set2);
} // namespace keymaster
#endif // EXTERNAL_KEYMASTER_KEY_AUTHORIZATION_SET_H_