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