Encryption support 94/45094/3
authorPawel Sikorski <p.sikorski@samsung.com>
Wed, 29 Jul 2015 13:58:24 +0000 (15:58 +0200)
committerPawel Sikorski <p.sikorski@samsung.com>
Mon, 10 Aug 2015 10:38:54 +0000 (12:38 +0200)
Seperate step introduced to implement WebApp files Encryption feature.

Note: original files are REPLACED by encrypted files

WARNING: not verified - WAE_ERROR_PERMISSION_DENIED returned from
wae_encrypt_web_application

Change-Id: Icbb2e507208629a5c02778e38b836ae866d450e8

CMakeLists.txt
packaging/app-installers.spec
src/wgt/CMakeLists.txt
src/wgt/step/step_encrypt_resources.cc [new file with mode: 0644]
src/wgt/step/step_encrypt_resources.h [new file with mode: 0644]
src/wgt/wgt_backend.cc

index efd073a..0b92d1c 100644 (file)
@@ -49,6 +49,7 @@ PKG_CHECK_MODULES(PKGMGR_PARSER_DEPS REQUIRED pkgmgr-parser)
 PKG_CHECK_MODULES(PKGMGR_INFO_DEPS REQUIRED pkgmgr-info)
 PKG_CHECK_MODULES(LIBXML_DEPS REQUIRED libxml-2.0)
 PKG_CHECK_MODULES(PRIVILEGE_CHECKER_DEPS REQUIRED capi-security-privilege-manager)
+PKG_CHECK_MODULES(ENCRYPTION_DEPS REQUIRED libwebappenc)
 
 FIND_PACKAGE(Boost REQUIRED COMPONENTS system filesystem regex)
 FIND_PACKAGE(GTest REQUIRED)
index d42505b..c139072 100644 (file)
@@ -30,6 +30,7 @@ BuildRequires:  pkgconfig(cert-svc-vcore)
 BuildRequires:  pkgconfig(manifest-parser)
 BuildRequires:  pkgconfig(manifest-handlers)
 BuildRequires:  pkgconfig(capi-security-privilege-manager)
+BuildRequires:  pkgconfig(libwebappenc)
 
 Requires: ca-certificates-tizen
 Requires: libtzplatform-config
