From ed0f67e5e8b7c89765a364a60b5e844f5ffd1245 Mon Sep 17 00:00:00 2001 From: Bartlomiej Grzelewski Date: Fri, 12 Jun 2015 15:32:28 +0200 Subject: [PATCH 01/16] Use new exception types in KeyProvider class. This commit also removed exception throw in object destructor. Change-Id: I55f58bd5e63261632404557f60caa7f0af393714 --- src/manager/service/ckm-logic.cpp | 33 ++----------------- src/manager/service/key-provider.cpp | 62 ++++++++++++++++-------------------- src/manager/service/key-provider.h | 17 ---------- tests/main.cpp | 12 ++++--- tests/test-key-provider.cpp | 5 +-- 5 files changed, 40 insertions(+), 89 deletions(-) diff --git a/src/manager/service/ckm-logic.cpp b/src/manager/service/ckm-logic.cpp index a2c3e45..7ec4213 100644 --- a/src/manager/service/ckm-logic.cpp +++ b/src/manager/service/ckm-logic.cpp @@ -162,12 +162,6 @@ int CKMLogic::unlockDatabase(uid_t user, const Password & password) handle.database.deleteKey(appSmackLabel); } } - } catch (const KeyProvider::Exception::PassWordError &e) { - LogError("Incorrect Password " << e.GetMessage()); - retCode = CKM_API_ERROR_AUTHENTICATION_FAILED; - } catch (const KeyProvider::Exception::Base &e) { - LogError("Error in KeyProvider " << e.GetMessage()); - retCode = CKM_API_ERROR_SERVER_ERROR; } catch (const Exc::Exception &e) { retCode = e.error(); } catch (const CKM::Exception &e) { @@ -283,12 +277,6 @@ RawBuffer CKMLogic::changeUserPassword( try { retCode = changeUserPasswordHelper(user, oldPassword, newPassword); - } catch (const KeyProvider::Exception::PassWordError &e) { - LogError("Incorrect Password " << e.GetMessage()); - retCode = CKM_API_ERROR_AUTHENTICATION_FAILED; - } catch (const KeyProvider::Exception::Base &e) { - LogError("Error in KeyProvider " << e.GetMessage()); - retCode = CKM_API_ERROR_SERVER_ERROR; } catch (const Exc::Exception &e) { retCode = e.error(); } catch (const CKM::Exception &e) { @@ -500,9 +488,6 @@ int CKMLogic::verifyAndSaveDataHelper( { retCode = saveDataHelper(cred, name, label, dataType, binaryData, policy); } - } catch (const KeyProvider::Exception::Base &e) { - LogError("KeyProvider failed with message: " << e.GetMessage()); - retCode = CKM_API_ERROR_SERVER_ERROR; } catch (const DB::Crypto::Exception::InternalError &e) { LogError("DB::Crypto failed with message: " << e.GetMessage()); retCode = CKM_API_ERROR_DB_ERROR; @@ -592,9 +577,8 @@ RawBuffer CKMLogic::savePKCS12( int retCode = CKM_API_ERROR_UNKNOWN; try { retCode = saveDataHelper(cred, name, label, pkcs, keyPolicy, certPolicy); - } catch (const KeyProvider::Exception::Base &e) { - LogError("KeyProvider failed with message: " << e.GetMessage()); - retCode = CKM_API_ERROR_SERVER_ERROR; + } catch (const Exc::Exception &e) { + retCode = e.error(); } catch (const DB::Crypto::Exception::InternalError &e) { LogError("DB::Crypto failed with message: " << e.GetMessage()); retCode = CKM_API_ERROR_DB_ERROR; @@ -876,9 +860,6 @@ RawBuffer CKMLogic::getData( try { retCode = readDataHelper(true, cred, dataType, name, label, password, row); - } catch (const KeyProvider::Exception::Base &e) { - LogError("KeyProvider failed with error: " << e.GetMessage()); - retCode = CKM_API_ERROR_SERVER_ERROR; } catch (const DB::Crypto::Exception::Base &e) { LogError("DB::Crypto failed with message: " << e.GetMessage()); retCode = CKM_API_ERROR_DB_ERROR; @@ -964,10 +945,6 @@ RawBuffer CKMLogic::getPKCS12( // prepare response if(retCode == CKM_API_SUCCESS) output = PKCS12Serializable(privKey, cert, caChain); - - } catch (const KeyProvider::Exception::Base &e) { - LogError("KeyProvider failed with error: " << e.GetMessage()); - retCode = CKM_API_ERROR_SERVER_ERROR; } catch (const DB::Crypto::Exception::Base &e) { LogError("DB::Crypto failed with message: " << e.GetMessage()); retCode = CKM_API_ERROR_DB_ERROR; @@ -1470,9 +1447,6 @@ RawBuffer CKMLogic::createSignature( if(retCode == CKM_API_SUCCESS) { signature = m_decider.getStore(row).getKey(row)->sign(cryptoAlg, message); } - } catch (const KeyProvider::Exception::Base &e) { - LogError("KeyProvider failed with message: " << e.GetMessage()); - retCode = CKM_API_ERROR_SERVER_ERROR; } catch (const DB::Crypto::Exception::Base &e) { LogError("DB::Crypto failed with message: " << e.GetMessage()); retCode = CKM_API_ERROR_DB_ERROR; @@ -1523,9 +1497,6 @@ RawBuffer CKMLogic::verifySignature( } } catch (const Exc::Exception &e) { retCode = e.error(); - } catch (const KeyProvider::Exception::Base &e) { - LogError("KeyProvider failed with error: " << e.GetMessage()); - retCode = CKM_API_ERROR_SERVER_ERROR; } catch (const DB::Crypto::Exception::Base &e) { LogError("DB::Crypto failed with message: " << e.GetMessage()); retCode = CKM_API_ERROR_DB_ERROR; diff --git a/src/manager/service/key-provider.cpp b/src/manager/service/key-provider.cpp index 48db9c0..23ca201 100644 --- a/src/manager/service/key-provider.cpp +++ b/src/manager/service/key-provider.cpp @@ -1,3 +1,4 @@ +#include #include #include @@ -100,14 +101,11 @@ KeyAndInfoContainer::~KeyAndInfoContainer() { // overwrite key char *ptr = reinterpret_cast(keyAndInfo); - for (size_t size = 0; size < sizeof(KeyAndInfo); ++size) - ptr[size] = 0; + memset(ptr, 0, sizeof(KeyAndInfo)); // verification for (size_t size = 0; size < sizeof(KeyAndInfo); ++size) { - if (0 != ptr[size]) { - delete keyAndInfo; - ThrowMsg(Exception::Base, "KeyAndInfo in KeyAndInfoContainer " - "was not destroyed!"); + if (ptr[size]) { + LogError("Write momory error! Memory used by key was not owerwritten."); } } delete keyAndInfo; @@ -127,12 +125,12 @@ KeyProvider::KeyProvider( , m_isInitialized(true) { if (!m_isInitialized) { - ThrowMsg(Exception::InitFailed, "Object not initialized!. Should not happened"); + ThrowErr(Exc::InternalError, "Object not initialized!. Should not happened"); } if (domainKEKInWrapForm.size() != sizeof(WrappedKeyAndInfo)) { LogError("input size:" << domainKEKInWrapForm.size() << " Expected: " << sizeof(WrappedKeyAndInfo)); - ThrowMsg(Exception::InputParamError, "buffer doesn't have proper size to store WrappedKeyAndInfo in KeyProvider Constructor"); + ThrowErr(Exc::InternalError, "buffer doesn't have proper size to store WrappedKeyAndInfo in KeyProvider Constructor"); } WrappedKeyAndInfoContainer wkmcDKEK = WrappedKeyAndInfoContainer(domainKEKInWrapForm.data()); @@ -154,7 +152,7 @@ KeyProvider::KeyProvider( PKEK1)) { delete[] concat_user_pass; - ThrowMsg(Exception::OpensslEngineError, "OPENSSL_ENGINE_ERROR"); + ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR"); } delete[] concat_user_pass; @@ -169,7 +167,7 @@ KeyProvider::KeyProvider( wkmcDKEK.getWrappedKeyAndInfo().keyInfo.iv, m_kmcDKEK->getKeyAndInfo().key))) { - ThrowMsg(Exception::PassWordError, "VerifyDomainKEK failed in KeyProvider Constructor"); + ThrowErr(Exc::AuthenticationFailed, "VerifyDomainKEK failed in KeyProvider Constructor"); } m_kmcDKEK->setKeyInfo(&(wkmcDKEK.getWrappedKeyAndInfo().keyInfo)); @@ -205,7 +203,7 @@ bool KeyProvider::isInitialized() RawBuffer KeyProvider::getPureDomainKEK() { if (!m_isInitialized) { - ThrowMsg(Exception::InitFailed, "Object not initialized!"); + ThrowErr(Exc::InternalError, "Object not initialized!"); } // TODO secure @@ -215,7 +213,7 @@ RawBuffer KeyProvider::getPureDomainKEK() RawBuffer KeyProvider::getWrappedDomainKEK(const Password &password) { if (!m_isInitialized) { - ThrowMsg(Exception::InitFailed, "Object not initialized!"); + ThrowErr(Exc::InternalError, "Object not initialized!"); } WrappedKeyAndInfoContainer wkmcDKEK = WrappedKeyAndInfoContainer(); @@ -237,7 +235,7 @@ RawBuffer KeyProvider::getWrappedDomainKEK(const Password &password) PKEK1)) { delete[] concat_user_pass; - ThrowMsg(Exception::OpensslEngineError, "OPENSSL_ENGINE_ERROR"); + ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR"); } delete[] concat_user_pass; @@ -254,7 +252,7 @@ RawBuffer KeyProvider::getWrappedDomainKEK(const Password &password) wkmcDKEK.getWrappedKeyAndInfo().wrappedKey, wkmcDKEK.getWrappedKeyAndInfo().keyInfo.tag))) { - ThrowMsg(Exception::InitFailed, "WrapDKEK Failed in KeyProvider::getDomainKEK"); + ThrowErr(Exc::InternalError, "WrapDKEK Failed in KeyProvider::getDomainKEK"); } wkmcDKEK.setKeyInfoKeyLength((unsigned int)wrappedKeyLength); @@ -267,13 +265,13 @@ RawBuffer KeyProvider::getWrappedDomainKEK(const Password &password) RawBuffer KeyProvider::getPureDEK(const RawBuffer &DEKInWrapForm) { if (!m_isInitialized) { - ThrowMsg(Exception::InitFailed, "Object not initialized!"); + ThrowErr(Exc::InternalError, "Object not initialized!"); } if (DEKInWrapForm.size() != sizeof(WrappedKeyAndInfo)){ LogError("input size:" << DEKInWrapForm.size() << " Expected: " << sizeof(WrappedKeyAndInfo)); - ThrowMsg(Exception::InputParamError, + ThrowErr(Exc::InternalError, "buffer doesn't have proper size to store " "WrappedKeyAndInfo in KeyProvider::getPureDEK"); } @@ -293,7 +291,7 @@ RawBuffer KeyProvider::getPureDEK(const RawBuffer &DEKInWrapForm) MAX_KEY_SIZE, PKEK2)) { - ThrowMsg(Exception::OpensslEngineError, "OPENSSL_ENGINE_ERROR"); + ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR"); } if (0 > (keyLength = decryptAes256Gcm( @@ -304,7 +302,7 @@ RawBuffer KeyProvider::getPureDEK(const RawBuffer &DEKInWrapForm) wkmcDEK.getWrappedKeyAndInfo().keyInfo.iv, kmcDEK.getKeyAndInfo().key))) { - ThrowMsg(Exception::UnwrapFailed, + ThrowErr(Exc::InternalError, "UnwrapDEK Failed in KeyProvider::getPureDEK"); } @@ -319,8 +317,7 @@ RawBuffer KeyProvider::getPureDEK(const RawBuffer &DEKInWrapForm) RawBuffer KeyProvider::generateDEK(const std::string &smackLabel) { if (!m_isInitialized) { - ThrowMsg(Exception::InitFailed, - "Object not initialized!"); + ThrowErr(Exc::InternalError, "Object not initialized!"); } WrappedKeyAndInfoContainer wkmcDEK = WrappedKeyAndInfoContainer(); @@ -336,7 +333,7 @@ RawBuffer KeyProvider::generateDEK(const std::string &smackLabel) if (!RAND_bytes(key, m_kmcDKEK->getKeyAndInfo().keyInfo.keyLength) || !RAND_bytes(wkmcDEK.getWrappedKeyAndInfo().keyInfo.iv, MAX_IV_SIZE)) { - ThrowMsg(Exception::OpensslEngineError, "OPENSSL_ENGINE_ERROR"); + ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR"); } if (!PKCS5_PBKDF2_HMAC_SHA1( @@ -348,7 +345,7 @@ RawBuffer KeyProvider::generateDEK(const std::string &smackLabel) MAX_KEY_SIZE, PKEK2)) { - ThrowMsg(Exception::OpensslEngineError, "OPENSSL_ENGINE_ERROR"); + ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR"); } int wrappedKeyLength; @@ -361,8 +358,7 @@ RawBuffer KeyProvider::generateDEK(const std::string &smackLabel) wkmcDEK.getWrappedKeyAndInfo().wrappedKey, wkmcDEK.getWrappedKeyAndInfo().keyInfo.tag))) { - ThrowMsg(Exception::GenFailed, - "GenerateDEK Failed in KeyProvider::generateDEK"); + ThrowErr(Exc::InternalError, "GenerateDEK Failed in KeyProvider::generateDEK"); } wkmcDEK.setKeyInfoKeyLength((unsigned int)wrappedKeyLength); @@ -381,7 +377,7 @@ RawBuffer KeyProvider::reencrypt( if (domainKEKInWrapForm.size() != sizeof(WrappedKeyAndInfo)) { LogError("input size:" << domainKEKInWrapForm.size() << " Expected: " << sizeof(WrappedKeyAndInfo)); - ThrowMsg(Exception::InputParamError, + ThrowErr(Exc::InternalError, "buffer doesn't have proper size to store " "WrappedKeyAndInfo in KeyProvider::reencrypt"); } @@ -409,7 +405,7 @@ RawBuffer KeyProvider::reencrypt( PKEK1)) { delete[] concat_user_pass; - ThrowMsg(Exception::OpensslEngineError, "OPENSSL_ENGINE_ERROR"); + ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR"); } delete[] concat_user_pass; @@ -421,8 +417,7 @@ RawBuffer KeyProvider::reencrypt( wkmcOldDKEK.getWrappedKeyAndInfo().keyInfo.iv, kmcDKEK.getKeyAndInfo().key))) { - ThrowMsg(Exception::PassWordError, - "Incorrect Old Password "); + ThrowErr(Exc::AuthenticationFailed, "Incorrect Old Password "); } kmcDKEK.setKeyInfo(&(wkmcOldDKEK.getWrappedKeyAndInfo().keyInfo)); @@ -442,7 +437,7 @@ RawBuffer KeyProvider::reencrypt( PKEK1)) { delete[] concat_user_pass; - ThrowMsg(Exception::OpensslEngineError, "OPENSSL_ENGINE_ERROR"); + ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR"); } delete[] concat_user_pass; @@ -458,8 +453,7 @@ RawBuffer KeyProvider::reencrypt( wkmcNewDKEK.getWrappedKeyAndInfo().wrappedKey, wkmcNewDKEK.getWrappedKeyAndInfo().keyInfo.tag))) { - ThrowMsg(Exception::UnwrapFailed, - "UpdateDomainKEK in KeyProvider::reencrypt Failed"); + ThrowErr(Exc::InternalError, "UpdateDomainKEK in KeyProvider::reencrypt Failed"); } wkmcNewDKEK.setKeyInfoKeyLength((unsigned int)wrappedKeyLength); @@ -479,7 +473,7 @@ RawBuffer KeyProvider::generateDomainKEK( if (!RAND_bytes(wkmcDKEK.getWrappedKeyAndInfo().keyInfo.salt, MAX_SALT_SIZE) || !RAND_bytes(key, MAX_KEY_SIZE) || !RAND_bytes(wkmcDKEK.getWrappedKeyAndInfo().keyInfo.iv, MAX_IV_SIZE)) - ThrowMsg(Exception::OpensslEngineError, "OPENSSL_ENGINE_ERROR"); + ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR"); int wrappedKeyLength; char *concat_user_pass = NULL; @@ -494,7 +488,7 @@ RawBuffer KeyProvider::generateDomainKEK( PKEK1)) { delete[] concat_user_pass; - ThrowMsg(Exception::OpensslEngineError, "OPENSSL_ENGINED_ERROR"); + ThrowErr(Exc::InternalError, "OPENSSL_ENGINED_ERROR"); } delete[] concat_user_pass; @@ -507,7 +501,7 @@ RawBuffer KeyProvider::generateDomainKEK( wkmcDKEK.getWrappedKeyAndInfo().wrappedKey, wkmcDKEK.getWrappedKeyAndInfo().keyInfo.tag))) { - ThrowMsg(Exception::GenFailed, + ThrowErr(Exc::InternalError, "GenerateDomainKEK Failed in KeyProvider::generateDomainKEK"); } diff --git a/src/manager/service/key-provider.h b/src/manager/service/key-provider.h index a386652..918a622 100644 --- a/src/manager/service/key-provider.h +++ b/src/manager/service/key-provider.h @@ -9,7 +9,6 @@ #include #include -#include #ifndef SUCCESS #define SUCCESS 0 @@ -82,10 +81,6 @@ private: class KeyAndInfoContainer{ public: - class Exception{ - public: - DECLARE_EXCEPTION_TYPE(CKM::Exception, Base) - }; KeyAndInfoContainer(); KeyAndInfoContainer(const unsigned char*); KeyAndInfo& getKeyAndInfo(); @@ -100,18 +95,6 @@ private: // This is internal api so all functions should throw exception on errors. class KeyProvider { public: - class Exception { - public: - DECLARE_EXCEPTION_TYPE(CKM::Exception, Base) - DECLARE_EXCEPTION_TYPE(Base, InitFailed) - DECLARE_EXCEPTION_TYPE(Base, GenFailed) - DECLARE_EXCEPTION_TYPE(Base, WrapFailed) - DECLARE_EXCEPTION_TYPE(Base, UnwrapFailed) - DECLARE_EXCEPTION_TYPE(Base, PassWordError) - DECLARE_EXCEPTION_TYPE(Base, InputParamError) - DECLARE_EXCEPTION_TYPE(Base, OpensslEngineError) - }; - // To store in std containers KeyProvider(); // In constructor you must check if SKMM is initialized. On error -> exception diff --git a/tests/main.cpp b/tests/main.cpp index 0a47fd8..efaf1be 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -28,6 +28,8 @@ #include #include +#include + struct TestConfig { TestConfig() { boost::unit_test::unit_test_log.set_threshold_level( boost::unit_test::log_test_units); @@ -42,17 +44,17 @@ bool isLibInitialized = false; struct KeyProviderLib { KeyProviderLib() { - Try { + try { CKM::KeyProvider::initializeLibrary(); isLibInitialized = true; - } - Catch (CKM::Exception) { + } catch (const CKM::Exc::Exception &) { std::cout << "Library initialization failed!" << std::endl; } } ~KeyProviderLib() { - Try { CKM::KeyProvider::closeLibrary(); } - Catch (CKM::Exception) { + try { + CKM::KeyProvider::closeLibrary(); + } catch (const CKM::Exc::Exception &) { std::cout << "Library deinitialization failed!" << std::endl; } } diff --git a/tests/test-key-provider.cpp b/tests/test-key-provider.cpp index 433e8ec..92f7e07 100644 --- a/tests/test-key-provider.cpp +++ b/tests/test-key-provider.cpp @@ -1,5 +1,6 @@ #define BOOST_TEST_MODULE KEY_MANAGER_TEST #include +#include #include #include #include @@ -36,7 +37,7 @@ BOOST_AUTO_TEST_CASE(KeyDomainKekInvalidPassword){ BOOST_REQUIRE_NO_THROW(rb_test = CKM::KeyProvider::generateDomainKEK(USERNAME_LONG, PASSWORD)); BOOST_REQUIRE_THROW(keyProvider = CKM::KeyProvider(rb_test, INCORRECT_PASSWORD), - CKM::KeyProvider::Exception::PassWordError); + CKM::Exc::AuthenticationFailed); BOOST_REQUIRE_MESSAGE(!keyProvider.isInitialized(), "KeyProvider not created, but initialized"); } @@ -114,7 +115,7 @@ BOOST_AUTO_TEST_CASE(KeyReencrypt_incorrect_password){ BOOST_REQUIRE_NO_THROW(rb_test = CKM::KeyProvider::generateDomainKEK(USERNAME_LONG, PASSWORD)); BOOST_REQUIRE_THROW((rb_test = CKM::KeyProvider::reencrypt(rb_test, INCORRECT_PASSWORD, - NEW_PASSWORD)), CKM::KeyProvider::Exception::PassWordError); + NEW_PASSWORD)), CKM::Exc::AuthenticationFailed); } BOOST_AUTO_TEST_CASE(KeyGetPureDEK_after_reencrypt){ -- 2.7.4 From 09ae820e0cae03defd55ef3351456b50656cf37e Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Fri, 29 May 2015 16:59:57 +0200 Subject: [PATCH 02/16] Add encryption service [Feature] Encryption/decryption implementation [Solution] Encryption service added [Verification] Run test: ckm-tests --group=CKM_ENCRYPTION_DECRYPTION Change-Id: I3ff79b06eabb6957ef2bbbe9a5bf7e5e2a995a21 --- packaging/key-manager.spec | 3 + src/CMakeLists.txt | 2 + src/manager/client/client-manager-impl.cpp | 55 ++++------ src/manager/client/client-manager-impl.h | 7 ++ src/manager/main/key-manager-main.cpp | 2 + src/manager/service/crypto-request.h | 43 ++++++++ src/manager/service/encryption-logic.cpp | 55 ++++++++++ src/manager/service/encryption-logic.h | 46 +++++++++ src/manager/service/encryption-service.cpp | 120 ++++++++++++++++++++++ src/manager/service/encryption-service.h | 60 +++++++++++ src/manager/service/iencryption-service.h | 44 ++++++++ systemd/CMakeLists.txt | 1 + systemd/central-key-manager-api-encryption.socket | 14 +++ systemd/central-key-manager.service.in | 1 + 14 files changed, 417 insertions(+), 36 deletions(-) create mode 100644 src/manager/service/crypto-request.h create mode 100644 src/manager/service/encryption-logic.cpp create mode 100644 src/manager/service/encryption-logic.h create mode 100644 src/manager/service/encryption-service.cpp create mode 100644 src/manager/service/encryption-service.h create mode 100644 src/manager/service/iencryption-service.h create mode 100644 systemd/central-key-manager-api-encryption.socket diff --git a/packaging/key-manager.spec b/packaging/key-manager.spec index 9d32beb..f6d52d8 100644 --- a/packaging/key-manager.spec +++ b/packaging/key-manager.spec @@ -153,6 +153,7 @@ ln -s ../central-key-manager-listener.service %{buildroot}%{_unitdir}/multi-user ln -s ../central-key-manager-api-control.socket %{buildroot}%{_unitdir}/sockets.target.wants/central-key-manager-api-control.socket ln -s ../central-key-manager-api-storage.socket %{buildroot}%{_unitdir}/sockets.target.wants/central-key-manager-api-storage.socket ln -s ../central-key-manager-api-ocsp.socket %{buildroot}%{_unitdir}/sockets.target.wants/central-key-manager-api-ocsp.socket +ln -s ../central-key-manager-api-encryption.socket %{buildroot}%{_unitdir}/sockets.target.wants/central-key-manager-api-encryption.socket %clean rm -rf %{buildroot} @@ -222,6 +223,8 @@ fi %{_unitdir}/central-key-manager-api-storage.socket %{_unitdir}/sockets.target.wants/central-key-manager-api-ocsp.socket %{_unitdir}/central-key-manager-api-ocsp.socket +%{_unitdir}/sockets.target.wants/central-key-manager-api-encryption.socket +%{_unitdir}/central-key-manager-api-encryption.socket %{_datadir}/license/%{name} %{_datadir}/ckm/scripts/*.sql %{_datadir}/ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1460a53..fd79979 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -34,6 +34,8 @@ SET(KEY_MANAGER_SOURCES ${KEY_MANAGER_PATH}/service/db-crypto.cpp ${KEY_MANAGER_PATH}/service/ocsp-service.cpp ${KEY_MANAGER_PATH}/service/ocsp-logic.cpp + ${KEY_MANAGER_PATH}/service/encryption-service.cpp + ${KEY_MANAGER_PATH}/service/encryption-logic.cpp ${KEY_MANAGER_PATH}/initial-values/parser.cpp ${KEY_MANAGER_PATH}/initial-values/BufferHandler.cpp ${KEY_MANAGER_PATH}/initial-values/CertHandler.cpp diff --git a/src/manager/client/client-manager-impl.cpp b/src/manager/client/client-manager-impl.cpp index 76a5e57..ca9d250 100644 --- a/src/manager/client/client-manager-impl.cpp +++ b/src/manager/client/client-manager-impl.cpp @@ -763,11 +763,12 @@ int ManagerImpl::setPermission(const Alias &alias, }); } -int ManagerImpl::encrypt(const CryptoAlgorithm &algo, - const Alias &keyAlias, - const Password &password, - const RawBuffer& plain, - RawBuffer& encrypted) +int ManagerImpl::crypt(EncryptionCommand command, + const CryptoAlgorithm &algo, + const Alias &keyAlias, + const Password &password, + const RawBuffer& input, + RawBuffer& output) { int my_counter = ++m_counter; @@ -775,13 +776,13 @@ int ManagerImpl::encrypt(const CryptoAlgorithm &algo, MessageBuffer recv; AliasSupport helper(keyAlias); CryptoAlgorithmSerializable cas(algo); - auto send = MessageBuffer::Serialize(static_cast(EncryptionCommand::ENCRYPT), + auto send = MessageBuffer::Serialize(static_cast(command), my_counter, cas, helper.getName(), helper.getLabel(), password, - plain); + input); int retCode = m_encryptionConnection.processRequest(send.Pop(), recv); if (CKM_API_SUCCESS != retCode) @@ -789,7 +790,7 @@ int ManagerImpl::encrypt(const CryptoAlgorithm &algo, int command; int counter; - recv.Deserialize(command, counter, encrypted); + recv.Deserialize(command, counter, retCode, output); if (my_counter != counter) { return CKM_API_ERROR_UNKNOWN; @@ -799,40 +800,22 @@ int ManagerImpl::encrypt(const CryptoAlgorithm &algo, }); } +int ManagerImpl::encrypt(const CryptoAlgorithm &algo, + const Alias &keyAlias, + const Password &password, + const RawBuffer& plain, + RawBuffer& encrypted) +{ + return crypt(EncryptionCommand::ENCRYPT, algo, keyAlias, password, plain, encrypted); +} + int ManagerImpl::decrypt(const CryptoAlgorithm &algo, const Alias &keyAlias, const Password &password, const RawBuffer& encrypted, RawBuffer& decrypted) { - int my_counter = ++m_counter; - - return try_catch([&] { - MessageBuffer recv; - AliasSupport helper(keyAlias); - CryptoAlgorithmSerializable cas(algo); - auto send = MessageBuffer::Serialize(static_cast(EncryptionCommand::DECRYPT), - my_counter, - cas, - helper.getName(), - helper.getLabel(), - password, - encrypted); - - int retCode = m_encryptionConnection.processRequest(send.Pop(), recv); - if (CKM_API_SUCCESS != retCode) - return retCode; - - int command; - int counter; - recv.Deserialize(command, counter, decrypted); - - if (my_counter != counter) { - return CKM_API_ERROR_UNKNOWN; - } - - return retCode; - }); + return crypt(EncryptionCommand::DECRYPT, algo, keyAlias, password, encrypted, decrypted); } ManagerShPtr Manager::create() { diff --git a/src/manager/client/client-manager-impl.h b/src/manager/client/client-manager-impl.h index fce5992..e9df170 100644 --- a/src/manager/client/client-manager-impl.h +++ b/src/manager/client/client-manager-impl.h @@ -153,6 +153,13 @@ protected: const Policy &policyPrivateKey, const Policy &policyPublicKey); + int crypt(EncryptionCommand command, + const CryptoAlgorithm &algo, + const Alias &keyAlias, + const Password &password, + const RawBuffer& input, + RawBuffer& output); + int m_counter; CKM::ServiceConnection m_storageConnection; CKM::ServiceConnection m_ocspConnection; diff --git a/src/manager/main/key-manager-main.cpp b/src/manager/main/key-manager-main.cpp index 71c76e7..d1e486e 100644 --- a/src/manager/main/key-manager-main.cpp +++ b/src/manager/main/key-manager-main.cpp @@ -34,6 +34,7 @@ #include #include +#include #include #include @@ -100,6 +101,7 @@ int main(void) { REGISTER_SOCKET_SERVICE(manager, CKM::CKMService); REGISTER_SOCKET_SERVICE(manager, CKM::OCSPService); + REGISTER_SOCKET_SERVICE(manager, CKM::EncryptionService); manager.MainLoop(); } diff --git a/src/manager/service/crypto-request.h b/src/manager/service/crypto-request.h new file mode 100644 index 0000000..d8acf2b --- /dev/null +++ b/src/manager/service/crypto-request.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +/* + * @file crypto-request.h + * @author Krzysztof Jackiewicz (k.jackiewicz@samsung.com) + * @version 1.0 + */ + +#pragma once + +#include +#include +#include + +namespace CKM { + +struct CryptoRequest +{ + ConnectionID conn; + Credentials cred; + EncryptionCommand command; + int msgId; + CryptoAlgorithmSerializable cas; + Name name; + Label label; + Password password; + RawBuffer input; +}; + +} /* namespace CKM */ diff --git a/src/manager/service/encryption-logic.cpp b/src/manager/service/encryption-logic.cpp new file mode 100644 index 0000000..5baac5b --- /dev/null +++ b/src/manager/service/encryption-logic.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +/* + * @file encryption-logic.cpp + * @author Krzysztof Jackiewicz (k.jackiewicz@samsung.com) + * @version 1.0 + */ + +#include +#include +#include + +namespace CKM { + +void EncryptionLogic::Crypt(const CryptoRequest& request) +{ + // check arguments + if(request.input.empty()) { + LogError("No input data"); + m_service.RespondToClient(request, CKM_API_ERROR_INPUT_PARAM); + return; + } + + // store request in the map + auto ret = m_requests.insert(std::make_pair(request.msgId, request)); + if (!ret.second) { + LogError("Request with id " << request.msgId << " already exists"); + m_service.RespondToClient(request, CKM_API_ERROR_INPUT_PARAM); + return; + } + + // request key + try { + m_service.RequestKey(request.cred, request.name, request.label); + } catch (...) { + LogError("Key request failed"); + m_requests.erase(request.msgId); + m_service.RespondToClient(request, CKM_API_ERROR_SERVER_ERROR); + } +} + +} /* namespace CKM */ diff --git a/src/manager/service/encryption-logic.h b/src/manager/service/encryption-logic.h new file mode 100644 index 0000000..21876f6 --- /dev/null +++ b/src/manager/service/encryption-logic.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +/* + * @file encryption-logic.h + * @author Krzysztof Jackiewicz (k.jackiewicz@samsung.com) + * @version 1.0 + */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace CKM { + +class EncryptionLogic +{ +public: + EncryptionLogic(IEncryptionService& service) : m_service(service) {} + virtual ~EncryptionLogic() {} + + void Crypt(const CryptoRequest& request); +private: + IEncryptionService& m_service; + + std::map m_requests; +}; + +} /* namespace CKM */ diff --git a/src/manager/service/encryption-service.cpp b/src/manager/service/encryption-service.cpp new file mode 100644 index 0000000..47faf39 --- /dev/null +++ b/src/manager/service/encryption-service.cpp @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +/* + * @file encryption-service.cpp + * @author Krzysztof Jackiewicz (k.jackiewicz@samsung.com) + * @version 1.0 + */ + +#include +#include +#include +#include +#include +#include +#include + +namespace { +const CKM::InterfaceID SOCKET_ID_ENCRYPTION = 0; +} // namespace anonymous + +namespace CKM { + +EncryptionService::EncryptionService() : m_logic(*this) +{ +} + +EncryptionService::~EncryptionService() +{ +} + +void EncryptionService::RespondToClient(const CryptoRequest& request, + int retCode, + const RawBuffer& data) +{ + try { + RawBuffer response = MessageBuffer::Serialize( + static_cast(request.command), request.msgId, retCode, data).Pop(); + m_serviceManager->Write(request.conn, response); + } catch (...) { + LogError("Failed to send response to the client"); + } +} + +void EncryptionService::RequestKey(const Credentials& /*cred*/, + const Alias& /*alias*/, + const Label& /*label*/) +{ + // This will be replaced in next commit + throw std::runtime_error("Not supported"); +} + +GenericSocketService::ServiceDescriptionVector EncryptionService::GetServiceDescription() +{ + return ServiceDescriptionVector { + {SERVICE_SOCKET_ENCRYPTION, "key-manager::api-encryption", SOCKET_ID_ENCRYPTION} + }; +} + +void EncryptionService::Start() { + Create(); +} + +void EncryptionService::Stop() { + Join(); +} + +bool EncryptionService::ProcessOne( + const ConnectionID &conn, + ConnectionInfo &info) +{ + LogDebug ("process One"); + try { + if (!info.buffer.Ready()) + return false; + + ProcessEncryption(conn, info.credentials, info.buffer); + return true; + } catch (MessageBuffer::Exception::Base) { + LogError("Broken protocol. Closing socket."); + } catch (const std::exception &e) { + LogError("Std exception:: " << e.what()); + } catch (...) { + LogError("Unknown exception. Closing socket."); + } + + m_serviceManager->Close(conn); + return false; +} + +void EncryptionService::ProcessEncryption(const ConnectionID &conn, + const Credentials &cred, + MessageBuffer &buffer) +{ + int tmpCmd = 0; + CryptoRequest req; + + buffer.Deserialize(tmpCmd, req.msgId, req.cas, req.name, req.label, req.password, req.input); + req.command = static_cast(tmpCmd); + if (req.command != EncryptionCommand::ENCRYPT && req.command != EncryptionCommand::DECRYPT) + throw std::runtime_error("Unsupported command: " + tmpCmd); + + req.conn = conn; + req.cred = cred; + m_logic.Crypt(req); +} + +} /* namespace CKM */ diff --git a/src/manager/service/encryption-service.h b/src/manager/service/encryption-service.h new file mode 100644 index 0000000..70146a1 --- /dev/null +++ b/src/manager/service/encryption-service.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +/* + * @file encryption-service.h + * @author Krzysztof Jackiewicz (k.jackiewicz@samsung.com) + * @version 1.0 + */ + +#pragma once + +#include +#include +#include +#include + +namespace CKM { + +class EncryptionService : public ThreadService, public IEncryptionService +{ +public: + EncryptionService(); + virtual ~EncryptionService(); + NONCOPYABLE(EncryptionService); + + // from ThreadService + ServiceDescriptionVector GetServiceDescription(); + + void Start(); + void Stop(); +private: + bool ProcessOne(const ConnectionID &conn, ConnectionInfo &info); + void ProcessEncryption(const ConnectionID &conn, + const Credentials &cred, + MessageBuffer &buffer); + + // from IEncryptionService + virtual void RespondToClient(const CryptoRequest& request, + int retCode, + const RawBuffer& data = RawBuffer()); + virtual void RequestKey(const Credentials& cred, + const Alias& alias, + const Label& label); + + EncryptionLogic m_logic; +}; + +} /* namespace CKM */ diff --git a/src/manager/service/iencryption-service.h b/src/manager/service/iencryption-service.h new file mode 100644 index 0000000..8e1ff5f --- /dev/null +++ b/src/manager/service/iencryption-service.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +/* + * @file iencryption-service.h + * @author Krzysztof Jackiewicz (k.jackiewicz@samsung.com) + * @version 1.0 + */ + +#pragma once + +#include +#include +#include +#include +#include + +namespace CKM { + +class IEncryptionService { +public: + virtual void RespondToClient(const CryptoRequest& request, + int retCode, + const RawBuffer& data = RawBuffer()) = 0; + virtual void RequestKey(const Credentials& cred, + const Alias& alias, + const Label& label) = 0; +}; + +} // namespace CKM + + diff --git a/systemd/CMakeLists.txt b/systemd/CMakeLists.txt index f9005e7..cda16ec 100644 --- a/systemd/CMakeLists.txt +++ b/systemd/CMakeLists.txt @@ -8,6 +8,7 @@ INSTALL(FILES ${CMAKE_SOURCE_DIR}/systemd/central-key-manager-api-control.socket ${CMAKE_SOURCE_DIR}/systemd/central-key-manager-api-storage.socket ${CMAKE_SOURCE_DIR}/systemd/central-key-manager-api-ocsp.socket + ${CMAKE_SOURCE_DIR}/systemd/central-key-manager-api-encryption.socket DESTINATION ${SYSTEMD_UNIT_DIR} ) diff --git a/systemd/central-key-manager-api-encryption.socket b/systemd/central-key-manager-api-encryption.socket new file mode 100644 index 0000000..21e8e81 --- /dev/null +++ b/systemd/central-key-manager-api-encryption.socket @@ -0,0 +1,14 @@ +[Socket] +ListenStream=/tmp/.central-key-manager-api-encryption.sock +SocketMode=0777 +SmackLabelIPIn=key-manager::api-encryption +SmackLabelIPOut=@ + +Service=central-key-manager.service + +[Unit] +Wants=central-key-manager.target +Before=central-key-manager.target + +[Install] +WantedBy=sockets.target diff --git a/systemd/central-key-manager.service.in b/systemd/central-key-manager.service.in index 469db7a..0159131 100644 --- a/systemd/central-key-manager.service.in +++ b/systemd/central-key-manager.service.in @@ -8,6 +8,7 @@ ExecStart=/usr/bin/key-manager Sockets=central-key-manager-api-storage.socket Sockets=central-key-manager-api-control.socket Sockets=central-key-manager-api-ocsp.socket +Sockets=central-key-manager-api-encryption.socket EnvironmentFile=-@SYSTEMD_ENV_FILE@ [Install] -- 2.7.4 From 096e85b4663abeab22fae3b48ea0119714cb6563 Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Wed, 17 Jun 2015 12:55:53 +0200 Subject: [PATCH 03/16] CommunicationManager returns the number of called listeners [Problem] There's no way to find out if inter-service message reached some listeners. [Solution] SendMessage returns the number of called listeners. [Verification] Run ckm-tests-internal -t MESSAGE_MANAGER_TEST Change-Id: I0f9cba13991cb79e2901a6784a6b18e3b87c7150 --- src/manager/main/communication-manager.h | 14 ++++++++++---- tests/test_comm-manager.cpp | 21 ++++++++++----------- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/src/manager/main/communication-manager.h b/src/manager/main/communication-manager.h index 898d483..1637a07 100644 --- a/src/manager/main/communication-manager.h +++ b/src/manager/main/communication-manager.h @@ -44,10 +44,15 @@ public: } // Sends message of type M to all registered listeners - void SendMessage(const M& msg) + // Returns the number of listeners called + size_t SendMessage(const M& msg) const { - for(auto it : m_listeners) + size_t num = 0; + for(auto& it : m_listeners) { it(msg); + num++; + } + return num; } protected: MessageManager() {} @@ -82,10 +87,11 @@ public: } // M message type + // Sending a message calls an unknown listener callback on the receiving side. It may throw. template - void SendMessage(const M& msg) + size_t SendMessage(const M& msg) const { - MessageManager::SendMessage(msg); + return MessageManager::SendMessage(msg); } }; diff --git a/tests/test_comm-manager.cpp b/tests/test_comm-manager.cpp index ec9ccaf..facd20b 100644 --- a/tests/test_comm-manager.cpp +++ b/tests/test_comm-manager.cpp @@ -63,15 +63,14 @@ BOOST_AUTO_TEST_SUITE(MESSAGE_MANAGER_TEST) BOOST_AUTO_TEST_CASE(TMM_0010_NoListener) { CKM::CommunicationManager mgr; - //int reci = 0; - mgr.SendMessage(MessageA(22)); + BOOST_REQUIRE_MESSAGE(0 == mgr.SendMessage(MessageA(22)), "There should be no listener."); } BOOST_AUTO_TEST_CASE(TMM_0020_Basic) { CKM::CommunicationManager mgr; int received = 0; mgr.Register([&](const MessageA& msg){ received = msg.i; }); - mgr.SendMessage(MessageA(4)); + BOOST_REQUIRE_MESSAGE(1 == mgr.SendMessage(MessageA(4)), "No listener found"); BOOST_REQUIRE_MESSAGE(received != 0, "Message not received"); BOOST_REQUIRE_MESSAGE(received == 4, "Wrong message received i=" << received); } @@ -82,12 +81,12 @@ BOOST_AUTO_TEST_CASE(TMM_0030_MultipleMessages) { char recc = 0; mgr.Register([&](const MessageA& msg){ reci = msg.i; }); mgr.Register([&](const MessageB& msg){ recc = msg.c; }); - mgr.SendMessage(MessageB('c')); + BOOST_REQUIRE_MESSAGE(1 == mgr.SendMessage(MessageB('c')), "No listener found"); BOOST_REQUIRE_MESSAGE(reci == 0, "Unexpected message received"); BOOST_REQUIRE_MESSAGE(recc != 0, "Message not received"); BOOST_REQUIRE_MESSAGE(recc == 'c', "Wrong message received c=" << recc); - mgr.SendMessage(MessageA(42)); + BOOST_REQUIRE_MESSAGE(1 == mgr.SendMessage(MessageA(42)), "No listener found"); BOOST_REQUIRE_MESSAGE(reci!= 0, "Message not received"); BOOST_REQUIRE_MESSAGE(reci == 42, "Wrong message received i=" << reci); BOOST_REQUIRE_MESSAGE(recc == 'c', "Previous message overwritten c=" << recc); @@ -99,12 +98,12 @@ BOOST_AUTO_TEST_CASE(TMM_0040_Listener) { mgr.Register([&](const MessageC& msg){ l.Handle(msg); }); mgr.Register([&](const MessageA& msg){ l.Handle(msg); }); - mgr.SendMessage(MessageC("lorem ipsum")); + BOOST_REQUIRE_MESSAGE(1 == mgr.SendMessage(MessageC("lorem ipsum")), "No listener found"); BOOST_REQUIRE_MESSAGE(l.i == 0, "Unexpected message received"); BOOST_REQUIRE_MESSAGE(!l.str.empty(), "Message not received"); BOOST_REQUIRE_MESSAGE(l.str == "lorem ipsum", "Wrong message received c=" << l.str); - mgr.SendMessage(MessageA(3)); + BOOST_REQUIRE_MESSAGE(1 == mgr.SendMessage(MessageA(3)), "No listener found"); BOOST_REQUIRE_MESSAGE(l.i!= 0, "Message not received"); BOOST_REQUIRE_MESSAGE(l.i == 3, "Wrong message received i=" << l.i); BOOST_REQUIRE_MESSAGE(l.str == "lorem ipsum", "Previous message overwritten str=" << l.str); @@ -124,7 +123,7 @@ BOOST_AUTO_TEST_CASE(TMM_0050_2Listeners) { called[1] = true; }); - mgr.SendMessage(MessageA(5)); + BOOST_REQUIRE_MESSAGE(2 == mgr.SendMessage(MessageA(5)), "No listener found"); BOOST_REQUIRE_MESSAGE(called[0], "First listener not called"); BOOST_REQUIRE_MESSAGE(called[1], "Second listener not called"); } @@ -159,15 +158,15 @@ BOOST_AUTO_TEST_CASE(TMM_0060_Stress) { switch(message_dist(generator)) { case 0: - mgr.SendMessage(MessageA(42)); + BOOST_REQUIRE_MESSAGE(1 == mgr.SendMessage(MessageA(42)), "No listener found"); a--; break; case 1: - mgr.SendMessage(MessageB('c')); + BOOST_REQUIRE_MESSAGE(1 == mgr.SendMessage(MessageB('c')), "No listener found"); b--; break; case 2: - mgr.SendMessage(MessageC("lorem ipsum")); + BOOST_REQUIRE_MESSAGE(1 == mgr.SendMessage(MessageC("lorem ipsum")), "No listener found"); c--; break; default: -- 2.7.4 From 51fc0f4d8f80ab3a6249a0d2e0675bed1e864c37 Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Wed, 17 Jun 2015 13:07:58 +0200 Subject: [PATCH 04/16] Add inter-service messages [Feature] Development of inter-service communication [Solution] Create inter-service communication message class hierarchy including key request and response messages. [Verification] Successfull compilation Change-Id: I41de882a089560201395fbcfe0143c067c1aee1f --- src/manager/main/credentials.h | 37 +++++++++++++++ src/manager/main/generic-socket-manager.h | 9 +--- src/manager/main/service-messages.h | 78 +++++++++++++++++++++++++++++++ 3 files changed, 116 insertions(+), 8 deletions(-) create mode 100644 src/manager/main/credentials.h create mode 100644 src/manager/main/service-messages.h diff --git a/src/manager/main/credentials.h b/src/manager/main/credentials.h new file mode 100644 index 0000000..e54f5df --- /dev/null +++ b/src/manager/main/credentials.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +/* + * @file credentials.h + * @author Krzysztof Jackiewicz (k.jackiewicz@samsung.com) + * @version 1.0 + */ + +#pragma once + +#include +#include + +namespace CKM { + +struct Credentials { + Credentials() : clientUid(0) {} + Credentials(uid_t socketUid, const Label & socketLabel) + : clientUid(socketUid), smackLabel(socketLabel) {} + uid_t clientUid; + Label smackLabel; +}; + +} // namespace CKM diff --git a/src/manager/main/generic-socket-manager.h b/src/manager/main/generic-socket-manager.h index c9d5eda..4108c3b 100644 --- a/src/manager/main/generic-socket-manager.h +++ b/src/manager/main/generic-socket-manager.h @@ -35,6 +35,7 @@ #include #include #include +#include extern "C" { struct msghdr; @@ -44,14 +45,6 @@ namespace CKM { typedef int InterfaceID; -struct Credentials { - Credentials() : clientUid(0) {} - Credentials(uid_t socketUid, const Label & socketLabel) - : clientUid(socketUid), smackLabel(socketLabel) {} - uid_t clientUid; - Label smackLabel; -}; - struct ConnectionID { int sock; // This is decriptor used for connection int counter; // Unique handler per socket diff --git a/src/manager/main/service-messages.h b/src/manager/main/service-messages.h new file mode 100644 index 0000000..f23711f --- /dev/null +++ b/src/manager/main/service-messages.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +/* + * @file service-messages.h + * @author Krzysztof Jackiewicz (k.jackiewicz@samsung.com) + * @version 1.0 + */ + +#pragma once + +#include + +#include +#include +#include +#include +#include +#include + +namespace CKM { + +// inter-service communication message base class +struct MsgBase +{ + explicit MsgBase(int id) : id(id) {} + virtual ~MsgBase() {} + + int id; +}; + +// key request +struct MsgKeyRequest : public MsgBase +{ + MsgKeyRequest(int id, + const Credentials& cred, + const Name& name, + const Label& label, + const Password& password) : + MsgBase(id), + cred(cred), + name(name), + label(label), + password(password) + {} + Credentials cred; + Name name; + Label label; + Password password; +}; + +// key response +struct MsgKeyResponse : public MsgBase +{ + MsgKeyResponse(int id, const Crypto::GKeyShPtr& key, int errorCode = CKM_API_SUCCESS) : + MsgBase(id), + key(key), + error(errorCode) + {} + Crypto::GKeyShPtr key; + int error; +}; + +typedef CommunicationManager CommMgr; + +} /* namespace CKM */ -- 2.7.4 From 9e6b0c1884462d25634e28205b4a117770918e2e Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Wed, 17 Jun 2015 13:12:39 +0200 Subject: [PATCH 05/16] Add support for inter-service communication in SocketManager [Feature] Inter-service communication development. [Solution] Add CommunicationManager basing on existing messages to SocketManager. Set communication manager in services. [Verification] Successfull compilation. Run ckm-tests --output. Change-Id: Ic22b3496f7f40a424cec4794513cec9211a752d1 --- src/manager/main/generic-socket-manager.h | 7 ++++++- src/manager/main/socket-manager.cpp | 15 ++++++++------- src/manager/main/socket-manager.h | 2 ++ src/manager/main/thread-service.h | 3 ++- 4 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/manager/main/generic-socket-manager.h b/src/manager/main/generic-socket-manager.h index 4108c3b..bec21c6 100644 --- a/src/manager/main/generic-socket-manager.h +++ b/src/manager/main/generic-socket-manager.h @@ -36,6 +36,7 @@ #include #include #include +#include extern "C" { struct msghdr; @@ -100,6 +101,9 @@ struct GenericSocketService { virtual void SetSocketManager(GenericSocketManager *manager) { m_serviceManager = manager; } + virtual void SetCommManager(CommMgr *manager) { + m_commMgr = manager; + } virtual ServiceDescriptionVector GetServiceDescription() = 0; virtual void Event(const AcceptEvent &event) = 0; @@ -110,10 +114,11 @@ struct GenericSocketService { virtual void Start() = 0; virtual void Stop() = 0; - GenericSocketService() : m_serviceManager(NULL) {} + GenericSocketService() : m_serviceManager(NULL), m_commMgr(NULL) {} virtual ~GenericSocketService(){} protected: GenericSocketManager *m_serviceManager; + CommMgr *m_commMgr; }; struct GenericSocketManager { diff --git a/src/manager/main/socket-manager.cpp b/src/manager/main/socket-manager.cpp index 4a5e147..44a7d3c 100644 --- a/src/manager/main/socket-manager.cpp +++ b/src/manager/main/socket-manager.cpp @@ -94,10 +94,10 @@ struct DummyService : public GenericSocketService { void Start() {} void Stop() {} - void Event(const AcceptEvent &event) { (void)event; } - void Event(const WriteEvent &event) { (void)event; } - void Event(const ReadEvent &event) { (void)event; } - void Event(const CloseEvent &event) { (void)event; } + void Event(const AcceptEvent &) {} + void Event(const WriteEvent &) {} + void Event(const ReadEvent &) {} + void Event(const CloseEvent &) {} }; struct SignalService : public GenericSocketService { @@ -118,9 +118,9 @@ struct SignalService : public GenericSocketService { void Start() {} void Stop() {} - void Event(const AcceptEvent &event) { (void)event; } // not supported - void Event(const WriteEvent &event) { (void)event; } // not supported - void Event(const CloseEvent &event) { (void)event; } // not supported + void Event(const AcceptEvent &) {} // not supported + void Event(const WriteEvent &) {} // not supported + void Event(const CloseEvent &) {} // not supported void Event(const ReadEvent &event) { LogDebug("Get signal information"); @@ -564,6 +564,7 @@ void SocketManager::CreateDomainSocket( void SocketManager::RegisterSocketService(GenericSocketService *service) { service->SetSocketManager(this); + service->SetCommManager(&m_commMgr); auto serviceVector = service->GetServiceDescription(); Try { for (auto iter = serviceVector.begin(); iter != serviceVector.end(); ++iter) diff --git a/src/manager/main/socket-manager.h b/src/manager/main/socket-manager.h index 978dbee..5dbffdc 100644 --- a/src/manager/main/socket-manager.h +++ b/src/manager/main/socket-manager.h @@ -35,6 +35,7 @@ #include #include +#include namespace CKM { @@ -119,6 +120,7 @@ protected: int m_notifyMe[2]; int m_counter; std::priority_queue m_timeoutQueue; + CommMgr m_commMgr; }; } // namespace CKM diff --git a/src/manager/main/thread-service.h b/src/manager/main/thread-service.h index 2a4cadb..e8f0ac6 100644 --- a/src/manager/main/thread-service.h +++ b/src/manager/main/thread-service.h @@ -43,11 +43,12 @@ public: protected: virtual bool ProcessOne(const ConnectionID &conn, ConnectionInfo &info) = 0; -private: + template void ThreadEvent(const E& event) { CreateEvent([this, event]() { this->Handle(event); }); } +private: void Handle(const AcceptEvent &event); void Handle(const WriteEvent &event); -- 2.7.4 From ec79e495a168fdc562056bdf48a7d0c0d3040cea Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Wed, 17 Jun 2015 14:17:57 +0200 Subject: [PATCH 06/16] Add MessageService [Feature] Inter-service communication development [Solution] Add MessageService and ThreadMessageService classes to support/simplify transferring inter service messages between services/threads. [Verification] Verify together with next commit Change-Id: Id205e299ffc186a5e6eae6563d9804ce61fdec21 --- src/manager/main/message-service.h | 161 +++++++++++++++++++++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 src/manager/main/message-service.h diff --git a/src/manager/main/message-service.h b/src/manager/main/message-service.h new file mode 100644 index 0000000..65512c0 --- /dev/null +++ b/src/manager/main/message-service.h @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +/* + * @file message-service.h + * @author Krzysztof Jackiewicz (k.jackiewicz@samsung.com) + * @version 1.0 + */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace CKM { + +/* + * MessageService framework is a wrapper for inter service communication with use of + * CommunicationManager. It allows registering a service as a listener in CommunicationManager and + * provides thread safe message handling. The message received from communication manager in + * SENDER THREAD is passed to RECEIVER THREAD. The RECEIVER THREAD is notified with + * ServiceThread::CreateEvent which in turn calls provided callback in this thread. + */ + +template +class MessageService; + + +// aggregating template +template +class MessageService : public MessageService, public MessageService +{ +protected: + // RECEIVER THREAD + template + void Register(Mgr& mgr) { + MessageService::Register(mgr); + MessageService::Register(mgr); + } + // RECEIVER THREAD + void CheckMessages() { + MessageService::CheckMessages(); + MessageService::CheckMessages(); + } +}; + + +// single Message type (Msg) handler +template +class MessageService +{ +public: + MessageService() {} + virtual ~MessageService() {} + NONCOPYABLE(MessageService); + +protected: + // RECEIVER THREAD: register as a listener of Msg + template + void Register(Mgr& mgr); + + // SENDER THREAD: notify about new message + virtual void Notify() = 0; + + // RECEIVER THREAD: check if there are new messages and process each of them + void CheckMessages(); + + // RECEIVER THREAD: process single message + virtual void ProcessMessage(Msg msg) = 0; + +private: + // SENDER THREAD: add message to the list + void AddMessage(const Msg& msg); + + std::mutex m_messagesMutex; + std::list m_messages; +}; + +template +template +void MessageService::Register(Mgr& mgr) +{ + mgr.Register([this](const Msg& msg) { this->AddMessage(msg); }); +} + +template +void MessageService::AddMessage(const Msg& msg) +{ + m_messagesMutex.lock(); + m_messages.push_back(msg); + m_messagesMutex.unlock(); + Notify(); // notify about added message +} + +template +void MessageService::CheckMessages() +{ + while(true) { + m_messagesMutex.lock(); + if (m_messages.empty()) { + m_messagesMutex.unlock(); + break; + } + // move out the first message + Msg message = std::move(m_messages.front()); + m_messages.pop_front(); + m_messagesMutex.unlock(); + + try { + ProcessMessage(std::move(message)); + } catch(...) { + LogError("Uncaught exception in ProcessMessage"); + } + } +} + + +// thread based service with messages support +template +class ThreadMessageService : public ThreadService, public MessageService +{ +public: + ThreadMessageService() {} + virtual ~ThreadMessageService() {} + NONCOPYABLE(ThreadMessageService); + + // RECEIVER THREAD: register as a listener of all supported messages + template + void Register(Mgr& mgr) { + MessageService::Register(mgr); + } + +private: + // SENDER THREAD: adds callback to RECEIVER THREAD event queue and wakes it + virtual void Notify() { + CreateEvent([this]() { this->CheckMessages(); }); + } + + // RECEIVER THREAD + void CheckMessages() { + MessageService::CheckMessages(); + } +}; + +} /* namespace CKM */ -- 2.7.4 From f323b4d1e97670aae8380563ef8e539dd76337bc Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Wed, 17 Jun 2015 14:19:50 +0200 Subject: [PATCH 07/16] Implement key retrieval in encryption service [Feature] Encryption/decryption service implementation [Solution] Encryption service sends a key request, CKM service retrieves the key and returns it to Encryption service. [Verification] Run ckm-tests --group=CKM_ENCRYPTION_DECRYPTION and observe journalctl -f. TED_0010_encrypt_invalid_param_list should print: "Attempt to retrieve key failed with error: -15" (5 times) other failing tests should print: "Encryption/decryption not yet supported" Change-Id: I56dc8a08ba211e996295f962da12193027c1a78c --- src/manager/service/ckm-logic.cpp | 28 ++++++++++++++++++++++++++++ src/manager/service/ckm-logic.h | 7 +++++++ src/manager/service/ckm-service.cpp | 23 +++++++++++++++++++++++ src/manager/service/ckm-service.h | 9 +++++++-- src/manager/service/encryption-logic.cpp | 29 ++++++++++++++++++++++++++++- src/manager/service/encryption-logic.h | 1 + src/manager/service/encryption-service.cpp | 20 +++++++++++++++----- src/manager/service/encryption-service.h | 13 ++++++++----- src/manager/service/iencryption-service.h | 4 +--- 9 files changed, 118 insertions(+), 16 deletions(-) diff --git a/src/manager/service/ckm-logic.cpp b/src/manager/service/ckm-logic.cpp index 7ec4213..35e9613 100644 --- a/src/manager/service/ckm-logic.cpp +++ b/src/manager/service/ckm-logic.cpp @@ -503,6 +503,34 @@ int CKMLogic::verifyAndSaveDataHelper( return retCode; } +int CKMLogic::getKeyForService( + const Credentials &cred, + const Name &name, + const Label &label, + const Password &pass, + Crypto::GKeyShPtr &key) +{ + DB::Row row; + try { + // Key is for internal service use. It won't be exported to the client + int retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, name, label, pass, row); + if (retCode == CKM_API_SUCCESS) + key = m_decider.getStore(row).getKey(row); + return retCode; + } catch (const KeyProvider::Exception::Base &e) { + LogError("KeyProvider failed with error: " << e.GetMessage()); + return CKM_API_ERROR_SERVER_ERROR; + } catch (const DB::Crypto::Exception::Base &e) { + LogError("DB::Crypto failed with message: " << e.GetMessage()); + return CKM_API_ERROR_DB_ERROR; + } catch (const Exc::Exception &e) { + return e.error(); + } catch (const CKM::Exception &e) { + LogError("CKM::Exception: " << e.GetMessage()); + return CKM_API_ERROR_SERVER_ERROR; + } +} + RawBuffer CKMLogic::saveData( const Credentials &cred, int commandId, diff --git a/src/manager/service/ckm-logic.h b/src/manager/service/ckm-logic.h index afc90be..b6dc1eb 100644 --- a/src/manager/service/ckm-logic.h +++ b/src/manager/service/ckm-logic.h @@ -35,6 +35,7 @@ #include #include #include +#include #include @@ -201,6 +202,12 @@ public: DataType dataType, const PolicySerializable &policy); + int getKeyForService(const Credentials &cred, + const Name &name, + const Label &label, + const Password& pass, + Crypto::GKeyShPtr& key); + private: // select private/system database depending on asking uid and owner label. diff --git a/src/manager/service/ckm-service.cpp b/src/manager/service/ckm-service.cpp index 644e1c4..0631ddd 100644 --- a/src/manager/service/ckm-service.cpp +++ b/src/manager/service/ckm-service.cpp @@ -59,6 +59,12 @@ GenericSocketService::ServiceDescriptionVector CKMService::GetServiceDescription }; } +void CKMService::SetCommManager(CommMgr *manager) +{ + ThreadService::SetCommManager(manager); + Register(*manager); +} + bool CKMService::ProcessOne( const ConnectionID &conn, ConnectionInfo &info) @@ -378,5 +384,22 @@ RawBuffer CKMService::ProcessStorage(Credentials &cred, MessageBuffer &buffer) } } +void CKMService::ProcessMessage(MsgKeyRequest msg) +{ + Crypto::GKeyShPtr key; + int ret = m_logic->getKeyForService(msg.cred, + msg.name, + msg.label, + msg.password, + key); + MsgKeyResponse kResp(msg.id, key, ret); + try { + if (!m_commMgr->SendMessage(kResp)) + LogError("No listener found"); // can't do much more + } catch (...) { + LogError("Uncaught exception in SendMessage. Check listeners."); + } +} + } // namespace CKM diff --git a/src/manager/service/ckm-service.h b/src/manager/service/ckm-service.h index b8b6c55..5bc7230 100644 --- a/src/manager/service/ckm-service.h +++ b/src/manager/service/ckm-service.h @@ -21,7 +21,8 @@ */ #pragma once -#include +#include +#include #include #include @@ -29,7 +30,7 @@ namespace CKM { class CKMLogic; -class CKMService : public CKM::ThreadService +class CKMService : public ThreadMessageService { public: CKMService(); @@ -46,6 +47,8 @@ public: ServiceDescriptionVector GetServiceDescription(); private: + virtual void SetCommManager(CommMgr *manager); + class Exception { public: DECLARE_EXCEPTION_TYPE(CKM::Exception, Base) @@ -63,6 +66,8 @@ private: Credentials &cred, MessageBuffer &buffer); + virtual void ProcessMessage(MsgKeyRequest msg); + CKMLogic *m_logic; }; diff --git a/src/manager/service/encryption-logic.cpp b/src/manager/service/encryption-logic.cpp index 5baac5b..2fd733c 100644 --- a/src/manager/service/encryption-logic.cpp +++ b/src/manager/service/encryption-logic.cpp @@ -44,7 +44,7 @@ void EncryptionLogic::Crypt(const CryptoRequest& request) // request key try { - m_service.RequestKey(request.cred, request.name, request.label); + m_service.RequestKey(request); } catch (...) { LogError("Key request failed"); m_requests.erase(request.msgId); @@ -52,4 +52,31 @@ void EncryptionLogic::Crypt(const CryptoRequest& request) } } +void EncryptionLogic::KeyRetrieved(MsgKeyResponse response) +{ + auto it = m_requests.find(response.id); + if (it == m_requests.end()) { + LogError("No matching request found"); // nothing we can do + return; + } + CryptoRequest req = std::move(it->second); + m_requests.erase(it); + + if (response.error != CKM_API_SUCCESS) { + LogError("Attempt to retrieve key failed with error: " << response.error); + m_service.RespondToClient(req, response.error); + return; + } + + if (!response.key) { + LogError("Retrieved key is empty"); + m_service.RespondToClient(req, CKM_API_ERROR_SERVER_ERROR); + return; + } + + // TODO encrypt/decrypt + LogError("Encryption/decryption not yet supported"); + m_service.RespondToClient(req, CKM_API_ERROR_SERVER_ERROR); +} + } /* namespace CKM */ diff --git a/src/manager/service/encryption-logic.h b/src/manager/service/encryption-logic.h index 21876f6..8f941dd 100644 --- a/src/manager/service/encryption-logic.h +++ b/src/manager/service/encryption-logic.h @@ -37,6 +37,7 @@ public: virtual ~EncryptionLogic() {} void Crypt(const CryptoRequest& request); + void KeyRetrieved(MsgKeyResponse response); private: IEncryptionService& m_service; diff --git a/src/manager/service/encryption-service.cpp b/src/manager/service/encryption-service.cpp index 47faf39..f08dbfa 100644 --- a/src/manager/service/encryption-service.cpp +++ b/src/manager/service/encryption-service.cpp @@ -54,12 +54,11 @@ void EncryptionService::RespondToClient(const CryptoRequest& request, } } -void EncryptionService::RequestKey(const Credentials& /*cred*/, - const Alias& /*alias*/, - const Label& /*label*/) +void EncryptionService::RequestKey(const CryptoRequest& request) { - // This will be replaced in next commit - throw std::runtime_error("Not supported"); + MsgKeyRequest kReq(request.msgId, request.cred, request.name, request.label, request.password); + if (!m_commMgr->SendMessage(kReq)) + throw std::runtime_error("No listener found"); // TODO } GenericSocketService::ServiceDescriptionVector EncryptionService::GetServiceDescription() @@ -77,6 +76,12 @@ void EncryptionService::Stop() { Join(); } +void EncryptionService::SetCommManager(CommMgr *manager) +{ + ThreadService::SetCommManager(manager); + Register(*manager); +} + bool EncryptionService::ProcessOne( const ConnectionID &conn, ConnectionInfo &info) @@ -100,6 +105,11 @@ bool EncryptionService::ProcessOne( return false; } +void EncryptionService::ProcessMessage(MsgKeyResponse msg) +{ + m_logic.KeyRetrieved(std::move(msg)); +} + void EncryptionService::ProcessEncryption(const ConnectionID &conn, const Credentials &cred, MessageBuffer &buffer) diff --git a/src/manager/service/encryption-service.h b/src/manager/service/encryption-service.h index 70146a1..73140b7 100644 --- a/src/manager/service/encryption-service.h +++ b/src/manager/service/encryption-service.h @@ -21,14 +21,15 @@ #pragma once -#include +#include #include #include #include +#include namespace CKM { -class EncryptionService : public ThreadService, public IEncryptionService +class EncryptionService : public ThreadMessageService, public IEncryptionService { public: EncryptionService(); @@ -40,8 +41,12 @@ public: void Start(); void Stop(); + private: + virtual void SetCommManager(CommMgr *manager); + bool ProcessOne(const ConnectionID &conn, ConnectionInfo &info); + void ProcessMessage(MsgKeyResponse msg); void ProcessEncryption(const ConnectionID &conn, const Credentials &cred, MessageBuffer &buffer); @@ -50,9 +55,7 @@ private: virtual void RespondToClient(const CryptoRequest& request, int retCode, const RawBuffer& data = RawBuffer()); - virtual void RequestKey(const Credentials& cred, - const Alias& alias, - const Label& label); + virtual void RequestKey(const CryptoRequest& request); EncryptionLogic m_logic; }; diff --git a/src/manager/service/iencryption-service.h b/src/manager/service/iencryption-service.h index 8e1ff5f..2c1d906 100644 --- a/src/manager/service/iencryption-service.h +++ b/src/manager/service/iencryption-service.h @@ -34,9 +34,7 @@ public: virtual void RespondToClient(const CryptoRequest& request, int retCode, const RawBuffer& data = RawBuffer()) = 0; - virtual void RequestKey(const Credentials& cred, - const Alias& alias, - const Label& label) = 0; + virtual void RequestKey(const CryptoRequest& request) = 0; }; } // namespace CKM -- 2.7.4 From ea0e543ca73d9957e8ced12cc7058a8761b20c38 Mon Sep 17 00:00:00 2001 From: "Maciej J. Karpiuk" Date: Thu, 25 Jun 2015 14:34:09 +0200 Subject: [PATCH 08/16] encrypted initial values: schema enhancements plus SW device key schema. Change-Id: Ib0f47fc5c95a785a9d2263a2d0b16da2c1ea7460 --- doc/example.xml | 2 +- doc/example_device_key.xml | 28 ++++++++++++++++++++++++++++ doc/initial_values.xsd | 5 ++++- doc/sw_key.xsd | 41 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 doc/example_device_key.xml create mode 100644 doc/sw_key.xsd diff --git a/doc/example.xml b/doc/example.xml index c5d2874..7b07961 100644 --- a/doc/example.xml +++ b/doc/example.xml @@ -1,5 +1,5 @@ - + -----BEGIN PUBLIC KEY----- diff --git a/doc/example_device_key.xml b/doc/example_device_key.xml new file mode 100644 index 0000000..e191221 --- /dev/null +++ b/doc/example_device_key.xml @@ -0,0 +1,28 @@ + + + + + MIIEpAIBAAKCAQEAyJjUHY2pJJUBRBCrlerrgcS7aBiWlY3594dufu3m4qy48b9hsw1R/AHSNUPU + 11vzQ+kUcXkEZOby5SHRHBAXIJ1dLbTPtRwsVwgf1nmc/ZGGV/XOrOaKi7nSKgYHaglPgc9dLPuu + osRHs/EdIWh3o59MdY6rA6y+QTJrQm3axRKdT7unX3kFS3SsId02GWBkLtrw+yQVtvhCYlY/n2/T + uZBJpZN7vT2it0rJS4fQkfjcjAi8f/isZLrfUgDqxIDSWVbVyjlQOphIO+K3ABjev3ZbJMWl+w10 + pV0nbmF8lviEYft9mhERS9kUdQwzy3KIgyjyt+ewQG6hjyMJ/5y5KwIDAQABAoIBAQC3S06nIoZn + su/RLhpbhqljjkxgNfeC+JRsJghFW0UZ4xGrdGDlp0o+p7tYiH63uoFykEvp09a8DHvt+xSEO/+m + AaTe2tTgfLnXXMkaxU06Nfs37JfJTW9TdZwgYhnsPk20I7LUI7XTbN7IAY3ItRh9HlZTJOYHGZVP + Ja70qES6xUOTaVOvKIbB2W9XeiMX6cNoHTLM9rl1I8bA13Er0M0acKRtF4Rfw4z43nJKzORCYKm3 + mA3zqtQja7z+zdQBib34RHZiKgvuJDqg89p7FTLT9z+lbXONH+K/3MldaYG1O8mtgt4zv6onH199 + QBOrww158Z6keH3tBz+xsrClfIpBAoGBAPkar4ugZYLRgyuythby3uHrlMBNajmJf2gFwngvfUgO + JS45fLN2AIDrA5VYUiT8cFjVFfzEiu1xa33Juy8rfHlQuY8yOIVDnbdGJvOBYsrvlyYWY+9jEydd + cLctQKquACLb3jNYbrC9m8cBBcSZelRAVSF4O1k8HdlcdV7IIVyjAoGBAM4mY5PNLr3I/pyyNizw + 7cUmHdblU+sScwFdC/KDwfG5WOI3WorTLutD4EiEA3yQIDStuVJLiray4Pu+bqhUPAJumpRrpQJ4 + PCPxr/M98FhXvMmDWzGu/xK/6hLP5g1Ngp6qvVygnYNBkyqMzfM0rUAxQLS3qmocWk2xBKDEnjHZ + AoGBAJkWgVO52yiuQYKVbbpkv/zvnpcf/GwnyBjRkVXzOXcS2l6yDaTsnBqeU7FweespCJJPQhf5 + YbfSwFCprVOr0e9sYN1T69BaYY7EmiOEHIbC/4z0ra3soVTL4/1u3hMGpCbIIKJFcqFDpXyDcFwG + RluIvci37yFEBMQUQj1hmL8pAoGAJBHtfG/7TLO9cRdxiT2CrOs1b2Ni4o+w1b09GOra5XujxLkg + u4el/v46YRXQMlxZdj4rXe3f0IXN/d5dKFDMyzQlEfEfxyXYiAWC3tGomxyG6M92BmRzNwmjYDVG + MG+ueiqvxWRJCy1PHbPTWUmPQtsbUkOMqtJZLpzZjXO5pkkCgYA9uyQ8os9yfjALc1VDZ4HtGxaC + Uq8zy0jJEJxchRn1JUNHop/skaRA65x613lWDygfNCuakozjP5x+GA5WEIuxIE8V7JPac1zpEZW4 + 5nwmxoR1l3HUDT8kRYkLzMIo55PpLG9arNLwH9mSRh/taG8020aGg3nFSNCJNDs12x/9RA== + + + diff --git a/doc/initial_values.xsd b/doc/initial_values.xsd index 69068df..c28c33c 100644 --- a/doc/initial_values.xsd +++ b/doc/initial_values.xsd @@ -52,6 +52,9 @@ + + @@ -125,4 +128,4 @@ - \ No newline at end of file + diff --git a/doc/sw_key.xsd b/doc/sw_key.xsd new file mode 100644 index 0000000..d4434b4 --- /dev/null +++ b/doc/sw_key.xsd @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 2.7.4 From 85841ebd72c1b00be105d078d3c6b79d4bfe9cfb Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Thu, 18 Jun 2015 16:24:20 +0200 Subject: [PATCH 09/16] Encryption service calls proper encryption/decryption methods [Feature] Encryption srevice development [Solution] After key is retrieved it is used to perform encryption/decryption of data and return the result to the client. [Verification] Run ckm-tests --group=CKM_ENCRYPTION_DECRYPTION. TED_1250_gcm_aad may fail. Change-Id: Iaff45ac05df0470eabf3164c6fb427c68c9ef1a5 --- src/manager/crypto/generic-backend/gkey.h | 1 + src/manager/service/ckm-logic.cpp | 3 --- src/manager/service/encryption-logic.cpp | 17 ++++++++++++++--- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/manager/crypto/generic-backend/gkey.h b/src/manager/crypto/generic-backend/gkey.h index 530842d..b06926d 100644 --- a/src/manager/crypto/generic-backend/gkey.h +++ b/src/manager/crypto/generic-backend/gkey.h @@ -57,6 +57,7 @@ public: }; typedef std::unique_ptr GKeyUPtr; +typedef std::shared_ptr GKeyShPtr; } // namespace Crypto } // namespace CKM diff --git a/src/manager/service/ckm-logic.cpp b/src/manager/service/ckm-logic.cpp index 35e9613..a173cd7 100644 --- a/src/manager/service/ckm-logic.cpp +++ b/src/manager/service/ckm-logic.cpp @@ -517,9 +517,6 @@ int CKMLogic::getKeyForService( if (retCode == CKM_API_SUCCESS) key = m_decider.getStore(row).getKey(row); return retCode; - } catch (const KeyProvider::Exception::Base &e) { - LogError("KeyProvider failed with error: " << e.GetMessage()); - return CKM_API_ERROR_SERVER_ERROR; } catch (const DB::Crypto::Exception::Base &e) { LogError("DB::Crypto failed with message: " << e.GetMessage()); return CKM_API_ERROR_DB_ERROR; diff --git a/src/manager/service/encryption-logic.cpp b/src/manager/service/encryption-logic.cpp index 2fd733c..a2bad2b 100644 --- a/src/manager/service/encryption-logic.cpp +++ b/src/manager/service/encryption-logic.cpp @@ -74,9 +74,20 @@ void EncryptionLogic::KeyRetrieved(MsgKeyResponse response) return; } - // TODO encrypt/decrypt - LogError("Encryption/decryption not yet supported"); - m_service.RespondToClient(req, CKM_API_ERROR_SERVER_ERROR); + // encrypt/decrypt + try { + RawBuffer output; + if (req.command == EncryptionCommand::ENCRYPT) + output = response.key->encrypt(req.cas, req.input); + else + output = response.key->decrypt(req.cas, req.input); + m_service.RespondToClient(req, CKM_API_SUCCESS, output); + } catch (const Exc::Exception& ex) { + m_service.RespondToClient(req, ex.error()); + } catch (...) { + LogError("Uncaught exception from encrypt/decrypt."); + m_service.RespondToClient(req, CKM_API_ERROR_SERVER_ERROR); + } } } /* namespace CKM */ -- 2.7.4 From 07537558404c671d2bb26101ae87fe37bc9706e5 Mon Sep 17 00:00:00 2001 From: Dongsun Lee Date: Sat, 27 Jun 2015 15:27:54 +0900 Subject: [PATCH 10/16] add a solution in case for no password set Change-Id: Ie7d65c5165a2d0e162b4e990240c84e12d6227ed Signed-off-by: Dongsun Lee --- src/manager/service/ckm-service.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/manager/service/ckm-service.cpp b/src/manager/service/ckm-service.cpp index 644e1c4..3a21a64 100644 --- a/src/manager/service/ckm-service.cpp +++ b/src/manager/service/ckm-service.cpp @@ -166,6 +166,14 @@ RawBuffer CKMService::ProcessStorage(Credentials &cred, MessageBuffer &buffer) buffer.Deserialize(command); buffer.Deserialize(msgID); + // This is a workaround solution for locktype=None in Tizen 2.2.1 + // When locktype is None, lockscreen app doesn't interfere with unlocking process. + // Therefor lockscreen app cannot notify unlock events to key-manager when locktype is None. + // So, to unlock user data when lock type is None, key-manager always try to unlock user data with null password. + // Even if the result is fail, it will be ignored. + Password nullPassword(""); + m_logic->unlockUserKey(cred.clientUid, nullPassword); + LogDebug("Process storage. Command: " << command); switch(static_cast(command)) { -- 2.7.4 From 06d3064a993c97b2f6dba5d778ea41c319eb18ef Mon Sep 17 00:00:00 2001 From: Dongsun Lee Date: Sat, 27 Jun 2015 15:29:24 +0900 Subject: [PATCH 11/16] allow all clients to access storage socket and ocsp socket Change-Id: I38dc270b4e58cc791a219fb2c46520650f2bba0b Signed-off-by: Dongsun Lee --- systemd/central-key-manager-api-ocsp.socket | 2 +- systemd/central-key-manager-api-storage.socket | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/systemd/central-key-manager-api-ocsp.socket b/systemd/central-key-manager-api-ocsp.socket index b20e7e7..ee5307c 100644 --- a/systemd/central-key-manager-api-ocsp.socket +++ b/systemd/central-key-manager-api-ocsp.socket @@ -1,7 +1,7 @@ [Socket] ListenStream=/tmp/.central-key-manager-api-ocsp.sock SocketMode=0777 -SmackLabelIPIn=key-manager::api-ocsp +SmackLabelIPIn=* SmackLabelIPOut=@ Service=central-key-manager.service diff --git a/systemd/central-key-manager-api-storage.socket b/systemd/central-key-manager-api-storage.socket index 7bc5350..359923c 100644 --- a/systemd/central-key-manager-api-storage.socket +++ b/systemd/central-key-manager-api-storage.socket @@ -1,7 +1,7 @@ [Socket] ListenStream=/tmp/.central-key-manager-api-storage.sock SocketMode=0777 -SmackLabelIPIn=key-manager::api-storage +SmackLabelIPIn=* SmackLabelIPOut=@ Service=central-key-manager.service -- 2.7.4 From 2ddf3ea967433cebd888077c268779aa08f58c86 Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Mon, 29 Jun 2015 11:13:30 +0200 Subject: [PATCH 12/16] Fix C compilation [Problem] ckmc_param_list_s fails to compile when C compiler is used. [Solution] Proper typedef added. [Verification] Successfull compilation of security-tests (c-compilation.c). Change-Id: I90cbd8a530707961d593f51e5bc0f2cc9b4b38d3 --- src/include/ckmc/ckmc-type.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/include/ckmc/ckmc-type.h b/src/include/ckmc/ckmc-type.h index 19504de..611808e 100644 --- a/src/include/ckmc/ckmc-type.h +++ b/src/include/ckmc/ckmc-type.h @@ -246,7 +246,7 @@ typedef enum __ckmc_param_name { * @brief Structure for algorithm parameter list. * @since_tizen 3.0 */ -struct ckmc_param_list_s; +typedef struct __ckmc_param_list ckmc_param_list_s; /** * @brief Enumeration for crypto algorithm types. -- 2.7.4 From b5d73601f8a1a7a70797934e139617d5356c7f48 Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Fri, 19 Jun 2015 10:08:31 +0200 Subject: [PATCH 13/16] Add algorithm param validation [Problem] Algorithm param validation is quite complicated. We need a generic mechanism for parameter constraints definition. Aes key generation algorithm is missing. There's no validation of encryption params. [Solution] Created generic parameter validation framework. Defined constraints for all algorithms. Aes key algorithm added. Algorithm parameter validation refactored. [Verification] run ckm-tests --output=text Change-Id: Ia1df8a3f4bcda835a736d5fe1e4fbc7157d1a26c --- src/include/ckm/ckm-type.h | 1 + src/include/ckmc/ckmc-type.h | 13 +- src/manager/common/data-type.cpp | 23 ++- .../crypto/generic-backend/algo-validation.h | 199 ++++++++++++++++++++ src/manager/crypto/sw-backend/internals.cpp | 209 ++++++++++++++++++--- src/manager/crypto/sw-backend/internals.h | 5 +- src/manager/crypto/sw-backend/key.cpp | 45 ++++- src/manager/crypto/sw-backend/store.cpp | 30 +-- src/manager/service/ckm-logic.cpp | 1 + 9 files changed, 462 insertions(+), 64 deletions(-) create mode 100644 src/manager/crypto/generic-backend/algo-validation.h diff --git a/src/include/ckm/ckm-type.h b/src/include/ckm/ckm-type.h index 281f351..5ce89b6 100644 --- a/src/include/ckm/ckm-type.h +++ b/src/include/ckm/ckm-type.h @@ -148,6 +148,7 @@ enum class AlgoType : int { RSA_GEN, DSA_GEN, ECDSA_GEN, + AES_GEN, }; // cryptographic algorithm description diff --git a/src/include/ckmc/ckmc-type.h b/src/include/ckmc/ckmc-type.h index 611808e..a450b86 100644 --- a/src/include/ckmc/ckmc-type.h +++ b/src/include/ckmc/ckmc-type.h @@ -228,13 +228,13 @@ typedef enum __ckmc_param_name { // encryption & decryption CKMC_PARAM_ED_IV = 101, /**< 16B buffer (up to 2^64-1 bytes long in case of AES GCM) */ - CKMC_PARAM_ED_CTR_LEN, /**< integer */ + CKMC_PARAM_ED_CTR_LEN, /**< integer - ctr length in bits*/ CKMC_PARAM_ED_AAD, /**< buffer */ - CKMC_PARAM_ED_TAG_LEN, /**< integer */ + CKMC_PARAM_ED_TAG_LEN, /**< integer - tag length in bits */ CKMC_PARAM_ED_LABEL, /**< buffer */ // key generation - CKMC_PARAM_GEN_KEY_LEN = 201, /**< integer */ + CKMC_PARAM_GEN_KEY_LEN = 201, /**< integer - key length in bits */ CKMC_PARAM_GEN_EC, /**< integer - elliptic curve (ckmc_ec_type_e) */ // sign & verify @@ -307,10 +307,15 @@ typedef enum __ckmc_algo_type { - CKMC_PARAM_ALGO_TYPE, - CKMC_PARAM_GEN_KEY_LEN */ - CKMC_ALGO_ECDSA_GEN, /**< ECDA algorithm used for key generation + CKMC_ALGO_ECDSA_GEN, /**< ECDSA algorithm used for key generation Supported parameters: - CKMC_PARAM_ALGO_TYPE, - CKMC_PARAM_GEN_EC */ + + CKMC_ALGO_AES_GEN, /**< AES key generation + Supported parameters: + - CKMC_PARAM_ALGO_TYPE, + - CKMC_PARAM_GEN_KEY_LEN */ } ckmc_algo_type_e; /** diff --git a/src/manager/common/data-type.cpp b/src/manager/common/data-type.cpp index e8cfb84..a7fcf63 100644 --- a/src/manager/common/data-type.cpp +++ b/src/manager/common/data-type.cpp @@ -32,7 +32,8 @@ DataType::DataType(Type data) : m_dataType(data) { if (!isInRange(data)) - ThrowMsg(Exception::OutOfRange, "Invalid conversion from DataType to DBDataType"); + ThrowMsg(Exception::OutOfRange, + "Invalid conversion from DataType=" << static_cast(data) << " to DBDataType"); } DataType::DataType(KeyType key) { @@ -45,7 +46,8 @@ DataType::DataType(KeyType key) { case KeyType::KEY_ECDSA_PRIVATE: m_dataType = DataType::KEY_ECDSA_PRIVATE; break; case KeyType::KEY_AES: m_dataType = DataType::KEY_AES; break; default: - ThrowMsg(Exception::OutOfRange, "Invalid conversion from KeyType to DBDataType"); + ThrowMsg(Exception::OutOfRange, + "Invalid conversion from KeyType=" << static_cast(key) << " to DBDataType"); } } @@ -54,12 +56,19 @@ DataType::DataType(AlgoType algorithmType) { case AlgoType::AES_CTR: case AlgoType::AES_CBC: case AlgoType::AES_GCM: - case AlgoType::AES_CFB: m_dataType = DataType::KEY_AES; break; + case AlgoType::AES_CFB: + case AlgoType::AES_GEN: m_dataType = DataType::KEY_AES; break; + case AlgoType::RSA_SV: + case AlgoType::RSA_OAEP: case AlgoType::RSA_GEN: m_dataType = DataType::KEY_RSA_PUBLIC; break; + case AlgoType::DSA_SV: case AlgoType::DSA_GEN: m_dataType = DataType::KEY_DSA_PUBLIC; break; + case AlgoType::ECDSA_SV: case AlgoType::ECDSA_GEN: m_dataType = DataType::KEY_ECDSA_PUBLIC; break; default: - ThrowMsg(Exception::OutOfRange, "Invalid conversion from AlgoType to DBDataType"); + ThrowMsg(Exception::OutOfRange, + "Invalid conversion from AlgoType=" << static_cast(algorithmType) << + " to DBDataType"); } } @@ -67,7 +76,7 @@ DataType::DataType(int data) : m_dataType(static_cast(data)) { if (!isInRange(data)) - ThrowMsg(Exception::OutOfRange, "Invalid conversion from int to DBDataType"); + ThrowMsg(Exception::OutOfRange, "Invalid conversion from int=" << data << " to DBDataType"); } DataType::operator int () const { @@ -84,7 +93,9 @@ DataType::operator KeyType () const { case DataType::KEY_ECDSA_PUBLIC: return KeyType::KEY_ECDSA_PUBLIC; case DataType::KEY_AES: return KeyType::KEY_AES; default: - ThrowMsg(Exception::OutOfRange, "Invalid conversion from DBDataType to KeyType"); + ThrowMsg(Exception::OutOfRange, + "Invalid conversion from DBDataType=" << static_cast(m_dataType) << + " to KeyType" ); } } diff --git a/src/manager/crypto/generic-backend/algo-validation.h b/src/manager/crypto/generic-backend/algo-validation.h new file mode 100644 index 0000000..c8abc72 --- /dev/null +++ b/src/manager/crypto/generic-backend/algo-validation.h @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +/* + * @file algo-validation.h + * @author Krzysztof Jackiewicz (k.jackiewicz@samsung.com) + * @version 1.0 + */ + +#pragma once + +#include +#include +#include + +#include + +#include + +namespace CKM { +namespace Crypto { + +template +T unpack( + const CryptoAlgorithm &alg, + ParamName paramName) +{ + T result; + if (!alg.getParam(paramName, result)) { + ThrowErr(Exc::Crypto::InputParam, "Wrong input param"); + } + return result; +} + + +////////// Validators ////////////// + +// Always validates as true. Useful for checking parameter existence only +template +struct DefaultValidator { + static bool Check(const T&) { return true; } + static void Why(std::ostringstream& os) { os << "is ok"; } +}; + +// Validates as true if parameter value is equal to one of Args +template +struct Type { + template + struct Equals; + + template + struct Equals { + public: + static bool Check(const T& value) { + return First == value; + } + static void Why(std::ostringstream& os) { + os << "doesn't match " << static_cast(First); + } + }; + + template + struct Equals : public Equals, public Equals { + public: + static bool Check(const T& value) { + return Equals::Check(value) || Equals::Check(value); + } + static void Why(std::ostringstream& os) { + Equals::Why(os); + os << ", "; + Equals::Why(os); + } + }; +}; + + +////////// Getters ////////////// + +// simply returns parameter value +template +struct DefaultGetter { + static T Get(const T& value) { return value; } + static void What(std::ostringstream& os) { os << "value"; } +}; + +// returns buffer param size +struct BufferSizeGetter { + static size_t Get(const RawBuffer& buffer) { return buffer.size(); } + static void What(std::ostringstream& os) { os << "buffer size"; } +}; + + +////////// ErrorHandlers ////////////// + +struct ThrowingHandler { + static void Handle(std::string message) { + ThrowErr(Exc::Crypto::InputParam, message); + } +}; + + +// base class for parameter check +struct ParamCheckBase { + virtual ~ParamCheckBase() {} + virtual void Check(const CryptoAlgorithm& ca) const = 0; +}; + +typedef std::unique_ptr ParamCheckBasePtr; + +typedef std::vector ValidatorVector; + + +// ValidatorVector builder. Creates a vector of ParamCheckBasePtr's specified as Args +template +struct VBuilder; + +template +struct VBuilder { +static ValidatorVector Build() { + ValidatorVector validators; + Add(validators); + return validators; + } +protected: + static void Add(ValidatorVector& validators) { + validators.emplace_back(new First); + } +}; + +template +struct VBuilder : public VBuilder, public VBuilder { + static ValidatorVector Build() { + ValidatorVector validators; + Add(validators); + return validators; + } +protected: + static void Add(ValidatorVector& validators) { + VBuilder::Add(validators); + VBuilder::Add(validators); + } +}; + +/* + * Generic struct responsible for checking a single constraint on given algorithm parameter + * + * Name - name of param to check + * Type - type of param value + * Mandatory - true if param is mandatory + * Validator - class providing validation function bool Check(const CryptoAlgorithm&) + * Getter - gets the value used for validation (param value itself or a buffer size for example) + * ErrorHandler - class providing method for error handling void Handle(std::string) + */ + +template , + typename Getter = DefaultGetter, + typename ErrorHandler = ThrowingHandler> +struct ParamCheck : public ParamCheckBase { + void Check(const CryptoAlgorithm& ca) const { + Type value; + std::ostringstream os; + + // check existence + if(!ca.getParam(Name,value)) { + if (Mandatory) { + os << "Mandatory parameter " << static_cast(Name) << " doesn't exist"; + ErrorHandler::Handle(os.str()); + } + return; + } + // validate + if(!Validator::Check(Getter::Get(value))) { + os << "The "; + Getter::What(os); + os << " of param '" << static_cast(Name) << "'=" << + static_cast(Getter::Get(value)) << " "; + Validator::Why(os); + ErrorHandler::Handle(os.str()); + } + } +}; + +} // namespace Crypto +} // namespace CKM diff --git a/src/manager/crypto/sw-backend/internals.cpp b/src/manager/crypto/sw-backend/internals.cpp index 89c131f..8612631 100644 --- a/src/manager/crypto/sw-backend/internals.cpp +++ b/src/manager/crypto/sw-backend/internals.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -39,6 +40,7 @@ #include #include +#include #include #include @@ -47,6 +49,11 @@ #define DEV_HW_RANDOM_FILE "/dev/hwrng" #define DEV_URANDOM_FILE "/dev/urandom" +namespace CKM { +namespace Crypto { +namespace SW { +namespace Internals { + namespace { typedef std::unique_ptr> EvpMdCtxUPtr; typedef std::unique_ptr> EvpPkeyCtxUPtr; @@ -54,52 +61,162 @@ typedef std::unique_ptr> EvpPkeyUPtr; typedef std::unique_ptr> BioUniquePtr; typedef int(*I2D_CONV)(BIO*, EVP_PKEY*); -CKM::RawBuffer i2d(I2D_CONV fun, EVP_PKEY* pkey) { + +const size_t DEFAULT_AES_GCM_TAG_LEN = 128; // tag length in bits according to W3C Crypto API +const size_t DEFAULT_AES_IV_LEN = 16; // default iv size in bytes for AES + +RawBuffer i2d(I2D_CONV fun, EVP_PKEY* pkey) { BioUniquePtr bio(BIO_new(BIO_s_mem()), BIO_free_all); if (NULL == pkey) { - ThrowErr(CKM::Exc::Crypto::InternalError, "attempt to parse an empty key!"); + ThrowErr(Exc::Crypto::InternalError, "attempt to parse an empty key!"); } if (NULL == bio.get()) { - ThrowErr(CKM::Exc::Crypto::InternalError, "Error in memory allocation! Function: BIO_new."); + ThrowErr(Exc::Crypto::InternalError, "Error in memory allocation! Function: BIO_new."); } if (1 != fun(bio.get(), pkey)) { - ThrowErr(CKM::Exc::Crypto::InternalError, "Error in conversion EVP_PKEY to DER"); + ThrowErr(Exc::Crypto::InternalError, "Error in conversion EVP_PKEY to DER"); } - CKM::RawBuffer output(8196); + RawBuffer output(8196); int size = BIO_read(bio.get(), output.data(), output.size()); if (size <= 0) { - ThrowErr(CKM::Exc::Crypto::InternalError, "Error in BIO_read: ", size); + ThrowErr(Exc::Crypto::InternalError, "Error in BIO_read: ", size); } output.resize(size); return output; } -template -T unpack( - const CKM::CryptoAlgorithm &alg, - CKM::ParamName paramName) +// encryption / decryption +typedef ParamCheck::Equals> IsEncryption; + +typedef ParamCheck::Equals, + BufferSizeGetter> IvSizeCheck; + +typedef ParamCheck::Equals<128>> CtrLenCheck; + +typedef ParamCheck, + BufferSizeGetter> GcmIvCheck; + +typedef ParamCheck::Equals<32, 64, 96, 104, 112, 120, 128>> GcmTagCheck; + +// sign / verify +typedef ParamCheck::Equals> IsSignVerify; + +typedef ParamCheck::Equals> HashAlgoCheck; + +typedef ParamCheck::Equals> RsaPaddingCheck; + +// key generation +typedef ParamCheck::Equals> IsAsymGeneration; + +typedef ParamCheck::Equals> IsSymGeneration; + +typedef ParamCheck::Equals<1024, 2048, 4096>> RsaKeyLenCheck; + +typedef ParamCheck::Equals<1024, 2048, 3072, 4096>> DsaKeyLenCheck; + +typedef ParamCheck::Equals<128, 192, 256>> AesKeyLenCheck; + +typedef ParamCheck::Equals> EcdsaEcCheck; + +typedef std::map ValidatorMap; +ValidatorMap initValidators() { + ValidatorMap validators; + validators.emplace(AlgoType::RSA_SV, VBuilder::Build()); + validators.emplace(AlgoType::RSA_SV, VBuilder::Build()); + validators.emplace(AlgoType::DSA_SV, VBuilder::Build()); + validators.emplace(AlgoType::ECDSA_SV, VBuilder::Build()); + validators.emplace(AlgoType::RSA_GEN, VBuilder::Build()); + validators.emplace(AlgoType::DSA_GEN, VBuilder::Build()); + validators.emplace(AlgoType::ECDSA_GEN, VBuilder::Build()); + validators.emplace(AlgoType::AES_GEN, VBuilder::Build()); + validators.emplace(AlgoType::AES_CTR, VBuilder::Build()); + validators.emplace(AlgoType::AES_CBC, VBuilder::Build()); + validators.emplace(AlgoType::AES_CFB, VBuilder::Build()); + validators.emplace(AlgoType::AES_GCM, VBuilder::Build()); + return validators; +}; +ValidatorMap g_validators = initValidators(); + +template +void validateParams(const CryptoAlgorithm& ca) { - T result; - if (!alg.getParam(paramName, result)) { - ThrowErr(CKM::Exc::Crypto::InputParam, "Wrong input param"); + // check algorithm type (Encryption/Decryption, Sign/Verify, Key generation) + TypeCheck tc; + tc.Check(ca); + + AlgoType at = unpack(ca, ParamName::ALGO_TYPE); + for(const auto& validator : g_validators.at(at)) { + validator->Check(ca); } - return result; } } // anonymous namespace -namespace CKM { -namespace Crypto { -namespace SW { -namespace Internals { - int initialize() { int hw_rand_ret = 0; int u_rand_ret = 0; @@ -332,6 +449,34 @@ Token createKeyAES(CryptoBackend backendId, const int sizeBits) return Token(backendId, DataType(KeyType::KEY_AES), CKM::RawBuffer(key, key+sizeBytes)); } +TokenPair generateAKey(CryptoBackend backendId, const CryptoAlgorithm &algorithm) +{ + validateParams(algorithm); + + AlgoType keyType = unpack(algorithm, ParamName::ALGO_TYPE); + if(keyType == AlgoType::RSA_GEN || keyType == AlgoType::DSA_GEN) + { + int keyLength = unpack(algorithm, ParamName::GEN_KEY_LEN); + if(keyType == AlgoType::RSA_GEN) + return createKeyPairRSA(backendId, keyLength); + else + return createKeyPairDSA(backendId, keyLength); + } + else // AlgoType::ECDSA_GEN + { + ElipticCurve ecType = unpack(algorithm, ParamName::GEN_EC); + return createKeyPairECDSA(backendId, ecType); + } +} + +Token generateSKey(CryptoBackend backendId, const CryptoAlgorithm &algorithm) +{ + validateParams(algorithm); + + int keySizeBits = unpack(algorithm, ParamName::GEN_KEY_LEN); + return createKeyAES(backendId, keySizeBits); +} + RawBuffer encryptDataAesCbc( const RawBuffer &key, const RawBuffer &data, @@ -423,6 +568,7 @@ RawBuffer symmetricEncrypt(const RawBuffer &key, const CryptoAlgorithm &alg, const RawBuffer &data) { + validateParams(alg); AlgoType keyType = unpack(alg, ParamName::ALGO_TYPE); switch(keyType) @@ -430,8 +576,14 @@ RawBuffer symmetricEncrypt(const RawBuffer &key, case AlgoType::AES_CBC: return encryptDataAesCbc(key, data, unpack(alg, ParamName::ED_IV)); case AlgoType::AES_GCM: - return encryptDataAesGcmPacked(key, data, unpack(alg, ParamName::ED_IV), - unpack(alg, ParamName::ED_TAG_LEN)); + { + int tagLenBits = DEFAULT_AES_GCM_TAG_LEN; + alg.getParam(ParamName::ED_TAG_LEN, tagLenBits); + return encryptDataAesGcmPacked(key, + data, + unpack(alg, ParamName::ED_IV), + tagLenBits/8); + } default: break; } @@ -443,6 +595,7 @@ RawBuffer symmetricDecrypt(const RawBuffer &key, const CryptoAlgorithm &alg, const RawBuffer &data) { + validateParams(alg); AlgoType keyType = unpack(alg, ParamName::ALGO_TYPE); switch(keyType) @@ -450,8 +603,14 @@ RawBuffer symmetricDecrypt(const RawBuffer &key, case AlgoType::AES_CBC: return decryptDataAesCbc(key, data, unpack(alg, ParamName::ED_IV)); case AlgoType::AES_GCM: - return decryptDataAesGcmPacked(key, data, unpack(alg, ParamName::ED_IV), - unpack(alg, ParamName::ED_TAG_LEN)); + { + int tagLenBits = DEFAULT_AES_GCM_TAG_LEN; + alg.getParam(ParamName::ED_TAG_LEN, tagLenBits); + return decryptDataAesGcmPacked(key, + data, + unpack(alg, ParamName::ED_IV), + tagLenBits/8); + } default: break; } @@ -462,6 +621,8 @@ RawBuffer sign(EVP_PKEY *pkey, const CryptoAlgorithm &alg, const RawBuffer &message) { + validateParams(alg); + int rsa_padding = NOT_DEFINED; const EVP_MD *md_algo = NULL; @@ -600,6 +761,8 @@ int verify(EVP_PKEY *pkey, const RawBuffer &message, const RawBuffer &signature) { + validateParams(alg); + int rsa_padding = NOT_DEFINED; const EVP_MD *md_algo = NULL; diff --git a/src/manager/crypto/sw-backend/internals.h b/src/manager/crypto/sw-backend/internals.h index 833c88a..d9869b5 100644 --- a/src/manager/crypto/sw-backend/internals.h +++ b/src/manager/crypto/sw-backend/internals.h @@ -50,6 +50,9 @@ TokenPair createKeyPairDSA(CryptoBackend backendId, const int size); TokenPair createKeyPairECDSA(CryptoBackend backendId, ElipticCurve type1); Token createKeyAES(CryptoBackend backendId, const int sizeBits); +TokenPair generateAKey(CryptoBackend backendId, const CryptoAlgorithm &algorithm); +Token generateSKey(CryptoBackend backendId, const CryptoAlgorithm &algorithm); + RawBuffer symmetricEncrypt(const RawBuffer &key, const CryptoAlgorithm &alg, const RawBuffer &data); @@ -60,7 +63,7 @@ RawBuffer symmetricDecrypt(const RawBuffer &key, std::pair encryptDataAesGcm(const RawBuffer &key, const RawBuffer &data, const RawBuffer &iv, - int tagSize); + int tagSizeBits); RawBuffer decryptDataAesGcm(const RawBuffer &key, const RawBuffer &data, diff --git a/src/manager/crypto/sw-backend/key.cpp b/src/manager/crypto/sw-backend/key.cpp index 1e81a3b..7ff0ebb 100644 --- a/src/manager/crypto/sw-backend/key.cpp +++ b/src/manager/crypto/sw-backend/key.cpp @@ -37,6 +37,26 @@ namespace CKM { namespace Crypto { namespace SW { +namespace { + +AlgoType key2algo(DataType type) { + switch(static_cast(type)) { + case DataType::Type::KEY_RSA_PRIVATE: + case DataType::Type::KEY_RSA_PUBLIC: + return AlgoType::RSA_SV; + case DataType::Type::KEY_DSA_PRIVATE: + case DataType::Type::KEY_DSA_PUBLIC: + return AlgoType::DSA_SV; + case DataType::Type::KEY_ECDSA_PRIVATE: + case DataType::Type::KEY_ECDSA_PUBLIC: + return AlgoType::ECDSA_SV; + default: + ThrowErr(Exc::Crypto::InputParam, "Invalid key type: ", type); + } +} + +} // namespace anonymous + typedef std::unique_ptr> BioUniquePtr; RawBuffer SKey::getBinary() const { @@ -56,7 +76,9 @@ RawBuffer AKey::sign( const CryptoAlgorithm &alg, const RawBuffer &message) { - return Internals::sign(getEvpShPtr().get(), alg, message); + CryptoAlgorithm algWithType(alg); + algWithType.setParam(ParamName::ALGO_TYPE, key2algo(m_type)); + return Internals::sign(getEvpShPtr().get(), algWithType, message); } RawBuffer AKey::getBinary() const { @@ -64,7 +86,26 @@ RawBuffer AKey::getBinary() const { } int AKey::verify(const CryptoAlgorithm &alg, const RawBuffer &message, const RawBuffer &sign) { - return Internals::verify(getEvpShPtr().get(), alg, message, sign); + CryptoAlgorithm algWithType(alg); + EVP_PKEY* evp = getEvpShPtr().get(); + AlgoType type; + + // setup algorithm type basing on evp key type if it doesn't exist + if(!algWithType.getParam(ParamName::ALGO_TYPE, type)) { + int subType = EVP_PKEY_type(evp->type); + switch(subType) { + case EVP_PKEY_RSA: + type = AlgoType::RSA_SV; break; + case EVP_PKEY_DSA: + type = AlgoType::DSA_SV; break; + case EVP_PKEY_EC: + type = AlgoType::ECDSA_SV; break; + default: + ThrowErr(Exc::Crypto::InputParam, "Invalid key type: ", subType); + } + algWithType.setParam(ParamName::ALGO_TYPE, type); + } + return Internals::verify(evp, algWithType, message, sign); } EvpShPtr AKey::getEvpShPtr() { diff --git a/src/manager/crypto/sw-backend/store.cpp b/src/manager/crypto/sw-backend/store.cpp index 8888ea9..4d6b1bf 100644 --- a/src/manager/crypto/sw-backend/store.cpp +++ b/src/manager/crypto/sw-backend/store.cpp @@ -68,38 +68,12 @@ GKeyUPtr Store::getKey(const Token &token) { TokenPair Store::generateAKey(const CryptoAlgorithm &algorithm) { - AlgoType keyType = AlgoType::RSA_GEN; - algorithm.getParam(ParamName::ALGO_TYPE, keyType); - - if(keyType == AlgoType::RSA_GEN || keyType == AlgoType::DSA_GEN) - { - int keyLength = 0; - if(!algorithm.getParam(ParamName::GEN_KEY_LEN, keyLength)) - ThrowErr(Exc::Crypto::InputParam, "Error, parameter GEN_KEY_LEN not found."); - - if(keyType == AlgoType::RSA_GEN) - return Internals::createKeyPairRSA(m_backendId, keyLength); - else - return Internals::createKeyPairDSA(m_backendId, keyLength); - } - else if(keyType == AlgoType::ECDSA_GEN) - { - int ecType = 0; - if(!algorithm.getParam(ParamName::GEN_EC, ecType)) - ThrowErr(Exc::Crypto::InputParam, "Error, parameter GEN_EC not found."); - - return Internals::createKeyPairECDSA(m_backendId, static_cast(ecType)); - } - ThrowErr(Exc::Crypto::InputParam, "wrong key type"); + return Internals::generateAKey(m_backendId, algorithm); } Token Store::generateSKey(const CryptoAlgorithm &algorithm) { - int keyLength = 0; - if(!algorithm.getParam(ParamName::GEN_KEY_LEN, keyLength)) - ThrowErr(Exc::Crypto::InputParam, "Error, parameter GEN_KEY_LEN not found."); - - return Internals::createKeyAES(m_backendId, keyLength); + return Internals::generateSKey(m_backendId, algorithm); } Token Store::import(DataType dataType, const RawBuffer &buffer) { diff --git a/src/manager/service/ckm-logic.cpp b/src/manager/service/ckm-logic.cpp index a173cd7..0a6893f 100644 --- a/src/manager/service/ckm-logic.cpp +++ b/src/manager/service/ckm-logic.cpp @@ -1145,6 +1145,7 @@ int CKMLogic::createKeyAESHelper( const PolicySerializable &policy) { CryptoAlgorithm keyGenAlgorithm; + keyGenAlgorithm.setParam(ParamName::ALGO_TYPE, AlgoType::AES_GEN); keyGenAlgorithm.setParam(ParamName::GEN_KEY_LEN, size); Token key = m_decider.getStore(DataType::KEY_AES, policy.extractable).generateSKey(keyGenAlgorithm); -- 2.7.4 From f6d65de548e47f14eb4c4f485753f44468eb50ae Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Fri, 26 Jun 2015 14:19:36 +0200 Subject: [PATCH 14/16] Encryption service refactoring [Problem] Unnecessary counter in communication manager. Request map name. [Solution] Counter replaced by size(). Request map renamed. [Verification] Successfull compilation. Run tests Change-Id: I757d729de8f26a1bca8af65f1377d43afcc07d79 --- src/manager/main/communication-manager.h | 7 ++----- src/manager/service/encryption-logic.cpp | 10 +++++----- src/manager/service/encryption-logic.h | 2 +- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/src/manager/main/communication-manager.h b/src/manager/main/communication-manager.h index 1637a07..13a8a97 100644 --- a/src/manager/main/communication-manager.h +++ b/src/manager/main/communication-manager.h @@ -47,12 +47,9 @@ public: // Returns the number of listeners called size_t SendMessage(const M& msg) const { - size_t num = 0; - for(auto& it : m_listeners) { + for(auto& it : m_listeners) it(msg); - num++; - } - return num; + return m_listeners.size(); } protected: MessageManager() {} diff --git a/src/manager/service/encryption-logic.cpp b/src/manager/service/encryption-logic.cpp index a2bad2b..36c4e10 100644 --- a/src/manager/service/encryption-logic.cpp +++ b/src/manager/service/encryption-logic.cpp @@ -35,7 +35,7 @@ void EncryptionLogic::Crypt(const CryptoRequest& request) } // store request in the map - auto ret = m_requests.insert(std::make_pair(request.msgId, request)); + auto ret = m_requestsMap.insert(std::make_pair(request.msgId, request)); if (!ret.second) { LogError("Request with id " << request.msgId << " already exists"); m_service.RespondToClient(request, CKM_API_ERROR_INPUT_PARAM); @@ -47,20 +47,20 @@ void EncryptionLogic::Crypt(const CryptoRequest& request) m_service.RequestKey(request); } catch (...) { LogError("Key request failed"); - m_requests.erase(request.msgId); + m_requestsMap.erase(request.msgId); m_service.RespondToClient(request, CKM_API_ERROR_SERVER_ERROR); } } void EncryptionLogic::KeyRetrieved(MsgKeyResponse response) { - auto it = m_requests.find(response.id); - if (it == m_requests.end()) { + auto it = m_requestsMap.find(response.id); + if (it == m_requestsMap.end()) { LogError("No matching request found"); // nothing we can do return; } CryptoRequest req = std::move(it->second); - m_requests.erase(it); + m_requestsMap.erase(it); if (response.error != CKM_API_SUCCESS) { LogError("Attempt to retrieve key failed with error: " << response.error); diff --git a/src/manager/service/encryption-logic.h b/src/manager/service/encryption-logic.h index 8f941dd..9dbd7b0 100644 --- a/src/manager/service/encryption-logic.h +++ b/src/manager/service/encryption-logic.h @@ -41,7 +41,7 @@ public: private: IEncryptionService& m_service; - std::map m_requests; + std::map m_requestsMap; }; } /* namespace CKM */ -- 2.7.4 From a0fe93a32f0a9eff1489d36b5b3323fd6ca5651a Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Mon, 29 Jun 2015 15:52:45 +0200 Subject: [PATCH 15/16] Add support for different AES key sizes [Problem] AES encryption/decryption supports only 256-bit key size. [Solution] Add support for 128 and 192-bit key encryption/decryption. [Verification] Run ckm-tests --group=CKM_ENCRYPTION_DECRYPTION. Only TED_1250_gcm_aad may fail. Change-Id: Ia949250b7f3597dee5360c3373c9164dc2e4d9e8 --- src/manager/crypto/sw-backend/crypto.h | 17 ++++-- src/manager/crypto/sw-backend/internals.cpp | 83 ++++++++++++++++++++++++----- 2 files changed, 82 insertions(+), 18 deletions(-) diff --git a/src/manager/crypto/sw-backend/crypto.h b/src/manager/crypto/sw-backend/crypto.h index 9a09909..40fe42d 100644 --- a/src/manager/crypto/sw-backend/crypto.h +++ b/src/manager/crypto/sw-backend/crypto.h @@ -113,10 +113,19 @@ public: \ {} \ } -DEFINE_CIPHER(AesCbcEncryption, RawBuffer, EVP_aes_256_cbc(), true); -DEFINE_CIPHER(AesCbcDecryption, RawBuffer, EVP_aes_256_cbc(), false); -DEFINE_CIPHER(AesGcmEncryption, RawBuffer, EVP_aes_256_gcm(), true); -DEFINE_CIPHER(AesGcmDecryption, RawBuffer, EVP_aes_256_gcm(), false); +DEFINE_CIPHER(AesCbcEncryption128, RawBuffer, EVP_aes_128_cbc(), true); +DEFINE_CIPHER(AesCbcDecryption128, RawBuffer, EVP_aes_128_cbc(), false); +DEFINE_CIPHER(AesCbcEncryption192, RawBuffer, EVP_aes_192_cbc(), true); +DEFINE_CIPHER(AesCbcDecryption192, RawBuffer, EVP_aes_192_cbc(), false); +DEFINE_CIPHER(AesCbcEncryption256, RawBuffer, EVP_aes_256_cbc(), true); +DEFINE_CIPHER(AesCbcDecryption256, RawBuffer, EVP_aes_256_cbc(), false); + +DEFINE_CIPHER(AesGcmEncryption128, RawBuffer, EVP_aes_128_gcm(), true); +DEFINE_CIPHER(AesGcmDecryption128, RawBuffer, EVP_aes_128_gcm(), false); +DEFINE_CIPHER(AesGcmEncryption192, RawBuffer, EVP_aes_192_gcm(), true); +DEFINE_CIPHER(AesGcmDecryption192, RawBuffer, EVP_aes_192_gcm(), false); +DEFINE_CIPHER(AesGcmEncryption256, RawBuffer, EVP_aes_256_gcm(), true); +DEFINE_CIPHER(AesGcmDecryption256, RawBuffer, EVP_aes_256_gcm(), false); #undef DEFINE_CIPHER diff --git a/src/manager/crypto/sw-backend/internals.cpp b/src/manager/crypto/sw-backend/internals.cpp index 8612631..a6ad01a 100644 --- a/src/manager/crypto/sw-backend/internals.cpp +++ b/src/manager/crypto/sw-backend/internals.cpp @@ -215,6 +215,57 @@ void validateParams(const CryptoAlgorithm& ca) } } +typedef std::unique_ptr> EvpCipherPtr; + +typedef std::function InitCipherFn; + +// aes mode, key length in bits, encryption +typedef std::map>> CipherTree; + +template +void initCipher(EvpCipherPtr& ptr, const RawBuffer& key, const RawBuffer& iv) +{ + ptr.reset(new T(key, iv)); +} + +CipherTree initializeCipherTree() +{ + CipherTree tree; + tree[AlgoType::AES_CBC][128][true] = initCipher; + tree[AlgoType::AES_CBC][192][true] = initCipher; + tree[AlgoType::AES_CBC][256][true] = initCipher; + + tree[AlgoType::AES_CBC][128][false] = initCipher; + tree[AlgoType::AES_CBC][192][false] = initCipher; + tree[AlgoType::AES_CBC][256][false] = initCipher; + + tree[AlgoType::AES_GCM][128][true] = initCipher; + tree[AlgoType::AES_GCM][192][true] = initCipher; + tree[AlgoType::AES_GCM][256][true] = initCipher; + + tree[AlgoType::AES_GCM][128][false] = initCipher; + tree[AlgoType::AES_GCM][192][false] = initCipher; + tree[AlgoType::AES_GCM][256][false] = initCipher; + + return tree; +} + +CipherTree g_cipherTree = initializeCipherTree(); + +// key length in bytes +InitCipherFn selectCipher(AlgoType type, size_t key_len = 32, bool encryption = true) +{ + try { + return g_cipherTree.at(type).at(key_len*8).at(encryption); + } catch (const std::out_of_range&) { + ThrowErr(Exc::Crypto::InternalError, + "Unsupported cipher: ", + static_cast(type), ", ", + key_len, ", ", + encryption); + } +} + } // anonymous namespace int initialize() { @@ -482,9 +533,10 @@ RawBuffer encryptDataAesCbc( const RawBuffer &data, const RawBuffer &iv) { - Crypto::SW::Cipher::AesCbcEncryption enc(key, iv); - RawBuffer result = enc.Append(data); - RawBuffer tmp = enc.Finalize(); + EvpCipherPtr enc; + selectCipher(AlgoType::AES_CBC, key.size())(enc, key, iv); + RawBuffer result = enc->Append(data); + RawBuffer tmp = enc->Finalize(); std::copy(tmp.begin(), tmp.end(), std::back_inserter(result)); return result; } @@ -496,11 +548,12 @@ std::pair encryptDataAesGcm( int tagSize) { RawBuffer tag(tagSize); - Crypto::SW::Cipher::AesGcmEncryption enc(key, iv); - RawBuffer result = enc.Append(data); - RawBuffer tmp = enc.Finalize(); + EvpCipherPtr enc; + selectCipher(AlgoType::AES_GCM, key.size())(enc, key, iv); + RawBuffer result = enc->Append(data); + RawBuffer tmp = enc->Finalize(); std::copy(tmp.begin(), tmp.end(), std::back_inserter(result)); - if (0 == enc.Control(EVP_CTRL_GCM_GET_TAG, tagSize, tag.data())) { + if (0 == enc->Control(EVP_CTRL_GCM_GET_TAG, tagSize, tag.data())) { ThrowErr(Exc::Crypto::InternalError, "Error in AES control function. Get tag failed."); } return std::make_pair(result, tag); @@ -522,9 +575,10 @@ RawBuffer decryptDataAesCbc( const RawBuffer &data, const RawBuffer &iv) { - Crypto::SW::Cipher::AesCbcDecryption dec(key, iv); - RawBuffer result = dec.Append(data); - RawBuffer tmp = dec.Finalize(); + EvpCipherPtr dec; + selectCipher(AlgoType::AES_CBC, key.size(), false)(dec, key, iv); + RawBuffer result = dec->Append(data); + RawBuffer tmp = dec->Finalize(); std::copy(tmp.begin(), tmp.end(), std::back_inserter(result)); return result; } @@ -535,14 +589,15 @@ RawBuffer decryptDataAesGcm( const RawBuffer &iv, const RawBuffer &tag) { - Crypto::SW::Cipher::AesGcmDecryption dec(key, iv); + EvpCipherPtr dec; + selectCipher(AlgoType::AES_GCM, key.size(), false)(dec, key, iv); void *ptr = (void*)tag.data(); - if (0 == dec.Control(EVP_CTRL_GCM_SET_TAG, tag.size(), ptr)) { + if (0 == dec->Control(EVP_CTRL_GCM_SET_TAG, tag.size(), ptr)) { ThrowErr(Exc::Crypto::InternalError, "Error in AES control function. Set tag failed."); } - RawBuffer result = dec.Append(data); - RawBuffer tmp = dec.Finalize(); + RawBuffer result = dec->Append(data); + RawBuffer tmp = dec->Finalize(); std::copy(tmp.begin(), tmp.end(), std::back_inserter(result)); return result; } -- 2.7.4 From 3112828520f9f58b7a56ca0b73d458527f613523 Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Tue, 30 Jun 2015 11:19:02 +0200 Subject: [PATCH 16/16] Add support for AES CTR and AES CFB [Feature] Implementation of encryption service [Solution] CTR and CFB modes implemented [Verification] Run ckm-tests --group=CKM_ENCRYPTION_DECRYPTION. Only rsa tests and gcm aad test may fail. Change-Id: I71f8c71a0fce536037da7653986c674c3a63499a --- src/manager/crypto/sw-backend/crypto.h | 14 ++++++++++++ src/manager/crypto/sw-backend/internals.cpp | 34 ++++++++++++++++++++++++----- src/manager/crypto/sw-backend/internals.h | 6 +++-- src/manager/service/crypto-logic.cpp | 4 ++-- 4 files changed, 48 insertions(+), 10 deletions(-) diff --git a/src/manager/crypto/sw-backend/crypto.h b/src/manager/crypto/sw-backend/crypto.h index 40fe42d..d23aac0 100644 --- a/src/manager/crypto/sw-backend/crypto.h +++ b/src/manager/crypto/sw-backend/crypto.h @@ -127,6 +127,20 @@ DEFINE_CIPHER(AesGcmDecryption192, RawBuffer, EVP_aes_192_gcm(), false); DEFINE_CIPHER(AesGcmEncryption256, RawBuffer, EVP_aes_256_gcm(), true); DEFINE_CIPHER(AesGcmDecryption256, RawBuffer, EVP_aes_256_gcm(), false); +DEFINE_CIPHER(AesCtrEncryption128, RawBuffer, EVP_aes_128_ctr(), true); +DEFINE_CIPHER(AesCtrDecryption128, RawBuffer, EVP_aes_128_ctr(), false); +DEFINE_CIPHER(AesCtrEncryption192, RawBuffer, EVP_aes_192_ctr(), true); +DEFINE_CIPHER(AesCtrDecryption192, RawBuffer, EVP_aes_192_ctr(), false); +DEFINE_CIPHER(AesCtrEncryption256, RawBuffer, EVP_aes_256_ctr(), true); +DEFINE_CIPHER(AesCtrDecryption256, RawBuffer, EVP_aes_256_ctr(), false); + +DEFINE_CIPHER(AesCfbEncryption128, RawBuffer, EVP_aes_128_cfb(), true); +DEFINE_CIPHER(AesCfbDecryption128, RawBuffer, EVP_aes_128_cfb(), false); +DEFINE_CIPHER(AesCfbEncryption192, RawBuffer, EVP_aes_192_cfb(), true); +DEFINE_CIPHER(AesCfbDecryption192, RawBuffer, EVP_aes_192_cfb(), false); +DEFINE_CIPHER(AesCfbEncryption256, RawBuffer, EVP_aes_256_cfb(), true); +DEFINE_CIPHER(AesCfbDecryption256, RawBuffer, EVP_aes_256_cfb(), false); + #undef DEFINE_CIPHER } // namespace Cipher diff --git a/src/manager/crypto/sw-backend/internals.cpp b/src/manager/crypto/sw-backend/internals.cpp index a6ad01a..ad646fb 100644 --- a/src/manager/crypto/sw-backend/internals.cpp +++ b/src/manager/crypto/sw-backend/internals.cpp @@ -247,6 +247,22 @@ CipherTree initializeCipherTree() tree[AlgoType::AES_GCM][192][false] = initCipher; tree[AlgoType::AES_GCM][256][false] = initCipher; + tree[AlgoType::AES_CTR][128][true] = initCipher; + tree[AlgoType::AES_CTR][192][true] = initCipher; + tree[AlgoType::AES_CTR][256][true] = initCipher; + + tree[AlgoType::AES_CTR][128][false] = initCipher; + tree[AlgoType::AES_CTR][192][false] = initCipher; + tree[AlgoType::AES_CTR][256][false] = initCipher; + + tree[AlgoType::AES_CFB][128][true] = initCipher; + tree[AlgoType::AES_CFB][192][true] = initCipher; + tree[AlgoType::AES_CFB][256][true] = initCipher; + + tree[AlgoType::AES_CFB][128][false] = initCipher; + tree[AlgoType::AES_CFB][192][false] = initCipher; + tree[AlgoType::AES_CFB][256][false] = initCipher; + return tree; } @@ -528,13 +544,14 @@ Token generateSKey(CryptoBackend backendId, const CryptoAlgorithm &algorithm) return createKeyAES(backendId, keySizeBits); } -RawBuffer encryptDataAesCbc( +RawBuffer encryptDataAes( + AlgoType type, const RawBuffer &key, const RawBuffer &data, const RawBuffer &iv) { EvpCipherPtr enc; - selectCipher(AlgoType::AES_CBC, key.size())(enc, key, iv); + selectCipher(type, key.size())(enc, key, iv); RawBuffer result = enc->Append(data); RawBuffer tmp = enc->Finalize(); std::copy(tmp.begin(), tmp.end(), std::back_inserter(result)); @@ -570,13 +587,14 @@ RawBuffer encryptDataAesGcmPacked( return pair.first; } -RawBuffer decryptDataAesCbc( +RawBuffer decryptDataAes( + AlgoType type, const RawBuffer &key, const RawBuffer &data, const RawBuffer &iv) { EvpCipherPtr dec; - selectCipher(AlgoType::AES_CBC, key.size(), false)(dec, key, iv); + selectCipher(type, key.size(), false)(dec, key, iv); RawBuffer result = dec->Append(data); RawBuffer tmp = dec->Finalize(); std::copy(tmp.begin(), tmp.end(), std::back_inserter(result)); @@ -629,7 +647,9 @@ RawBuffer symmetricEncrypt(const RawBuffer &key, switch(keyType) { case AlgoType::AES_CBC: - return encryptDataAesCbc(key, data, unpack(alg, ParamName::ED_IV)); + case AlgoType::AES_CTR: + case AlgoType::AES_CFB: + return encryptDataAes(keyType, key, data, unpack(alg, ParamName::ED_IV)); case AlgoType::AES_GCM: { int tagLenBits = DEFAULT_AES_GCM_TAG_LEN; @@ -656,7 +676,9 @@ RawBuffer symmetricDecrypt(const RawBuffer &key, switch(keyType) { case AlgoType::AES_CBC: - return decryptDataAesCbc(key, data, unpack(alg, ParamName::ED_IV)); + case AlgoType::AES_CTR: + case AlgoType::AES_CFB: + return decryptDataAes(keyType, key, data, unpack(alg, ParamName::ED_IV)); case AlgoType::AES_GCM: { int tagLenBits = DEFAULT_AES_GCM_TAG_LEN; diff --git a/src/manager/crypto/sw-backend/internals.h b/src/manager/crypto/sw-backend/internals.h index d9869b5..df3b245 100644 --- a/src/manager/crypto/sw-backend/internals.h +++ b/src/manager/crypto/sw-backend/internals.h @@ -70,11 +70,13 @@ RawBuffer decryptDataAesGcm(const RawBuffer &key, const RawBuffer &iv, const RawBuffer &tag); -RawBuffer encryptDataAesCbc(const RawBuffer &key, +RawBuffer encryptDataAes(AlgoType type, + const RawBuffer &key, const RawBuffer &data, const RawBuffer &iv); -RawBuffer decryptDataAesCbc(const RawBuffer &key, +RawBuffer decryptDataAes(AlgoType type, + const RawBuffer &key, const RawBuffer &data, const RawBuffer &iv); diff --git a/src/manager/service/crypto-logic.cpp b/src/manager/service/crypto-logic.cpp index 10960fb..75c9b40 100644 --- a/src/manager/service/crypto-logic.cpp +++ b/src/manager/service/crypto-logic.cpp @@ -155,7 +155,7 @@ void CryptoLogic::encryptRow(const Password &password, DB::Row &row) if (!password.empty()) { key = passwordToKey(password, crow.iv, AES_CBC_KEY_SIZE); - crow.data = Crypto::SW::Internals::encryptDataAesCbc(key, crow.data, crow.iv); + crow.data = Crypto::SW::Internals::encryptDataAes(AlgoType::AES_CBC, key, crow.data, crow.iv); crow.encryptionScheme |= ENCR_PASSWORD; } @@ -200,7 +200,7 @@ void CryptoLogic::decryptRow(const Password &password, DB::Row &row) if (crow.encryptionScheme & ENCR_PASSWORD) { key = passwordToKey(password, crow.iv, AES_CBC_KEY_SIZE); - crow.data = Crypto::SW::Internals::decryptDataAesCbc(key, crow.data, crow.iv); + crow.data = Crypto::SW::Internals::decryptDataAes(AlgoType::AES_CBC, key, crow.data, crow.iv); } if (crow.encryptionScheme & ENCR_APPKEY) { -- 2.7.4