323e489b5c1f76d182afdedbf1fc35efa5908fd1
[platform/core/security/tef-simulator.git] / TEEStub / PropertyAccess / PropertyApi.cpp
1 /**\r
2  * Copyright (c) 2015-2017 Samsung Electronics Co., Ltd All Rights Reserved\r
3  *\r
4  *    Licensed under the Apache License, Version 2.0 (the "License");\r
5  *    you may not use this file except in compliance with the License.\r
6  *    You may obtain a copy of the License at\r
7  *\r
8  *        http://www.apache.org/licenses/LICENSE-2.0\r
9  *\r
10  *    Unless required by applicable law or agreed to in writing, software\r
11  *    distributed under the License is distributed on an "AS IS" BASIS,\r
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
13  *    See the License for the specific language governing permissions and\r
14  *    limitations under the License.\r
15  */\r
16 \r
17 /**\r
18  * @file\r
19  * @author Krishna Raghottam Devale (k.devale@samsung.com)\r
20  * @brief  PropertyApi class\r
21  */\r
22 \r
23 \r
24 /*-----------------------------------------------------------------------------\r
25  *  Include files\r
26  *-----------------------------------------------------------------------------*/\r
27 #include <PropertyAccess/Property.h>\r
28 #include <PropertyAccess/PropertyApi.h>\r
29 #include <PropertyAccess/ClientProperty.h>\r
30 #include <PropertyAccess/TEEProperty.h>\r
31 #include <PropertyAccess/TAProperty.h>\r
32 #include <PropertyAccess/PropertyUtility.h>\r
33 #include "config.h"\r
34 #include <string.h>\r
35 #include <set>\r
36 #include "log.h"\r
37 \r
38 using namespace std;\r
39 \r
40 // PRIVATE TO THIS API FILE\r
41 static Property* clientProperty;\r
42 static Property* taProperty;\r
43 static Property* teeProperty;\r
44 static uint32_t clientLoginGlobal = 0;\r
45 static string thisTAUUIDGlobal = "";\r
46 bool _allowPropertyAccess = false;\r
47 \r
48 /**\r
49  * Static local function to identify the right object of Property\r
50  * If propsetOrEnumerator is a constant propset then existing objects of\r
51  * Property on given propset is returned. If propsetOrEnumerator is a handle to\r
52  * an enumerator then PropertyEnumHandle object is returned.\r
53  * @param propsetOrEnumerator[in]   A handle of type TEE_PropSetHandle\r
54  * @return NULL if handle is invalid else returns valid handle\r
55  */\r
56 static Property* _GetTargetProperty(TEE_PropSetHandle propsetOrEnumerator);\r
57 static uintptr_t _GetTargetPropsetType(TEE_PropSetHandle propsetOrEnumerator);\r
58 \r
59 //GLOBAL DEFNS\r
60 typedef struct {\r
61         Property* property;\r
62 } PropertyEnumHandle;\r
63 \r
64 std::set<PropertyEnumHandle*> propertyEnumHandleSet;\r
65 \r
66 /*-----------------------------------------------------------------------------\r
67  *  Member functions\r
68  *-----------------------------------------------------------------------------*/\r
69 /**\r
70  * Initialization routine of PropertyAccess Module. This function should be\r
71  * called when TA stub starts with UUID of this TA.\r
72  * @param uuid[in]          UUID of our TA\r
73  * @param taDir[in]         Directory in which TA resides\r
74  * @param clientLogin[in]   login method to this TA from client.\r
75  *                          Refer Table 4-13: Client Identities\r
76  * @return TEE_ERROR_OUT_OF_MEMORY on failure to initialize else TEE_SUCCESS\r
77  */\r
78 TEE_Result InitPropertyModule(const std::string& uuid,\r
79         const std::string& taDir, uint32_t clientLogin) {\r
80         PropertyValue pv;\r
81         pv.type = "identity";\r
82         pv.value = "" + clientLogin;\r
83 \r
84         clientLoginGlobal = clientLogin;\r
85         thisTAUUIDGlobal = uuid;\r
86 \r
87         try {\r
88                 clientProperty = new ClientProperty(pv);\r
89                 clientProperty->start();\r
90                 teeProperty = new TEEProperty();\r
91                 teeProperty->start();\r
92                 taProperty = new TAProperty(taDir + uuid + ".manifest");\r
93                 taProperty->start();\r
94         } catch (std::bad_alloc &ba) {\r
95                 return TEE_ERROR_OUT_OF_MEMORY;\r
96         }\r
97         return TEE_SUCCESS;\r
98 }\r
99 \r
100 /**\r
101  * Deallocate Property Access objects\r
102  */\r
103 void DeInitPropertyModule() {\r
104         delete clientProperty;\r
105         delete taProperty;\r
106         delete teeProperty;\r
107 }\r
108 \r
109 string getQueryProp(TEE_PropSetHandle propsetOrEnumerator, string name) {\r
110         size_t pos;\r
111         uintptr_t propSet = _GetTargetPropsetType(propsetOrEnumerator);\r
112         if(propSet == TEE_PROPSET_CURRENT_TA &&\r
113                 (pos = name.rfind(".")) != string::npos) {\r
114                 return name.substr(pos + 1);\r
115         }\r
116         return name;\r
117 }\r
118 \r
119 //TODO: TEE_ERROR_ITEM_NOT_FOUND also to be returned when the string\r
120 //received in not UTF8 encoded format\r
121 //Assuming valueBufferLen is [in] param only.\r
122 \r
123 TEE_Result TEE_GetPropertyAsString(TEE_PropSetHandle propsetOrEnumerator,\r
124     const char* name, char* valueBuffer, size_t* valueBufferLen) {\r
125         TEE_Result returnValue = TEE_SUCCESS;\r
126         Property* targetProperty = NULL;\r
127         PropertyValue pv;\r
128         string queryProp = "";\r
129 \r
130         if (NULL == propsetOrEnumerator){\r
131                 return TEE_ERROR_ITEM_NOT_FOUND;\r
132         }\r
133 \r
134         if (NULL != name) queryProp = getQueryProp(propsetOrEnumerator, name);\r
135         // 1. Select the enumerator object based on propset or consider given enumerator\r
136         // if any\r
137         targetProperty = _GetTargetProperty(propsetOrEnumerator);\r
138         // 2. after selecting targetProperty fetch the property name\r
139         if (targetProperty\r
140             && ((NULL != name && targetProperty->getPropertyByName(queryProp, pv))\r
141                 || (NULL == name && targetProperty->getPropertyValue(pv)))) {\r
142                 if (valueBuffer && pv.value.size() < *valueBufferLen)\r
143                         strncpy(valueBuffer, pv.value.c_str(), *valueBufferLen);\r
144                 else returnValue = TEE_ERROR_SHORT_BUFFER;\r
145         }
146         else returnValue = TEE_ERROR_ITEM_NOT_FOUND;\r
147 \r
148 // Above is optimized version of below\r
149 #if 0\r
150 \r
151         if (NULL != name && targetProperty && targetProperty->getPropertyByName(queryProp, pv))\r
152         {\r
153                 // SIZE FITS IN BUFFER\r
154                 if (pv.value.size() < *valueBufferLen)\r
155                 strcpy(valueBuffer, pv.value.c_str());\r
156                 else\r
157                 returnValue = TEE_ERROR_SHORT_BUFFER;\r
158         } else if (NULL == name && targetProperty && targetProperty->getPropertyValue(pv)) {\r
159                 if (pv.value.size() < *valueBufferLen)\r
160                 strcpy(valueBuffer, pv.value.c_str());\r
161                 else\r
162                 returnValue = TEE_ERROR_SHORT_BUFFER;\r
163         }\r
164         else returnValue = TEE_ERROR_ITEM_NOT_FOUND;\r
165 #endif\r
166         return returnValue;\r
167 }\r
168 \r
169 TEE_Result TEE_GetPropertyAsBool(TEE_PropSetHandle propsetOrEnumerator,\r
170     const char* name, bool* value) {\r
171         TEE_Result returnValue = TEE_SUCCESS;\r
172         Property* targetProperty = NULL;\r
173         PropertyValue pv;\r
174         string queryProp = "";\r
175         if (NULL != name) queryProp = getQueryProp(propsetOrEnumerator, name);\r
176         // 1. Select the enumerator object based on propset or consider given enumerator\r
177         // if any\r
178         targetProperty = _GetTargetProperty(propsetOrEnumerator);\r
179         // 2. after selecting targetProperty fetch the property by name or as in\r
180         // pointed by enumerator marker\r
181         if (targetProperty\r
182             && ((NULL != name && targetProperty->getPropertyByName(queryProp, pv))\r
183                 || (NULL == name && targetProperty->getPropertyValue(pv)))) {\r
184                 returnValue = PropertyUtility::convertToBool(pv, *value);\r
185         }\r
186         else returnValue = TEE_ERROR_ITEM_NOT_FOUND;\r
187 // Above is optimized version of below\r
188 #if 0\r
189         if (NULL != name && targetProperty && targetProperty->getPropertyByName(queryProp, pv))\r
190         {\r
191                 returnValue = PropertyUtility::convertToBool(pv, *value);\r
192         } else if (NULL == name && targetProperty && targetProperty->getPropertyValue(pv)) {\r
193                 returnValue = PropertyUtility::convertToBool(pv, *value);\r
194         }\r
195         else returnValue = TEE_ERROR_ITEM_NOT_FOUND;\r
196 #endif\r
197         return returnValue;\r
198 }\r
199 \r
200 TEE_Result TEE_GetPropertyAsU32(TEE_PropSetHandle propsetOrEnumerator,\r
201     const char* name, uint32_t* value) {\r
202         TEE_Result returnValue = TEE_SUCCESS;\r
203         Property* targetProperty = NULL;\r
204         PropertyValue pv;\r
205         string queryProp = "";\r
206         if (NULL != name) queryProp = getQueryProp(propsetOrEnumerator, name);\r
207         // 1. Select the enumerator object based on propset or consider given enumerator\r
208         // if any\r
209         targetProperty = _GetTargetProperty(propsetOrEnumerator);\r
210         // 2. after selecting targetProperty fetch the property by name or as in\r
211         // pointed by enumerator marker\r
212         if (targetProperty\r
213             && ((NULL != name && targetProperty->getPropertyByName(queryProp, pv))\r
214                 || (NULL == name && targetProperty->getPropertyValue(pv)))) {\r
215                 returnValue = PropertyUtility::convertToU32(pv, *value);\r
216         }\r
217         else returnValue = TEE_ERROR_ITEM_NOT_FOUND;\r
218         return returnValue;\r
219 }\r
220 \r
221 TEE_Result TEE_GetPropertyAsBinaryBlock(TEE_PropSetHandle propsetOrEnumerator,\r
222     const char* name, void* valueBuffer, size_t* valueBufferLen) {\r
223         TEE_Result returnValue = TEE_SUCCESS;\r
224         Property* targetProperty = NULL;\r
225         PropertyValue pv;\r
226         string queryProp = "";\r
227         if (NULL != name) queryProp = getQueryProp(propsetOrEnumerator, name);\r
228         // Select the enumerator object based on propset or consider given enumerator\r
229         // if any\r
230         targetProperty = _GetTargetProperty(propsetOrEnumerator);\r
231         // After selecting targetProperty fetch the property name\r
232         if (targetProperty\r
233             && ((NULL != name && targetProperty->getPropertyByName(queryProp, pv))\r
234                 || (NULL == name && targetProperty->getPropertyValue(pv)))) {\r
235                 string binaryBlockOut;\r
236                 returnValue = PropertyUtility::convertToBinaryBlock(pv, binaryBlockOut);\r
237                 bool conversionStatus = (returnValue == TEE_SUCCESS) ? true : false;\r
238                 if (valueBuffer && conversionStatus\r
239                     && binaryBlockOut.size() < *valueBufferLen) {\r
240                         strncpy((char*)valueBuffer, binaryBlockOut.c_str(), *valueBufferLen);\r
241                 }\r
242                 else returnValue = TEE_ERROR_SHORT_BUFFER;\r
243         }\r
244         else returnValue = TEE_ERROR_ITEM_NOT_FOUND;\r
245         return returnValue;\r
246 }\r
247 \r
248 // TODO: In spec: value: A pointer filled with the UUID. MUST NOT be NULL.\r
249 // What does it mean? Must not be NULL\r
250 TEE_Result TEE_GetPropertyAsUUID(TEE_PropSetHandle propsetOrEnumerator,\r
251     const char* name, TEE_UUID* value) {\r
252         TEE_Result returnValue = TEE_SUCCESS;\r
253         Property* targetProperty = NULL;\r
254         PropertyValue pv;\r
255         string queryProp = "";\r
256         if (NULL != name) queryProp = getQueryProp(propsetOrEnumerator, name);\r
257         // 1. Select the enumerator object based on propset or consider given enumerator\r
258         // if any\r
259         targetProperty = _GetTargetProperty(propsetOrEnumerator);\r
260         // 2. after selecting targetProperty fetch the property by name or as in\r
261         // pointed by enumerator marker\r
262         if (targetProperty\r
263             && ((NULL != name && targetProperty->getPropertyByName(queryProp, pv))\r
264                 || (NULL == name && targetProperty->getPropertyValue(pv)))) {\r
265                 returnValue = PropertyUtility::convertToUUID(pv, *value);\r
266         }\r
267         else returnValue = TEE_ERROR_ITEM_NOT_FOUND;\r
268         return returnValue;\r
269 }\r
270 \r
271 // TODO: In spec: value: A pointer filled with the UUID. MUST NOT be NULL.\r
272 // What does it mean? Must not be NULL\r
273 TEE_Result TEE_GetPropertyAsIdentity(TEE_PropSetHandle propsetOrEnumerator,\r
274     const char* name, TEE_Identity* value) {\r
275         TEE_Result returnValue = TEE_SUCCESS;\r
276         Property* targetProperty = NULL;\r
277         PropertyValue pv;\r
278         string queryProp = "";\r
279         if (NULL != name) queryProp = getQueryProp(propsetOrEnumerator, name);\r
280         // 1. Select the enumerator object based on propset or consider given enumerator\r
281         // if any\r
282         targetProperty = _GetTargetProperty(propsetOrEnumerator);\r
283         // 2. after selecting targetProperty fetch the property by name or as in\r
284         // pointed by enumerator marker\r
285         if (targetProperty\r
286             && ((NULL != name && targetProperty->getPropertyByName(queryProp, pv))\r
287                 || (NULL == name && targetProperty->getPropertyValue(pv)))) {\r
288                 returnValue = PropertyUtility::convertToIdentity(pv, *value);\r
289         }\r
290         else returnValue = TEE_ERROR_ITEM_NOT_FOUND;\r
291         return returnValue;\r
292 }\r
293 \r
294 TEE_Result TEE_AllocatePropertyEnumerator(TEE_PropSetHandle* enumerator) {\r
295         try {\r
296                 PropertyEnumHandle *newEnumHandle = new PropertyEnumHandle;\r
297                 newEnumHandle->property = NULL;\r
298                 *enumerator = (TEE_PropSetHandle)newEnumHandle;\r
299                 propertyEnumHandleSet.insert(newEnumHandle);\r
300         } catch (std::bad_alloc &ba) {\r
301                 return TEE_ERROR_OUT_OF_MEMORY;\r
302         }\r
303         return TEE_SUCCESS;\r
304 }\r
305 \r
306 void TEE_FreePropertyEnumerator(TEE_PropSetHandle enumerator) {\r
307         PropertyEnumHandle* enumeratorHandle = (PropertyEnumHandle*)enumerator;\r
308         if (enumeratorHandle) {\r
309                 set<PropertyEnumHandle*>::iterator it = propertyEnumHandleSet.find((PropertyEnumHandle*)enumerator);\r
310                 if(it != propertyEnumHandleSet.end())\r
311                 {\r
312                         propertyEnumHandleSet.erase(it);\r
313                         delete enumeratorHandle->property;\r
314                         delete enumeratorHandle;\r
315                 } else {\r
316                         TEE_Panic(0);\r
317                 }\r
318         }\r
319 }\r
320 \r
321 //TODO: propSet value sent from user has to typecased to TEE_PropSetHandle\r
322 // this shouldnt happen, make it straight\r
323 void TEE_StartPropertyEnumerator(TEE_PropSetHandle enumerator,\r
324     TEE_PropSetHandle propSet) {\r
325         PropertyEnumHandle *newEnumHandle = (PropertyEnumHandle*)enumerator;\r
326         switch ((uintptr_t)propSet) {\r
327                 case TEE_PROPSET_CURRENT_TA: {\r
328                         newEnumHandle->property = new TAProperty(\r
329                             string(TEE_EXTRACT_ROOT) + thisTAUUIDGlobal + "-ext/"\r
330                                 + thisTAUUIDGlobal + ".manifest");\r
331                         break;\r
332                 }\r
333                 case TEE_PROPSET_CURRENT_CLIENT: {\r
334                         PropertyValue pv;\r
335                         pv.type = "identity";\r
336                         pv.value = "" + clientLoginGlobal;\r
337                         if(!_allowPropertyAccess)\r
338                         {\r
339                                 break;\r
340                         }\r
341                         newEnumHandle->property = new ClientProperty(pv);\r
342                         break;\r
343                 }\r
344                 case TEE_PROPSET_TEE_IMPLEMENTATION: {\r
345                         newEnumHandle->property = new TEEProperty();\r
346                         break;\r
347                 }\r
348                 default: {\r
349                         // Nothing\r
350                         break;\r
351                 }\r
352         }\r
353 \r
354         if (newEnumHandle && newEnumHandle->property) {\r
355                 newEnumHandle->property->setPropSet((uintptr_t)propSet);\r
356                 newEnumHandle->property->start();
357         }\r
358 }\r
359 \r
360 void TEE_ResetPropertyEnumerator(TEE_PropSetHandle enumerator) {\r
361         Property* targetProperty = _GetTargetProperty(enumerator);
362         if (targetProperty != NULL
363                         && targetProperty != teeProperty
364                         && targetProperty != clientProperty
365                         && targetProperty != taProperty) {
366                 PropertyEnumHandle* enumeratorHandle = (PropertyEnumHandle*)enumerator;
367                 delete enumeratorHandle->property;
368                 enumeratorHandle->property = NULL;
369         }
370 }\r
371 \r
372 /*\r
373  * Considers nameBufferLen as [in] param as spec. is ambiguous\r
374  */\r
375 TEE_Result TEE_GetPropertyName(TEE_PropSetHandle enumerator, void* nameBuffer,\r
376     size_t* nameBufferLen) {\r
377         Property* targetProperty = NULL;\r
378         // 1. Select the enumerator object based on propset or consider given enumerator\r
379         // if any\r
380         targetProperty = _GetTargetProperty(enumerator);\r
381         PropertyEnumHandle* enumeratorHandle = (PropertyEnumHandle*)enumerator;\r
382         // Check if enumerator and property are valid\r
383         //if (enumeratorHandle && enumeratorHandle->property) {\r
384         if (enumeratorHandle && targetProperty) {\r
385                 string propName;\r
386                 // If item exists and and not reached end of enumerator, get the name\r
387                 if (enumeratorHandle->property->getPropertyName(propName)) {\r
388                         if (*nameBufferLen < propName.size() + 1) return TEE_ERROR_SHORT_BUFFER;\r
389                         strncpy((char*)nameBuffer, propName.c_str(), *nameBufferLen);\r
390                 }\r
391                 // item not found or enumerator end has reached\r
392                 else return TEE_ERROR_ITEM_NOT_FOUND;\r
393         }\r
394         else return TEE_ERROR_ITEM_NOT_FOUND;\r
395         return TEE_SUCCESS;\r
396 }\r
397 \r
398 TEE_Result TEE_GetNextProperty(TEE_PropSetHandle enumerator) {\r
399         PropertyEnumHandle* enumeratorHandle = (PropertyEnumHandle*)enumerator;\r
400         // Check if enumerator and property are valid and enumerator has not reached end of enum\r
401         if (enumeratorHandle && enumeratorHandle->property\r
402             && enumeratorHandle->property->getNextProperty()) {\r
403                 return TEE_SUCCESS;\r
404         }\r
405         else return TEE_ERROR_ITEM_NOT_FOUND;\r
406 }\r
407 \r
408 uintptr_t _GetTargetPropsetType(TEE_PropSetHandle propsetOrEnumerator) {\r
409         switch ((uintptr_t)propsetOrEnumerator) {\r
410                 case TEE_PROPSET_TEE_IMPLEMENTATION:\r
411                 case TEE_PROPSET_CURRENT_CLIENT:\r
412                 case TEE_PROPSET_CURRENT_TA:\r
413                         return (uintptr_t)propsetOrEnumerator;\r
414         }\r
415         set<PropertyEnumHandle*>::iterator it =\r
416                 propertyEnumHandleSet.find((PropertyEnumHandle*)propsetOrEnumerator);\r
417         if(it != propertyEnumHandleSet.end()) {\r
418                 Property *targetProperty = NULL;\r
419                 PropertyEnumHandle *enumHandle =\r
420                         (PropertyEnumHandle*)propsetOrEnumerator;\r
421                 if (enumHandle && enumHandle->property) {\r
422                         targetProperty = enumHandle->property;\r
423                         return targetProperty->m_propset;\r
424                 }\r
425         }\r
426         return 0;\r
427 }\r
428 \r
429 Property* _GetTargetProperty(TEE_PropSetHandle propsetOrEnumerator) {\r
430         Property *targetProperty = NULL;\r
431         switch ((uintptr_t)propsetOrEnumerator) {\r
432                 case TEE_PROPSET_TEE_IMPLEMENTATION: {\r
433                         targetProperty = teeProperty;\r
434                         break;\r
435                 }\r
436                 case TEE_PROPSET_CURRENT_CLIENT: {\r
437                         if(!_allowPropertyAccess)\r
438                         {\r
439                                 break;\r
440                         }\r
441                         targetProperty = clientProperty;\r
442                         break;\r
443                 }\r
444                 case TEE_PROPSET_CURRENT_TA: {\r
445                         targetProperty = taProperty;\r
446                         break;\r
447                 }\r
448         }\r
449         if(targetProperty == NULL) {\r
450                 set<PropertyEnumHandle*>::iterator it =\r
451                         propertyEnumHandleSet.find((PropertyEnumHandle*)propsetOrEnumerator);\r
452                 if(it != propertyEnumHandleSet.end()) {\r
453                         PropertyEnumHandle *enumHandle =\r
454                                 (PropertyEnumHandle*)propsetOrEnumerator;\r
455                         if (enumHandle && enumHandle->property)\r
456                                 targetProperty = enumHandle->property;\r
457                 }\r
458         }\r
459         return targetProperty;\r
460 }\r
461 \r