index 92a359a..ce9e194 100644 (file)
@@ -3,6 +3,7 @@ SET(SRCS
   rds_parser.cc
   step/step_check_settings_level.cc
   step/step_create_symbolic_link.cc
+  step/step_encrypt_resources.cc
   step/step_parse.cc
   step/step_rds_parse.cc
   step/step_rds_modify.cc
@@ -30,6 +31,7 @@ APPLY_PKG_CONFIG(${TARGET_WGT_BACKEND} PUBLIC
   MANIFEST_HANDLERS_DEPS
   MANIFEST_PARSER_DEPS
   PKGMGR_INSTALLER_DEPS
+  ENCRYPTION_DEPS
 )
 
 # Target - in-package deps
diff --git a/src/wgt/step/step_encrypt_resources.cc b/src/wgt/step/step_encrypt_resources.cc
new file mode 100644 (file)
index 0000000..1511431
--- /dev/null
@@ -0,0 +1,201 @@
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#include "wgt/step/step_encrypt_resources.h"
+
+#include <web_app_enc.h>
+
+#include <boost/filesystem/operations.hpp>
+#include <boost/system/error_code.hpp>
+#include <algorithm>
+#include <cstdio>
+#include <cstdlib>
+#include <set>
+#include <string>
+
+#include "common/utils/file_util.h"
+#include "common/utils/logging.h"
+
+namespace {
+
+const std::set<std::string> encryptSet { ".html", ".htm", ".css", ".js"};
+
+}  // namespace
+
+
+namespace wgt {
+namespace encrypt {
+
+namespace bf = boost::filesystem;
+namespace bs = boost::system;
+
+common_installer::Step::Status StepEncryptResources::precheck() {
+  backend_data_ = static_cast<WgtBackendData*>(context_->backend_data.get());
+  if (!backend_data_) {
+    LOG(ERROR) << "no backend data";
+    return common_installer::Step::Status::ERROR;
+  }
+
+  input_ = context_->unpacked_dir_path.get();
+
+  if (input_.empty()) {
+    LOG(ERROR) << "unpacked_dir_path attribute is empty";
+    return Step::Status::INVALID_VALUE;
+  }
+  if (!bf::exists(input_)) {
+    LOG(ERROR) << "unpacked_dir_path (" << input_ << ") path does not exist";
+    return Step::Status::INVALID_VALUE;
+  }
+
+  return common_installer::Step::Status::OK;
+}
+
+common_installer::Step::Status StepEncryptResources::process() {
+  if (!backend_data_->settings.get().encryption_enabled()) {
+    LOG(DEBUG) << "no encryption";
+    return common_installer::Step::Status::OK;
+  }
+
+  if (!Encrypt(input_)) {
+    LOG(ERROR) << "Error during encryption";
+    return common_installer::Step::Status::ERROR;
+  }
+
+  return common_installer::Step::Status::OK;
+}
+
+bool StepEncryptResources::Encrypt(const bf::path &src) {
+  // traversing through src dir (recurrence if subdir found)
+  // for every file found, check if it should be encrypted (ToBeEncrypted)
+  // if yes, encrypt it (and replace original one)
+  // if not, leave it
+  for (bf::directory_iterator file(src);
+       file != bf::directory_iterator();
+       ++file) {
+    bs::error_code error_code;
+    bf::path current(file->path());
+
+    bool is_dir = bf::is_directory(current, error_code);
+    if (error_code)
+      return false;
+    if (is_dir) {
+      if (!Encrypt(current))
+        return false;
+      continue;
+    }
+
+    bool is_sym = bf::is_symlink(current, error_code);
+    if (error_code)
+      return false;
+    if (is_sym)
+      continue;  // TODO(p.sikorski) is it enough?
+
+    // it is regular file (not dir, not symlink)
+    if (ToBeEncrypted(current)) {
+      LOG(INFO) << "File for encryption: " << current;
+      if (!EncryptFile(current))
+        return false;
+    }
+  }
+  return true;
+}
+
+bool StepEncryptResources::EncryptFile(const bf::path &src) {
+  FILE *input = fopen(src.string().c_str(), "rb");
+  if (!input) {
+    LOG(ERROR) << "Cannot open file for encryption: " << src;
+    return false;
+  }
+
+  // read size
+  fseek(input , 0 , SEEK_END);
+  size_t length = ftell(input);
+  rewind(input);
+
+  char *input_buffer = new char[length];
+  if (length != fread(input_buffer, sizeof(char), length, input)) {
+    LOG(ERROR) << "Read error, file: " << src;
+    fclose(input);
+    delete []input_buffer;
+    return false;
+  }
+  fclose(input);
+
+  unsigned char* encrypted_data = nullptr;
+  size_t enc_data_len = 0;
+  // TODO(p.sikorski) check if it is Preloaded
+  int is_preloaded = 0;
+
+  int ret = wae_encrypt_web_application(
+              context_->pkgid.get().c_str(),
+              is_preloaded,
+              reinterpret_cast<const unsigned char*>(input_buffer),
+              length,
+              &encrypted_data,
+              &enc_data_len);
+  delete []input_buffer;
+  if (WAE_ERROR_NONE != ret) {
+    switch (ret) {
+    case WAE_ERROR_INVALID_PARAMETER:
+      LOG(ERROR) << "Error during encrypting: WAE_ERROR_INVALID_PARAMETER";
+      break;
+    case WAE_ERROR_PERMISSION_DENIED:
+      LOG(ERROR) << "Error during encrypting: WAE_ERROR_PERMISSION_DENIED";
+      break;
+    case WAE_ERROR_NO_KEY:
+      LOG(ERROR) << "Error during encrypting: WAE_ERROR_NO_KEY";
+      break;
+    case WAE_ERROR_KEY_MANAGER:
+      LOG(ERROR) << "Error during encrypting: WAE_ERROR_KEY_MANAGER";
+      break;
+    case WAE_ERROR_CRYPTO:
+      LOG(ERROR) << "Error during encrypting: WAE_ERROR_CRYPTO";
+      break;
+    case WAE_ERROR_UNKNOWN:
+      LOG(ERROR) << "Error during encrypting: WAE_ERROR_UNKNOWN";
+      break;
+    default:
+      LOG(ERROR) << "Error during encrypting: UNKNOWN";
+      break;
+    }
+    return false;
+  }
+
+  // original file is treated as destination!
+  FILE *output = fopen(src.string().c_str(), "wb");
+  if (!output) {
+    LOG(ERROR) << "Cannot create encrypted file: " << src;
+    free(encrypted_data);
+    return false;
+  }
+
+  if (enc_data_len != fwrite(reinterpret_cast<const char*>(encrypted_data),
+                             sizeof(char),
+                             enc_data_len,
+                             output)) {
+    LOG(ERROR) << "Write error, file: " << src;
+    free(encrypted_data);
+    fclose(output);
+    return false;
+  }
+
+
+  fclose(output);
+  free(encrypted_data);
+  return true;
+}
+
+bool StepEncryptResources::ToBeEncrypted(const bf::path &file) {
+  size_t found_key = file.string().rfind(".");
+  if (std::string::npos != found_key) {
+    std::string mimeType = file.string().substr(found_key);
+    std::transform(mimeType.begin(), mimeType.end(), mimeType.begin(),
+                   ::tolower);
+    return encryptSet.count(mimeType) > 0;
+  }
+  return false;
+}
+
+}  // namespace encrypt
+}  // namespace wgt
diff --git a/src/wgt/step/step_encrypt_resources.h b/src/wgt/step/step_encrypt_resources.h
new file mode 100644 (file)
index 0000000..0875976
--- /dev/null
@@ -0,0 +1,36 @@
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#ifndef WGT_STEP_STEP_ENCRYPT_RESOURCES_H_
+#define WGT_STEP_STEP_ENCRYPT_RESOURCES_H_
+
+#include <boost/filesystem/path.hpp>
+
+#include "common/step/step.h"
+#include "common/utils/logging.h"
+#include "wgt/wgt_backend_data.h"
+
+namespace wgt {
+namespace encrypt {
+
+class StepEncryptResources : public common_installer::Step {
+ public:
+  using Step::Step;
+
+  Status process() override;
+  Status clean() override { return Status::OK; }
+  Status undo() override { return Status::OK; }
+  Status precheck() override;
+
+ private:
+  bool Encrypt(const boost::filesystem::path &src);
+  bool EncryptFile(const boost::filesystem::path &src);
+  bool ToBeEncrypted(const boost::filesystem::path &file);
+  WgtBackendData* backend_data_;
+  boost::filesystem::path input_;
+  SCOPE_LOG_TAG(EncryptResources)
+};
+}  // namespace encrypt
+}  // namespace wgt
+#endif  // WGT_STEP_STEP_ENCRYPT_RESOURCES_H_
index ca667c3..a3cb9c2 100644 (file)
@@ -30,6 +30,7 @@
 
 #include "wgt/step/step_create_symbolic_link.h"
 #include "wgt/step/step_check_settings_level.h"
+#include "wgt/step/step_encrypt_resources.h"
 #include "wgt/step/step_parse.h"
 #include "wgt/step/step_rds_parse.h"
 #include "wgt/step/step_rds_modify.h"
@@ -59,6 +60,7 @@ int main(int argc, char** argv) {
       installer.AddStep<wgt::parse::StepParse>();
       installer.AddStep<ci::security::StepCheckSignature>();
       installer.AddStep<wgt::security::StepCheckSettingsLevel>();
+      installer.AddStep<wgt::encrypt::StepEncryptResources>();
       installer.AddStep<wgt::filesystem::StepWgtResourceDirectory>();
       installer.AddStep<ci::filesystem::StepCopy>();
       installer.AddStep<wgt::filesystem::StepWgtCreateStorageDirectories>();
@@ -77,6 +79,7 @@ int main(int argc, char** argv) {
       installer.AddStep<ci::security::StepCheckSignature>();
       installer.AddStep<wgt::security::StepCheckSettingsLevel>();
       installer.AddStep<ci::security::StepCheckOldCertificate>();
+      installer.AddStep<wgt::encrypt::StepEncryptResources>();
       installer.AddStep<wgt::filesystem::StepWgtResourceDirectory>();
       installer.AddStep<ci::backup::StepOldManifest>();
       installer.AddStep<ci::backup::StepBackupManifest>();