2 * Copyright (c) 2015-2017 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 * @author CHERYL (cb) (cheryl.b@samsung.com)
20 * @brief TABinaryManager class
24 /*-----------------------------------------------------------------------------
26 *-----------------------------------------------------------------------------*/
27 #include "TABinaryManager.h"
34 #include <sys/types.h>
37 #include <boost/filesystem.hpp>
38 /*-----------------------------------------------------------------------------
40 *-----------------------------------------------------------------------------*/
41 TABinaryManager *TABinaryManager::instance = NULL;
42 pthread_rwlock_t binaryMapLock;
43 map<string, StructBinaryInfo> binaryMap;
45 /*-----------------------------------------------------------------------------
47 *-----------------------------------------------------------------------------*/
49 * Checks if a characters is part of base64 encoding character set
50 * @param c character to be verified
51 * @return true if conformant to base64 charset else false
53 bool TABinaryManager::is_base64(unsigned char c) {
54 return (isalnum(c) || (c == '+') || (c == '/'));
58 * Thanks to: René Nyffenegger
59 * Reused from: http://www.adp-gmbh.ch/cpp/common/base64.html
61 * Copyright (C) 2004-2008 René Nyffenegger
63 * This source code is provided 'as-is', without any express or implied
64 * warranty. In no event will the author be held liable for any damages
65 * arising from the use of this software.
67 * Permission is granted to anyone to use this software for any purpose,
68 * including commercial applications, and to alter it and redistribute it
69 * freely, subject to the following restrictions:
71 * 1. The origin of this source code must not be misrepresented; you must not
72 * claim that you wrote the original source code. If you use this source code
73 * in a product, an acknowledgment in the product documentation would be
74 * appreciated but is not required.
76 * 2. Altered source versions must be plainly marked as such, and must not be
77 * misrepresented as being the original source code.
79 * 3. This notice may not be removed or altered from any source distribution.
81 * René Nyffenegger rene.nyffenegger@adp-gmbh.ch
83 * @param encoded_string
86 string TABinaryManager::base64_decode(std::string const& encoded_string) {
87 int in_len = encoded_string.size();
91 unsigned char char_array_4[4], char_array_3[3];
94 while (in_len-- && (encoded_string[in_] != '=')
95 && is_base64(encoded_string[in_])) {
96 char_array_4[i++] = encoded_string[in_];
99 for (i = 0; i < 4; i++)
100 char_array_4[i] = base64_chars.find(char_array_4[i]);
101 char_array_3[0] = (char_array_4[0] << 2)
102 + ((char_array_4[1] & 0x30) >> 4);
103 char_array_3[1] = ((char_array_4[1] & 0xf) << 4)
104 + ((char_array_4[2] & 0x3c) >> 2);
105 char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
106 for (i = 0; (i < 3); i++)
107 ret += char_array_3[i];
112 for (j = i; j < 4; j++)
114 for (j = 0; j < 4; j++)
115 char_array_4[j] = base64_chars.find(char_array_4[j]);
116 char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
117 char_array_3[1] = ((char_array_4[1] & 0xf) << 4)
118 + ((char_array_4[2] & 0x3c) >> 2);
119 char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
120 for (j = 0; (j < i - 1); j++)
121 ret += char_array_3[j];
128 * This is the constructor of TABinaryManger.
130 TABinaryManager::TABinaryManager() {
133 /// Constant charset of base64 encoding
134 base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
135 "abcdefghijklmnopqrstuvwxyz"
138 pthread_rwlock_init(&binaryMapLock, NULL);
139 pthread_mutex_init(&taLock, NULL);
143 * This function returns the TA Binary Manager instance if already created
144 * else creates the instance and returns it
146 TABinaryManager* TABinaryManager::getInstance() {
147 if (NULL == instance) {
149 instance = new TABinaryManager();
150 }catch (std::bad_alloc &ba) {
158 * This function add TA at given path to BinaryManager if it exists.
159 * @return On successful completion of above operations returns true else false.
161 bool TABinaryManager::initTAatPath(const string &path, const string &uuid) {
162 LOGD(SIM_DAEMON, "");
164 pthread_rwlock_wrlock(&binaryMapLock);
165 StructBinaryInfo value;
167 StructBinaryInfo info;
169 if (boost::filesystem::exists(path + uuid)) {
170 pthread_mutex_lock(&taLock);
172 if (unpackBinary(uuid, path, info)) {
173 binaryMap[uuid] = info;
179 pthread_mutex_unlock(&taLock);
181 pthread_rwlock_unlock(&binaryMapLock);
187 * This function decrypts the TA Binary image
188 * @param uuid TA UUID in string format
189 * @param info TA Binary info
191 void TABinaryManager::decryptImage(StructBinaryInfo& info) {
192 string cipher = "-aes-256-cbc";
193 string secret = base64_decode (info.manifest.taencryption.model.plainkeydata);
194 string keyhashFilename = info.imagePath + ".keyhash";
195 secret.erase(secret.size()-2);
196 string keyHash = "echo -n " + secret + " | openssl dgst -sha256 | awk '{print $2}' > " + keyhashFilename;
197 int result = system(keyHash.c_str());
199 LOGE(SIM_DAEMON, "Hashing key failed");
203 ifstream myfile(keyhashFilename.c_str());
204 if (myfile.is_open()) {
205 getline(myfile, line);
209 // hash of Keydata is not required.
210 string dec_command = "openssl enc " + cipher + " -d -nopad -nosalt -K " + secret
211 + " -in " + info.imagePath + " -out " + info.imagePath
212 + "_dec -iv 0000000000000000";
213 result = system(dec_command.c_str());
215 LOGE(SIM_DAEMON, "Image decryption failed");
218 string removeEncImage = "rm -f " + info.imagePath;
219 result = system(removeEncImage.c_str());
221 LOGE(SIM_DAEMON, "Post decryption operations failed");
224 string renameDecImage = "mv " + info.imagePath + "_dec " + info.imagePath;
225 result = system(renameDecImage.c_str());
227 LOGE(SIM_DAEMON, "Post decryption operations failed");
230 string removeKeyHash = "rm -f " + keyhashFilename;
231 result = system(removeKeyHash.c_str());
233 LOGE(SIM_DAEMON, "Post decryption operations failed");
238 * This function reads unpacks files to their respective locations.
239 * It also reads manifest file and keeps it ready for queries on fields
241 * @param uuid TA UUID in string format
242 * @param info TA Binary info
243 * @return On successful completion of above operations returns true else false.
244 * It is very important to check for return value from this function.
247 bool TABinaryManager::unpackBinary(const string &uuid, const string &path, StructBinaryInfo& info) {
248 TAUnpack* unpacker = TAUnpack::getInstance();
250 LOGE(SIM_DAEMON, "Unpacking TA %s in %s", uuid.c_str(), path.c_str());
251 if (0 == unpacker->unpackTA(path, uuid)) {
252 LOGE(SIM_DAEMON, "Unpacked, filling info");
253 // 1. Set binary info
254 info.path = path + uuid;
255 info.extractpath = 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);
261 LOGE(SIM_DAEMON, "Decrypting");
262 // 3. Decrypt image using secret value in manifest
263 if (info.manifest.properties.extension.launchMode == "debug")
266 string s = "chmod +x " + info.imagePath;
267 int result = system(s.c_str());
269 LOGE(SIM_DAEMON, "Unpacking executable TA failed");
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
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;
289 if (it != binaryMap.end()) {
293 SingleInstance = value.manifest.properties.general.singleInstance;
295 pthread_rwlock_unlock(&binaryMapLock);
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
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;
311 if (it != binaryMap.end()) {
315 KeepAlive = value.manifest.properties.general.instanceKeepAlive;
317 pthread_rwlock_unlock(&binaryMapLock);
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
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;
332 if (it != binaryMap.end()) {
336 MultipleSession = value.manifest.properties.general.multiSession;
338 pthread_rwlock_unlock(&binaryMapLock);
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
347 string TABinaryManager::getImagePath(string uuid) {
348 pthread_rwlock_wrlock(&binaryMapLock);
349 map<string, StructBinaryInfo>::iterator it = binaryMap.find(uuid);
350 StructBinaryInfo value;
352 if (it != binaryMap.end()) {
355 ret = value.imagePath;
357 pthread_rwlock_unlock(&binaryMapLock);
362 * Constant to TA Manifest object
363 * @param uuid UUID of TA
364 * @return NULL pointer if
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()) {
372 returnValue = &(it->second.manifest);
374 pthread_rwlock_unlock(&binaryMapLock);
379 * Constant to port string
380 * @param uuid UUID of TA
381 * @return NULL pointer if
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;
390 pthread_rwlock_unlock(&binaryMapLock);
395 * Converts UUID from TEEC_UUID to a string
396 * @return string of TEEC_UUID
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);
407 return strStream.str();
411 TABinaryManager::~TABinaryManager() {
412 pthread_rwlock_destroy(&binaryMapLock);
413 pthread_mutex_destroy(&taLock);