sync with master
[platform/framework/native/appfw.git] / src / io / FIo_SecureIoUtil.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 /**
19  * @file                FIo_SecureIoUtil.cpp
20  * @brief               This is the implementation file for the %_SecureIoUilt class.
21  *
22  */
23
24 #include <stdio.h>
25 #include <errno.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <fcntl.h>
29 #include <stdlib.h>
30 #include <limits.h>
31 #include <unistd.h>
32 #include <new>
33 #include <unique_ptr.h>
34
35 #include <FBaseString.h>
36 #include <FIoFile.h>
37 #include <FBaseResult.h>
38 #include <FSecSecretKey.h>
39 #include <FSecSecretKeyGenerator.h>
40 #include <FSecCryptoSha1Hash.h>
41 #include <FSecCryptoAesCipher.h>
42
43 #include <FBase_NativeError.h>
44 #include <FBaseSysLog.h>
45 #include <FSec_DeviceKeyGenerator.h>
46 #include <FBase_StringConverter.h>
47 #include <FIo_SecureIoUtil.h>
48 #include <FIo_FileUtil.h>
49 #include <FApp_AppInfo.h>
50
51 using namespace std;
52 using namespace Tizen::Base;
53 using namespace Tizen::Security;
54 using namespace Tizen::Security::Crypto;
55 using namespace Tizen::App;
56
57 namespace Tizen { namespace Io
58 {
59
60 static const int SECURE_IO_4_BITS = 4;
61 static const int SECURE_IO_8_BITS = 8;
62 static const int SECURE_IO_3_BYTES = 3;
63 static const int SECURE_IO_4_BYTES = 4;
64 static const int SECURE_IO_5_BYTES = 5;
65 static const int SECURE_IO_8_BYTES = 8;
66 static const int SECURE_IO_9_BYTES = 9;
67 static const int SECURE_IO_HEX_0F = 0x0f;
68 static const int SECURE_IO_HEX_FC = 0xfc;
69 static const int SECURE_IO_HEX_FD = 0xfd;
70 static const int SECURE_IO_HEX_FE = 0xfe;
71 static const int SECURE_IO_HEX_FF = 0xff;
72 static const int DATABASE_KEY_LENGTH = 16;
73 static const int AES_KEY_LENGTH = 16;
74
75 const char SECURE_FILE_HEADER_STRING[] = {0x74, 0x69, 0x7a, 0x65, 0x6e, 0x20, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x66, 0x69, 0x6c, 0x65};
76 const char SECURE_REG_HEADER_STRING[] = {0x74, 0x69, 0x7a, 0x65, 0x6e, 0x20, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79};
77 static const wchar_t* _CIPHER_INFORMATION = L"CBC/128/NOPADDING";
78
79 ByteBuffer*
80 _SecureIoUtil::GetSecureKeyN(const ByteBuffer* pUserKey)
81 {
82         result r = E_SUCCESS;
83
84         unique_ptr< Tizen::Base::ByteBuffer > pKey(new (std::nothrow) ByteBuffer());
85         SysTryReturn(NID_IO, pKey != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
86
87         r = pKey->Construct(AES_KEY_LENGTH);
88         SysTryReturn(NID_IO, !IsFailed(r), null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
89
90         if (pUserKey->GetRemaining() >= AES_KEY_LENGTH)
91         {
92                 r = pKey->SetArray(pUserKey->GetPointer(), 0, AES_KEY_LENGTH);
93                 SysTryReturn(NID_IO, !IsFailed(r), null, r, "[%s] Propagated.", GetErrorMessage(r));
94
95         }
96
97         else
98         {
99                 int tempLength = pUserKey->GetRemaining();
100                 int loopCount = AES_KEY_LENGTH / tempLength;
101
102                 for(int  i = 0; i < loopCount; i++)
103                 {
104
105                         r = pKey->SetArray(pUserKey->GetPointer(), 0, tempLength);
106                         SysTryReturn(NID_IO, !IsFailed(r), null, r, "[%s] Propagated.", GetErrorMessage(r));
107
108                 }
109
110                 if (AES_KEY_LENGTH % tempLength)
111                 {
112                         r = pKey->SetArray(pUserKey->GetPointer(), 0, (AES_KEY_LENGTH % tempLength));
113                         SysTryReturn(NID_IO, !IsFailed(r), null, r, "[%s] Propagated.", GetErrorMessage(r));
114
115                 }
116
117         }
118
119
120         pKey->Flip();
121
122         SetLastResult(r);
123         return pKey.release();
124 }
125
126 ByteBuffer*
127 _SecureIoUtil::DoCipherAesN(const String transformation, const ByteBuffer& input, const ByteBuffer& key, CipherOperation encMode)
128 {
129         result r = E_SUCCESS;
130         ByteBuffer ivBuffer;
131         AesCipher aesCipher;
132         SecretKeyGenerator secKeyGenerator;
133
134         static byte ivArray[] = {0x3E, 0xB5, 0x01, 0x45, 0xE4, 0xF8, 0x75, 0x3F, 0x08, 0x9D, 0x9F, 0x57, 0x3B, 0x63, 0xEF, 0x4B };
135
136         r = aesCipher.Construct(transformation, encMode);
137         SysTryReturn(NID_IO, !IsFailed(r), null, r, "[%s] Propagated.", GetErrorMessage(r));
138
139         r = ivBuffer.Construct(sizeof(ivArray));
140         SysTryReturn(NID_IO, !IsFailed(r), null, r, "[%s] Propagated.", GetErrorMessage(r));
141
142         r = ivBuffer.SetArray(ivArray, 0, sizeof(ivArray));
143         SysTryReturn(NID_IO, !IsFailed(r), null, r, "[%s] Propagated.", GetErrorMessage(r));
144
145         ivBuffer.Flip();
146
147         r = aesCipher.SetInitialVector(ivBuffer);
148         SysTryReturn(NID_IO, !IsFailed(r), null, r, "[%s] Propagated.", GetErrorMessage(r));
149
150         r = secKeyGenerator.Construct(key);
151         SysTryReturn(NID_IO, !IsFailed(r), null, r, "[%s] Propagated.", GetErrorMessage(r));
152
153         unique_ptr< ISecretKey > pKey(reinterpret_cast< ISecretKey* >(secKeyGenerator.GenerateKeyN()));
154         SysTryReturn(NID_IO, pKey != null, null, GetLastResult(), "[%s]  Failed to generate key.", GetErrorMessage(GetLastResult()));
155
156         r = aesCipher.SetKey(*pKey.get());
157         SysTryReturn(NID_IO, !IsFailed(r), null, r, "[%s] Failed to set secret key.", GetErrorMessage(r));
158
159         unique_ptr< ByteBuffer > pOutBuf(null);
160
161         if (encMode == CIPHER_ENCRYPT)
162         {
163                 pOutBuf = unique_ptr< ByteBuffer >(aesCipher.EncryptN(input));
164         }
165         else
166         {
167                 pOutBuf = unique_ptr< ByteBuffer >(aesCipher.DecryptN(input));
168         }
169
170         SysTryReturn(NID_IO, pOutBuf != null, null, GetLastResult(), "[%s] Failed to decrypt data.", GetErrorMessage(GetLastResult()));
171
172         SetLastResult(E_SUCCESS);
173         return pOutBuf.release();
174 }
175
176 bool
177 _SecureIoUtil::IsEndOfFile(_NormalFile* pNormalFile)
178 {
179         result r = E_SUCCESS;
180         bool eofSet = false;
181         byte flag = 0;
182         int current = pNormalFile->Tell();
183         SysTryReturn(NID_IO, current != -1, false, GetLastResult(), "[%s] Failed to tell in file.", GetErrorMessage(GetLastResult()));
184
185         int ret = pNormalFile->Read(&flag, 1); //ignore ret as we are only looking for EOF.
186         if (GetLastResult() == E_END_OF_FILE && ret == 0)
187         {
188                 eofSet = true;
189         }
190
191         r = pNormalFile->Seek(FILESEEKPOSITION_BEGIN, current);
192         SysTryReturn(NID_IO, !IsFailed(r), false, r, "[%s] Failed to seek in file.", GetErrorMessage(r));
193
194         return eofSet;
195 }
196
197 result
198 _SecureIoUtil::InsertSecureFileHeader(_NormalFile* pNormalFile)
199 {
200         result r = E_SUCCESS;
201         int ret = 0;
202         byte secureHeader[SECURE_FILE_HEADER_SIZE_V1];
203         byte reservedValue[SECURE_IO_STATIC_BIN_LEN] = {0xCA, 0xFE, 0xBE, 0xBE, 0xDA, 0xEF, 0xEB, 0xEB};
204
205         ClearLastResult();
206         r = pNormalFile->Seek(FILESEEKPOSITION_BEGIN, 0);
207         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to seek in file.", GetErrorMessage(r));
208
209         ret = pNormalFile->Read(secureHeader, SECURE_FILE_HEADER_SIZE_V1);
210         if (ret < SECURE_FILE_HEADER_SIZE_V1)
211         {
212                 r = GetLastResult();
213
214                 if (ret == 0 && IsEndOfFile(pNormalFile)) //is true
215                 {
216                         memcpy(secureHeader, SECURE_FILE_HEADER_STRING, SECURE_FILE_HEADER_STRING_SIZE);
217                         memcpy(secureHeader + SECURE_FILE_HEADER_STRING_SIZE, reservedValue, SECURE_IO_STATIC_BIN_LEN);
218                         secureHeader[SECURE_FILE_HEADER_STRING_SIZE + SECURE_IO_STATIC_BIN_LEN] = SECURE_IO_2_BYTES;
219                         secureHeader[SECURE_FILE_HEADER_STRING_SIZE + SECURE_IO_STATIC_BIN_LEN + SECURE_IO_FLAG_SIZE] = 0;
220                         memset(secureHeader + SECURE_FILE_HEADER_STRING_SIZE + SECURE_IO_STATIC_BIN_LEN + SECURE_IO_FLAG_SIZE + SECURE_IO_INDEX_SIZE, 0, SECURE_IO_LOF_SIZE);
221                         memset(secureHeader + SECURE_FILE_HEADER_STRING_SIZE + SECURE_IO_STATIC_BIN_LEN + SECURE_IO_FLAG_SIZE + SECURE_IO_INDEX_SIZE + SECURE_IO_LOF_SIZE, 0, SECURE_IO_LOF_SIZE);
222
223                         r = pNormalFile->Write(secureHeader, SECURE_FILE_HEADER_SIZE_V1);
224                         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] [%s] Failed to write in file.", GetErrorMessage(r));
225
226                 }
227                 else
228                 {
229                         SysLog(NID_IO, "[%s] Failed to read data from file.", GetErrorMessage(r));
230                 }
231         } //Else it means that header is already written
232
233         return r;
234 }
235
236 result
237 _SecureIoUtil::SaveLengthOfFile(_NormalFile* pNormalFile)
238 {
239         result r = E_SUCCESS;
240         int length = 0;
241         byte lengthOfFile[SECURE_IO_LOF_SIZE] = {0, 0, 0, 0};
242
243         ClearLastResult();
244         r = pNormalFile->Seek(FILESEEKPOSITION_END, 0);
245         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to seek in file.", GetErrorMessage(r));
246
247         length = pNormalFile->Tell();
248         SysTryReturn(NID_IO, length != -1, GetLastResult(), GetLastResult(), "[%s] Failed to tell in file.", GetErrorMessage(GetLastResult()));
249
250         r = pNormalFile->Seek(FILESEEKPOSITION_BEGIN, SECURE_FILE_HEADER_STRING_SIZE + SECURE_IO_10_BYTES);
251         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to seek in file.", GetErrorMessage(r));
252
253         if (sizeof(length) != SECURE_IO_LOF_SIZE)
254         {
255                 memcpy(lengthOfFile + SECURE_IO_LOF_SIZE - sizeof(length), &length, sizeof(length));
256         }
257         else
258         {
259                 memcpy(lengthOfFile, &length, SECURE_IO_LOF_SIZE);
260         }
261
262         r = pNormalFile->Write(lengthOfFile, SECURE_IO_LOF_SIZE);
263         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to write in file.", GetErrorMessage(r));
264
265         return r;
266 }
267
268 result
269 _SecureIoUtil::SelectCipherBlock(_NormalFile* pNormalFile, long virtualFilePointer, int* pPosition)
270 {
271         result r = E_SUCCESS;
272         int count = 0;
273         int dataSize = 0;
274         int ret = 0;
275         long blockDataSize = 0;
276         byte secureHeader[SECURE_FILE_HEADER_SIZE_V1] = {0, };
277         byte blockHeader[CIPHER_BLOCK_HEADER_SIZE] = {0, 0, 0};
278         byte* pBlockDataCur = null;
279
280         ClearLastResult();
281         r = pNormalFile->Seek(FILESEEKPOSITION_BEGIN, 0);
282         *pPosition = 0;
283
284         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to seek in file.", GetErrorMessage(r));
285
286         ret = pNormalFile->Read(secureHeader, SECURE_FILE_HEADER_SIZE_V1);
287         if (ret < SECURE_FILE_HEADER_SIZE_V1)
288         {
289                 r = GetLastResult();
290
291                 if (ret == 0 && IsEndOfFile(pNormalFile))
292                 {
293                         return E_SUCCESS;
294                 }
295
296                 SysLog(NID_IO, "[%s] Failed to read data from file.", GetErrorMessage(r));
297                 return r;
298         }
299
300         //read 1byte to check padding size
301         while (true)
302         {
303                 r = pNormalFile->Seek(FILESEEKPOSITION_BEGIN, count * (CIPHER_BLOCK_SIZE + CIPHER_BLOCK_HEADER_SIZE) + SECURE_FILE_HEADER_SIZE_V1);
304                 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to seek in file.", GetErrorMessage(r));
305
306                 ret = pNormalFile->Read(blockHeader, CIPHER_BLOCK_HEADER_SIZE);
307                 if (ret < CIPHER_BLOCK_HEADER_SIZE) //less data read
308                 {
309                         r = GetLastResult();
310
311                         if (ret == 0 && IsEndOfFile(pNormalFile))
312                         {
313                                 return E_SUCCESS;
314                         }
315
316                         SysLog(NID_IO, "[%s] Failed to read data from file", GetErrorMessage(r));
317                         return r;
318                 }
319
320
321                 blockDataSize = 0;
322                 pBlockDataCur = (byte*) (&blockDataSize);
323                 *pBlockDataCur = blockHeader[SECURE_IO_2_BYTES];
324                 *(pBlockDataCur + 1) = blockHeader[1];
325                 *(pBlockDataCur + SECURE_IO_2_BYTES) = blockHeader[0];
326
327                 if (virtualFilePointer <= dataSize + blockDataSize)
328                 {
329                         *pPosition = virtualFilePointer - dataSize;
330                         if (*pPosition == CIPHER_BLOCK_SIZE)
331                         {
332                                 r = pNormalFile->Seek(FILESEEKPOSITION_CURRENT, CIPHER_BLOCK_SIZE);
333                                 *pPosition = 0;
334                         }
335                         else
336                         {
337                                 r = pNormalFile->Seek(FILESEEKPOSITION_CURRENT, -CIPHER_BLOCK_HEADER_SIZE);
338                         }
339
340
341                         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to seek in file.", GetErrorMessage(r));
342                         break;
343                 }
344                 else
345                 {
346                         dataSize = dataSize + blockDataSize;
347                 }
348
349                 count++;
350         }
351
352         return E_SUCCESS;
353 }
354
355 bool
356 _SecureIoUtil::DetectNewLine(byte* pData, int readSize, int preReadSize, int* pTerminationCur, int* newLineSize)
357 {
358         int count = 0;
359
360         *newLineSize = 0;
361         ClearLastResult();
362         for (count = preReadSize; count < readSize; count++)
363         {
364                 if (pData[count] == '\r' && pData[count + 1] == '\n')
365                 {
366                         *pTerminationCur = count;
367                         *newLineSize = SECURE_IO_2_BYTES;
368                         return true;
369                 }
370
371                 if (pData[count] == '\n')
372                 {
373                         *pTerminationCur = count;
374                         *newLineSize = 1;
375                         return true;
376                 }
377         }
378
379         return false;
380 }
381
382 result
383 _SecureIoUtil::MakeCipherBlock(byte* pData, int dataSize, byte** ppEncryptedData, int* pEncryptedDataSize, const ByteBuffer& key)
384 {
385         result r = E_SUCCESS;
386         int blockCount = 0;
387         int lastDataSize = 0;
388         int tempSize = 0;
389         int inputSize = 0;
390         byte* pTempRealloc = null;
391         byte* pTempEncryptedData = null;
392         ByteBuffer input;
393
394         SysTryReturnResult(NID_SEC, dataSize > 0, E_INVALID_ARG, "Input data is not valid.");
395
396         ClearLastResult();
397         *pEncryptedDataSize = 0;
398
399         blockCount = dataSize / CIPHER_BLOCK_SIZE;
400         lastDataSize = dataSize % CIPHER_BLOCK_SIZE;
401         if (lastDataSize != 0)
402         {
403                 blockCount = blockCount + 1;
404         }
405         else
406         {
407                 lastDataSize = CIPHER_BLOCK_SIZE;
408         }
409
410         for (int i = 0; i < blockCount; i++)
411         {
412                 if (i == blockCount - 1)
413                 {
414                         tempSize = lastDataSize;
415                 }
416                 else
417                 {
418                         tempSize = CIPHER_BLOCK_SIZE;
419                 }
420
421                 inputSize = tempSize;
422
423                 if (tempSize % ONE_BLOCK_SIZE != 0)
424                 {
425                         tempSize = (tempSize / ONE_BLOCK_SIZE) * ONE_BLOCK_SIZE + ONE_BLOCK_SIZE;
426                 }
427
428                 r = input.Construct(tempSize);
429                 SysTryCatch(NID_IO, !IsFailed(r), , r, "[%s] Propagated.", GetErrorMessage(r));
430
431                 r = input.SetArray((byte*) (pData + i * CIPHER_BLOCK_SIZE), 0, inputSize);
432                 SysTryCatch(NID_IO, !IsFailed(r), , r, "[%s] Propagated.", GetErrorMessage(r));
433
434                 if (inputSize < tempSize)
435                 {
436                         unique_ptr< char[] > pFill(new (std::nothrow) char[tempSize - inputSize]);
437                         SysTryCatch(NID_IO, pFill != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
438
439                         memset(pFill.get(), 0, tempSize - inputSize);
440
441                         r = input.SetArray(reinterpret_cast< byte* >(pFill.get()), 0, tempSize - inputSize);
442                         SysTryCatch(NID_IO, !IsFailed(r), , r, "[%s] Propagated.", GetErrorMessage(r));
443
444                 }
445
446                 input.Flip();
447
448                 unique_ptr< ByteBuffer > pEncryptedBuffer(DoCipherAesN(_CIPHER_INFORMATION, input, key, CIPHER_ENCRYPT));
449                 SysTryCatch(NID_IO, pEncryptedBuffer != null, r = E_IO, E_IO, "[E_IO] Failed to encrypt data.");
450
451                 pTempEncryptedData = const_cast< byte* >(pEncryptedBuffer->GetPointer());
452                 SysTryCatch(NID_IO, pTempEncryptedData != null, , r, "[%s] Failed to get encrypted data.", GetErrorMessage(r));
453
454                 pTempRealloc = (byte*) new (std::nothrow) byte[*pEncryptedDataSize + tempSize + CIPHER_BLOCK_HEADER_SIZE];
455                 SysTryCatch(NID_IO, pTempRealloc != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
456
457                 if (*ppEncryptedData)
458                 {
459                         memcpy(pTempRealloc, *ppEncryptedData, *pEncryptedDataSize);
460
461                         delete[]* ppEncryptedData;
462                         *ppEncryptedData = null;
463                 }
464
465                 *ppEncryptedData = pTempRealloc;
466
467                 if (i == blockCount - 1)
468                 {
469
470                         *(*ppEncryptedData + i * (CIPHER_BLOCK_SIZE + CIPHER_BLOCK_HEADER_SIZE) + SECURE_IO_2_BYTES) \
471                                         = (byte) (lastDataSize & SECURE_IO_HEX_FF);
472                         *(*ppEncryptedData + i * (CIPHER_BLOCK_SIZE + CIPHER_BLOCK_HEADER_SIZE) + 1) \
473                                         = (byte) ((lastDataSize >> SECURE_IO_8_BITS) & SECURE_IO_HEX_FF);
474                         *(*ppEncryptedData + i * (CIPHER_BLOCK_SIZE + CIPHER_BLOCK_HEADER_SIZE)) \
475                                         = (byte) ((lastDataSize >> (SECURE_IO_8_BITS * SECURE_IO_2_BYTES)) & SECURE_IO_HEX_FF);
476                 }
477                 else
478                 {
479                         *(*ppEncryptedData + i * (CIPHER_BLOCK_SIZE + CIPHER_BLOCK_HEADER_SIZE) + SECURE_IO_2_BYTES) \
480                                         = (byte) (CIPHER_BLOCK_SIZE & SECURE_IO_HEX_FF);
481                         *(*ppEncryptedData + i * (CIPHER_BLOCK_SIZE + CIPHER_BLOCK_HEADER_SIZE) + 1) \
482                                         = (byte) ((CIPHER_BLOCK_SIZE >> SECURE_IO_8_BITS) & SECURE_IO_HEX_FF);
483                         *(*ppEncryptedData + i * (CIPHER_BLOCK_SIZE + CIPHER_BLOCK_HEADER_SIZE)) \
484                                         = (byte) ((CIPHER_BLOCK_SIZE >> (SECURE_IO_8_BITS * SECURE_IO_2_BYTES)) & SECURE_IO_HEX_FF);
485                 }
486
487                 memcpy(*ppEncryptedData + i * (CIPHER_BLOCK_SIZE + CIPHER_BLOCK_HEADER_SIZE) + CIPHER_BLOCK_HEADER_SIZE, pTempEncryptedData, tempSize);
488                 *pEncryptedDataSize = *pEncryptedDataSize + tempSize + CIPHER_BLOCK_HEADER_SIZE;
489         }
490
491         CATCH:
492
493         if (IsFailed(r))
494         {
495                 *pEncryptedDataSize = 0;
496                 delete[]* ppEncryptedData;
497                 *ppEncryptedData = null;
498         }
499
500         return r;
501 }
502
503 result
504 _SecureIoUtil::WriteDataInCipherBlock(_NormalFile* pNormalFile, int dataPosition, bool eofSet, int dataSize, byte* pData, const ByteBuffer& key)
505 {
506         result r = E_SUCCESS;
507         int availableSize = 0;
508         int encryptedDataSize = 0;
509         int ret = 0;
510         long blockDataSize = 0;
511         long tempBlockDataSize = 0;
512         bool isFirstBlockSet = false;
513         byte* pBlockDataCur = null;
514         byte* pCipherBlockData = null;
515         byte* pDataPos = null;
516         byte blockHeader[CIPHER_BLOCK_HEADER_SIZE] = {0, 0, 0};
517         ByteBuffer input;
518
519         pDataPos = pData;
520
521         ClearLastResult();
522         while (true)
523         {
524                 if (eofSet != false && dataPosition == 0)
525                 {
526                         r = MakeCipherBlock(pDataPos, dataSize, &pCipherBlockData, &encryptedDataSize, key);
527                         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to make cipher block for file.", GetErrorMessage(r));
528
529                         unique_ptr< byte[] > pEncryptedBlockData(pCipherBlockData);
530                         pCipherBlockData = null;
531
532                         SysTryReturn(NID_IO, pEncryptedBlockData != null, r, r, "[%s] Failed to make cipher block for file.", GetErrorMessage(r));
533
534                         r = pNormalFile->Write(pEncryptedBlockData.get(), encryptedDataSize);
535                         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to make cipher block for file.", GetErrorMessage(r));
536                         break;
537                 }
538                 else
539                 {
540                         ret = pNormalFile->Read(blockHeader, CIPHER_BLOCK_HEADER_SIZE);
541                         if (ret < CIPHER_BLOCK_HEADER_SIZE)
542                         {
543                                 r = GetLastResult();
544
545                                 if (ret == 0 && IsEndOfFile(pNormalFile))
546                                 {
547                                         r = E_END_OF_FILE;
548                                 }
549
550                                 SysLog(NID_IO, "[%s] Failed to read data from file.", GetErrorMessage(r));
551                                 return r;
552                         }
553
554                         blockDataSize = 0;
555                         pBlockDataCur = (byte*) (&blockDataSize);
556                         *pBlockDataCur = blockHeader[SECURE_IO_2_BYTES];
557                         *(pBlockDataCur + 1) = blockHeader[1];
558                         *(pBlockDataCur + SECURE_IO_2_BYTES) = blockHeader[0];
559
560                         unique_ptr< byte[] > pTempEncryptedData(new (std::nothrow) byte[CIPHER_BLOCK_SIZE]);
561                         SysTryReturnResult(NID_IO, pTempEncryptedData != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
562
563                         memset(pTempEncryptedData.get(), 0, CIPHER_BLOCK_SIZE);
564
565                         if (blockDataSize % ONE_BLOCK_SIZE != 0)
566                         {
567                                 tempBlockDataSize = blockDataSize + ONE_BLOCK_SIZE - blockDataSize % ONE_BLOCK_SIZE;
568                         }
569                         else
570                         {
571                                 tempBlockDataSize = blockDataSize;
572                         }
573
574                         ret = pNormalFile->Read(pTempEncryptedData.get(), tempBlockDataSize);
575                         if (ret < tempBlockDataSize)
576                         {
577                                 r = GetLastResult();
578
579                                 if (ret == 0 && IsEndOfFile(pNormalFile))
580                                 {
581                                         r = E_END_OF_FILE;
582                                 }
583
584                                 SysLog(NID_IO, "[%s] Failed to read data from file.", GetErrorMessage(r));
585                                 return r;
586                         }
587
588                         r = input.Construct(tempBlockDataSize);
589                         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
590
591                         r = input.SetArray(pTempEncryptedData.get(), 0, tempBlockDataSize);
592
593                         pTempEncryptedData.reset(null);
594
595                         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
596
597                         input.Flip();
598
599                         unique_ptr< ByteBuffer > pDecryptedBuffer(DoCipherAesN(_CIPHER_INFORMATION, input, key, CIPHER_DECRYPT));
600                         SysTryReturn(NID_IO, pDecryptedBuffer != null, E_IO, E_IO, "[E_IO] Failed to encrypt data.");
601
602                         unique_ptr< byte[] > pDecryptedBlockData(new (std::nothrow) byte[tempBlockDataSize]);
603                         SysTryReturnResult(NID_IO, pDecryptedBlockData != null, E_OUT_OF_MEMORY, "The memory is insufficient");
604
605                         r = pDecryptedBuffer->GetArray(reinterpret_cast< byte* >(pDecryptedBlockData.get()), 0, tempBlockDataSize);
606                         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to get decrypted buffer.", GetErrorMessage(r));
607
608                         pDecryptedBuffer->Flip();
609
610                         pDecryptedBuffer.reset(null);
611
612                         if (isFirstBlockSet == false)
613                         {
614                                 availableSize = CIPHER_BLOCK_SIZE - dataPosition;
615                                 if (availableSize >= dataSize)
616                                 {
617                                         if (tempBlockDataSize < dataPosition + dataSize)
618                                         {
619                                                 unique_ptr< byte[] > pTempRealloc(new (std::nothrow) byte[dataPosition + dataSize]);
620                                                 SysTryReturnResult(NID_IO, pTempRealloc != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
621
622                                                 memcpy(pTempRealloc.get(), pDecryptedBlockData.get(), tempBlockDataSize);
623
624                                                 pDecryptedBlockData.reset(null);
625                                                 pDecryptedBlockData = move(pTempRealloc);
626                                         }
627
628                                         memcpy(reinterpret_cast< byte* >(pDecryptedBlockData.get()) + dataPosition, pDataPos, dataSize);
629
630                                         if (blockDataSize < dataPosition + dataSize)
631                                         {
632                                                 r = MakeCipherBlock(pDecryptedBlockData.get(), dataPosition + dataSize, &pCipherBlockData, &encryptedDataSize, key);
633                                         }
634                                         else
635                                         {
636                                                 r = MakeCipherBlock(pDecryptedBlockData.get(), blockDataSize, &pCipherBlockData, &encryptedDataSize, key);
637                                         }
638
639                                         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s]  Failed to make cipher block for file.", GetErrorMessage(r));
640
641                                         unique_ptr< byte[] > pEncryptedBlockData(pCipherBlockData);
642                                         pCipherBlockData = null;
643
644                                         SysTryReturn(NID_IO, pEncryptedBlockData != null, r, r, "[%s] Failed to make cipher block for file.", GetErrorMessage(r));
645
646                                         r = pNormalFile->Seek(FILESEEKPOSITION_CURRENT, -(tempBlockDataSize + CIPHER_BLOCK_HEADER_SIZE));
647                                         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to seek in file.", GetErrorMessage(r));
648
649                                         r = pNormalFile->Write(pEncryptedBlockData.get(), encryptedDataSize);
650                                         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to write in file.", GetErrorMessage(r));
651
652
653                                         break;
654                                 }
655                                 else  //(availableSize < dataSize)
656                                 {
657                                         if (tempBlockDataSize < dataPosition + availableSize)
658                                         {
659                                                 unique_ptr< byte[] > pTempRelloc(new (std::nothrow) byte[dataPosition + availableSize]);
660                                                 SysTryReturnResult(NID_IO, pTempRelloc != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
661
662                                                 memcpy(pTempRelloc.get(), pDecryptedBlockData.get(), tempBlockDataSize);
663
664                                                 pDecryptedBlockData.reset(null);
665                                                 pDecryptedBlockData = move(pTempRelloc);
666                                         }
667
668                                         memcpy(reinterpret_cast< byte* >(pDecryptedBlockData.get()) + dataPosition, pDataPos, availableSize);
669
670                                         pDataPos = pDataPos + availableSize;
671                                         dataSize = dataSize - availableSize;
672
673                                         r = MakeCipherBlock(pDecryptedBlockData.get(), CIPHER_BLOCK_SIZE, &pCipherBlockData, &encryptedDataSize, key);
674                                         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s]  Failed to make cipher block for file.", GetErrorMessage(r));
675
676                                         unique_ptr< byte[] > pEncryptedBlockData(pCipherBlockData);
677                                         pCipherBlockData = null;
678                                         SysTryReturn(NID_IO, pEncryptedBlockData != null, r, r, "[%s] Failed to make cipher block for file.", GetErrorMessage(r));
679
680                                         r = pNormalFile->Seek(FILESEEKPOSITION_CURRENT, -(tempBlockDataSize + CIPHER_BLOCK_HEADER_SIZE));
681                                         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to seek in file.", GetErrorMessage(r));
682
683                                         r = pNormalFile->Write(pEncryptedBlockData.get(), encryptedDataSize);
684                                         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to write in file.", GetErrorMessage(r));
685
686
687                                         dataPosition = 0;
688                                 }
689
690                                 isFirstBlockSet = true;
691                         }
692                         else
693                         {
694                                 availableSize = CIPHER_BLOCK_SIZE;
695                                 if (availableSize >= dataSize)
696                                 {
697                                         if (tempBlockDataSize < dataSize)
698                                         {
699                                                 unique_ptr< byte[] > pTempRelloc(new (std::nothrow) byte[dataSize]);
700                                                 SysTryReturnResult(NID_IO, pTempRelloc != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
701
702                                                 memcpy(pTempRelloc.get(), pDecryptedBlockData.get(), tempBlockDataSize);
703
704                                                 pDecryptedBlockData.reset(null);
705                                                 pDecryptedBlockData = move(pTempRelloc);
706                                         }
707
708                                         memcpy(pDecryptedBlockData.get(), pDataPos, dataSize);
709
710                                         if (blockDataSize < dataPosition + dataSize)
711                                         {
712                                                 r = MakeCipherBlock(pDecryptedBlockData.get(), dataSize, &pCipherBlockData, &encryptedDataSize, key);
713                                         }
714                                         else
715                                         {
716                                                 r = MakeCipherBlock(pDecryptedBlockData.get(), blockDataSize, &pCipherBlockData, &encryptedDataSize, key);
717                                         }
718
719                                         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to make cipher block for file.", GetErrorMessage(r));
720
721                                         unique_ptr< byte[] > pEncryptedBlockData(pCipherBlockData);
722                                         pCipherBlockData = null;
723
724                                         SysTryReturn(NID_IO, pEncryptedBlockData != null, r, r, "[%s] Failed to make cipher block for file.", GetErrorMessage(r));
725
726                                         r = pNormalFile->Seek(FILESEEKPOSITION_CURRENT, -(tempBlockDataSize + CIPHER_BLOCK_HEADER_SIZE));
727                                         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to seek in file.", GetErrorMessage(r));
728
729                                         r = pNormalFile->Write(pEncryptedBlockData.get(), encryptedDataSize);
730                                         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to write in file.", GetErrorMessage(r));
731
732                                         break;
733                                 }
734                                 else  //availableSize < dataSize
735                                 {
736                                         if (tempBlockDataSize < availableSize)
737                                         {
738                                                 unique_ptr< byte[] > pTempRelloc(new (std::nothrow) byte[availableSize]);
739                                                 SysTryReturnResult(NID_IO, pTempRelloc != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
740
741                                                 memcpy(pTempRelloc.get(), pDecryptedBlockData.get(), tempBlockDataSize);
742
743                                                 pDecryptedBlockData.reset(null);
744                                                 pDecryptedBlockData = move(pTempRelloc);
745                                         }
746
747                                         memcpy(pDecryptedBlockData.get(), pDataPos, availableSize);
748
749                                         pDataPos = pDataPos + availableSize;
750                                         dataSize = dataSize - availableSize;
751
752                                         r = MakeCipherBlock(pDecryptedBlockData.get(), CIPHER_BLOCK_SIZE, &pCipherBlockData, &encryptedDataSize, key);
753                                         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s]  Failed to make cipher block for file.", GetErrorMessage(r));
754
755                                         unique_ptr< byte[] > pEncryptedBlockData(pCipherBlockData);
756                                         pCipherBlockData = null;
757
758                                         SysTryReturn(NID_IO, pEncryptedBlockData != null, r, r, "[%s] Failed to make cipher block for file.", GetErrorMessage(r));
759
760                                         r = pNormalFile->Seek(FILESEEKPOSITION_CURRENT, -(tempBlockDataSize + CIPHER_BLOCK_HEADER_SIZE));
761                                         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to seek in file.", GetErrorMessage(r));
762
763                                         r = pNormalFile->Write(pEncryptedBlockData.get(), encryptedDataSize);
764                                         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to write in file.", GetErrorMessage(r));
765
766                                         dataPosition = 0;
767                                 }
768                         }
769                 }
770
771                 eofSet = IsEndOfFile(pNormalFile);
772         }
773
774         return E_SUCCESS;
775 }
776
777 result
778 _SecureIoUtil::ReadDataFromCipherBlock(_NormalFile* pNormalFile, int dataPosition, int bufferSize, byte* pData, _DataFormat dataMode, int* readItems, const ByteBuffer& key)
779 {
780         result r = E_SUCCESS;
781         int readingSize = 0;
782         int tempSize = 0;
783         int terminationCur = 0;
784         bool eofSet = false;
785         int newLineSize = 0;
786         int ret = 0;
787         long blockDataSize = 0;
788         long tempBlockDataSize = 0;
789         byte* pBlockDataCur = null;
790         byte* pDecryptedBlockData = null;
791         byte blockHeader[CIPHER_BLOCK_HEADER_SIZE] = {0, 0, 0};
792         ByteBuffer input;
793
794         ClearLastResult();
795         ret = pNormalFile->Read(blockHeader, CIPHER_BLOCK_HEADER_SIZE);
796         if (ret < CIPHER_BLOCK_HEADER_SIZE)
797         {
798                 r = GetLastResult();
799
800                 if (ret == 0 && IsEndOfFile(pNormalFile))
801                 {
802                         r = E_END_OF_FILE;
803                 }
804
805                 SysLog(NID_IO, "[%s] Failed to read data from file.", GetErrorMessage(r));
806                 return r;
807         }
808
809         blockDataSize = 0;
810         pBlockDataCur = (byte*) (&blockDataSize);
811         *pBlockDataCur = blockHeader[SECURE_IO_2_BYTES];
812         *(pBlockDataCur + 1) = blockHeader[1];
813         *(pBlockDataCur + SECURE_IO_2_BYTES) = blockHeader[0];
814
815         unique_ptr< byte[] > pBlockData(new (std::nothrow) byte[CIPHER_BLOCK_SIZE]);
816         SysTryReturnResult(NID_IO, pBlockData != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
817
818         memset(pBlockData.get(), 0, CIPHER_BLOCK_SIZE);
819
820         if (blockDataSize % ONE_BLOCK_SIZE != 0)
821         {
822                 tempBlockDataSize = blockDataSize + ONE_BLOCK_SIZE - blockDataSize % ONE_BLOCK_SIZE;
823         }
824         else
825         {
826                 tempBlockDataSize = blockDataSize;
827         }
828
829         ret = pNormalFile->Read(pBlockData.get(), tempBlockDataSize);
830         if (ret < tempBlockDataSize)
831         {
832                 r = GetLastResult();
833
834                 if (ret == 0 && IsEndOfFile(pNormalFile))
835                 {
836                         r = E_END_OF_FILE;
837                 }
838
839                 SysLog(NID_IO, "[%s] Failed to read data from file.", GetErrorMessage(r));
840                 return r;
841         }
842
843         readingSize = blockDataSize - dataPosition;
844         SysTryReturn(NID_IO, readingSize != 0, r = E_END_OF_FILE, r, "[%s] Failed to get positive value of readingSize.", GetErrorMessage(r));
845
846         r = input.Construct(tempBlockDataSize);
847         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
848
849         r = input.SetArray(pBlockData.get(), 0, tempBlockDataSize);
850         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
851
852         input.Flip();
853
854         unique_ptr< ByteBuffer > pDecryptedBuffer(DoCipherAesN(_CIPHER_INFORMATION, input, key, CIPHER_DECRYPT));
855         SysTryReturn(NID_IO, pDecryptedBuffer != null, E_IO, E_IO, "[E_IO] Failed to encrypt data.");
856
857         pDecryptedBlockData = const_cast< byte* >(pDecryptedBuffer->GetPointer());
858         SysTryReturn(NID_IO, pDecryptedBlockData, r, r, "[%s] Failed to get encrypted data.", GetErrorMessage(r));
859
860         unique_ptr< byte[] > pTemp(new (std::nothrow) byte[readingSize]);
861         SysTryReturnResult(NID_IO, pTemp != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
862
863         memcpy(pTemp.get(), pDecryptedBlockData + dataPosition, readingSize);
864
865         pDecryptedBuffer.reset(null);
866
867         while (true)
868         {
869                 eofSet = IsEndOfFile(pNormalFile);
870
871                 if (dataMode == DATA_FORMAT_BYTE && (readingSize >= bufferSize))
872                 {
873                         memcpy(pData, pTemp.get(), bufferSize);
874                         *readItems = bufferSize;
875                         break;
876                 }
877                 else if (dataMode == DATA_FORMAT_STRING && ((readingSize >= bufferSize) || DetectNewLine(pTemp.get(), readingSize, tempSize, &terminationCur, &newLineSize)))
878                 {
879                         if (terminationCur != 0)
880                         {
881                                 memcpy(pData, pTemp.get(), terminationCur);
882                                 *(pData + terminationCur) = '\n';
883                                 *readItems = terminationCur + newLineSize;
884                         }
885                         else
886                         {
887                                 memcpy(pData, pTemp.get(), bufferSize);
888                                 *readItems = bufferSize;
889                         }
890                         break;
891                 }
892                 else if (eofSet && (readingSize < bufferSize))
893                 {
894                         memcpy(pData, pTemp.get(), readingSize);
895                         *readItems = readingSize;
896                         break;
897                 }
898                 else
899                 {
900                         ret = pNormalFile->Read(blockHeader, CIPHER_BLOCK_HEADER_SIZE);
901                         if (ret < CIPHER_BLOCK_HEADER_SIZE)
902                         {
903                                 r = GetLastResult();
904
905                                 if (ret == 0 && IsEndOfFile(pNormalFile))
906                                 {
907                                         r = E_SUCCESS;
908                                         continue;
909                                 }
910
911                                 SysLog(NID_IO, "[%s] Failed to read data from file.", GetErrorMessage(r));
912                                 return r;
913                         }
914
915                         blockDataSize = 0;
916                         pBlockDataCur = (byte*) (&blockDataSize);
917                         *pBlockDataCur = blockHeader[SECURE_IO_2_BYTES];
918                         *(pBlockDataCur + 1) = blockHeader[1];
919                         *(pBlockDataCur + SECURE_IO_2_BYTES) = blockHeader[0];
920
921                         memset(pBlockData.get(), 0, CIPHER_BLOCK_SIZE);
922
923                         if (blockDataSize % ONE_BLOCK_SIZE != 0)
924                         {
925                                 tempBlockDataSize = blockDataSize + ONE_BLOCK_SIZE - blockDataSize % ONE_BLOCK_SIZE;
926                         }
927                         else
928                         {
929                                 tempBlockDataSize = blockDataSize;
930                         }
931
932                         ret = pNormalFile->Read(pBlockData.get(), tempBlockDataSize);
933                         if (ret < tempBlockDataSize)
934                         {
935                                 r = GetLastResult();
936
937                                 if (ret == 0 && IsEndOfFile(pNormalFile))
938                                 {
939                                         r = E_END_OF_FILE;
940                                 }
941
942                                 SysLog(NID_IO, "[%s] Failed to read data from file.", GetErrorMessage(r));
943                                 return r;
944                         }
945
946                         r = input.Construct(tempBlockDataSize);
947                         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
948
949                         r = input.SetArray(pBlockData.get(), 0, tempBlockDataSize);
950                         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
951
952                         input.Flip();
953
954                         unique_ptr< ByteBuffer > pDecryptedNextBuffer(DoCipherAesN(_CIPHER_INFORMATION, input, key, CIPHER_DECRYPT));
955                         SysTryReturn(NID_IO, pDecryptedNextBuffer != null, E_IO, E_IO, "[E_IO] Failed to encrypt data.");
956
957                         pDecryptedBlockData = const_cast< byte* >(pDecryptedNextBuffer->GetPointer());
958                         SysTryReturn(NID_IO, pDecryptedBlockData != null, r, r, "[%s] Failed to get encrypted data.", GetErrorMessage(r));
959
960                         tempSize = readingSize;
961                         readingSize = readingSize + blockDataSize;
962
963                         unique_ptr< byte[] > pTempRealloc(new (std::nothrow) byte[readingSize]);
964                         SysTryReturnResult(NID_IO, pTempRealloc != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
965
966                         memcpy(pTempRealloc.get(), pTemp.get(), tempSize);
967
968                         pTemp.reset(null);
969                         pTemp = move(pTempRealloc);
970
971                         memcpy(reinterpret_cast< byte* >(pTemp.get()) + tempSize, pDecryptedBlockData, blockDataSize);
972                 }
973
974         }
975
976         return E_SUCCESS;
977 }
978
979 result
980 _SecureIoUtil::GetDataLengh(_NormalFile* pNormalFile, long int* dataLength)
981 {
982         result r = E_SUCCESS;
983         int ret = 0;
984         long blockDataSize = 0;
985         byte* pBlockDataCur = null;
986         byte secureHeader[SECURE_FILE_HEADER_SIZE_V1];
987         byte blockHeader[CIPHER_BLOCK_HEADER_SIZE] = {0, 0, 0};
988
989         *dataLength = 0;
990
991         ClearLastResult();
992         r = pNormalFile->Seek(FILESEEKPOSITION_BEGIN, 0);
993         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to seek in file.", GetErrorMessage(r));
994
995         ret = pNormalFile->Read(secureHeader, SECURE_FILE_HEADER_SIZE_V1);
996         if (ret < SECURE_FILE_HEADER_SIZE_V1)
997         {
998                 r = GetLastResult();
999
1000                 if (ret == 0 && IsEndOfFile(pNormalFile))
1001                 {
1002                         return E_SUCCESS;
1003                 }
1004
1005                 SysLog(NID_IO, "[%s] Failed to seek in file", GetErrorMessage(r));
1006                 return r;
1007         }
1008         while (true)
1009         {
1010                 ret = pNormalFile->Read(blockHeader, CIPHER_BLOCK_HEADER_SIZE);
1011                 if (ret < CIPHER_BLOCK_HEADER_SIZE)
1012                 {
1013                         r = GetLastResult();
1014
1015                         if (ret == 0 && IsEndOfFile(pNormalFile))
1016                         {
1017                                 r = E_SUCCESS;
1018                                 break;
1019                         }
1020
1021                         SysLog(NID_IO, "[%s] Failed to read data from file.", GetErrorMessage(r));
1022                         return r;
1023                 }
1024
1025                 blockDataSize = 0;
1026                 pBlockDataCur = (byte*) (&blockDataSize);
1027                 *pBlockDataCur = blockHeader[SECURE_IO_2_BYTES];
1028                 *(pBlockDataCur + 1) = blockHeader[1];
1029                 *(pBlockDataCur + SECURE_IO_2_BYTES) = blockHeader[0];
1030                 *dataLength = *dataLength + blockDataSize;
1031
1032                 if (blockDataSize % ONE_BLOCK_SIZE != 0)
1033                 {
1034                         r = pNormalFile->Seek(FILESEEKPOSITION_CURRENT, blockDataSize + ONE_BLOCK_SIZE - blockDataSize % ONE_BLOCK_SIZE);
1035                 }
1036                 else
1037                 {
1038                         r = pNormalFile->Seek(FILESEEKPOSITION_CURRENT, blockDataSize);
1039                 }
1040
1041                 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to seek in file.", GetErrorMessage(r));
1042
1043         }
1044
1045         return pNormalFile->Seek(FILESEEKPOSITION_END, 0);
1046 }
1047
1048 result
1049 _SecureIoUtil::CheckSecureFileHeader(const Tizen::Base::String& filePath, const ByteBuffer* pSecretKey)
1050 {
1051         result r = E_SUCCESS;
1052         int ret = 0;
1053         _NormalFile normalFile;
1054         byte secureFileHeader[SECURE_FILE_HEADER_SIZE_V1];
1055         byte reservedValue[SECURE_IO_STATIC_BIN_LEN] = {0xCA, 0xFE, 0xBE, 0xBE, 0xDA, 0xEF, 0xEB, 0xEB};
1056
1057         ClearLastResult();
1058
1059         r = normalFile.Construct(filePath, "r");
1060         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to call constuct.", GetErrorMessage(r));
1061
1062         ret = normalFile.Read(secureFileHeader, SECURE_FILE_HEADER_SIZE_V1);
1063         if (ret < SECURE_FILE_HEADER_SIZE_V1)
1064         {
1065                 r  = GetLastResult();
1066                 if (IsEndOfFile(&normalFile))
1067                 {
1068                         if (ret && pSecretKey)
1069                         {
1070                                 return E_INVALID_ARG;
1071                         }
1072                         else
1073                         {
1074                                 return E_SUCCESS;
1075                         }
1076                 }
1077                 return r;
1078         }
1079
1080         //check if the file is encrypted file. (in normal and secure mode)
1081         ret = memcmp(secureFileHeader, SECURE_FILE_HEADER_STRING, SECURE_FILE_HEADER_STRING_SIZE);
1082         ret |= memcmp(secureFileHeader + SECURE_FILE_HEADER_STRING_SIZE, reservedValue, SECURE_IO_STATIC_BIN_LEN);
1083
1084         SysTryReturnResult(NID_IO, !(ret && pSecretKey), E_INVALID_ARG, "Failed to match secure header in file.");
1085
1086         return E_SUCCESS;
1087 }
1088
1089 result
1090 _SecureIoUtil::SetRegistryFlag(void* pFileSecure, _FlagState flag)
1091 {
1092         result r = E_SUCCESS;
1093         int readItems = 0;
1094         int current = 0;
1095         byte currentFlag = 0;
1096         _FileImpl* pFile = (_FileImpl*) pFileSecure;
1097
1098         ClearLastResult();
1099         current = pFile->Tell();
1100         SysTryReturn(NID_IO, current != -1, GetLastResult(), GetLastResult(), "[%s] Tell file has failed.", GetErrorMessage(GetLastResult()));
1101
1102         r = pFile->Seek(FILESEEKPOSITION_BEGIN, SECURE_REG_HEADER_STRING_SIZE + SECURE_IO_STATIC_BIN_LEN);
1103         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to seek in file.", GetErrorMessage(r));
1104
1105         readItems = pFile->Read(&currentFlag, 1);
1106         SysTryReturn(NID_IO, readItems == 1, r = E_INVALID_STATE, E_INVALID_STATE, "[E_INVALID_STATE] Tell file has failed.");
1107
1108         if (flag == FLAG_STATE_CVF)
1109         {
1110                 currentFlag = currentFlag | SECURE_IO_2_BYTES;
1111                 currentFlag = currentFlag & SECURE_IO_HEX_FE;
1112         }
1113         else if (flag == FLAG_STATE_CTF)
1114         {
1115                 currentFlag = currentFlag | 1;
1116                 currentFlag = currentFlag & SECURE_IO_HEX_FD;
1117         }
1118         else if (flag == FLAG_STATE_CVF_CTF)
1119         {
1120                 currentFlag = currentFlag | SECURE_IO_3_BYTES;
1121         }
1122         else if (flag == FLAG_STATE_NONE)
1123         {
1124                 currentFlag = currentFlag & SECURE_IO_HEX_FC;
1125         }
1126         else
1127         {
1128                 return E_INVALID_STATE;
1129         }
1130
1131         r = pFile->Seek(FILESEEKPOSITION_BEGIN, SECURE_REG_HEADER_STRING_SIZE + SECURE_IO_STATIC_BIN_LEN);
1132         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to seek in file.", GetErrorMessage(r));
1133
1134         r = pFile->Write(&currentFlag, 1);
1135         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to write data in file.", GetErrorMessage(r));
1136
1137         r = pFile->Seek(FILESEEKPOSITION_BEGIN, current);
1138         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to seek in file.", GetErrorMessage(r));
1139
1140         return r;
1141 }
1142
1143 _FlagState
1144 _SecureIoUtil::CheckRegistryFlag(byte* pHeader)
1145 {
1146         ClearLastResult();
1147         byte flag = *(pHeader + SECURE_REG_HEADER_STRING_SIZE + SECURE_IO_STATIC_BIN_LEN);
1148
1149         if (((flag | SECURE_IO_HEX_FD) == SECURE_IO_HEX_FF) && ((flag | SECURE_IO_HEX_FE) != SECURE_IO_HEX_FF))
1150         {
1151                 return FLAG_STATE_CVF;
1152         }
1153         else if (((flag | SECURE_IO_HEX_FD) != SECURE_IO_HEX_FF) && ((flag | SECURE_IO_HEX_FE) == SECURE_IO_HEX_FF))
1154         {
1155                 return FLAG_STATE_CTF;
1156         }
1157         else if ((flag | SECURE_IO_HEX_FC) == SECURE_IO_HEX_FF)
1158         {
1159                 return FLAG_STATE_CVF_CTF;
1160         }
1161         else
1162         {
1163                 return FLAG_STATE_NONE;
1164         }
1165 }
1166
1167 const String
1168 _SecureIoUtil::MakeRegistryReplica(const String fileName, byte* pNameIndex)
1169 {
1170         result r = E_SUCCESS;
1171         String replicaName;
1172         int nameIndex = *pNameIndex;
1173
1174         ClearLastResult();
1175         while (true)
1176         {
1177                 SysTryReturn(NID_IO, nameIndex <= SECURE_IO_HEX_64, replicaName, E_INVALID_ARG, "[E_INVALID_ARG] Index number is too big.");
1178
1179                 if (nameIndex == 0)
1180                 {
1181                         replicaName = fileName + L".rpa ";
1182                         if (!File::IsFileExist(replicaName))
1183                         {
1184                                 break;
1185                         }
1186                 }
1187                 else
1188                 {
1189                         replicaName = fileName + L"_";
1190                         replicaName.Append((int) nameIndex);
1191                         replicaName.Append(L".rpa");
1192
1193                         if (!File::IsFileExist(replicaName))
1194                         {
1195                                 break;
1196                         }
1197                 }
1198
1199                 nameIndex++;
1200         }
1201
1202         *pNameIndex = nameIndex;
1203
1204         if (_FileImpl::IsFileExist(fileName))
1205         {
1206                 r = _FileImpl::Copy(fileName, replicaName, true);
1207                 SysTryReturn(NID_IO, !IsFailed(r), replicaName, r, "[%s] Failed to copy file.", GetErrorMessage(r));
1208         }
1209         else
1210         {
1211                 // open registry replica file
1212                 _FileImpl fileImpl;
1213                 r = fileImpl.Construct(replicaName, "w", false, null);
1214                 SysTryReturn(NID_IO, !IsFailed(r), replicaName, r, "[%s] Failed to create empty file.", GetErrorMessage(r));
1215         }
1216
1217         SetLastResult(r);
1218         return replicaName;
1219 }
1220
1221 result
1222 _SecureIoUtil::DeleteRegistryReplica(byte* pHeader, const String fileName)
1223 {
1224         result r = E_SUCCESS;
1225         String replicaName;
1226         byte nameIndex = *(pHeader + SECURE_REG_HEADER_STRING_SIZE + SECURE_IO_9_BYTES);
1227
1228         ClearLastResult();
1229
1230         SysTryReturnResult(NID_IO, nameIndex <= SECURE_IO_HEX_64, E_INVALID_ARG, "Index number is too big.");
1231
1232         if (nameIndex == 0)
1233         {
1234                 replicaName = fileName + L".rpa ";
1235         }
1236         else
1237         {
1238                 replicaName = fileName + L"_";
1239                 replicaName.Append((int) nameIndex);
1240                 replicaName.Append(L".rpa");
1241         }
1242
1243         _FileImpl::Remove(replicaName);
1244
1245         return r;
1246 }
1247
1248 result
1249 _SecureIoUtil::LoadRegistryReplica(byte** pHeader, int* pHeaderLen, const String fileName)
1250 {
1251         result r = E_SUCCESS;
1252         int readItems = 0;
1253         int length = 0;
1254         char indexStr[MAX_BLOCK_INDEX_LEN];
1255         String replicaName;
1256         byte nameIndex = 0;
1257         _FileImpl replicaFile;
1258
1259         ClearLastResult();
1260         memset(indexStr, 0, MAX_BLOCK_INDEX_LEN);
1261         nameIndex = *(*pHeader + SECURE_REG_HEADER_STRING_SIZE + SECURE_IO_9_BYTES);
1262
1263         delete[]* pHeader;
1264         *pHeader = null;
1265         *pHeaderLen = 0;
1266
1267         SysTryReturnResult(NID_IO, nameIndex <= SECURE_IO_HEX_64, E_INVALID_ARG, "Index number is too big.");
1268
1269         if (nameIndex == 0)
1270         {
1271                 replicaName = fileName + L".rpa ";
1272         }
1273         else
1274         {
1275                 replicaName = fileName + L"_";
1276                 replicaName.Append((int) nameIndex);
1277                 replicaName.Append(L".rpa");
1278         }
1279
1280         if (Tizen::Io::_FileImpl::IsFileExist(replicaName))
1281         {
1282                 r = replicaFile.Construct(replicaName, "r", false, null);
1283                 SysTryCatch(NID_IO, !IsFailed(r), , r, "[%s] Constructing the file has failed.", GetErrorMessage(r));
1284
1285                 r = replicaFile.Seek(FILESEEKPOSITION_END, 0);
1286                 SysTryCatch(NID_IO, !IsFailed(r), , r, "[%s] Failed to seek in file.", GetErrorMessage(r));
1287
1288                 length = replicaFile.Tell();
1289                 if (length > 0)
1290                 {
1291                         *pHeader = new (std::nothrow) byte[length];
1292                         SysTryCatch(NID_IO, *pHeader != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
1293                         *pHeaderLen = length;
1294
1295                         r = replicaFile.Seek(FILESEEKPOSITION_BEGIN, 0);
1296                         SysTryCatch(NID_IO, !IsFailed(r), , r, "[%s] Failed to seek in file.", GetErrorMessage(r));
1297
1298                         readItems = replicaFile.Read(*pHeader, length);
1299                         SysTryCatch(NID_IO, readItems >= length, r = GetLastResult(), GetLastResult(), "[%s] Failed to read data from file.", GetErrorMessage(GetLastResult()));
1300
1301                 }
1302         }
1303
1304         CATCH:
1305
1306         if (IsFailed(r))
1307         {
1308                 delete[]* pHeader;
1309                 *pHeader = null;
1310                 *pHeaderLen = 0;
1311         }
1312         return r;
1313 }
1314
1315 result
1316 _SecureIoUtil::CheckSecureRegistryHeader(byte** pHeader, int* pHeaderLen, const String strFilePathPath, bool secureMode)
1317 {
1318         result r = E_SUCCESS;
1319         int readLen = 0;
1320         int ret = 0;
1321         _FileImpl fileImpl;
1322         _FlagState flag = FLAG_STATE_NONE;
1323         byte reservedValue[SECURE_IO_STATIC_BIN_LEN] = {0xCA, 0xFE, 0xBE, 0xBE, 0xDA, 0xEF, 0xEB, 0xEB};
1324         byte* pSecureRegistryHeader = *pHeader;
1325
1326         ClearLastResult();
1327         //check if the registry is encrypted . (in normal and secure mode)
1328         ret = memcmp(pSecureRegistryHeader, SECURE_REG_HEADER_STRING, SECURE_REG_HEADER_STRING_SIZE);
1329         ret |= memcmp(pSecureRegistryHeader + SECURE_REG_HEADER_STRING_SIZE, reservedValue, SECURE_IO_STATIC_BIN_LEN);
1330         SysTryReturnResult(NID_IO, !(ret && secureMode == true), E_INVALID_ARG, "Failed to match secure header in file.");
1331
1332         if (secureMode)
1333         {
1334                 flag = CheckRegistryFlag(pSecureRegistryHeader);
1335
1336                 if (_FileImpl::IsFileExist(strFilePathPath) && !_SecureIoUtil::IsEmpty(strFilePathPath))
1337                 {
1338                         r = fileImpl.Construct(strFilePathPath, "a+", false, null);
1339                         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Constructing the file has failed.", GetErrorMessage(r));
1340
1341                         if (flag == FLAG_STATE_CVF_CTF)
1342                         {
1343                                 r = DeleteRegistryReplica(pSecureRegistryHeader, strFilePathPath);
1344                                 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to delete registry replica.", GetErrorMessage(r));
1345
1346                                 r = SetRegistryFlag(&fileImpl, FLAG_STATE_CVF);
1347                                 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to set registry flags.", GetErrorMessage(r));
1348
1349                         }
1350                         else if (flag == FLAG_STATE_CTF)
1351                         {
1352                                 r = LoadRegistryReplica(pHeader, &readLen, strFilePathPath);
1353                                 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to load registry replica.", GetErrorMessage(r));
1354
1355                                 SysTryReturn(NID_IO, *pHeader, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Failed to read secure registry file header.");
1356
1357                                 pSecureRegistryHeader = *pHeader;
1358                                 *pHeaderLen = readLen;
1359
1360                                 r = DeleteRegistryReplica(pSecureRegistryHeader, strFilePathPath);
1361                                 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to delete registry replica.", GetErrorMessage(r));
1362
1363                                 r = SetRegistryFlag(&fileImpl, FLAG_STATE_CVF);
1364                                 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to set registry flags.", GetErrorMessage(r));
1365                         }
1366                         else if (flag == FLAG_STATE_CVF)
1367                         {
1368                                 ; //Do nothing
1369                         }
1370                         else
1371                         {
1372                                 r = E_INVALID_STATE;
1373                         }
1374                 }
1375         }
1376
1377         return r;
1378 }
1379
1380 result
1381 _SecureIoUtil::CheckFlag(_NormalFile* pNormalFile, _FlagState* pFlag)
1382 {
1383         result r = E_SUCCESS;
1384         int ret = 0;
1385         byte flag = 0;
1386
1387         ClearLastResult();
1388         r = pNormalFile->Seek(FILESEEKPOSITION_BEGIN, SECURE_FILE_HEADER_STRING_SIZE + SECURE_IO_STATIC_BIN_LEN);
1389         if (r != E_SUCCESS)
1390         {
1391                 return r;
1392         }
1393         ret = pNormalFile->Read(&flag, SECURE_IO_FLAG_SIZE);
1394         if (ret < 1)
1395         {
1396 #if 1
1397                 r = GetLastResult();
1398                 SysTryReturnResult(NID_IO, !(ret == 0 && r == E_END_OF_FILE), E_INVALID_ARG, "Failed to read secure file header.");
1399 #else
1400                 r = GetLastResult();
1401
1402                 if (ret == 0 && IsEndOfFile(pNormalFile))
1403                 {
1404                         r = E_END_OF_FILE;
1405                 }
1406
1407                 SysLog(NID_IO, "[%s] Failed to read data from file.", GetErrorMessage(r));
1408 #endif
1409                 return r;
1410         }
1411
1412         if (((flag | SECURE_IO_HEX_FD) == SECURE_IO_HEX_FF) && ((flag | SECURE_IO_HEX_FE) != SECURE_IO_HEX_FF))
1413         {
1414                 *pFlag = FLAG_STATE_CVF;
1415         }
1416         else if (((flag | SECURE_IO_HEX_FD) != SECURE_IO_HEX_FF) && ((flag | SECURE_IO_HEX_FE) == SECURE_IO_HEX_FF))
1417         {
1418                 *pFlag = FLAG_STATE_CTF;
1419         }
1420         else if ((flag | SECURE_IO_HEX_FC) == SECURE_IO_HEX_FF)
1421         {
1422                 *pFlag = FLAG_STATE_CVF_CTF;
1423         }
1424         else
1425         {
1426                 *pFlag = FLAG_STATE_NONE;
1427         }
1428
1429         return r;
1430 }
1431
1432 result
1433 _SecureIoUtil::SetFlag(_NormalFile* pNormalFile, _FlagState flag)
1434 {
1435         result r = E_SUCCESS;
1436         int readItems = 0;
1437         int current = 0;
1438         byte currentFlag = 0;
1439
1440         ClearLastResult();
1441         current = pNormalFile->Tell();
1442         if (current == -1)
1443         {
1444                 r = GetLastResult();
1445                 SysLog(NID_IO, "[%s] Failed to tell in file", GetErrorMessage(r));
1446                 return r;
1447         }
1448
1449         r = pNormalFile->Seek(FILESEEKPOSITION_BEGIN, SECURE_FILE_HEADER_STRING_SIZE + SECURE_IO_STATIC_BIN_LEN);
1450         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to seek in file", GetErrorMessage(r));
1451
1452         readItems = pNormalFile->Read(&currentFlag, SECURE_IO_FLAG_SIZE);
1453         if (readItems < 1)
1454         {
1455                 r = GetLastResult();
1456
1457                 if (readItems == 0 && IsEndOfFile(pNormalFile))
1458                 {
1459                         r = E_END_OF_FILE;
1460                 }
1461
1462                 SysLog(NID_IO, "[%s] Failed to read data from file.", GetErrorMessage(r));
1463                 return r;
1464         }
1465
1466         if (flag == FLAG_STATE_CVF)
1467         {
1468                 currentFlag = currentFlag | SECURE_IO_2_BYTES;
1469                 currentFlag = currentFlag & SECURE_IO_HEX_FE;
1470         }
1471         else if (flag == FLAG_STATE_CTF)
1472         {
1473                 currentFlag = currentFlag | 1;
1474                 currentFlag = currentFlag & SECURE_IO_HEX_FD;
1475         }
1476         else if (flag == FLAG_STATE_CVF_CTF)
1477         {
1478                 currentFlag = currentFlag | SECURE_IO_3_BYTES;
1479         }
1480         else if (flag == FLAG_STATE_NONE)
1481         {
1482                 currentFlag = currentFlag & SECURE_IO_HEX_FC;
1483         }
1484         else
1485         {
1486                 SysAssert(false); // should not happen!
1487         }
1488         r = pNormalFile->Seek(FILESEEKPOSITION_BEGIN, SECURE_FILE_HEADER_STRING_SIZE + SECURE_IO_STATIC_BIN_LEN);
1489         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to seek in file", GetErrorMessage(r));
1490
1491         r = pNormalFile->Write(&currentFlag, SECURE_IO_FLAG_SIZE);
1492         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to write in file", GetErrorMessage(r));
1493
1494         r = pNormalFile->Seek(FILESEEKPOSITION_BEGIN, current);
1495         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to seek in file", GetErrorMessage(r));
1496
1497         return r;
1498 }
1499
1500 result
1501 _SecureIoUtil::DeleteBlockReplica(_NormalFile* pNormalFile, const String filePath)
1502 {
1503         result r = E_SUCCESS;
1504         int readItems = 0;
1505         String replicaName;
1506         byte nameIndex = 0;
1507
1508         ClearLastResult();
1509         r = pNormalFile->Seek(FILESEEKPOSITION_BEGIN, SECURE_FILE_HEADER_STRING_SIZE + SECURE_IO_9_BYTES);
1510         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to seek in file", GetErrorMessage(r));
1511
1512         readItems = pNormalFile->Read(&nameIndex, SECURE_IO_INDEX_SIZE);
1513         if (readItems < 1)
1514         {
1515                 r = GetLastResult();
1516
1517                 if (readItems == 0 && IsEndOfFile(pNormalFile))
1518                 {
1519                         r = E_END_OF_FILE;
1520                 }
1521
1522                 SysLog(NID_IO, "[%s] Failed to read data from file.", GetErrorMessage(r));
1523                 return r;
1524         }
1525
1526         SysTryReturnResult(NID_IO, nameIndex <= SECURE_IO_HEX_64, E_INVALID_ARG, "Index number is too big.");
1527
1528         if (nameIndex == 0)
1529         {
1530                 replicaName = filePath + L".rpa ";
1531         }
1532         else
1533         {
1534                 replicaName = filePath + L"_";
1535                 replicaName.Append((int) nameIndex);
1536                 replicaName.Append(L".rpa");
1537         }
1538
1539         _FileImpl::Remove(replicaName);
1540
1541         return r;
1542 }
1543
1544 result
1545 _SecureIoUtil::RestoreCorruptBlock(_NormalFile* pNormalFile, String fileName)
1546 {
1547         result r = E_SUCCESS;
1548         String blockName = null;
1549         byte nameIndex = 0;
1550         byte blockHeader[CIPHER_BLOCK_HEADER_SIZE] = {0, 0, 0};
1551         byte* pBlockDataCur = null;
1552         _NormalFile replicaFile;
1553         int startBlockNum = 0;
1554         int readItems = 0;
1555         int fileLength = 0;
1556         int dataLen = 0;
1557
1558         ClearLastResult();
1559         r = pNormalFile->Seek(FILESEEKPOSITION_BEGIN, SECURE_FILE_HEADER_STRING_SIZE + SECURE_IO_9_BYTES);
1560         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to seek in file", GetErrorMessage(r));
1561
1562         readItems = pNormalFile->Read(&nameIndex, SECURE_IO_INDEX_SIZE);  // read index of temporary block name
1563         if (readItems < SECURE_IO_INDEX_SIZE)
1564         {
1565                 r = GetLastResult();
1566
1567                 if (readItems == 0 && IsEndOfFile(pNormalFile))
1568                 {
1569                         r = E_END_OF_FILE;
1570                 }
1571
1572                 SysLog(NID_IO, "[%s] Failed to read data from file.", GetErrorMessage(r));
1573                 return r;
1574         }
1575
1576         readItems = pNormalFile->Read(&dataLen, SECURE_IO_LOF_SIZE);
1577         if (readItems < SECURE_IO_LOF_SIZE)
1578         {
1579                 r = GetLastResult();
1580
1581                 if (readItems == 0 && IsEndOfFile(pNormalFile))
1582                 {
1583                         r = E_END_OF_FILE;
1584                 }
1585
1586                 SysLog(NID_IO, "[%s] Failed to read data from file.", GetErrorMessage(r));
1587                 return r;
1588         }
1589
1590         SysTryReturnResult(NID_IO, nameIndex < SECURE_IO_HEX_64, E_INVALID_ARG, "Index number is too big.");
1591
1592         if (nameIndex == 0)
1593         {
1594                 blockName = fileName + L".rpa ";
1595         }
1596         else
1597         {
1598                 blockName = fileName + L"_";
1599                 blockName.Append((int) nameIndex);
1600                 blockName.Append(L".rpa");
1601         }
1602
1603         if (_FileUtil::IsFileExist(blockName))
1604         {
1605                 r = replicaFile.Construct(blockName, "r");
1606                 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to conctruct replica file.", GetErrorMessage(r));
1607
1608                 readItems = replicaFile.Read(blockHeader, CIPHER_BLOCK_HEADER_SIZE); //Read start block number (3bytes)
1609                 if (readItems < CIPHER_BLOCK_HEADER_SIZE)
1610                 {
1611                         r = GetLastResult();
1612
1613                         if (readItems == 0 && IsEndOfFile(pNormalFile))
1614                         {
1615                                 r = E_END_OF_FILE;
1616                         }
1617
1618                         SysLog(NID_IO, "[%s] Failed to read data from file.", GetErrorMessage(r));
1619                         return r;
1620                 }
1621
1622                 pBlockDataCur = (byte*) (&startBlockNum);
1623                 *pBlockDataCur = blockHeader[SECURE_IO_2_BYTES];
1624                 *(pBlockDataCur + 1) = blockHeader[1];
1625                 *(pBlockDataCur + SECURE_IO_2_BYTES) = blockHeader[0];
1626
1627                 r = replicaFile.Seek(FILESEEKPOSITION_END, 0);
1628                 fileLength = replicaFile.Tell();
1629                 SysTryReturn(NID_IO, fileLength != -1, GetLastResult(), GetLastResult(), "[%s] Failed to tell in file.", GetErrorMessage(GetLastResult()));
1630
1631                 r = replicaFile.Seek(FILESEEKPOSITION_BEGIN, CIPHER_BLOCK_HEADER_SIZE);
1632                 unique_ptr< byte[] > pBlock(new (std::nothrow) byte[fileLength - CIPHER_BLOCK_HEADER_SIZE]);
1633                 SysTryReturnResult(NID_IO, pBlock != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
1634
1635                 memset(pBlock.get(), 0, fileLength - CIPHER_BLOCK_HEADER_SIZE);
1636
1637                 readItems = replicaFile.Read(pBlock.get(), fileLength - CIPHER_BLOCK_HEADER_SIZE);
1638                 if (readItems < (fileLength - CIPHER_BLOCK_HEADER_SIZE))
1639                 {
1640                         r = GetLastResult();
1641
1642                         if (readItems == 0 && IsEndOfFile(pNormalFile))
1643                         {
1644                                 r = E_END_OF_FILE;
1645                         }
1646
1647                         SysLog(NID_IO, "[%s] Failed to read data from file.", GetErrorMessage(r));
1648                         return r;
1649                 }
1650
1651                 r = pNormalFile->Seek(FILESEEKPOSITION_BEGIN, SECURE_FILE_HEADER_SIZE_V1 + (CIPHER_BLOCK_SIZE + CIPHER_BLOCK_HEADER_SIZE) * startBlockNum);
1652
1653                 r = pNormalFile->Write(pBlock.get(), fileLength - CIPHER_BLOCK_HEADER_SIZE);
1654                 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to write in file.", GetErrorMessage(r));
1655
1656         }
1657
1658         r = pNormalFile->Truncate(dataLen);
1659         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to truncate in file.", GetErrorMessage(r));
1660
1661         return E_SUCCESS;
1662 }
1663
1664 result
1665 _SecureIoUtil::MakeCipherBlockReplica(_NormalFile* pNormalFile, const String filePath, int dataPosition, int dataSize)
1666 {
1667         result r = E_SUCCESS;
1668         int totalDataSize = 0;
1669         int blockSize = 0;
1670         int headPos = 0;
1671         int tailPos = 0;
1672         int startBlockNum = 0;
1673         int ret = 0;
1674         long blockDataSize = 0;
1675         bool isEndOfBlock = false;
1676         String replicaName;
1677         byte* pBlockDataCur = null;
1678         byte blockHeader[CIPHER_BLOCK_HEADER_SIZE] = {0, 0, 0};
1679         byte nameIndex = 0;
1680         _NormalFile tempBlockFile;
1681
1682         totalDataSize = dataPosition + dataSize;
1683
1684         ClearLastResult();
1685         headPos = pNormalFile->Tell();
1686         SysTryReturn(NID_IO, headPos != -1, GetLastResult(), GetLastResult(), "[%s] Failed to tell in file.", GetErrorMessage(GetLastResult()));
1687
1688         ret = pNormalFile->Read(blockHeader, CIPHER_BLOCK_HEADER_SIZE);
1689         if (ret < CIPHER_BLOCK_HEADER_SIZE)
1690         {
1691                 r = GetLastResult();
1692
1693                 if (ret == 0 && IsEndOfFile(pNormalFile))
1694                 {
1695                         r = E_END_OF_FILE;
1696                 }
1697
1698                 SysLog(NID_IO, "[%s] Failed to read data from file.", GetErrorMessage(r));
1699                 return r;
1700         }
1701
1702         while (true)
1703         {
1704                 blockDataSize = 0;
1705                 pBlockDataCur = (byte*) (&blockDataSize);
1706                 *pBlockDataCur = blockHeader[SECURE_IO_2_BYTES];
1707                 *(pBlockDataCur + 1) = blockHeader[1];
1708                 *(pBlockDataCur + SECURE_IO_2_BYTES) = blockHeader[0];
1709                 blockSize = blockSize + blockDataSize;
1710
1711                 if (blockSize >= totalDataSize)
1712                 {
1713                         isEndOfBlock = true;
1714                 }
1715
1716                 if (blockDataSize % ONE_BLOCK_SIZE != 0)
1717                 {
1718                         r = pNormalFile->Seek(FILESEEKPOSITION_CURRENT, blockDataSize + ONE_BLOCK_SIZE - blockDataSize % ONE_BLOCK_SIZE);
1719                 }
1720                 else
1721                 {
1722                         r = pNormalFile->Seek(FILESEEKPOSITION_CURRENT, blockDataSize);
1723                 }
1724
1725                 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to seek in file.", GetErrorMessage(r));
1726
1727                 if (isEndOfBlock)
1728                 {
1729                         break;
1730                 }
1731
1732                 if (IsEndOfFile(pNormalFile))
1733                 {
1734                         break;
1735                 }
1736
1737                 ret = pNormalFile->Read(blockHeader, CIPHER_BLOCK_HEADER_SIZE);
1738                 if (ret < CIPHER_BLOCK_HEADER_SIZE)
1739                 {
1740                         r = GetLastResult();
1741
1742                         if (ret == 0 && IsEndOfFile(pNormalFile))
1743                         {
1744                                 break;
1745                         }
1746
1747                         SysLog(NID_IO, "[%s] Failed to read data from file.", GetErrorMessage(r));
1748                         return r;
1749                 }
1750
1751         }
1752
1753         tailPos = pNormalFile->Tell();
1754         SysTryReturn(NID_IO, tailPos != -1, GetLastResult(), GetLastResult(), "[%s] Failed to tell in file.", GetErrorMessage(GetLastResult()));
1755
1756         startBlockNum = (headPos - SECURE_FILE_HEADER_SIZE_V1) / (CIPHER_BLOCK_SIZE + CIPHER_BLOCK_HEADER_SIZE);
1757
1758         r = pNormalFile->Seek(FILESEEKPOSITION_BEGIN, headPos);
1759         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to seek in file.", GetErrorMessage(r));
1760
1761         unique_ptr< byte[] > pBlockReplica(new (std::nothrow) byte[tailPos - headPos + CIPHER_BLOCK_HEADER_SIZE]);
1762         SysTryReturnResult(NID_IO, pBlockReplica != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
1763
1764         *(reinterpret_cast< byte* >(pBlockReplica.get()) + SECURE_IO_2_BYTES) = (byte) (startBlockNum & SECURE_IO_HEX_FF);
1765         *(reinterpret_cast< byte* >(pBlockReplica.get()) + 1) = (byte) ((startBlockNum >> SECURE_IO_8_BITS) & SECURE_IO_HEX_FF);
1766         *(reinterpret_cast< byte* >(pBlockReplica.get())) = (byte) ((startBlockNum >> (SECURE_IO_8_BITS * SECURE_IO_2_BYTES)) & SECURE_IO_HEX_FF);
1767
1768         ret = pNormalFile->Read(reinterpret_cast< byte* >(pBlockReplica.get()) + CIPHER_BLOCK_HEADER_SIZE, tailPos - headPos);
1769         if (ret < (tailPos - headPos))
1770         {
1771                 r = GetLastResult();
1772
1773                 if (ret == 0 && IsEndOfFile(pNormalFile))
1774                 {
1775                         r = E_END_OF_FILE;
1776                 }
1777
1778                 SysLog(NID_IO, "[%s] Failed to read data from file.", GetErrorMessage(r));
1779                 return r;
1780         }
1781
1782         while (true)
1783         {
1784                 SysTryReturnResult(NID_IO, nameIndex <= SECURE_IO_HEX_64, E_INVALID_ARG, "Index number is too big.");
1785
1786                 if (nameIndex == 0)
1787                 {
1788                         replicaName = filePath + L".rpa ";
1789                         if (!File::IsFileExist(replicaName))
1790                         {
1791                                 break;
1792                         }
1793                 }
1794                 else
1795                 {
1796                         replicaName = filePath + L"_";
1797                         replicaName.Append((int) nameIndex);
1798                         replicaName.Append(L".rpa");
1799
1800                         if (!File::IsFileExist(replicaName))
1801                         {
1802                                 break;
1803                         }
1804                 }
1805                 nameIndex++;
1806         }
1807
1808         r = tempBlockFile.Construct(replicaName, "w");
1809         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to call construct.", GetErrorMessage(r));
1810
1811         r = tempBlockFile.Write(pBlockReplica.get(), tailPos - headPos + CIPHER_BLOCK_HEADER_SIZE);
1812         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to write in file.", GetErrorMessage(r));
1813
1814         r = pNormalFile->Seek(FILESEEKPOSITION_BEGIN, 25);
1815         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to seek in file.", GetErrorMessage(r));
1816
1817         r = pNormalFile->Write(&nameIndex, 1);
1818         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to write in file.", GetErrorMessage(r));
1819
1820         r = pNormalFile->Seek(FILESEEKPOSITION_BEGIN, headPos);
1821         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to seek in file.", GetErrorMessage(r));
1822
1823         return r;
1824 }
1825
1826 bool
1827 _SecureIoUtil::IsNormalDatabase(_DatabaseMode mode)
1828 {
1829         ClearLastResult();
1830         if (mode == DATABASE_MODE_NORMAL)
1831         {
1832                 return true;
1833         }
1834         return false;
1835 }
1836
1837 bool
1838 _SecureIoUtil::IsSecureDatabase(_DatabaseMode mode)
1839 {
1840         ClearLastResult();
1841         if (mode == DATABASE_MODE_SECURE)
1842         {
1843                 return true;
1844         }
1845         return false;
1846 }
1847
1848 _DatabaseMode
1849 _SecureIoUtil::GetDatabaseMode(char* pStrPhysicalDbPath)
1850 {
1851         result r = E_SUCCESS;
1852         int fileLength = 0;
1853         unsigned long readBytes = 0;
1854         char buffer[SQLITE_HEADER_SIZE] = {0, };
1855         char magicNum1[SECURE_IO_MAGIC_NUMBER_SIZE] = {0xCA, 0xFE, 0xBE, 0xBE};
1856         char magicNum2[SECURE_IO_MAGIC_NUMBER_SIZE] = {0xDA, 0xEF, 0xEF, 0xEB};
1857         _NormalFile normalFile;
1858
1859         ClearLastResult();
1860
1861         r = normalFile.Construct(pStrPhysicalDbPath, "r");
1862         SysTryReturn(NID_IO, !IsFailed(r), DATABASE_MODE_ERROR, r, "[%s] Failed to open file (%s) in read mode", GetErrorMessage(r), pStrPhysicalDbPath);
1863
1864         r = normalFile.Seek(FILESEEKPOSITION_END, 0);
1865         SysTryReturn(NID_IO, !IsFailed(r), DATABASE_MODE_ERROR, r, "[%s] Failed to seek in file.", GetErrorMessage(r));
1866
1867         fileLength = normalFile.Tell();
1868         if (fileLength <= 0)
1869         {
1870                 return DATABASE_MODE_NONE;
1871         }
1872
1873         r = normalFile.Seek(FILESEEKPOSITION_BEGIN, 0);
1874         SysTryReturn(NID_IO, !IsFailed(r), DATABASE_MODE_ERROR, r, "[%s] Failed to seek in file.", GetErrorMessage(r));
1875
1876         readBytes = normalFile.Read(buffer, SQLITE_HEADER_SIZE);
1877         r = GetLastResult();
1878         SysTryReturn(NID_IO, readBytes > 0, DATABASE_MODE_ERROR, r, "[%s] File is not opened for reading or else failed to read data from file.", GetErrorMessage(r));
1879
1880         if (!strncmp(buffer, "SQLite format 3", SQLITE_FORMAT_STR_SIZE))
1881         {
1882                 return DATABASE_MODE_NORMAL;
1883         } //is normal file
1884         else if (!memcmp((void*) buffer, magicNum1, SECURE_IO_MAGIC_NUMBER_SIZE) && !memcmp((void*) (buffer + SECURE_IO_12_BYTES), magicNum2, SECURE_IO_MAGIC_NUMBER_SIZE))
1885         {
1886                 return DATABASE_MODE_SECURE;
1887         } //is secure file
1888
1889         return DATABASE_MODE_ERROR;
1890 }
1891
1892 byte*
1893 _SecureIoUtil::GenerateDatabaseKeyN(const Tizen::Base::ByteBuffer* pUserKey)
1894 {
1895         byte lowByte = 0;
1896         byte highByte = 0;
1897         byte* pKey = null;
1898         byte* pDbKey = null;
1899
1900         ClearLastResult();
1901
1902         unique_ptr< ByteBuffer > pKeyBuffer(GetSecureKeyN(pUserKey));
1903
1904         SysTryReturn(NID_IO, pKeyBuffer != null, null, E_INVALID_ARG, "[E_INVALID_ARG] Failed to generate secure key.");
1905
1906         pKey = const_cast< byte* >(pKeyBuffer->GetPointer());
1907
1908         pDbKey = new (std::nothrow) byte[DATABASE_KEY_LENGTH * SECURE_IO_2_BYTES + 1];
1909         SysTryReturn(NID_IO, pDbKey != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
1910
1911         memset(pDbKey, 0, DATABASE_KEY_LENGTH * SECURE_IO_2_BYTES + 1);
1912
1913         for (int i = 0; i < DATABASE_KEY_LENGTH; i++)
1914         {
1915                 lowByte = pKey[i] & SECURE_IO_HEX_0F;
1916                 highByte = (pKey[i] >> SECURE_IO_4_BITS) & SECURE_IO_HEX_0F;
1917                 if (lowByte <= SECURE_IO_9_BYTES)
1918                 {
1919                         pDbKey[i * SECURE_IO_2_BYTES + 1] = lowByte + '0';
1920                 }
1921                 else
1922                 {
1923                         pDbKey[i * SECURE_IO_2_BYTES + 1] = lowByte - SECURE_IO_10_BYTES + 'A';
1924                 }
1925
1926                 if (highByte <= SECURE_IO_9_BYTES)
1927                 {
1928                         pDbKey[i * SECURE_IO_2_BYTES] = highByte + '0';
1929                 }
1930                 else
1931                 {
1932                         pDbKey[i * SECURE_IO_2_BYTES] = highByte - SECURE_IO_10_BYTES + 'A';
1933                 }
1934         }
1935
1936         return pDbKey;
1937 }
1938
1939 bool
1940 _SecureIoUtil::IsEmpty(const String& filePath)
1941 {
1942         result r = E_SUCCESS;
1943         FileAttributes attribute;
1944
1945         SetLastResult(r);
1946         r = File::GetAttributes(filePath, attribute);
1947         if (IsFailed(r))
1948         {
1949                 SetLastResult(r);
1950                 return false;
1951         }
1952
1953         if (attribute.GetFileSize() == 0)
1954         {
1955                 return true;
1956         }
1957         else
1958         {
1959                 return false;
1960         }
1961 }
1962
1963 } } //Tizen::Io