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"
35 #include <sys/types.h>
38 #include <boost/filesystem.hpp>
39 /*-----------------------------------------------------------------------------
41 *-----------------------------------------------------------------------------*/
42 TABinaryManager *TABinaryManager::instance = NULL;
43 pthread_rwlock_t binaryMapLock;
44 map<string, StructBinaryInfo> binaryMap;
46 /*-----------------------------------------------------------------------------
48 *-----------------------------------------------------------------------------*/
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
54 bool TABinaryManager::is_base64(unsigned char c) {
55 return (isalnum(c) || (c == '+') || (c == '/'));
59 * Thanks to: René Nyffenegger
60 * Reused from: http://www.adp-gmbh.ch/cpp/common/base64.html
62 * Copyright (C) 2004-2008 René Nyffenegger
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.
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:
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.
77 * 2. Altered source versions must be plainly marked as such, and must not be
78 * misrepresented as being the original source code.
80 * 3. This notice may not be removed or altered from any source distribution.
82 * René Nyffenegger rene.nyffenegger@adp-gmbh.ch
84 * @param encoded_string
87 string TABinaryManager::base64_decode(std::string const& encoded_string) {
88 int in_len = encoded_string.size();
92 unsigned char char_array_4[4], char_array_3[3];
95 while (in_len-- && (encoded_string[in_] != '=')
96 && is_base64(encoded_string[in_])) {
97 char_array_4[i++] = encoded_string[in_];
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];
113 for (j = i; j < 4; j++)
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];
129 * This is the constructor of TABinaryManger.
131 TABinaryManager::TABinaryManager() {
134 /// Constant charset of base64 encoding
135 base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
136 "abcdefghijklmnopqrstuvwxyz"
139 pthread_rwlock_init(&binaryMapLock, NULL);
140 pthread_mutex_init(&taLock, NULL);
144 * This function returns the TA Binary Manager instance if already created
145 * else creates the instance and returns it
147 TABinaryManager* TABinaryManager::getInstance() {
148 if (NULL == instance) {
150 instance = new TABinaryManager();
151 }catch (std::bad_alloc &ba) {
159 * This function add TA to BinaryManager if it exists.
160 * @return On successful completion of above operations returns true else false.
162 bool TABinaryManager::initTA(const string &uuid) {
163 LOGD(SIM_DAEMON, "Entry");
165 pthread_rwlock_wrlock(&binaryMapLock);
166 StructBinaryInfo value;
168 StructBinaryInfo info;
170 if (boost::filesystem::exists(TA_STORE_PATH + uuid)) {
171 pthread_mutex_lock(&taLock);
173 if (unpackBinary(uuid, info)) {
174 binaryMap[uuid] = info;
180 pthread_mutex_unlock(&taLock);
182 pthread_rwlock_unlock(&binaryMapLock);
188 * This function decrypts the TA Binary image
189 * @param uuid TA UUID in string format
190 * @param info TA Binary info
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());
200 LOGE(SIM_DAEMON, "Hashing key failed");
204 ifstream myfile(keyhashFilename.c_str());
205 if (myfile.is_open()) {
206 getline(myfile, line);
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());
216 LOGE(SIM_DAEMON, "Image decryption failed");
219 string removeEncImage = "rm -f " + info.imagePath;
220 result = system(removeEncImage.c_str());
222 LOGE(SIM_DAEMON, "Post decryption operations failed");
225 string renameDecImage = "mv " + info.imagePath + "_dec " + info.imagePath;
226 result = system(renameDecImage.c_str());
228 LOGE(SIM_DAEMON, "Post decryption operations failed");
231 string removeKeyHash = "rm -f " + keyhashFilename;
232 result = system(removeKeyHash.c_str());
234 LOGE(SIM_DAEMON, "Post decryption operations failed");
239 * This function reads unpacks files to their respective locations.
240 * It also reads manifest file and keeps it ready for queries on fields
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.
248 bool TABinaryManager::unpackBinary(const string &uuid, StructBinaryInfo& info) {
249 TAUnpack* unpacker = TAUnpack::getInstance();
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);
261 LOGD(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);