From: Przemyslaw Ciezkowski Date: Mon, 4 May 2015 13:31:16 +0000 (+0200) Subject: [KeyManager] loadFromPKCS12File implementation X-Git-Tag: submit/tizen_tv/20150603.064601~1^2~40 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=af85e502c92cce1e7ad45a7a5c7b195863c43700;p=platform%2Fcore%2Fapi%2Fwebapi-plugins.git [KeyManager] loadFromPKCS12File implementation [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 --- diff --git a/src/keymanager/async_file_reader.cc b/src/keymanager/async_file_reader.cc new file mode 100644 index 00000000..02379910 --- /dev/null +++ b/src/keymanager/async_file_reader.cc @@ -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(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(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 index 00000000..1717afef --- /dev/null +++ b/src/keymanager/async_file_reader.h @@ -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 +#include +#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_ + diff --git a/src/keymanager/keymanager.gyp b/src/keymanager/keymanager.gyp index 65ddb7fc..238565a9 100644 --- a/src/keymanager/keymanager.gyp +++ b/src/keymanager/keymanager.gyp @@ -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', diff --git a/src/keymanager/keymanager_instance.cc b/src/keymanager/keymanager_instance.cc index 35f1b90e..f9ff7207 100644 --- a/src/keymanager/keymanager_instance.cc +++ b/src/keymanager/keymanager_instance.cc @@ -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(); + const std::string& key_alias = args.get("privKeyName").get(); + const std::string& cert_alias = args.get("certificateName").get(); + std::string password; + if (args.get("password").is()) { + password = args.get("password").get(); + } + LoadFilePKCS12* reader = new LoadFilePKCS12(this, + args.get("callbackId").get(), + 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 diff --git a/src/keymanager/keymanager_instance.h b/src/keymanager/keymanager_instance.h index fa15037e..e1aed065 100644 --- a/src/keymanager/keymanager_instance.h +++ b/src/keymanager/keymanager_instance.h @@ -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 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; }; diff --git a/src/keymanager/keymanager_observers.cc b/src/keymanager/keymanager_observers.cc index 9509de91..c18dd0ee 100644 --- a/src/keymanager/keymanager_observers.cc +++ b/src/keymanager/keymanager_observers.cc @@ -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(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(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 diff --git a/src/keymanager/keymanager_observers.h b/src/keymanager/keymanager_observers.h index 912e2e73..ccef4922 100644 --- a/src/keymanager/keymanager_observers.h +++ b/src/keymanager/keymanager_observers.h @@ -6,14 +6,15 @@ #define KEYMANAGER_KEYMANAGER_OBSERVERS_H_ #include -#include #include #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