[KeyManager] loadFromPKCS12File implementation
authorPrzemyslaw Ciezkowski <p.ciezkowski@samsung.com>
Mon, 4 May 2015 13:31:16 +0000 (15:31 +0200)
committerPawel Andruszkiewicz <p.andruszkie@samsung.com>
Mon, 11 May 2015 12:32:24 +0000 (14:32 +0200)
[Verification]
tizen.keymanager.loadFromPKCS12File("file:///opt/usr/media/Others/pkcs12.p12",
   "priv_load1", "cert_load1",
   function() {
       console.log('ok');
   },
   function(e) {
       console.log(e.code);
       console.log(e.message);
   },
   "password"
);

Change-Id: Ia6af4f506195d7e387e0a238e384fa022a0da3f1
Signed-off-by: Przemyslaw Ciezkowski <p.ciezkowski@samsung.com>
src/keymanager/async_file_reader.cc [new file with mode: 0644]
src/keymanager/async_file_reader.h [new file with mode: 0644]
src/keymanager/keymanager.gyp
src/keymanager/keymanager_instance.cc
src/keymanager/keymanager_instance.h
src/keymanager/keymanager_observers.cc
src/keymanager/keymanager_observers.h

diff --git a/src/keymanager/async_file_reader.cc b/src/keymanager/async_file_reader.cc
new file mode 100644 (file)
index 0000000..0237991
--- /dev/null
@@ -0,0 +1,80 @@
+// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "keymanager/async_file_reader.h"
+#include "common/logger.h"
+
+namespace extension {
+namespace keymanager {
+
+const gsize kBufferSize = 4096;
+
+using common::PlatformResult;
+using common::ErrorCode;
+
+AsyncFileReader::AsyncFileReader(): buffer_(nullptr) {}
+
+void AsyncFileReader::LoadFileAsync(const std::string& file_uri) {
+  LoggerD("Enter");
+  GFile* file = g_file_new_for_uri(file_uri.c_str());
+  g_file_read_async(file, G_PRIORITY_DEFAULT, nullptr, OnFileRead, this);
+}
+
+void AsyncFileReader::OnFileRead(GObject* source_object,
+  GAsyncResult* res, gpointer user_data) {
+  LoggerD("Enter");
+  AsyncFileReader* This = static_cast<AsyncFileReader*>(user_data);
+  GError* err = nullptr;
+  GFileInputStream* stream = g_file_read_finish(G_FILE(source_object),
+    res, &err);
+  g_object_unref(source_object);
+  if (stream == nullptr) {
+      LoggerE("Failed to read file: %d", err->code);
+      if (err->code == G_FILE_ERROR_NOENT) {
+        This->OnError(PlatformResult(ErrorCode::NOT_FOUND_ERR,
+            "File not found"));
+      } else {
+        This->OnError(PlatformResult(ErrorCode::IO_ERR,
+            "Failed to load file"));
+      }
+      return;
+  }
+
+  This->buffer_ = new guint8[kBufferSize];
+  g_input_stream_read_async(G_INPUT_STREAM(stream), This->buffer_, kBufferSize,
+    G_PRIORITY_DEFAULT, nullptr, OnStreamRead, This);
+}
+
+void AsyncFileReader::OnStreamRead(GObject* source_object,
+  GAsyncResult* res, gpointer user_data) {
+  LoggerD("Enter");
+
+  AsyncFileReader* This = static_cast<AsyncFileReader*>(user_data);
+  gssize size = g_input_stream_read_finish(G_INPUT_STREAM(source_object),
+    res, nullptr);
+  switch (size){
+    case -1:
+      LoggerE("Error occured");
+      This->OnError(PlatformResult(ErrorCode::IO_ERR,
+          "Failed to load file"));
+      g_object_unref(source_object);
+      break;
+    case 0:
+      LoggerD("End of file");
+      This->OnFileLoaded();
+      g_object_unref(source_object);
+      break;
+    default:
+      This->AppendBuffer(This->buffer_, size);
+      g_input_stream_read_async(G_INPUT_STREAM(source_object), This->buffer_,
+        kBufferSize, G_PRIORITY_DEFAULT, nullptr, OnStreamRead, This);
+  }
+}
+
+AsyncFileReader::~AsyncFileReader() {
+  delete[] buffer_;
+}
+
+} // namespace keymanager
+} // namespace extension
diff --git a/src/keymanager/async_file_reader.h b/src/keymanager/async_file_reader.h
new file mode 100644 (file)
index 0000000..1717afe
--- /dev/null
@@ -0,0 +1,41 @@
+// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef KEYMANAGER_ASYNC_FILE_READER_H_
+#define KEYMANAGER_ASYNC_FILE_READER_H_
+
+#include <glib.h>
+#include <gio/gio.h>
+#include "common/platform_result.h"
+
+namespace extension {
+namespace keymanager {
+
+class AsyncFileReader {
+public:
+  AsyncFileReader();
+  void LoadFileAsync(const std::string &file_uri);
+  virtual ~AsyncFileReader();
+
+protected:
+  virtual void AppendBuffer(guint8* buffer, gssize size) = 0;
+  virtual void OnError(const common::PlatformResult& result) = 0;
+  virtual void OnFileLoaded() = 0;
+
+private:
+  guint8* buffer_;
+
+  static void OnFileRead(GObject *source_object,
+    GAsyncResult *res,
+    gpointer user_data);
+  static void OnStreamRead(GObject *source_object,
+    GAsyncResult *res,
+    gpointer user_data);
+};
+
+} // namespace keymanager
+} // namespace extension
+
+#endif // KEYMANAGER_ASYNC_FILE_READER_H_
+
index 65ddb7fca9e6de3dc6a0651f0b8b6c4d995fd700..238565a9203a3527ffad063086330f4412b6ca59 100644 (file)
@@ -11,6 +11,8 @@
       ],
       'sources': [
         'keymanager_api.js',
+        'async_file_reader.cc',
+        'async_file_reader.h',
         'keymanager_extension.cc',
         'keymanager_extension.h',
         'keymanager_instance.cc',
index 35f1b90e8ad073fb27f3f975ea7c413f5f2ae1c4..f9ff7207df73dd2af27a74585d369f29b27966d6 100644 (file)
@@ -58,6 +58,8 @@ KeyManagerInstance::KeyManagerInstance() {
       std::bind(&KeyManagerInstance::CreateSignature, this, _1, _2));
   RegisterSyncHandler("KeyManager_verifySignature",
       std::bind(&KeyManagerInstance::VerifySignature, this, _1, _2));
+  RegisterSyncHandler("KeyManager_loadFromPKCS12File",
+      std::bind(&KeyManagerInstance::LoadFromPKCS12File, this, _1, _2));
 }
 
 KeyManagerInstance::~KeyManagerInstance() {
@@ -433,13 +435,13 @@ void KeyManagerInstance::OnCertFileLoaded(LoadFileCert* reader,
   if (result.IsError()) {
     LoggerE("There was an error");
     picojson::value::object dict;
-    dict["callbackId"] = picojson::value(reader->callbackId);
+    dict["callbackId"] = picojson::value(reader->callback_id);
     ReportError(result, &dict);
     picojson::value res(dict);
     PostMessage(res.serialize().c_str());
   } else {
-    SaveCert(reader->fileContent, reader->password, reader->alias,
-      reader->extractable, reader->callbackId);
+    SaveCert(reader->file_content, reader->password, reader->alias,
+      reader->extractable, reader->callback_id);
   }
   delete reader;
 }
@@ -642,5 +644,75 @@ void KeyManagerInstance::OnVerifySignature(double callbackId,
   PostMessage(res.serialize().c_str());
 }
 
+void KeyManagerInstance::LoadFromPKCS12File(const picojson::value& args,
+    picojson::object& out) {
+  LoggerD("Enter");
+
+  const std::string& file = args.get("fileURI").get<std::string>();
+  const std::string& key_alias = args.get("privKeyName").get<std::string>();
+  const std::string& cert_alias = args.get("certificateName").get<std::string>();
+  std::string password;
+  if (args.get("password").is<std::string>()) {
+    password = args.get("password").get<std::string>();
+  }
+  LoadFilePKCS12* reader = new LoadFilePKCS12(this,
+    args.get("callbackId").get<double>(),
+    password,
+    key_alias,
+    cert_alias);
+  reader->LoadFileAsync(file);
+
+  ReportSuccess(out);
+}
+
+void KeyManagerInstance::OnPKCS12FileLoaded(LoadFilePKCS12* reader,
+    const common::PlatformResult& result) {
+  LoggerD("Enter");
+
+  if (result.IsError()) {
+    LoggerE("There was an error");
+    picojson::value::object dict;
+    dict["callbackId"] = picojson::value(reader->callback_id);
+    ReportError(result, &dict);
+    picojson::value res(dict);
+    PostMessage(res.serialize().c_str());
+  } else {
+    CKM::Password pass(reader->password.c_str());
+    CKM::PKCS12ShPtr pkcs = CKM::PKCS12::create(reader->file_content, pass);
+    if (!pkcs) {
+      LoggerE("Failed to parse PKCS12 file");
+      picojson::value::object dict;
+      dict["callbackId"] = picojson::value(reader->callback_id);
+      common::PlatformResult err(common::ErrorCode::INVALID_VALUES_ERR,
+          "Failed to parse PKCS12 file");
+      ReportError(err, &dict);
+      picojson::value res(dict);
+      PostMessage(res.serialize().c_str());
+    } else {
+      CKM::Policy keyPolicy;
+      CKM::Policy certPolicy;
+      CKM::ManagerAsync::ObserverPtr observer(new SavePKCS12Observer(this,
+          reader->callback_id));
+      m_manager.saveCertificate(observer, reader->cert_alias, pkcs->getCertificate(), certPolicy);
+      m_manager.saveKey(observer, reader->key_alias, pkcs->getKey(), keyPolicy);
+    }
+  }
+  delete reader;
+}
+
+void KeyManagerInstance::OnSavePKCS12(double callbackId,
+  const common::PlatformResult& result) {
+  LoggerD("Enter");
+
+  picojson::value::object dict;
+  dict["callbackId"] = picojson::value(callbackId);
+  if (result.IsError()) {
+    LoggerE("There was an error");
+    ReportError(result, &dict);
+  }
+  picojson::value res(dict);
+  PostMessage(res.serialize().c_str());
+}
+
 } // namespace keymanager
 } // namespace extension
