[Release] wrt_0.8.225
[platform/framework/web/wrt.git] / src / view / webkit / injected-bundle / injected_bundle_decryption_support.cpp
1 /*
2  * Copyright (c) 2012 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  * @file    injected_bundle_decryption_support.cpp
18  * @author  Jihoon Chung (jihoon.chung@samsung.com)
19  * @version 1.0
20  */
21
22 #include "injected_bundle_decryption_support.h"
23
24 #include <memory>
25 #include <set>
26 #include <string>
27 #include <sys/stat.h>
28 #include <ss_manager.h>
29 #include <openssl/sha.h>
30 #include <openssl/hmac.h>
31 #include <openssl/evp.h>
32 #include <openssl/bio.h>
33 #include <openssl/buffer.h>
34
35 #include <dpl/log/log.h>
36 #include <dpl/assert.h>
37 #include <dpl/string.h>
38 #include <dpl/wrt-dao-ro/widget_dao_read_only.h>
39 #include <dpl/wrt-dao-ro/global_config.h>
40 #include <dpl/utils/mime_type_utils.h>
41
42 namespace InjectedBundle {
43 namespace {
44 const char * const SCHEME_FILE_SLASH = "file://";
45 const char * const DATA_STRING = "data:";
46 const char * const BASE64_STRING = ";base64,";
47 const char QUESTION_MARK = '?';
48 const char ASTERISK_MARK = '#';
49 }
50
51 //Implementation class
52 class DecryptionSupportImplementation
53 {
54   private:
55     bool m_initialized;
56
57     WrtDB::TizenAppId m_appId;
58     WrtDB::EncryptedFileList m_encryptedFiles;
59     bool m_isEncrypted;
60     std::set<WrtDB::EncryptedFileInfo>::iterator m_targetIt;
61     bool m_isPreload;
62     WrtDB::TizenPkgId m_pkgId;
63
64
65     std::string getFilePath(const std::string& url)
66     {
67         std::string filePath = url;
68
69         size_t pos = filePath.find_first_not_of(SCHEME_FILE_SLASH);
70         if (pos != std::string::npos) {
71             filePath = filePath.substr(pos - 1);
72         }
73
74         pos = filePath.find_first_of(ASTERISK_MARK);
75         if (pos != std::string::npos) {
76             filePath = filePath.substr(0, pos);
77         }
78
79         pos = filePath.find_first_of(QUESTION_MARK);
80         if (pos != std::string::npos) {
81             filePath = filePath.substr(0, pos);
82         }
83
84         return filePath;
85     }
86
87     int ssmDecrypt(const std::string pkgId, const char* inBuf, int inSize, char** outBuf, int* outSize)
88     {
89         if (m_isPreload) {
90             return ssm_decrypt_preloaded_application(inBuf, inSize, outBuf,
91                     outSize);
92         } else {
93             return ssm_decrypt(pkgId.c_str(), pkgId.length(), inBuf, inSize, outBuf, outSize);
94         }
95     }
96
97     std::string doDecrypt(std::string filePath, int size)
98     {
99         struct stat buf;
100         if (0 == stat(filePath.c_str(), &buf)) {
101             const std::size_t fileSize = buf.st_size;
102             std::unique_ptr<unsigned char[]> inChunk;
103
104             FILE* fp = fopen(filePath.c_str(), "rb");
105             if (NULL == fp) {
106                 LogDebug("Couldnot open file : " << filePath);
107                 return std::string();
108             }
109
110             std::unique_ptr<unsigned char[]> DecryptedString(new unsigned
111                     char[fileSize]);
112             std::string pkgid(DPL::ToUTF8String(m_pkgId));
113
114             int writeCount = 0;
115             do {
116                 unsigned char getDecSize[4];
117                 memset(getDecSize, 0x00, sizeof(getDecSize));
118
119                 size_t readSize = fread(getDecSize, sizeof(unsigned char), sizeof(getDecSize), fp);
120                 if (0 != readSize) {
121                     unsigned int readBufSize = 0;
122                     std::istringstream(std::string((char*)getDecSize)) >> readBufSize;
123                     inChunk.reset(new unsigned char[readBufSize]);
124
125                     size_t decReadSize = fread(inChunk.get(), sizeof(unsigned char), readBufSize, fp);
126
127                     if (0 != decReadSize) {
128                         char *outChunk = NULL;
129                         int outSize = 0;
130                         if (0 != ssmDecrypt(pkgid, (char*)inChunk.get(), (int)decReadSize, &outChunk, &outSize))
131                         {
132                             LogError("Failed to get decrypted resource");
133                             fclose(fp);
134                             return std::string();
135                         }
136                         memcpy(DecryptedString.get() + writeCount, outChunk, outSize);
137                         writeCount += outSize;
138                     }
139                 }
140             } while( 0 == std::feof(fp));
141             fclose(fp);
142             memset(DecryptedString.get() + size, '\n', fileSize - size);
143             LogDebug("resource need to encoding base64");
144             BIO *bmem, *b64;
145             BUF_MEM *bptr;
146
147             b64 = BIO_new(BIO_f_base64());
148             bmem = BIO_new(BIO_s_mem());
149             b64 = BIO_push(b64, bmem);
150             BIO_write(b64, DecryptedString.get(), fileSize);
151             BIO_flush(b64);
152             BIO_get_mem_ptr(b64, &bptr);
153
154             std::string base64Enc((char *)bptr->data, bptr->length - 1);
155             BIO_free_all(b64);
156
157             return base64Enc;
158         }
159         return std::string();
160     }
161
162   public:
163     DecryptionSupportImplementation() :
164         m_initialized(false),
165         m_isEncrypted(false),
166         m_isPreload(false)
167     {
168     }
169
170     void initialize(WrtDB::TizenAppId appId)
171     {
172         LogInfo("initialize");
173
174         m_appId = appId;
175         WrtDB::WidgetDAOReadOnly dao(m_appId);
176         dao.getEncryptedFileList(m_encryptedFiles);
177         if (!m_encryptedFiles.empty()) {
178           m_isEncrypted = true;
179           LogDebug("encrypted application");
180         }
181         m_pkgId = dao.getTzPkgId();
182
183         std::string installedPath =
184             DPL::ToUTF8String(*dao.getWidgetInstalledPath());
185         std::string preloadPath(WrtDB::GlobalConfig::GetUserPreloadedWidgetPath());
186         if (0 == installedPath.compare(0, preloadPath.length(), preloadPath)) {
187             m_isPreload = true;
188             LogDebug("preload application");
189         }
190
191         m_initialized = true;
192     }
193
194     void deinitialize(void)
195     {
196         LogInfo("deinitialize");
197
198         m_encryptedFiles.clear();
199         m_targetIt = m_encryptedFiles.end();
200         m_isEncrypted = false;
201         m_appId = DPL::String(L"");
202         m_initialized = false;
203     }
204
205     bool isNeedDecryption(std::string url)
206     {
207         if (!m_initialized) {
208             LogInfo("not initialize");
209             return false;
210         }
211
212         if (0 != strncmp(url.c_str(), SCHEME_FILE_SLASH, strlen(SCHEME_FILE_SLASH))) {
213             return false;
214         }
215
216         std::set<WrtDB::EncryptedFileInfo>::iterator it;
217         WrtDB::EncryptedFileInfo info;
218         std::string filePath = getFilePath(url);
219         info.fileName = DPL::FromUTF8String(filePath);
220         if (m_encryptedFiles.end() != (it = m_encryptedFiles.find(info))) {
221             LogDebug(" info file name : " << it->fileName);
222             LogDebug(" info file size : " << it->fileSize);
223             m_targetIt = it;
224             return true;
225         }
226         return false;
227     }
228
229     std::string decryptResource(std::string url)
230     {
231         if (!m_initialized) {
232             LogInfo("not initialize");
233             return std::string();
234         }
235
236         std::string filePath = getFilePath(url);
237         if (filePath != DPL::ToUTF8String(m_targetIt->fileName)) {
238             if (!isNeedDecryption(filePath)) {
239                 return std::string();
240             }
241         }
242
243         std::string decryptString =
244             doDecrypt(DPL::ToUTF8String(m_targetIt->fileName),
245                       m_targetIt->fileSize);
246         if (!decryptString.empty()) {
247             std::string destString = DATA_STRING;
248
249             std::string mimeString =
250                 DPL::ToUTF8String(
251                     MimeTypeUtils::identifyFileMimeType(
252                         DPL::FromUTF8String(url)));
253
254             destString += mimeString;
255             destString += BASE64_STRING;
256
257             decryptString.insert(0, destString);
258         }
259         return decryptString;
260     }
261 };
262
263 DecryptionSupport::DecryptionSupport() :
264     m_impl(new DecryptionSupportImplementation)
265 {
266 }
267
268 DecryptionSupport::~DecryptionSupport()
269 {
270 }
271
272 void DecryptionSupport::initialize(WrtDB::TizenAppId appId)
273 {
274     m_impl->initialize(appId);
275 }
276
277 void DecryptionSupport::deinitialize(void)
278 {
279     m_impl->deinitialize();
280 }
281
282 bool DecryptionSupport::isNeedDecryption(std::string url)
283 {
284     return m_impl->isNeedDecryption(url);
285 }
286
287 std::string DecryptionSupport::decryptResource(std::string url)
288 {
289     return m_impl->decryptResource(url);
290 }
291 }  // namespace InjectedBundle