X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fjobs%2Fwidget_install%2Ftask_encrypt_resource.cpp;h=bca566575455274e304f75699a132136e0834f6e;hb=333a1bbb85bc9e6917330ec04b9d6f5265e24055;hp=b6fe72007b7635546892243075c9dca46f3b1b63;hpb=8751fcd683990373dd3d8275dc01052a658fe34f;p=framework%2Fweb%2Fwrt-installer.git diff --git a/src/jobs/widget_install/task_encrypt_resource.cpp b/src/jobs/widget_install/task_encrypt_resource.cpp index b6fe720..bca5665 100644 --- a/src/jobs/widget_install/task_encrypt_resource.cpp +++ b/src/jobs/widget_install/task_encrypt_resource.cpp @@ -24,25 +24,41 @@ #undef __USE_FILE_OFFSET64 #include -#include #include #include #include #include +#include +#include +#include + +#include #include #include #include +#include #include +#include +#include +#include #include #include #include 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& getSupportedForEncryption() { static std::set encryptSet; @@ -63,6 +79,150 @@ bool isSupportedForEncryption(const std::string &file) } 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(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(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 { @@ -77,135 +237,162 @@ TaskEncryptResource::TaskEncryptResource(InstallerContext& context) : void TaskEncryptResource::StepEncryptResource() { LogDebug("Step Encrypt resource"); - m_resEnc = new ResourceEncryptor; - m_resEnc->CreateEncryptionKey(DPL::ToUTF8String(m_context. - widgetConfig.tzAppid)); 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(path.c_str()), NULL}; + char * const paths[] = { const_cast(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 inChunk(new unsigned char[chunkSize]); + std::unique_ptr 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( + 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); + 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