index fa15037e9e6654785ffdfc9de662d274160f2a4c..e1aed0652a071aeb6b5c000281c15edd4e99037c 100644 (file)
@@ -27,6 +27,9 @@ class KeyManagerInstance :
   void OnSaveData(double callbackId, const common::PlatformResult& result);
   void OnCreateSignature(double callbackId, const common::PlatformResult& result, CKM::RawBuffer buffer);
   void OnVerifySignature(double callbackId, const common::PlatformResult& result);
+  void OnPKCS12FileLoaded(LoadFilePKCS12* reader, const common::PlatformResult& result);
+  void OnSavePKCS12(double callbackId, const common::PlatformResult& result);
+
  private:
   void GetAliasList(std::function<int(CKM::AliasVector&)> coreFunc,
       picojson::object& out);
@@ -53,6 +56,7 @@ class KeyManagerInstance :
   void GetData(const picojson::value& args, picojson::object& out);
   void CreateSignature(const picojson::value& args, picojson::object& out);
   void VerifySignature(const picojson::value& args, picojson::object& out);
+  void LoadFromPKCS12File(const picojson::value& args, picojson::object& out);
 
   CKM::ManagerAsync m_manager;
 };
index 9509de9111d51deaba722e381e7af5735b7ac845..c18dd0ee1df41ba58245a0e0add28db70b85166d 100644 (file)
@@ -118,74 +118,24 @@ LoadFileCert::LoadFileCert(KeyManagerListener* _listener,
     const std::string &_password,
     const std::string &_alias,
     bool _extractable):
