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