Remove dead code related to downloadable TA
[platform/core/security/tef-simulator.git] / simulatordaemon / src / TABinaryManager / TABinaryManager.cpp
1 /**
2  * Copyright (c) 2015-2017 Samsung Electronics Co., Ltd All Rights Reserved
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 /**
18  * @file
19  * @author CHERYL (cb) (cheryl.b@samsung.com)
20  * @brief  TABinaryManager class
21  */
22
23
24 /*-----------------------------------------------------------------------------
25  *  Include files
26  *-----------------------------------------------------------------------------*/
27 #include "TABinaryManager.h"
28 #include "Config.h"
29 #include <iostream>
30 #include <fstream>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <time.h>
34 #include <sys/stat.h>
35 #include <sys/types.h>
36 #include <sys/file.h>
37 #include <algorithm>
38 #include <boost/filesystem.hpp>
39 /*-----------------------------------------------------------------------------
40  *  Globals
41  *-----------------------------------------------------------------------------*/
42 TABinaryManager *TABinaryManager::instance = NULL;
43 pthread_rwlock_t binaryMapLock;
44 map<string, StructBinaryInfo> binaryMap;
45
46 /*-----------------------------------------------------------------------------
47  *  Member functions
48  *-----------------------------------------------------------------------------*/
49 /**
50  * Checks if a characters is part of base64 encoding character set
51  * @param c character to be verified
52  * @return true if conformant to base64 charset else false
53  */
54 bool TABinaryManager::is_base64(unsigned char c) {
55         return (isalnum(c) || (c == '+') || (c == '/'));
56 }
57
58 /**
59  * Thanks to: René Nyffenegger
60  * Reused from: http://www.adp-gmbh.ch/cpp/common/base64.html
61  * License Notice:
62  * Copyright (C) 2004-2008 René Nyffenegger
63  *
64  *  This source code is provided 'as-is', without any express or implied
65  *  warranty. In no event will the author be held liable for any damages
66  *  arising from the use of this software.
67  *
68  *  Permission is granted to anyone to use this software for any purpose,
69  *  including commercial applications, and to alter it and redistribute it
70  *  freely, subject to the following restrictions:
71  *
72  *  1. The origin of this source code must not be misrepresented; you must not
73  *     claim that you wrote the original source code. If you use this source code
74  *     in a product, an acknowledgment in the product documentation would be
75  *     appreciated but is not required.
76  *
77  *  2. Altered source versions must be plainly marked as such, and must not be
78  *     misrepresented as being the original source code.
79  *
80  *  3. This notice may not be removed or altered from any source distribution.
81  *
82  *  René Nyffenegger rene.nyffenegger@adp-gmbh.ch
83  *
84  * @param encoded_string
85  * @return
86  */
87 string TABinaryManager::base64_decode(std::string const& encoded_string) {
88         int in_len = encoded_string.size();
89         int i = 0;
90         int j = 0;
91         int in_ = 0;
92         unsigned char char_array_4[4], char_array_3[3];
93         std::string ret;
94
95         while (in_len-- && (encoded_string[in_] != '=')
96             && is_base64(encoded_string[in_])) {
97                 char_array_4[i++] = encoded_string[in_];
98                 in_++;
99                 if (i == 4) {
100                         for (i = 0; i < 4; i++)
101                                 char_array_4[i] = base64_chars.find(char_array_4[i]);
102                         char_array_3[0] = (char_array_4[0] << 2)
103                             + ((char_array_4[1] & 0x30) >> 4);
104                         char_array_3[1] = ((char_array_4[1] & 0xf) << 4)
105                             + ((char_array_4[2] & 0x3c) >> 2);
106                         char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
107                         for (i = 0; (i < 3); i++)
108                                 ret += char_array_3[i];
109                         i = 0;
110                 }
111         }
112         if (i) {
113                 for (j = i; j < 4; j++)
114                         char_array_4[j] = 0;
115                 for (j = 0; j < 4; j++)
116                         char_array_4[j] = base64_chars.find(char_array_4[j]);
117                 char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
118                 char_array_3[1] = ((char_array_4[1] & 0xf) << 4)
119                     + ((char_array_4[2] & 0x3c) >> 2);
120                 char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
121                 for (j = 0; (j < i - 1); j++)
122                         ret += char_array_3[j];
123         }
124         return ret;
125 }
126
127
128 /**
129  * This is the constructor of TABinaryManger.
130  */
131 TABinaryManager::TABinaryManager() {
132         //Stat for mod time
133
134         /// Constant charset of base64 encoding
135         base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
136                         "abcdefghijklmnopqrstuvwxyz"
137                         "0123456789+/";
138
139         pthread_rwlock_init(&binaryMapLock, NULL);
140         pthread_mutex_init(&taLock, NULL);
141 }
142
143 /**
144  * This function returns the TA Binary Manager instance if already created
145  * else creates the instance and returns it
146  */
147 TABinaryManager* TABinaryManager::getInstance() {
148         if (NULL == instance) {
149             try {
150                     instance = new TABinaryManager();
151                 }catch (std::bad_alloc &ba) {
152                     return NULL;
153             }
154         }
155         return instance;
156 }
157
158 /**
159  * This function add TA to BinaryManager if it exists.
160  * @return On successful completion of above operations returns true else false.
161  */
162 bool TABinaryManager::initTA(const string &uuid) {
163         LOGD(SIM_DAEMON, "Entry");
164
165         pthread_rwlock_wrlock(&binaryMapLock);
166         StructBinaryInfo value;
167         bool res = false;
168         StructBinaryInfo info;
169
170         if (boost::filesystem::exists(TA_STORE_PATH + uuid)) {
171                 pthread_mutex_lock(&taLock);
172                 try {
173                         if (unpackBinary(uuid, info)) {
174                                 binaryMap[uuid] = info;
175                                 res = true;
176                         }
177                 } catch (...) {
178                         res = false;
179                 }
180                 pthread_mutex_unlock(&taLock);
181         }
182         pthread_rwlock_unlock(&binaryMapLock);
183         return res;
184 }
185
186
187 /**
188  * This function decrypts the TA Binary image
189  * @param uuid TA UUID in string format
190  * @param info TA Binary info
191  */
192 void TABinaryManager::decryptImage(StructBinaryInfo& info) {
193         string cipher = "-aes-256-cbc";
194         string secret = base64_decode(info.manifest.taencryption.model.plainkeydata);
195         string keyhashFilename = info.imagePath + ".keyhash";
196         secret.erase(secret.size() - 2);
197         string keyHash = "echo -n " + secret + " | openssl dgst -sha256 | awk '{print $2}' > " + keyhashFilename;
198         int result = system(keyHash.c_str());
199         if (result != 0) {
200                 LOGE(SIM_DAEMON, "Hashing key failed");
201         }
202
203         string line;
204         ifstream myfile(keyhashFilename.c_str());
205         if (myfile.is_open()) {
206                 getline(myfile, line);
207                 myfile.close();
208         }
209
210         // hash of Keydata is not required.
211         string dec_command = "openssl enc " + cipher + " -d -nopad -nosalt -K " + secret
212                 + " -in " + info.imagePath + " -out " + info.imagePath
213                 + "_dec -iv 0000000000000000";
214         result = system(dec_command.c_str());
215         if (result != 0) {
216                 LOGE(SIM_DAEMON, "Image decryption failed");
217         }
218
219         string removeEncImage = "rm -f " + info.imagePath;
220         result = system(removeEncImage.c_str());
221         if (result != 0) {
222                 LOGE(SIM_DAEMON, "Post decryption operations failed");
223         }
224
225         string renameDecImage = "mv " + info.imagePath + "_dec " + info.imagePath;
226         result = system(renameDecImage.c_str());
227         if (result != 0) {
228                 LOGE(SIM_DAEMON, "Post decryption operations failed");
229         }
230
231         string removeKeyHash = "rm -f " + keyhashFilename;
232         result = system(removeKeyHash.c_str());
233         if (result != 0) {
234                 LOGE(SIM_DAEMON, "Post decryption operations failed");
235         }
236 }
237
238 /**
239  * This function reads unpacks files to their respective locations.
240  * It also reads manifest file and keeps it ready for queries on fields
241  * in manifest.
242  * @param uuid TA UUID in string format
243  * @param info TA Binary info
244  * @return On successful completion of above operations returns true else false.
245  * It is very important to check for return value from this function.
246  */
247
248 bool TABinaryManager::unpackBinary(const string &uuid, StructBinaryInfo& info) {
249         TAUnpack* unpacker = TAUnpack::getInstance();
250         bool ret = false;
251         if (0 == unpacker->unpackTA(string(TA_STORE_PATH), uuid)) {
252                 LOGD(SIM_DAEMON, "Unpacked, filling info");
253                 // 1. Set binary info
254                 info.path = string(TA_STORE_PATH)+ uuid;
255                 info.extractpath = string(TA_STORE_PATH) + uuid + "-ext/";
256                 info.imagePath = info.extractpath + uuid + ".image";
257                 info.manifestPath = info.extractpath + uuid + ".manifest";
258                 // 2. Parse manifest and store results
259                 info.manifest.processXML(info.manifestPath);
260
261                 LOGD(SIM_DAEMON, "Decrypting");
262                 // 3. Decrypt image using secret value in manifest
263                 if (info.manifest.properties.extension.launchMode == "debug")
264                   decryptImage(info);
265
266                 string s = "chmod +x " + info.imagePath;
267                 int result = system(s.c_str());
268                 if (result != 0) {
269                         LOGE(SIM_DAEMON, "Unpacking executable TA failed");
270                 }
271
272                 ret = true;
273         }
274         return ret;
275 }
276
277 /**
278  * Check if TA is single instance
279  * @param[in] uuid UUID of TA
280  * @param[out] isSingleInstance returns value from this parameter.
281  * @return -1 if uuid is not found else on success 0
282  */
283
284 int TABinaryManager::isSingleInstance(string uuid, bool &SingleInstance) {
285         pthread_rwlock_wrlock(&binaryMapLock);
286         map<string, StructBinaryInfo>::iterator it = binaryMap.find(uuid);
287         StructBinaryInfo value;
288         int ret = -1;
289         if (it != binaryMap.end()) {
290                 //element found;
291                 value = it->second;
292                 ret = 0;
293                 SingleInstance = value.manifest.properties.general.singleInstance;
294         }
295         pthread_rwlock_unlock(&binaryMapLock);
296         return ret;
297 }
298
299 /**
300  * Check if TA is KeepAlive
301  * @param[in] uuid UUID of TA
302  * @param[out] isKeepAlive returns value from this parameter.
303  * @return -1 if uuid is not found else on success 0
304  */
305
306 int TABinaryManager::isKeepAlive(string uuid, bool &KeepAlive) {
307         pthread_rwlock_wrlock(&binaryMapLock);
308         map<string, StructBinaryInfo>::iterator it = binaryMap.find(uuid);
309         StructBinaryInfo value;
310         int ret = -1;
311         if (it != binaryMap.end()) {
312                 //element found;
313                 value = it->second;
314                 ret = 0;
315                 KeepAlive = value.manifest.properties.general.instanceKeepAlive;
316         }
317         pthread_rwlock_unlock(&binaryMapLock);
318         return ret;
319 }
320
321 /**
322  * Check if TA is multi instance type
323  * @param[in] uuid UUID of TA
324  * @param[out] isMultipleSession returns value from this parameter.
325  * @return -1 if uuid is not found else on success 0
326  */
327 int TABinaryManager::isMultipleSession(string uuid, bool &MultipleSession) {
328         pthread_rwlock_wrlock(&binaryMapLock);
329         map<string, StructBinaryInfo>::iterator it = binaryMap.find(uuid);
330         StructBinaryInfo value;
331         int ret = -1;
332         if (it != binaryMap.end()) {
333                 //element found;
334                 value = it->second;
335                 ret = 0;
336                 MultipleSession = value.manifest.properties.general.multiSession;
337         }
338         pthread_rwlock_unlock(&binaryMapLock);
339         return ret;
340 }
341
342 /**
343  * Get TA executable image path
344  * @param uuid UUID of TA
345  * @return Empty string if UUID doesn't exist, else path to TA
346  */
347 string TABinaryManager::getImagePath(string uuid) {
348         pthread_rwlock_wrlock(&binaryMapLock);
349         map<string, StructBinaryInfo>::iterator it = binaryMap.find(uuid);
350         StructBinaryInfo value;
351         string ret = "";
352         if (it != binaryMap.end()) {
353                 //element found;
354                 value = it->second;
355                 ret = value.imagePath;
356         }
357         pthread_rwlock_unlock(&binaryMapLock);
358         return ret;
359 }
360
361 /**
362  * Constant to TA Manifest object
363  * @param uuid UUID of TA
364  * @return NULL pointer if
365  */
366 const TAManifest* TABinaryManager::getManifest(string uuid) {
367         pthread_rwlock_wrlock(&binaryMapLock);
368         map<string, StructBinaryInfo>::iterator it = binaryMap.find(uuid);
369         TAManifest *returnValue = NULL;
370         if (it != binaryMap.end()) {
371                 //element found;
372                 returnValue = &(it->second.manifest);
373         }
374         pthread_rwlock_unlock(&binaryMapLock);
375         return returnValue;
376 }
377
378 /**
379  * Constant to port string
380  * @param uuid UUID of TA
381  * @return NULL pointer if
382  */
383 string TABinaryManager::getPort(string uuid) {
384         pthread_rwlock_wrlock(&binaryMapLock);
385         map<string, StructBinaryInfo>::iterator it = binaryMap.find(uuid);
386         string returnValue = "";
387         if (it != binaryMap.end()) {
388                 returnValue = it->second.port;
389         }
390         pthread_rwlock_unlock(&binaryMapLock);
391         return returnValue;
392 }
393
394 /**
395  * Converts UUID from TEEC_UUID to a string
396  * @return string of TEEC_UUID
397  */
398 string TABinaryManager::getUUIDAsString(TEEC_UUID uuid) {
399         // E.g. returns a string in the format 79B7778897894a7aA2BEB60155EEF5F3
400         std::stringstream strStream;
401         strStream << IntToHex(uuid.timeLow);
402         strStream << IntToHex(uuid.timeMid);
403         strStream << IntToHex(uuid.timeHiAndVersion);
404         for (int i = 0; i < 8; i++) {
405                 strStream << IntToHex((short)uuid.clockSeqAndNode[i], 2);
406         }
407         return strStream.str();
408 }
409
410
411 TABinaryManager::~TABinaryManager() {
412         pthread_rwlock_destroy(&binaryMapLock);
413         pthread_mutex_destroy(&taLock);
414         delete instance;
415 }