-    callbackId(callbackId),
+    callback_id(callbackId),
     password(_password),
     alias(_alias),
     extractable(_extractable),
-    fileContent(""),
-    buffer(NULL),
-    listener(_listener) {}
-
-void LoadFileCert::LoadFileAsync(const std::string& fileUri) {
-  LoggerD("Enter");
-  GFile* file = g_file_new_for_uri(fileUri.c_str());
-  g_file_read_async(file, G_PRIORITY_DEFAULT, NULL, OnFileRead, this);
+    file_content(""),
+    listener(_listener) {
 }
 
-void LoadFileCert::OnFileRead(GObject* source_object,
-  GAsyncResult* res, gpointer user_data) {
-  LoggerD("Enter");
-  LoadFileCert* This = static_cast<LoadFileCert*>(user_data);
-  GError* err = NULL;
-  GFileInputStream* stream = g_file_read_finish(G_FILE(source_object),
-    res, &err);
-  g_object_unref(source_object);
-  if (stream == NULL) {
-      LoggerE("Failed to read file: %d", err->code);
-      if (err->code == G_FILE_ERROR_NOENT) {
-        This->listener->OnCertFileLoaded(This,
-          PlatformResult(ErrorCode::NOT_FOUND_ERR, "Certificate file not found"));
-      } else {
-        This->listener->OnCertFileLoaded(This,
-          PlatformResult(ErrorCode::IO_ERR, "Failed to load certificate file"));
-      }
-      return;
-  }
-
-  This->buffer = new guint8[4096];
-  g_input_stream_read_async(G_INPUT_STREAM(stream), This->buffer, 4096,
-    G_PRIORITY_DEFAULT, NULL, OnStreamRead, This);
+void LoadFileCert::AppendBuffer(guint8* buffer, gssize size) {
+  file_content.append(buffer, buffer + size);
 }
 
-void LoadFileCert::OnStreamRead(GObject* source_object,
-  GAsyncResult* res, gpointer user_data) {
-  LoggerD("Enter");
-
-  LoadFileCert* This = static_cast<LoadFileCert*>(user_data);
-  gssize size = g_input_stream_read_finish(G_INPUT_STREAM(source_object),
-    res, NULL);
-  switch (size){
-    case -1:
-      LoggerE("Error occured");
-      This->listener->OnCertFileLoaded(This,
-        PlatformResult(ErrorCode::IO_ERR, "Failed to load certificate file"));
-      g_object_unref(source_object);
-      break;
-    case 0:
-      LoggerD("End of file");
-      This->listener->OnCertFileLoaded(This,
-        PlatformResult(ErrorCode::NO_ERROR));
-      g_object_unref(source_object);
-      break;
-    default:
-      This->fileContent.append(This->buffer, This->buffer + size);
-      g_input_stream_read_async(G_INPUT_STREAM(source_object), This->buffer,
-        4096, G_PRIORITY_DEFAULT, NULL, OnStreamRead, This);
-  }
+void LoadFileCert::OnError(const common::PlatformResult& result) {
+  listener->OnCertFileLoaded(this, result);
 }
 
-LoadFileCert::~LoadFileCert() {
-  delete[] buffer;
+void LoadFileCert::OnFileLoaded() {
+  listener->OnCertFileLoaded(this, PlatformResult(ErrorCode::NO_ERROR));
 }
 
 SaveDataObserver::SaveDataObserver(KeyManagerListener* listener, double callbackId):
@@ -257,5 +207,64 @@ void VerifySignatureObserver::ReceivedVerifySignature() {
     PlatformResult(ErrorCode::NO_ERROR)));
 }
 
+LoadFilePKCS12::LoadFilePKCS12(KeyManagerListener* listener,
+    double callback_id,
+    const std::string &password,
+    const std::string &key_alias,
+    const std::string &cert_alias):
+    callback_id(callback_id),
+    password(password),
+    key_alias(key_alias),
+    cert_alias(cert_alias),
+    listener(listener) {
+}
+
+void LoadFilePKCS12::AppendBuffer(guint8* buffer, gssize size) {
+  file_content.insert(file_content.end(), buffer, buffer + size);
+}
+
+void LoadFilePKCS12::OnError(const common::PlatformResult& result) {
+  listener->OnPKCS12FileLoaded(this, result);
+}
+
+void LoadFilePKCS12::OnFileLoaded() {
+  listener->OnPKCS12FileLoaded(this, PlatformResult(ErrorCode::NO_ERROR));
+}
+
+SavePKCS12Observer::SavePKCS12Observer(KeyManagerListener* listener, double callback_id):
+    CommonObserver(listener, callback_id),
+    cert_saved(false), key_saved(false) {}
+
+void SavePKCS12Observer::ReceivedError(int error) {
+  LoggerD("Enter, error: %d", error);
+  ErrorCode code = ErrorCode::UNKNOWN_ERR;
+  if (error == CKM_API_ERROR_INPUT_PARAM) {
+    code = ErrorCode::INVALID_VALUES_ERR;
+  }
+  common::TaskQueue::GetInstance().Async(std::bind(
+    &KeyManagerListener::OnSavePKCS12, listener, callbackId,
+    PlatformResult(code, "Failed to save pkcs12 file")));
+}
+
+void SavePKCS12Observer::ReceivedSaveKey() {
+  LoggerD("Enter");
+  key_saved = true;
+  if (cert_saved) {
+   common::TaskQueue::GetInstance().Async(std::bind(
+    &KeyManagerListener::OnSavePKCS12, listener, callbackId,
+    PlatformResult(ErrorCode::NO_ERROR)));
+  }
+}
+
+void SavePKCS12Observer::ReceivedSaveCertificate() {
+  LoggerD("Enter");
+  cert_saved = true;
+  if (key_saved) {
+    common::TaskQueue::GetInstance().Async(std::bind(
+      &KeyManagerListener::OnSavePKCS12, listener, callbackId,
+      PlatformResult(ErrorCode::NO_ERROR)));
+  }
+}
+
 } // namespace keymanager
 } // namespace extension
