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