Merge "[2.2] Add Unshareable marker in String" into tizen_2.2
[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         result r = E_SUCCESS;
1050         int ret = 0;
1051         _NormalFile normalFile;
1052         byte secureFileHeader[SECURE_FILE_HEADER_SIZE_V1];
1053         byte reservedValue[SECURE_IO_STATIC_BIN_LEN] = {0xCA, 0xFE, 0xBE, 0xBE, 0xDA, 0xEF, 0xEB, 0xEB};
1054
1055         ClearLastResult();
1056
1057         r = normalFile.Construct(filePath, "r");
1058         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to call constuct.", GetErrorMessage(r));
1059
1060         ret = normalFile.Read(secureFileHeader, SECURE_FILE_HEADER_SIZE_V1);
1061         if (ret < SECURE_FILE_HEADER_SIZE_V1)
1062         {
1063                 r  = GetLastResult();
1064                 if (IsEndOfFile(&normalFile))
1065                 {
1066                         if (ret && pSecretKey)
1067                         {
1068                                 return E_INVALID_ARG;
1069                         }
1070                         else
1071                         {
1072                                 return E_SUCCESS;
1073                         }
1074                 }
1075                 return r;
1076         }
1077
1078         //check if the file is encrypted file. (in normal and secure mode)
1079         ret = memcmp(secureFileHeader, SECURE_FILE_HEADER_STRING, SECURE_FILE_HEADER_STRING_SIZE);
1080         ret |= memcmp(secureFileHeader + SECURE_FILE_HEADER_STRING_SIZE, reservedValue, SECURE_IO_STATIC_BIN_LEN);
1081
1082         SysTryReturnResult(NID_IO, !(ret && pSecretKey), E_INVALID_ARG, "Failed to match secure header in file.");
1083
1084         return E_SUCCESS;
1085 }
1086
1087 result
1088 _SecureIoUtil::SetRegistryFlag(void* pFileSecure, _FlagState flag)
1089 {
1090         result r = E_SUCCESS;
1091         int readItems = 0;
1092         int current = 0;
1093         byte currentFlag = 0;
1094         _FileImpl* pFile = (_FileImpl*) pFileSecure;
1095
1096         ClearLastResult();
1097         current = pFile->Tell();
1098         SysTryReturn(NID_IO, current != -1, GetLastResult(), GetLastResult(), "[%s] Tell file has failed.", GetErrorMessage(GetLastResult()));
1099
1100         r = pFile->Seek(FILESEEKPOSITION_BEGIN, SECURE_REG_HEADER_STRING_SIZE + SECURE_IO_STATIC_BIN_LEN);
1101         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to seek in file.", GetErrorMessage(r));
1102
1103         readItems = pFile->Read(&currentFlag, 1);
1104         SysTryReturn(NID_IO, readItems == 1, r = E_INVALID_STATE, E_INVALID_STATE, "[E_INVALID_STATE] Tell file has failed.");
1105
1106         if (flag == FLAG_STATE_CVF)
1107         {
1108                 currentFlag = currentFlag | SECURE_IO_2_BYTES;
1109                 currentFlag = currentFlag & SECURE_IO_HEX_FE;
1110         }
1111         else if (flag == FLAG_STATE_CTF)
1112         {
1113                 currentFlag = currentFlag | 1;
1114                 currentFlag = currentFlag & SECURE_IO_HEX_FD;
1115         }
1116         else if (flag == FLAG_STATE_CVF_CTF)
1117         {
1118                 currentFlag = currentFlag | SECURE_IO_3_BYTES;
1119         }
1120         else if (flag == FLAG_STATE_NONE)
1121         {
1122                 currentFlag = currentFlag & SECURE_IO_HEX_FC;
1123         }
1124         else
1125         {
1126                 return E_INVALID_STATE;
1127         }
1128
1129         r = pFile->Seek(FILESEEKPOSITION_BEGIN, SECURE_REG_HEADER_STRING_SIZE + SECURE_IO_STATIC_BIN_LEN);
1130         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to seek in file.", GetErrorMessage(r));
1131
1132         r = pFile->Write(&currentFlag, 1);
1133         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to write data in file.", GetErrorMessage(r));
1134
1135         r = pFile->Seek(FILESEEKPOSITION_BEGIN, current);
1136         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to seek in file.", GetErrorMessage(r));
1137
1138         return r;
1139 }
1140
1141 _FlagState
1142 _SecureIoUtil::CheckRegistryFlag(byte* pHeader)
1143 {
1144         ClearLastResult();
1145         byte flag = *(pHeader + SECURE_REG_HEADER_STRING_SIZE + SECURE_IO_STATIC_BIN_LEN);
1146
1147         if (((flag | SECURE_IO_HEX_FD) == SECURE_IO_HEX_FF) && ((flag | SECURE_IO_HEX_FE) != SECURE_IO_HEX_FF))
1148         {
1149                 return FLAG_STATE_CVF;
1150         }
1151         else if (((flag | SECURE_IO_HEX_FD) != SECURE_IO_HEX_FF) && ((flag | SECURE_IO_HEX_FE) == SECURE_IO_HEX_FF))
1152         {
1153                 return FLAG_STATE_CTF;
1154         }
1155         else if ((flag | SECURE_IO_HEX_FC) == SECURE_IO_HEX_FF)
1156         {
1157                 return FLAG_STATE_CVF_CTF;
1158         }
1159         else
1160         {
1161                 return FLAG_STATE_NONE;
1162         }
1163 }
1164
1165 const String
1166 _SecureIoUtil::MakeRegistryReplica(const String fileName, byte* pNameIndex)
1167 {
1168         result r = E_SUCCESS;
1169         String replicaName;
1170         int nameIndex = *pNameIndex;
1171
1172         ClearLastResult();
1173         while (true)
1174         {
1175                 SysTryReturn(NID_IO, nameIndex <= SECURE_IO_HEX_64, replicaName, E_INVALID_ARG, "[E_INVALID_ARG] Index number is too big.");
1176
1177                 if (nameIndex == 0)
1178                 {
1179                         replicaName = fileName + L".rpa ";
1180                         if (!File::IsFileExist(replicaName))
1181                         {
1182                                 break;
1183                         }
1184                 }
1185                 else
1186                 {
1187                         replicaName = fileName + L"_";
1188                         replicaName.Append((int) nameIndex);
1189                         replicaName.Append(L".rpa");
1190
1191                         if (!File::IsFileExist(replicaName))
1192                         {
1193                                 break;
1194                         }
1195                 }
1196
1197                 nameIndex++;
1198         }
1199
1200         *pNameIndex = nameIndex;
1201
1202         if (_FileImpl::IsFileExist(fileName))
1203         {
1204                 r = _FileImpl::Copy(fileName, replicaName, true);
1205                 SysTryReturn(NID_IO, !IsFailed(r), replicaName, r, "[%s] Failed to copy file.", GetErrorMessage(r));
1206         }
1207         else
1208         {
1209                 // open registry replica file
1210                 _FileImpl fileImpl;
1211                 r = fileImpl.Construct(replicaName, "w", false, null);
1212                 SysTryReturn(NID_IO, !IsFailed(r), replicaName, r, "[%s] Failed to create empty file.", GetErrorMessage(r));
1213         }
1214
1215         SetLastResult(r);
1216         return replicaName;
1217 }
1218
1219 result
1220 _SecureIoUtil::DeleteRegistryReplica(byte* pHeader, const String fileName)
1221 {
1222         result r = E_SUCCESS;
1223         String replicaName;
1224         byte nameIndex = *(pHeader + SECURE_REG_HEADER_STRING_SIZE + SECURE_IO_9_BYTES);
1225
1226         ClearLastResult();
1227
1228         SysTryReturnResult(NID_IO, nameIndex <= SECURE_IO_HEX_64, E_INVALID_ARG, "Index number is too big.");
1229
1230         if (nameIndex == 0)
1231         {
1232                 replicaName = fileName + L".rpa ";
1233         }
1234         else
1235         {
1236                 replicaName = fileName + L"_";
1237                 replicaName.Append((int) nameIndex);
1238                 replicaName.Append(L".rpa");
1239         }
1240
1241         _FileImpl::Remove(replicaName);
1242
1243         return r;
1244 }
1245
1246 result
1247 _SecureIoUtil::LoadRegistryReplica(byte** pHeader, int* pHeaderLen, const String fileName)
1248 {
1249         result r = E_SUCCESS;
1250         int readItems = 0;
1251         int length = 0;
1252         char indexStr[MAX_BLOCK_INDEX_LEN];
1253         String replicaName;
1254         byte nameIndex = 0;
1255         _FileImpl replicaFile;
1256
1257         ClearLastResult();
1258         memset(indexStr, 0, MAX_BLOCK_INDEX_LEN);
1259         nameIndex = *(*pHeader + SECURE_REG_HEADER_STRING_SIZE + SECURE_IO_9_BYTES);
1260
1261         delete[]* pHeader;
1262         *pHeader = null;
1263         *pHeaderLen = 0;
1264
1265         SysTryReturnResult(NID_IO, nameIndex <= SECURE_IO_HEX_64, E_INVALID_ARG, "Index number is too big.");
1266
1267         if (nameIndex == 0)
1268         {
1269                 replicaName = fileName + L".rpa ";
1270         }
1271         else
1272         {
1273                 replicaName = fileName + L"_";
1274                 replicaName.Append((int) nameIndex);
1275                 replicaName.Append(L".rpa");
1276         }
1277
1278         if (Tizen::Io::_FileImpl::IsFileExist(replicaName))
1279         {
1280                 r = replicaFile.Construct(replicaName, "r", false, null);
1281                 SysTryCatch(NID_IO, !IsFailed(r), , r, "[%s] Constructing the file has failed.", GetErrorMessage(r));
1282
1283                 r = replicaFile.Seek(FILESEEKPOSITION_END, 0);
1284                 SysTryCatch(NID_IO, !IsFailed(r), , r, "[%s] Failed to seek in file.", GetErrorMessage(r));
1285
1286                 length = replicaFile.Tell();
1287                 if (length > 0)
1288                 {
1289                         *pHeader = new (std::nothrow) byte[length];
1290                         SysTryCatch(NID_IO, *pHeader != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
1291                         *pHeaderLen = length;
1292
1293                         r = replicaFile.Seek(FILESEEKPOSITION_BEGIN, 0);
1294                         SysTryCatch(NID_IO, !IsFailed(r), , r, "[%s] Failed to seek in file.", GetErrorMessage(r));
1295
1296                         readItems = replicaFile.Read(*pHeader, length);
1297                         SysTryCatch(NID_IO, readItems >= length, r = GetLastResult(), GetLastResult(), "[%s] Failed to read data from file.", GetErrorMessage(GetLastResult()));
1298
1299                 }
1300         }
1301
1302         CATCH:
1303
1304         if (IsFailed(r))
1305         {
1306                 delete[]* pHeader;
1307                 *pHeader = null;
1308                 *pHeaderLen = 0;
1309         }
1310         return r;
1311 }
1312
1313 result
1314 _SecureIoUtil::CheckSecureRegistryHeader(byte** pHeader, int* pHeaderLen, const String strFilePathPath, bool secureMode)
1315 {
1316         result r = E_SUCCESS;
1317         int readLen = 0;
1318         int ret = 0;
1319         _FileImpl fileImpl;
1320         _FlagState flag = FLAG_STATE_NONE;
1321         byte reservedValue[SECURE_IO_STATIC_BIN_LEN] = {0xCA, 0xFE, 0xBE, 0xBE, 0xDA, 0xEF, 0xEB, 0xEB};
1322         byte* pSecureRegistryHeader = *pHeader;
1323
1324         ClearLastResult();
1325         //check if the registry is encrypted . (in normal and secure mode)
1326         ret = memcmp(pSecureRegistryHeader, SECURE_REG_HEADER_STRING, SECURE_REG_HEADER_STRING_SIZE);
1327         ret |= memcmp(pSecureRegistryHeader + SECURE_REG_HEADER_STRING_SIZE, reservedValue, SECURE_IO_STATIC_BIN_LEN);
1328         SysTryReturnResult(NID_IO, !(ret && secureMode == true), E_INVALID_ARG, "Failed to match secure header in file.");
1329
1330         if (secureMode)
1331         {
1332                 flag = CheckRegistryFlag(pSecureRegistryHeader);
1333
1334                 if (_FileImpl::IsFileExist(strFilePathPath) && !_SecureIoUtil::IsEmpty(strFilePathPath))
1335                 {
1336                         r = fileImpl.Construct(strFilePathPath, "a+", false, null);
1337                         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Constructing the file has failed.", GetErrorMessage(r));
1338
1339                         if (flag == FLAG_STATE_CVF_CTF)
1340                         {
1341                                 r = DeleteRegistryReplica(pSecureRegistryHeader, strFilePathPath);
1342                                 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to delete registry replica.", GetErrorMessage(r));
1343
1344                                 r = SetRegistryFlag(&fileImpl, FLAG_STATE_CVF);
1345                                 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to set registry flags.", GetErrorMessage(r));
1346
1347                         }
1348                         else if (flag == FLAG_STATE_CTF)
1349                         {
1350                                 r = LoadRegistryReplica(pHeader, &readLen, strFilePathPath);
1351                                 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to load registry replica.", GetErrorMessage(r));
1352
1353                                 SysTryReturn(NID_IO, *pHeader, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Failed to read secure registry file header.");
1354
1355                                 pSecureRegistryHeader = *pHeader;
1356                                 *pHeaderLen = readLen;
1357
1358                                 r = DeleteRegistryReplica(pSecureRegistryHeader, strFilePathPath);
1359                                 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to delete registry replica.", GetErrorMessage(r));
1360
1361                                 r = SetRegistryFlag(&fileImpl, FLAG_STATE_CVF);
1362                                 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to set registry flags.", GetErrorMessage(r));
1363                         }
1364                         else if (flag == FLAG_STATE_CVF)
1365                         {
1366                                 ; //Do nothing
1367                         }
1368                         else
1369                         {
1370                                 r = E_INVALID_STATE;
1371                         }
1372                 }
1373         }
1374
1375         return r;
1376 }
1377
1378 result
1379 _SecureIoUtil::CheckFlag(_NormalFile* pNormalFile, _FlagState* pFlag)
1380 {
1381         result r = E_SUCCESS;
1382         int ret = 0;
1383         byte flag = 0;
1384
1385         ClearLastResult();
1386         r = pNormalFile->Seek(FILESEEKPOSITION_BEGIN, SECURE_FILE_HEADER_STRING_SIZE + SECURE_IO_STATIC_BIN_LEN);
1387         if (r != E_SUCCESS)
1388         {
1389                 return r;
1390         }
1391         ret = pNormalFile->Read(&flag, SECURE_IO_FLAG_SIZE);
1392         if (ret < 1)
1393         {
1394 #if 1
1395                 r = GetLastResult();
1396                 SysTryReturnResult(NID_IO, !(ret == 0 && r == E_END_OF_FILE), E_INVALID_ARG, "Failed to read secure file header.");
1397 #else
1398                 r = GetLastResult();
1399
1400                 if (ret == 0 && IsEndOfFile(pNormalFile))
1401                 {
1402                         r = E_END_OF_FILE;
1403                 }
1404
1405                 SysLog(NID_IO, "[%s] Failed to read data from file.", GetErrorMessage(r));
1406 #endif
1407                 return r;
1408         }
1409
1410         if (((flag | SECURE_IO_HEX_FD) == SECURE_IO_HEX_FF) && ((flag | SECURE_IO_HEX_FE) != SECURE_IO_HEX_FF))
1411         {
1412                 *pFlag = FLAG_STATE_CVF;
1413         }
1414         else if (((flag | SECURE_IO_HEX_FD) != SECURE_IO_HEX_FF) && ((flag | SECURE_IO_HEX_FE) == SECURE_IO_HEX_FF))
1415         {
1416                 *pFlag = FLAG_STATE_CTF;
1417         }
1418         else if ((flag | SECURE_IO_HEX_FC) == SECURE_IO_HEX_FF)
1419         {
1420                 *pFlag = FLAG_STATE_CVF_CTF;
1421         }
1422         else
1423         {
1424                 *pFlag = FLAG_STATE_NONE;
1425         }
1426
1427         return r;
1428 }
1429
1430 result
1431 _SecureIoUtil::SetFlag(_NormalFile* pNormalFile, _FlagState flag)
1432 {
1433         result r = E_SUCCESS;
1434         int readItems = 0;
1435         int current = 0;
1436         byte currentFlag = 0;
1437
1438         ClearLastResult();
1439         current = pNormalFile->Tell();
1440         if (current == -1)
1441         {
1442                 r = GetLastResult();
1443                 SysLog(NID_IO, "[%s] Failed to tell in file", GetErrorMessage(r));
1444                 return r;
1445         }
1446
1447         r = pNormalFile->Seek(FILESEEKPOSITION_BEGIN, SECURE_FILE_HEADER_STRING_SIZE + SECURE_IO_STATIC_BIN_LEN);
1448         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to seek in file", GetErrorMessage(r));
1449
1450         readItems = pNormalFile->Read(&currentFlag, SECURE_IO_FLAG_SIZE);
1451         if (readItems < 1)
1452         {
1453                 r = GetLastResult();
1454
1455                 if (readItems == 0 && IsEndOfFile(pNormalFile))
1456                 {
1457                         r = E_END_OF_FILE;
1458                 }
1459
1460                 SysLog(NID_IO, "[%s] Failed to read data from file.", GetErrorMessage(r));
1461                 return r;
1462         }
1463
1464         if (flag == FLAG_STATE_CVF)
1465         {
1466                 currentFlag = currentFlag | SECURE_IO_2_BYTES;
1467                 currentFlag = currentFlag & SECURE_IO_HEX_FE;
1468         }
1469         else if (flag == FLAG_STATE_CTF)
1470         {
1471                 currentFlag = currentFlag | 1;
1472                 currentFlag = currentFlag & SECURE_IO_HEX_FD;
1473         }
1474         else if (flag == FLAG_STATE_CVF_CTF)
1475         {
1476                 currentFlag = currentFlag | SECURE_IO_3_BYTES;
1477         }
1478         else if (flag == FLAG_STATE_NONE)
1479         {
1480                 currentFlag = currentFlag & SECURE_IO_HEX_FC;
1481         }
1482         else
1483         {
1484                 SysAssert(false); // should not happen!
1485         }
1486         r = pNormalFile->Seek(FILESEEKPOSITION_BEGIN, SECURE_FILE_HEADER_STRING_SIZE + SECURE_IO_STATIC_BIN_LEN);
1487         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to seek in file", GetErrorMessage(r));
1488
1489         r = pNormalFile->Write(&currentFlag, SECURE_IO_FLAG_SIZE);
1490         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to write in file", GetErrorMessage(r));
1491
1492         r = pNormalFile->Seek(FILESEEKPOSITION_BEGIN, current);
1493         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to seek in file", GetErrorMessage(r));
1494
1495         return r;
1496 }
1497
1498 result
1499 _SecureIoUtil::DeleteBlockReplica(_NormalFile* pNormalFile, const String filePath)
1500 {
1501         result r = E_SUCCESS;
1502         int readItems = 0;
1503         String replicaName;
1504         byte nameIndex = 0;
1505
1506         ClearLastResult();
1507         r = pNormalFile->Seek(FILESEEKPOSITION_BEGIN, SECURE_FILE_HEADER_STRING_SIZE + SECURE_IO_9_BYTES);
1508         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to seek in file", GetErrorMessage(r));
1509
1510         readItems = pNormalFile->Read(&nameIndex, SECURE_IO_INDEX_SIZE);
1511         if (readItems < 1)
1512         {
1513                 r = GetLastResult();
1514
1515                 if (readItems == 0 && IsEndOfFile(pNormalFile))
1516                 {
1517                         r = E_END_OF_FILE;
1518                 }
1519
1520                 SysLog(NID_IO, "[%s] Failed to read data from file.", GetErrorMessage(r));
1521                 return r;
1522         }
1523
1524         SysTryReturnResult(NID_IO, nameIndex <= SECURE_IO_HEX_64, E_INVALID_ARG, "Index number is too big.");
1525
1526         if (nameIndex == 0)
1527         {
1528                 replicaName = filePath + L".rpa ";
1529         }
1530         else
1531         {
1532                 replicaName = filePath + L"_";
1533                 replicaName.Append((int) nameIndex);
1534                 replicaName.Append(L".rpa");
1535         }
1536
1537         _FileImpl::Remove(replicaName);
1538
1539         return r;
1540 }
1541
1542 result
1543 _SecureIoUtil::RestoreCorruptBlock(_NormalFile* pNormalFile, String fileName)
1544 {
1545         result r = E_SUCCESS;
1546         String blockName = null;
1547         byte nameIndex = 0;
1548         byte blockHeader[CIPHER_BLOCK_HEADER_SIZE] = {0, 0, 0};
1549         byte* pBlockDataCur = null;
1550         _NormalFile replicaFile;
1551         int startBlockNum = 0;
1552         int readItems = 0;
1553         int fileLength = 0;
1554         int dataLen = 0;
1555
1556         ClearLastResult();
1557         r = pNormalFile->Seek(FILESEEKPOSITION_BEGIN, SECURE_FILE_HEADER_STRING_SIZE + SECURE_IO_9_BYTES);
1558         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to seek in file", GetErrorMessage(r));
1559
1560         readItems = pNormalFile->Read(&nameIndex, SECURE_IO_INDEX_SIZE);  // read index of temporary block name
1561         if (readItems < SECURE_IO_INDEX_SIZE)
1562         {
1563                 r = GetLastResult();
1564
1565                 if (readItems == 0 && IsEndOfFile(pNormalFile))
1566                 {
1567                         r = E_END_OF_FILE;
1568                 }
1569
1570                 SysLog(NID_IO, "[%s] Failed to read data from file.", GetErrorMessage(r));
1571                 return r;
1572         }
1573
1574         readItems = pNormalFile->Read(&dataLen, SECURE_IO_LOF_SIZE);
1575         if (readItems < SECURE_IO_LOF_SIZE)
1576         {
1577                 r = GetLastResult();
1578
1579                 if (readItems == 0 && IsEndOfFile(pNormalFile))
1580                 {
1581                         r = E_END_OF_FILE;
1582                 }
1583
1584                 SysLog(NID_IO, "[%s] Failed to read data from file.", GetErrorMessage(r));
1585                 return r;
1586         }
1587
1588         SysTryReturnResult(NID_IO, nameIndex < SECURE_IO_HEX_64, E_INVALID_ARG, "Index number is too big.");
1589
1590         if (nameIndex == 0)
1591         {
1592                 blockName = fileName + L".rpa ";
1593         }
1594         else
1595         {
1596                 blockName = fileName + L"_";
1597                 blockName.Append((int) nameIndex);
1598                 blockName.Append(L".rpa");
1599         }
1600
1601         if (_FileUtil::IsFileExist(blockName))
1602         {
1603                 r = replicaFile.Construct(blockName, "r");
1604                 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to conctruct replica file.", GetErrorMessage(r));
1605
1606                 readItems = replicaFile.Read(blockHeader, CIPHER_BLOCK_HEADER_SIZE); //Read start block number (3bytes)
1607                 if (readItems < CIPHER_BLOCK_HEADER_SIZE)
1608                 {
1609                         r = GetLastResult();
1610
1611                         if (readItems == 0 && IsEndOfFile(pNormalFile))
1612                         {
1613                                 r = E_END_OF_FILE;
1614                         }
1615
1616                         SysLog(NID_IO, "[%s] Failed to read data from file.", GetErrorMessage(r));
1617                         return r;
1618                 }
1619
1620                 pBlockDataCur = (byte*) (&startBlockNum);
1621                 *pBlockDataCur = blockHeader[SECURE_IO_2_BYTES];
1622                 *(pBlockDataCur + 1) = blockHeader[1];
1623                 *(pBlockDataCur + SECURE_IO_2_BYTES) = blockHeader[0];
1624
1625                 r = replicaFile.Seek(FILESEEKPOSITION_END, 0);
1626                 fileLength = replicaFile.Tell();
1627                 SysTryReturn(NID_IO, fileLength != -1, GetLastResult(), GetLastResult(), "[%s] Failed to tell in file.", GetErrorMessage(GetLastResult()));
1628
1629                 r = replicaFile.Seek(FILESEEKPOSITION_BEGIN, CIPHER_BLOCK_HEADER_SIZE);
1630                 unique_ptr< byte[] > pBlock(new (std::nothrow) byte[fileLength - CIPHER_BLOCK_HEADER_SIZE]);
1631                 SysTryReturnResult(NID_IO, pBlock != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
1632
1633                 memset(pBlock.get(), 0, fileLength - CIPHER_BLOCK_HEADER_SIZE);
1634
1635                 readItems = replicaFile.Read(pBlock.get(), fileLength - CIPHER_BLOCK_HEADER_SIZE);
1636                 if (readItems < (fileLength - CIPHER_BLOCK_HEADER_SIZE))
1637                 {
1638                         r = GetLastResult();
1639
1640                         if (readItems == 0 && IsEndOfFile(pNormalFile))
1641                         {
1642                                 r = E_END_OF_FILE;
1643                         }
1644
1645                         SysLog(NID_IO, "[%s] Failed to read data from file.", GetErrorMessage(r));
1646                         return r;
1647                 }
1648
1649                 r = pNormalFile->Seek(FILESEEKPOSITION_BEGIN, SECURE_FILE_HEADER_SIZE_V1 + (CIPHER_BLOCK_SIZE + CIPHER_BLOCK_HEADER_SIZE) * startBlockNum);
1650
1651                 r = pNormalFile->Write(pBlock.get(), fileLength - CIPHER_BLOCK_HEADER_SIZE);
1652                 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to write in file.", GetErrorMessage(r));
1653
1654         }
1655
1656         r = pNormalFile->Truncate(dataLen);
1657         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to truncate in file.", GetErrorMessage(r));
1658
1659         return E_SUCCESS;
1660 }
1661
1662 result
1663 _SecureIoUtil::MakeCipherBlockReplica(_NormalFile* pNormalFile, const String filePath, int dataPosition, int dataSize)
1664 {
1665         result r = E_SUCCESS;
1666         int totalDataSize = 0;
1667         int blockSize = 0;
1668         int headPos = 0;
1669         int tailPos = 0;
1670         int startBlockNum = 0;
1671         int ret = 0;
1672         long blockDataSize = 0;
1673         bool isEndOfBlock = false;
1674         String replicaName;
1675         byte* pBlockDataCur = null;
1676         byte blockHeader[CIPHER_BLOCK_HEADER_SIZE] = {0, 0, 0};
1677         byte nameIndex = 0;
1678         _NormalFile tempBlockFile;
1679
1680         totalDataSize = dataPosition + dataSize;
1681
1682         ClearLastResult();
1683         headPos = pNormalFile->Tell();
1684         SysTryReturn(NID_IO, headPos != -1, GetLastResult(), GetLastResult(), "[%s] Failed to tell in file.", GetErrorMessage(GetLastResult()));
1685
1686         ret = pNormalFile->Read(blockHeader, CIPHER_BLOCK_HEADER_SIZE);
1687         if (ret < CIPHER_BLOCK_HEADER_SIZE)
1688         {
1689                 r = GetLastResult();
1690
1691                 if (ret == 0 && IsEndOfFile(pNormalFile))
1692                 {
1693                         r = E_END_OF_FILE;
1694                 }
1695
1696                 SysLog(NID_IO, "[%s] Failed to read data from file.", GetErrorMessage(r));
1697                 return r;
1698         }
1699
1700         while (true)
1701         {
1702                 blockDataSize = 0;
1703                 pBlockDataCur = (byte*) (&blockDataSize);
1704                 *pBlockDataCur = blockHeader[SECURE_IO_2_BYTES];
1705                 *(pBlockDataCur + 1) = blockHeader[1];
1706                 *(pBlockDataCur + SECURE_IO_2_BYTES) = blockHeader[0];
1707                 blockSize = blockSize + blockDataSize;
1708
1709                 if (blockSize >= totalDataSize)
1710                 {
1711                         isEndOfBlock = true;
1712                 }
1713
1714                 if (blockDataSize % ONE_BLOCK_SIZE != 0)
1715                 {
1716                         r = pNormalFile->Seek(FILESEEKPOSITION_CURRENT, blockDataSize + ONE_BLOCK_SIZE - blockDataSize % ONE_BLOCK_SIZE);
1717                 }
1718                 else
1719                 {
1720                         r = pNormalFile->Seek(FILESEEKPOSITION_CURRENT, blockDataSize);
1721                 }
1722
1723                 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to seek in file.", GetErrorMessage(r));
1724
1725                 if (isEndOfBlock)
1726                 {
1727                         break;
1728                 }
1729
1730                 if (IsEndOfFile(pNormalFile))
1731                 {
1732                         break;
1733                 }
1734
1735                 ret = pNormalFile->Read(blockHeader, CIPHER_BLOCK_HEADER_SIZE);
1736                 if (ret < CIPHER_BLOCK_HEADER_SIZE)
1737                 {
1738                         r = GetLastResult();
1739
1740                         if (ret == 0 && IsEndOfFile(pNormalFile))
1741                         {
1742                                 break;
1743                         }
1744
1745                         SysLog(NID_IO, "[%s] Failed to read data from file.", GetErrorMessage(r));
1746                         return r;
1747                 }
1748
1749         }
1750
1751         tailPos = pNormalFile->Tell();
1752         SysTryReturn(NID_IO, tailPos != -1, GetLastResult(), GetLastResult(), "[%s] Failed to tell in file.", GetErrorMessage(GetLastResult()));
1753
1754         startBlockNum = (headPos - SECURE_FILE_HEADER_SIZE_V1) / (CIPHER_BLOCK_SIZE + CIPHER_BLOCK_HEADER_SIZE);
1755
1756         r = pNormalFile->Seek(FILESEEKPOSITION_BEGIN, headPos);
1757         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to seek in file.", GetErrorMessage(r));
1758
1759         unique_ptr< byte[] > pBlockReplica(new (std::nothrow) byte[tailPos - headPos + CIPHER_BLOCK_HEADER_SIZE]);
1760         SysTryReturnResult(NID_IO, pBlockReplica != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
1761
1762         *(reinterpret_cast< byte* >(pBlockReplica.get()) + SECURE_IO_2_BYTES) = (byte) (startBlockNum & SECURE_IO_HEX_FF);
1763         *(reinterpret_cast< byte* >(pBlockReplica.get()) + 1) = (byte) ((startBlockNum >> SECURE_IO_8_BITS) & SECURE_IO_HEX_FF);
1764         *(reinterpret_cast< byte* >(pBlockReplica.get())) = (byte) ((startBlockNum >> (SECURE_IO_8_BITS * SECURE_IO_2_BYTES)) & SECURE_IO_HEX_FF);
1765
1766         ret = pNormalFile->Read(reinterpret_cast< byte* >(pBlockReplica.get()) + CIPHER_BLOCK_HEADER_SIZE, tailPos - headPos);
1767         if (ret < (tailPos - headPos))
1768         {
1769                 r = GetLastResult();
1770
1771                 if (ret == 0 && IsEndOfFile(pNormalFile))
1772                 {
1773                         r = E_END_OF_FILE;
1774                 }
1775
1776                 SysLog(NID_IO, "[%s] Failed to read data from file.", GetErrorMessage(r));
1777                 return r;
1778         }
1779
1780         while (true)
1781         {
1782                 SysTryReturnResult(NID_IO, nameIndex <= SECURE_IO_HEX_64, E_INVALID_ARG, "Index number is too big.");
1783
1784                 if (nameIndex == 0)
1785                 {
1786                         replicaName = filePath + L".rpa ";
1787                         if (!File::IsFileExist(replicaName))
1788                         {
1789                                 break;
1790                         }
1791                 }
1792                 else
1793                 {
1794                         replicaName = filePath + L"_";
1795                         replicaName.Append((int) nameIndex);
1796                         replicaName.Append(L".rpa");
1797
1798                         if (!File::IsFileExist(replicaName))
1799                         {
1800                                 break;
1801                         }
1802                 }
1803                 nameIndex++;
1804         }
1805
1806         r = tempBlockFile.Construct(replicaName, "w");
1807         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to call construct.", GetErrorMessage(r));
1808
1809         r = tempBlockFile.Write(pBlockReplica.get(), tailPos - headPos + CIPHER_BLOCK_HEADER_SIZE);
1810         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to write in file.", GetErrorMessage(r));
1811
1812         r = pNormalFile->Seek(FILESEEKPOSITION_BEGIN, 25);
1813         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to seek in file.", GetErrorMessage(r));
1814
1815         r = pNormalFile->Write(&nameIndex, 1);
1816         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to write in file.", GetErrorMessage(r));
1817
1818         r = pNormalFile->Seek(FILESEEKPOSITION_BEGIN, headPos);
1819         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to seek in file.", GetErrorMessage(r));
1820
1821         return r;
1822 }
1823
1824 bool
1825 _SecureIoUtil::IsNormalDatabase(_DatabaseMode mode)
1826 {
1827         ClearLastResult();
1828         if (mode == DATABASE_MODE_NORMAL)
1829         {
1830                 return true;
1831         }
1832         return false;
1833 }
1834
1835 bool
1836 _SecureIoUtil::IsSecureDatabase(_DatabaseMode mode)
1837 {
1838         ClearLastResult();
1839         if (mode == DATABASE_MODE_SECURE)
1840         {
1841                 return true;
1842         }
1843         return false;
1844 }
1845
1846 _DatabaseMode
1847 _SecureIoUtil::GetDatabaseMode(char* pStrPhysicalDbPath)
1848 {
1849         result r = E_SUCCESS;
1850         int fileLength = 0;
1851         unsigned long readBytes = 0;
1852         char buffer[SQLITE_HEADER_SIZE] = {0, };
1853         char magicNum1[SECURE_IO_MAGIC_NUMBER_SIZE] = {0xCA, 0xFE, 0xBE, 0xBE};
1854         char magicNum2[SECURE_IO_MAGIC_NUMBER_SIZE] = {0xDA, 0xEF, 0xEF, 0xEB};
1855         _NormalFile normalFile;
1856
1857         ClearLastResult();
1858
1859         r = normalFile.Construct(pStrPhysicalDbPath, "r");
1860         SysTryReturn(NID_IO, !IsFailed(r), DATABASE_MODE_ERROR, r, "[%s] Failed to open file (%s) in read mode", GetErrorMessage(r), pStrPhysicalDbPath);
1861
1862         r = normalFile.Seek(FILESEEKPOSITION_END, 0);
1863         SysTryReturn(NID_IO, !IsFailed(r), DATABASE_MODE_ERROR, r, "[%s] Failed to seek in file.", GetErrorMessage(r));
1864
1865         fileLength = normalFile.Tell();
1866         if (fileLength <= 0)
1867         {
1868                 return DATABASE_MODE_NONE;
1869         }
1870
1871         r = normalFile.Seek(FILESEEKPOSITION_BEGIN, 0);
1872         SysTryReturn(NID_IO, !IsFailed(r), DATABASE_MODE_ERROR, r, "[%s] Failed to seek in file.", GetErrorMessage(r));
1873
1874         readBytes = normalFile.Read(buffer, SQLITE_HEADER_SIZE);
1875         r = GetLastResult();
1876         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));
1877
1878         if (!strncmp(buffer, "SQLite format 3", SQLITE_FORMAT_STR_SIZE))
1879         {
1880                 return DATABASE_MODE_NORMAL;
1881         } //is normal file
1882         else if (!memcmp((void*) buffer, magicNum1, SECURE_IO_MAGIC_NUMBER_SIZE) && !memcmp((void*) (buffer + SECURE_IO_12_BYTES), magicNum2, SECURE_IO_MAGIC_NUMBER_SIZE))
1883         {
1884                 return DATABASE_MODE_SECURE;
1885         } //is secure file
1886
1887         return DATABASE_MODE_ERROR;
1888 }
1889
1890 byte*
1891 _SecureIoUtil::GenerateDatabaseKeyN(const Tizen::Base::ByteBuffer* pUserKey)
1892 {
1893         byte lowByte = 0;
1894         byte highByte = 0;
1895         byte* pKey = null;
1896         byte* pDbKey = null;
1897
1898         ClearLastResult();
1899
1900         unique_ptr< ByteBuffer > pKeyBuffer(GetSecureKeyN(pUserKey));
1901
1902         SysTryReturn(NID_IO, pKeyBuffer != null, null, E_INVALID_ARG, "[E_INVALID_ARG] Failed to generate secure key.");
1903
1904         pKey = const_cast< byte* >(pKeyBuffer->GetPointer());
1905
1906         pDbKey = new (std::nothrow) byte[DATABASE_KEY_LENGTH * SECURE_IO_2_BYTES + 1];
1907         SysTryReturn(NID_IO, pDbKey != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
1908
1909         memset(pDbKey, 0, DATABASE_KEY_LENGTH * SECURE_IO_2_BYTES + 1);
1910
1911         for (int i = 0; i < DATABASE_KEY_LENGTH; i++)
1912         {
1913                 lowByte = pKey[i] & SECURE_IO_HEX_0F;
1914                 highByte = (pKey[i] >> SECURE_IO_4_BITS) & SECURE_IO_HEX_0F;
1915                 if (lowByte <= SECURE_IO_9_BYTES)
1916                 {
1917                         pDbKey[i * SECURE_IO_2_BYTES + 1] = lowByte + '0';
1918                 }
1919                 else
1920                 {
1921                         pDbKey[i * SECURE_IO_2_BYTES + 1] = lowByte - SECURE_IO_10_BYTES + 'A';
1922                 }
1923
1924                 if (highByte <= SECURE_IO_9_BYTES)
1925                 {
1926                         pDbKey[i * SECURE_IO_2_BYTES] = highByte + '0';
1927                 }
1928                 else
1929                 {
1930                         pDbKey[i * SECURE_IO_2_BYTES] = highByte - SECURE_IO_10_BYTES + 'A';
1931                 }
1932         }
1933
1934         return pDbKey;
1935 }
1936
1937 bool
1938 _SecureIoUtil::IsEmpty(const String& filePath)
1939 {
1940         result r = E_SUCCESS;
1941         FileAttributes attribute;
1942
1943         SetLastResult(r);
1944         r = File::GetAttributes(filePath, attribute);
1945         if (IsFailed(r))
1946         {
1947                 SetLastResult(r);
1948                 return false;
1949         }
1950
1951         if (attribute.GetFileSize() == 0)
1952         {
1953                 return true;
1954         }
1955         else
1956         {
1957                 return false;
1958         }
1959 }
1960
1961 } } //Tizen::Io