#undef __USE_FILE_OFFSET64
#include <unistd.h>
-#include <string>
#include <sys/stat.h>
#include <fts.h>
#include <string.h>
#include <errno.h>
+#include <cstdio>
+#include <sstream>
+#include<iostream>
+
+#include <memory>
#include <dpl/log/log.h>
#include <dpl/errno_string.h>
#include <dpl/foreach.h>
+#include <dpl/scoped_fclose.h>
#include <dpl/wrt-dao-ro/global_config.h>
+#include <dpl/string.h>
+#include <FBaseByteBuffer.h>
+#include <security/FSecCrypto_TrustZoneService.h>
#include <widget_install/job_widget_install.h>
#include <widget_install/widget_install_context.h>
#include <widget_install/widget_install_errors.h>
using namespace WrtDB;
-using namespace WRTEncryptor;
+
+extern "C"
+{
+ void InitWebAppInfo(const char* appId, const char* rootPath);
+}
namespace {
+const std::size_t ENCRYPTION_CHUNK_MAX_SIZE = 4096; // bytes
+const std::size_t ENCRYPTION_DEC_CHUNK_SIZE = 4; // bytes
+static bool initWebApp = false;
+
std::set<std::string>& getSupportedForEncryption()
{
static std::set<std::string> encryptSet;
}
return false;
}
+
+/**
+ * Opens a file.
+ *
+ * @param path Path to a file.
+ * @param mode Mode.
+ * @return Stream handle.
+ * @throw ExtractFileFailed If error (other than EINTR) occurs.
+ */
+FILE* openFile(const std::string& path, const std::string& mode)
+{
+ FILE* result = NULL;
+
+ do
+ {
+ result = fopen(path.c_str(), mode.c_str());
+ } while ((NULL == result) && (EINTR == errno));
+
+ if (NULL == result)
+ {
+ ThrowMsg(Jobs::WidgetInstall::Exceptions::EncryptionFailed,
+ "Could not open file " << path);
+ }
+
+ return result;
+}
+
+/**
+ * Reads bytes from a stream.
+ *
+ * @param buffer Buffer to read the bytes into.
+ * @param count Number of bytes to read.
+ * @param stream Stream to read from.
+ * @return Number of bytes read
+ * @throw ExtractFileFailed If error (other than EINTR) occurs.
+ */
+std::size_t readBytes(unsigned char* buffer, std::size_t count, FILE* stream)
+{
+ std::size_t result = std::fread(buffer,
+ sizeof(unsigned char),
+ count,
+ stream);
+
+ if (result != count)
+ {
+ int error = errno;
+ if (0 != std::ferror(stream))
+ {
+ if (EINTR != error)
+ {
+ ThrowMsg(Jobs::WidgetInstall::Exceptions::ErrorExternalInstallingFailure,
+ "Error while reading data" <<
+ " [" << DPL::GetErrnoString(error) << "]");
+ }
+ }
+ }
+
+ return result;
+}
+
+/**
+ * Writes bytes to a stream.
+ *
+ * @param buffer Data to write.
+ * @param count Number of bytes.
+ * @param stream Stream to write to.
+ * @throw ExtractFileFailed If error (other than EINTR) occurs.
+ */
+void writeBytes(unsigned char* buffer, std::size_t count, FILE* stream)
+{
+ std::size_t bytesWritten = 0;
+ std::size_t bytesToWrite = 0;
+ do
+ {
+ bytesToWrite = count - bytesWritten;
+ bytesWritten = std::fwrite(buffer + bytesWritten,
+ sizeof(unsigned char),
+ count - bytesWritten,
+ stream);
+ if ((bytesWritten != bytesToWrite) && (EINTR != errno))
+ {
+ int error = errno;
+ ThrowMsg(Jobs::WidgetInstall::Exceptions::EncryptionFailed,
+ "Error while writing data" <<
+ " [" << DPL::GetErrnoString(error) << "]");
+ }
+ } while ((bytesWritten != bytesToWrite) && (EINTR == errno));
+}
+
+/*
+ * get encrypted string from trustzone
+*/
+Tizen::Base::ByteBuffer* EncryptChunkByTrustZone(
+ Tizen::Base::ByteBuffer* appInfo,
+ const unsigned char *plainBuffer,
+ int pBufSize)
+{
+ using namespace Tizen::Base;
+ if(!initWebApp)
+ {
+ char* pAppId = null;
+ pAppId = (char*)calloc(appInfo->GetRemaining()+1, 1);
+ memcpy(pAppId, appInfo->GetPointer(), appInfo->GetRemaining());
+ InitWebAppInfo(pAppId, "");
+ free (pAppId);
+ initWebApp = true;
+ }
+
+ Tizen::Security::Crypto::_TrustZoneService* pInstance;
+ pInstance = Tizen::Security::Crypto::_TrustZoneService::GetInstance();
+
+ ByteBuffer pBuf;
+ pBuf.Construct(pBufSize);
+ const byte *pByte = reinterpret_cast<const byte*>(plainBuffer);
+ if (pBuf.SetArray(pByte, 0, pBufSize) != E_SUCCESS) {
+ LogDebug("Couldnot set pBuf");
+ return NULL;
+ }
+ pBuf.Flip();
+
+ return pInstance->_TrustZoneService::EncryptN(*appInfo, pBuf);
+}
+
+Tizen::Base::ByteBuffer* TEST_dec(
+ Tizen::Base::ByteBuffer* appInfo,
+ const unsigned char *plainBuffer,
+ int pBufSize)
+{
+ using namespace Tizen::Base;
+
+ Tizen::Security::Crypto::_TrustZoneService* pInstance;
+ pInstance = Tizen::Security::Crypto::_TrustZoneService::GetInstance();
+
+ ByteBuffer pBuf;
+ pBuf.Construct(pBufSize);
+ const byte *pByte = reinterpret_cast<const byte*>(plainBuffer);
+ if (pBuf.SetArray(pByte, 0, pBufSize) != E_SUCCESS) {
+ LogDebug("Couldnot set pBuf");
+ return NULL;
+ }
+ pBuf.Flip();
+
+ return pInstance->_TrustZoneService::DecryptN(*appInfo, pBuf);
+}
}
namespace Jobs {
void TaskEncryptResource::StepEncryptResource()
{
LogDebug("Step Encrypt resource");
- m_resEnc = new ResourceEncryptor;
- m_resEnc->CreateEncryptionKey(DPL::ToUTF8String(*m_context.
- widgetConfig.pkgname));
EncryptDirectory(m_context.locations->getTemporaryRootDir());
+ m_context.job->UpdateProgress(
+ InstallerContext::INSTALL_ECRYPTION_FILES,
+ "Ecrypt resource files");
}
void TaskEncryptResource::EncryptDirectory(std::string path)
{
FTS *fts;
FTSENT *ftsent;
- char * const paths[] = {const_cast<char * const>(path.c_str()), NULL};
+ char * const paths[] = { const_cast<char * const>(path.c_str()), NULL };
- if ((fts = fts_open(paths, FTS_PHYSICAL|FTS_NOCHDIR, NULL)) == NULL) {
+ if ((fts = fts_open(paths, FTS_PHYSICAL | FTS_NOCHDIR, NULL)) == NULL) {
//ERROR
int error = errno;
LogWarning(__PRETTY_FUNCTION__ << ": fts_open failed with error: "
- << strerror(error));
- ThrowMsg(Exceptions::InternalError, "Error reading directory: "
- << path);
+ << strerror(error));
+ ThrowMsg(Exceptions::EncryptionFailed, "Error reading directory: "
+ << path);
}
while ((ftsent = fts_read(fts)) != NULL) {
switch (ftsent->fts_info) {
- case FTS_DP:
- case FTS_DC:
- case FTS_D:
- case FTS_DEFAULT:
- case FTS_SLNONE:
- //directories, non-regular files, dangling symbolic links
- break;
- case FTS_F:
- case FTS_NSOK:
- case FTS_SL:
- //regular files and other objects that can be counted
- if (isSupportedForEncryption(ftsent->fts_path)) {
- EncryptFile(ftsent->fts_path);
- }
- break;
- case FTS_NS:
- case FTS_DOT:
- case FTS_DNR:
- case FTS_ERR:
- default:
- LogWarning(__PRETTY_FUNCTION__
- << ": traversal failed on file: "
- << ftsent->fts_path
- << " with error: "
- << strerror(ftsent->fts_errno));
- ThrowMsg(Exceptions::InternalError, "Error reading file");
+ case FTS_DP:
+ case FTS_DC:
+ case FTS_D:
+ case FTS_DEFAULT:
+ case FTS_SLNONE:
+ //directories, non-regular files, dangling symbolic links
+ break;
+ case FTS_F:
+ case FTS_NSOK:
+ case FTS_SL:
+ //regular files and other objects that can be counted
+ if (isSupportedForEncryption(ftsent->fts_path)) {
+ EncryptFile(ftsent->fts_path);
+ }
+ break;
+ case FTS_NS:
+ case FTS_DOT:
+ case FTS_DNR:
+ case FTS_ERR:
+ default:
+ LogWarning(__PRETTY_FUNCTION__
+ << ": traversal failed on file: "
+ << ftsent->fts_path
+ << " with error: "
+ << strerror(ftsent->fts_errno));
+ ThrowMsg(Exceptions::EncryptionFailed, "Error reading file");
+ break;
}
}
if (fts_close(fts) == -1) {
int error = errno;
LogWarning(__PRETTY_FUNCTION__ << ": fts_close failed with error: "
- << strerror(error));
+ << strerror(error));
}
}
void TaskEncryptResource::EncryptFile(const std::string &fileName)
{
- Try
+ LogDebug("Encrypt file: " << fileName);
+ std::string encFile = fileName + ".enc";
+
+ struct stat info;
+ memset(&info, 0, sizeof(info));
+ if (stat(fileName.c_str(), &info) != 0)
{
- LogDebug("Need to ecnrypt file Name " << fileName);
- std::string encFile = fileName + ".enc";
-
- struct stat buf;
- int ret = stat(fileName.c_str(), &buf);
- if(ret == 0) {
- size_t fileSize = buf.st_size;
-
- FILE* resFp = fopen(fileName.c_str(), "r");
- if ( NULL == resFp) {
- LogError("Couldnot open file : " << fileName);
- return;
- }
+ int error = errno;
+ ThrowMsg(Exceptions::EncryptionFailed,
+ "Could not access file " << fileName <<
+ "[" << DPL::GetErrnoString(error) << "]");
+ }
+ const std::size_t fileSize = info.st_size;
- int blockSize = m_resEnc->GetBlockSize(fileSize);
- LogDebug("Get block size : " << blockSize);
+ DPL::ScopedFClose inFile(openFile(fileName, "r"));
+ DPL::ScopedFClose outFile(openFile(encFile, "w"));
- unsigned char readBuf[fileSize];
- unsigned char outEncBuf[blockSize];
- memset(readBuf, 0, fileSize);
- memset(outEncBuf, 0, blockSize);
+ const std::size_t chunkSize = (fileSize > ENCRYPTION_CHUNK_MAX_SIZE
+ ? ENCRYPTION_CHUNK_MAX_SIZE : fileSize);
- ret = fread(readBuf, sizeof(unsigned char), fileSize, resFp);
- if (ret!=fileSize){
- LogError("Failed to read ecryption buffer with error: " << strerror(errno) );
- fclose(resFp);
- return;
- }
+ std::unique_ptr<unsigned char[]> inChunk(new unsigned char[chunkSize]);
+ std::unique_ptr<unsigned char[]> outChunk;
- m_resEnc->EncryptChunk(readBuf, outEncBuf, fileSize);
+ std::size_t bytesRead = 0;
+ using namespace Tizen::Base;
- FILE* encFp = fopen(encFile.c_str(), "w");
- if (NULL == encFp) {
- LogError("Failed to open ecryption file");
- fclose(resFp);
- return;
- }
- fwrite(outEncBuf, sizeof(unsigned char), blockSize, encFp);
+ std::string pkgid =
+ DPL::ToUTF8String(m_context.widgetConfig.tzAppid).c_str();
+ const byte *b_pkgid = reinterpret_cast<const byte*>(
+ pkgid.c_str());
+ ByteBuffer appInfo;
+ appInfo.Construct(pkgid.length());
- fclose(resFp);
- fclose(encFp);
+ if (appInfo.SetArray(b_pkgid, 0, pkgid.length()) != E_SUCCESS) {
+ LogDebug("Couldnot set appInfo");
+ return;
+ }
- LogDebug("Success to encrypt file");
- LogDebug("Remove unecrypted file : " << fileName);
+ appInfo.Flip();
- unlink(fileName.c_str());
- if ((rename(encFile.c_str(), fileName.c_str())) != 0) {
- ThrowMsg(Exceptions::ExtractFileFailed, fileName);
+ do
+ {
+ bytesRead = readBytes(inChunk.get(), chunkSize, inFile.Get());
+ if (0 != bytesRead) {
+ ByteBuffer *getBuffer = EncryptChunkByTrustZone(
+ &appInfo,
+ inChunk.get(), bytesRead);
+ if (getBuffer == NULL) {
+ ThrowMsg(Exceptions::EncryptionFailed,
+ "Encryption Failed using TrustZone");
}
+ int decBufSize = getBuffer->GetRemaining();
- std::string realPath = fileName;
- realPath.replace(0, m_context.locations->getTemporaryRootDir().length(),
- m_context.locations->getSourceDir());
+ outChunk.reset(new unsigned char[decBufSize]);
+ memcpy(outChunk.get(), getBuffer->GetPointer(), getBuffer->GetRemaining());
+ getBuffer->Reset();
- WrtDB::EncryptedFileInfo info;
- info.fileName = DPL::FromUTF8String(realPath);
- info.fileSize = fileSize;
+ char writeSize[ENCRYPTION_DEC_CHUNK_SIZE];
+ memset(writeSize, 0x00, ENCRYPTION_DEC_CHUNK_SIZE);
+ std::stringstream toString;
+ toString << decBufSize;
+ strncpy(writeSize, toString.str().c_str(), toString.str().length());
- m_context.widgetConfig.encryptedFiles.insert(info);
+ writeBytes((unsigned char*)writeSize,
+ ENCRYPTION_DEC_CHUNK_SIZE, outFile.Get());
+ writeBytes(outChunk.get(), decBufSize, outFile.Get());
}
+
+ } while (0 == std::feof(inFile.Get()));
+
+ outFile.Reset();
+ inFile.Reset();
+
+ LogDebug("File encrypted successfully");
+ LogDebug("Remove plain-text file: " << fileName);
+ if (0 != unlink(fileName.c_str()))
+ {
+ Throw(Exceptions::EncryptionFailed);
}
- Catch(ResourceEncryptor::Exception::Base)
+
+ LogDebug("Rename encrypted file");
+ if (0 != std::rename(encFile.c_str(), fileName.c_str()))
{
- ReThrowMsg(Exceptions::ExtractFileFailed, fileName);
+ Throw(Exceptions::EncryptionFailed);
}
+
+ std::string realPath = fileName;
+ realPath.replace(0,
+ m_context.locations->getTemporaryRootDir().length(),
+ m_context.locations->getSourceDir());
+
+ WrtDB::EncryptedFileInfo fileInfo;
+ fileInfo.fileName = DPL::FromUTF8String(realPath);
+ fileInfo.fileSize = fileSize;
+
+ m_context.widgetConfig.encryptedFiles.insert(fileInfo);
}
+
} //namespace WidgetInstall
} //namespace Jobs