1 /* 2 * Copyright 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef SYSTEM_KEYMASTER_AUTHORIZATION_SET_H_ 18 #define SYSTEM_KEYMASTER_AUTHORIZATION_SET_H_ 19 20 #include <UniquePtr.h> 21 22 #include <keymaster/keymaster_defs.h> 23 #include <keymaster/keymaster_tags.h> 24 #include <keymaster/serializable.h> 25 26 namespace keymaster { 27 28 /** 29 * A container that manages a set of keymaster_key_param_t objects, providing serialization, 30 * de-serialization and accessors. 31 */ 32 class AuthorizationSet : public Serializable { 33 public: 34 /** 35 * Construct an empty, dynamically-allocated, growable AuthorizationSet. Does not actually 36 * allocate any storage until elements are added, so there is no cost to creating an 37 * AuthorizationSet with this constructor and then reinitializing it to point at pre-allocated 38 * buffers, with \p Reinitialize. 39 */ AuthorizationSet()40 AuthorizationSet() 41 : elems_(NULL), elems_size_(0), elems_capacity_(0), indirect_data_(NULL), 42 indirect_data_size_(0), indirect_data_capacity_(0), error_(OK) {} 43 44 /** 45 * Construct an AuthorizationSet from the provided array. The AuthorizationSet copies the data 46 * from the provided array (and the data referenced by its embedded pointers, if any) into 47 * dynamically-allocated storage. If allocation of the needed storage fails, \p is_valid() will 48 * return ALLOCATION_FAILURE. It is the responsibility of the caller to check before using the 49 * set, if allocations might fail. 50 */ AuthorizationSet(const keymaster_key_param_t * elems,size_t count)51 AuthorizationSet(const keymaster_key_param_t* elems, size_t count) 52 : elems_(NULL), indirect_data_(NULL) { 53 Reinitialize(elems, count); 54 } 55 AuthorizationSet(const uint8_t * serialized_set,size_t serialized_size)56 AuthorizationSet(const uint8_t* serialized_set, size_t serialized_size) 57 : elems_(NULL), indirect_data_(NULL) { 58 Deserialize(&serialized_set, serialized_set + serialized_size); 59 } 60 61 // Copy constructor. 62 AuthorizationSet(const AuthorizationSet&); 63 64 /** 65 * Reinitialize an AuthorizationSet as a dynamically-allocated, growable copy of the data in the 66 * provided array (and the data referenced by its embedded pointers, if any). If the allocation 67 * of the needed storage fails this method will return false and \p is_valid() will return 68 * ALLOCATION_FAILURE. 69 */ 70 bool Reinitialize(const keymaster_key_param_t* elems, size_t count); 71 Reinitialize(const AuthorizationSet & set)72 bool Reinitialize(const AuthorizationSet& set) { 73 return Reinitialize(set.elems_, set.elems_size_); 74 } 75 76 ~AuthorizationSet(); 77 78 enum Error { 79 OK, 80 ALLOCATION_FAILURE, 81 MALFORMED_DATA, 82 }; 83 is_valid()84 Error is_valid() const { return error_; } 85 86 /** 87 * Returns the size of the set. 88 */ size()89 size_t size() const { return elems_size_; } 90 91 /** 92 * Returns the total size of all indirect data referenced by set elements. 93 */ indirect_size()94 size_t indirect_size() const { return indirect_data_size_; } 95 96 /** 97 * Returns the data in the set, directly. Be careful with this. 98 */ 99 const keymaster_key_param_t* data() const; 100 101 /** 102 * Returns the offset of the next entry that matches \p tag, starting from the element after \p 103 * begin. If not found, returns -1. 104 */ 105 int find(keymaster_tag_t tag, int begin = -1) const; 106 107 /** 108 * Returns the nth element of the set. 109 */ 110 keymaster_key_param_t operator[](int n) const; 111 112 /** 113 * If the specified integer-typed \p tag exists, places its value in \p val and returns true. 114 * If \p tag is not present, leaves \p val unmodified and returns false. 115 */ 116 template <keymaster_tag_t T> GetTagValue(TypedTag<KM_INT,T> tag,uint32_t * val)117 inline bool GetTagValue(TypedTag<KM_INT, T> tag, uint32_t* val) const { 118 return GetTagValueInt(tag, val); 119 } 120 121 /** 122 * If the specified instance of the specified integer-typed \p tag exists, places its value 123 * in \p val and returns true. If \p tag is not present, leaves \p val unmodified and returns 124 * false. 125 */ 126 template <keymaster_tag_t Tag> GetTagValue(TypedTag<KM_INT_REP,Tag> tag,size_t instance,uint32_t * val)127 bool GetTagValue(TypedTag<KM_INT_REP, Tag> tag, size_t instance, uint32_t* val) const { 128 return GetTagValueIntRep(tag, instance, val); 129 } 130 131 /** 132 * If the specified long-typed \p tag exists, places its value in \p val and returns true. 133 * If \p tag is not present, leaves \p val unmodified and returns false. 134 */ 135 template <keymaster_tag_t T> GetTagValue(TypedTag<KM_LONG,T> tag,uint64_t * val)136 inline bool GetTagValue(TypedTag<KM_LONG, T> tag, uint64_t* val) const { 137 return GetTagValueLong(tag, val); 138 } 139 140 /** 141 * If the specified enumeration-typed \p tag exists, places its value in \p val and returns 142 * true. If \p tag is not present, leaves \p val unmodified and returns false. 143 */ 144 template <keymaster_tag_t Tag, typename T> GetTagValue(TypedEnumTag<KM_ENUM,Tag,T> tag,T * val)145 bool GetTagValue(TypedEnumTag<KM_ENUM, Tag, T> tag, T* val) const { 146 return GetTagValueEnum(tag, reinterpret_cast<uint32_t*>(val)); 147 } 148 149 /** 150 * If the specified instance of the specified enumeration-typed \p tag exists, places its value 151 * in \p val and returns true. If \p tag is not present, leaves \p val unmodified and returns 152 * false. 153 */ 154 template <keymaster_tag_t Tag, typename T> GetTagValue(TypedEnumTag<KM_ENUM_REP,Tag,T> tag,size_t instance,T * val)155 bool GetTagValue(TypedEnumTag<KM_ENUM_REP, Tag, T> tag, size_t instance, T* val) const { 156 return GetTagValueEnumRep(tag, instance, reinterpret_cast<uint32_t*>(val)); 157 } 158 159 /** 160 * If the specified date-typed \p tag exists, places its value in \p val and returns 161 * true. If \p tag is not present, leaves \p val unmodified and returns false. 162 */ 163 template <keymaster_tag_t Tag> GetTagValue(TypedTag<KM_INT_REP,Tag> tag,size_t instance,typename TypedTag<KM_INT_REP,Tag>::value_type * val)164 bool GetTagValue(TypedTag<KM_INT_REP, Tag> tag, size_t instance, 165 typename TypedTag<KM_INT_REP, Tag>::value_type* val) const { 166 return GetTagValueIntRep(tag, instance, val); 167 } 168 169 /** 170 * If the specified bytes-typed \p tag exists, places its value in \p val and returns 171 * true. If \p tag is not present, leaves \p val unmodified and returns false. 172 */ 173 template <keymaster_tag_t Tag> GetTagValue(TypedTag<KM_BYTES,Tag> tag,keymaster_blob_t * val)174 bool GetTagValue(TypedTag<KM_BYTES, Tag> tag, keymaster_blob_t* val) const { 175 return GetTagValueBlob(tag, val); 176 } 177 178 /** 179 * If the specified bignum-typed \p tag exists, places its value in \p val and returns 180 * true. If \p tag is not present, leaves \p val unmodified and returns false. 181 */ 182 template <keymaster_tag_t Tag> GetTagValue(TypedTag<KM_BIGNUM,Tag> tag,keymaster_blob_t * val)183 bool GetTagValue(TypedTag<KM_BIGNUM, Tag> tag, keymaster_blob_t* val) const { 184 return GetTagValueBlob(tag, val); 185 } 186 187 /** 188 * If the specified \p tag exists, places its value in \p val and returns true. If \p tag is 189 * not present, leaves \p val unmodified and returns false. 190 */ 191 template <keymaster_tag_t Tag, keymaster_tag_type_t Type> GetTagValue(TypedTag<Type,Tag> tag,typename TagValueType<Type>::value_type * val)192 bool GetTagValue(TypedTag<Type, Tag> tag, typename TagValueType<Type>::value_type* val) const { 193 return GetTagValueLong(tag, val); 194 } 195 196 bool push_back(keymaster_key_param_t elem); 197 198 /** 199 * Grow the elements array to ensure it can contain \p count entries. Preserves any existing 200 * entries. 201 */ 202 bool reserve_elems(size_t count); 203 204 /** 205 * Grow the indirect data array to ensure it can contain \p length bytes. Preserves any 206 * existing indirect data. 207 */ 208 bool reserve_indirect(size_t length); 209 210 bool push_back(const AuthorizationSet& set); 211 212 template <keymaster_tag_t Tag, keymaster_tag_type_t Type, typename KeymasterEnum> push_back(TypedEnumTag<Type,Tag,KeymasterEnum> tag,KeymasterEnum val)213 bool push_back(TypedEnumTag<Type, Tag, KeymasterEnum> tag, KeymasterEnum val) { 214 return push_back(Authorization(tag, val)); 215 } 216 push_back(TypedTag<KM_BOOL,Tag> tag)217 template <keymaster_tag_t Tag> bool push_back(TypedTag<KM_BOOL, Tag> tag) { 218 return push_back(Authorization(tag)); 219 } 220 221 template <keymaster_tag_t Tag> push_back(TypedTag<KM_BYTES,Tag> tag,const void * bytes,size_t bytes_len)222 bool push_back(TypedTag<KM_BYTES, Tag> tag, const void* bytes, size_t bytes_len) { 223 return push_back(keymaster_param_blob(tag, static_cast<const uint8_t*>(bytes), bytes_len)); 224 } 225 226 template <keymaster_tag_t Tag> push_back(TypedTag<KM_BIGNUM,Tag> tag,const void * bytes,size_t bytes_len)227 bool push_back(TypedTag<KM_BIGNUM, Tag> tag, const void* bytes, size_t bytes_len) { 228 return push_back(keymaster_param_blob(tag, static_cast<const uint8_t*>(bytes), bytes_len)); 229 } 230 231 template <keymaster_tag_t Tag, keymaster_tag_type_t Type> push_back(TypedTag<Type,Tag> tag,typename TypedTag<Type,Tag>::value_type val)232 bool push_back(TypedTag<Type, Tag> tag, typename TypedTag<Type, Tag>::value_type val) { 233 return push_back(Authorization(tag, val)); 234 } 235 236 template <keymaster_tag_t Tag, keymaster_tag_type_t Type> push_back(TypedTag<Type,Tag> tag,const void * bytes,size_t bytes_len)237 bool push_back(TypedTag<Type, Tag> tag, const void* bytes, size_t bytes_len) { 238 return push_back(Authorization(tag, bytes, bytes_len)); 239 } 240 241 /* Virtual methods from Serializable */ 242 size_t SerializedSize() const; 243 uint8_t* Serialize(uint8_t* serialized_set, const uint8_t* end) const; 244 bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end); 245 246 size_t SerializedSizeOfElements() const; 247 248 private: 249 // Disallow assignment 250 void operator=(const AuthorizationSet&); 251 252 void FreeData(); 253 void set_invalid(Error err); 254 255 static size_t ComputeIndirectDataSize(const keymaster_key_param_t* elems, size_t count); 256 void CopyIndirectData(); 257 bool CheckIndirectData(); 258 259 bool DeserializeIndirectData(const uint8_t** buf_ptr, const uint8_t* end); 260 bool DeserializeElementsData(const uint8_t** buf_ptr, const uint8_t* end); 261 262 bool GetTagValueEnum(keymaster_tag_t tag, uint32_t* val) const; 263 bool GetTagValueEnumRep(keymaster_tag_t tag, size_t instance, uint32_t* val) const; 264 bool GetTagValueInt(keymaster_tag_t tag, uint32_t* val) const; 265 bool GetTagValueIntRep(keymaster_tag_t tag, size_t instance, uint32_t* val) const; 266 bool GetTagValueLong(keymaster_tag_t tag, uint64_t* val) const; 267 bool GetTagValueDate(keymaster_tag_t tag, uint64_t* val) const; 268 bool GetTagValueBlob(keymaster_tag_t tag, keymaster_blob_t* val) const; 269 270 keymaster_key_param_t* elems_; 271 size_t elems_size_; 272 size_t elems_capacity_; 273 uint8_t* indirect_data_; 274 size_t indirect_data_size_; 275 size_t indirect_data_capacity_; 276 Error error_; 277 }; 278 279 } // namespace keymaster 280 281 #endif // SYSTEM_KEYMASTER_KEY_AUTHORIZATION_SET_H_ 282