index 912e2e73c87d1c37a51a297f47dea0e643e67b5c..ccef4922cc0df2110c3e9db161a71f799d77959b 100644 (file)
@@ -6,14 +6,15 @@
 #define KEYMANAGER_KEYMANAGER_OBSERVERS_H_
 
 #include <ckm/ckm-manager-async.h>
-#include <gio/gio.h>
 #include <string>
 #include "common/platform_result.h"
+#include "keymanager/async_file_reader.h"
 
 namespace extension {
 namespace keymanager {
 
 class LoadFileCert;
+class LoadFilePKCS12;
 
 class KeyManagerListener {
 public:
@@ -25,6 +26,9 @@ public:
   virtual void OnSaveData(double callbackId, const common::PlatformResult& result) = 0;
   virtual void OnCreateSignature(double callbackId, const common::PlatformResult& result, CKM::RawBuffer buffer) = 0;
   virtual void OnVerifySignature(double callbackId, const common::PlatformResult& result) = 0;
+  virtual void OnPKCS12FileLoaded(LoadFilePKCS12* reader,
+    const common::PlatformResult& result) = 0;
+  virtual void OnSavePKCS12(double callbackId, const common::PlatformResult& result) = 0;
   virtual ~KeyManagerListener() {}
 };
 
@@ -60,30 +64,48 @@ struct SaveCertObserver: public CommonObserver {
   void ReceivedSaveCertificate();
 };
 
-struct LoadFileCert {
+struct LoadFileCert: public AsyncFileReader {
   LoadFileCert(KeyManagerListener* listener,
     double callbackId,
     const std::string &password,
     const std::string &alias,
     bool extractable);
-  void LoadFileAsync(const std::string &fileUri);
-  virtual ~LoadFileCert();
 
-  double callbackId;
+  double callback_id;
   std::string password;
   const std::string alias;
   bool extractable;
-  std::string fileContent;
+  std::string file_content;
+
+protected:
+  void AppendBuffer(guint8* buffer, gssize size);
+  void OnError(const common::PlatformResult& result);
+  void OnFileLoaded();
+
 private:
-  guint8* buffer;
   KeyManagerListener* listener;
+};
+
+struct LoadFilePKCS12: public AsyncFileReader {
+  LoadFilePKCS12(KeyManagerListener* listener,
+    double callbackId,
+    const std::string &password,
+    const std::string &keyAlias,
+    const std::string &certAlias);
+
+  double callback_id;
+  std::string password;
+  const std::string key_alias;
+  const std::string cert_alias;
+  CKM::RawBuffer file_content;
 
-  static void OnFileRead(GObject *source_object,
-    GAsyncResult *res,
-    gpointer user_data);
-  static void OnStreamRead(GObject *source_object,
-    GAsyncResult *res,
-    gpointer user_data);
+protected:
+  void AppendBuffer(guint8* buffer, gssize size);
+  void OnError(const common::PlatformResult& result);
+  void OnFileLoaded();
+
+private:
+  KeyManagerListener* listener;
 };
 
 struct SaveDataObserver: public CommonObserver {
@@ -104,6 +126,17 @@ struct VerifySignatureObserver: public CommonObserver {
   void ReceivedVerifySignature();
 };
 
+struct SavePKCS12Observer: public CommonObserver {
+  SavePKCS12Observer(KeyManagerListener* listener, double callback_id);
+  void ReceivedError(int error);
+  void ReceivedSaveKey();
+  void ReceivedSaveCertificate();
+
+private:
+    bool cert_saved;
+    bool key_saved;
+};
+
 } // namespace keymanager
 } // namespace extension