From d22ce2b55451a8164775c5945eb158e507a25a4d Mon Sep 17 00:00:00 2001 From: "Maciej J. Karpiuk" Date: Fri, 14 Nov 2014 16:08:25 +0100 Subject: Add PKCS12 support. Change-Id: I389c56611fed80cf27bbbfa279b1c17e55572b14 --- src/include/ckm/ckm-manager-async.h | 10 + src/include/ckm/ckm-manager.h | 7 + src/include/ckmc/ckmc-manager.h | 113 ++++- src/include/ckmc/ckmc-type.h | 84 +++- .../client-async/client-manager-async-impl.cpp | 38 ++ .../client-async/client-manager-async-impl.h | 10 + src/manager/client-async/client-manager-async.cpp | 15 + src/manager/client-async/storage-receiver.cpp | 37 +- src/manager/client-async/storage-receiver.h | 2 + src/manager/client-capi/ckmc-manager.cpp | 133 +++++- src/manager/client-capi/ckmc-type.cpp | 76 +++- src/manager/client/client-manager-impl.cpp | 129 ++++-- src/manager/client/client-manager-impl.h | 8 + src/manager/common/certificate-impl.cpp | 9 +- src/manager/common/certificate-impl.h | 2 +- src/manager/common/pkcs12-impl.cpp | 39 ++ src/manager/common/pkcs12-impl.h | 13 +- src/manager/common/protocols.cpp | 73 +++ src/manager/common/protocols.h | 56 ++- src/manager/service/ckm-logic.cpp | 487 +++++++++++++++++---- src/manager/service/ckm-logic.h | 89 +++- src/manager/service/ckm-service.cpp | 26 +- src/manager/service/db-crypto.cpp | 67 ++- src/manager/service/db-crypto.h | 18 + src/manager/service/db-row.h | 2 + 25 files changed, 1386 insertions(+), 157 deletions(-) (limited to 'src') diff --git a/src/include/ckm/ckm-manager-async.h b/src/include/ckm/ckm-manager-async.h index 48bca055..1f0c7646 100644 --- a/src/include/ckm/ckm-manager-async.h +++ b/src/include/ckm/ckm-manager-async.h @@ -27,6 +27,7 @@ #include #include #include +#include // Central Key Manager namespace namespace CKM { @@ -50,12 +51,14 @@ public: virtual void ReceivedSaveKey() {} virtual void ReceivedSaveCertificate() {} virtual void ReceivedSaveData() {} + virtual void ReceivedSavePKCS12() {} virtual void ReceivedRemovedAlias() {} virtual void ReceivedKey(Key &&) {} virtual void ReceivedCertificate(Certificate &&) {} virtual void ReceivedData(RawBuffer &&) {} + virtual void ReceivedPKCS12(PKCS12ShPtr &&) {} virtual void ReceivedKeyAliasVector(AliasVector &&) {} virtual void ReceivedCertificateAliasVector(AliasVector &&) {} @@ -96,12 +99,19 @@ public: const Alias& alias, const RawBuffer& data, const Policy& policy); + void savePKCS12( + const ObserverPtr& observer, + const Alias &alias, + const PKCS12ShPtr &pkcs, + const Policy &keyPolicy, + const Policy &certPolicy); void removeAlias(const ObserverPtr& observer, const Alias& alias); void getKey(const ObserverPtr& observer, const Alias& alias, const Password& password); void getCertificate(const ObserverPtr& observer, const Alias& alias, const Password& password); void getData(const ObserverPtr& observer, const Alias& alias, const Password& password); + void getPKCS12(const ObserverPtr& observer, const Alias &alias); // send request for list of all keys/certificates/data that application/user may use void getKeyAliasVector(const ObserverPtr& observer); diff --git a/src/include/ckm/ckm-manager.h b/src/include/ckm/ckm-manager.h index 53363d87..d7821693 100644 --- a/src/include/ckm/ckm-manager.h +++ b/src/include/ckm/ckm-manager.h @@ -27,6 +27,7 @@ #include #include #include +#include #include // Central Key Manager namespace @@ -41,6 +42,11 @@ public: virtual int saveKey(const Alias &alias, const KeyShPtr &key, const Policy &policy) = 0; virtual int saveCertificate(const Alias &alias, const CertificateShPtr &cert, const Policy &policy) = 0; + virtual int savePKCS12( + const Alias &alias, + const PKCS12ShPtr &pkcs, + const Policy &keyPolicy, + const Policy &certPolicy) = 0; /* * Data must be extractable. If you set extractable bit to false function will @@ -56,6 +62,7 @@ public: const Password &password, CertificateShPtr &certificate) = 0; virtual int getData(const Alias &alias, const Password &password, RawBuffer &data) = 0; + virtual int getPKCS12(const Alias &alias, PKCS12ShPtr &pkcs) = 0; // send request for list of all keys/certificates/data that application/user may use virtual int getKeyAliasVector(AliasVector &aliasVector) = 0; diff --git a/src/include/ckmc/ckmc-manager.h b/src/include/ckmc/ckmc-manager.h index 3d08fb3c..d2be99b9 100644 --- a/src/include/ckmc/ckmc-manager.h +++ b/src/include/ckmc/ckmc-manager.h @@ -63,7 +63,7 @@ extern "C" { * @retval #CKMC_ERROR_DB_LOCKED A user key is not loaded in memory (a user is not logged in) * @retval #CKMC_ERROR_DB_ALIAS_EXISTS Alias already exists * @retval #CKMC_ERROR_INVALID_FORMAT The format of raw_key is not valid - * @retval #CKMC_ERROR_DB_ERROR Failed due to other DB transaction unexpectedly + * @retval #CKMC_ERROR_DB_ERROR Failed due to a database error * @retval #CKMC_ERROR_PERMISSION_DENIED Failed to access key manager * * @pre User is already logged in and the user key is already loaded into memory in plain text form. @@ -93,7 +93,7 @@ int ckmc_save_key(const char *alias, const ckmc_key_s key, const ckmc_policy_s p * @retval #CKMC_ERROR_NONE Successful * @retval #CKMC_ERROR_INVALID_PARAMETER Input parameter is invalid * @retval #CKMC_ERROR_DB_LOCKED A user key is not loaded in memory (a user is not logged in) - * @retval #CKMC_ERROR_DB_ERROR Failed due to the error with unknown reason + * @retval #CKMC_ERROR_DB_ERROR Failed due to a database error * @retval #CKMC_ERROR_DB_ALIAS_UNKNOWN Alias does not exist * @retval #CKMC_ERROR_PERMISSION_DENIED Failed to access key manager * @@ -126,7 +126,7 @@ int ckmc_remove_key(const char *alias); * @retval #CKMC_ERROR_NONE Successful * @retval #CKMC_ERROR_INVALID_PARAMETER Input parameter is invalid * @retval #CKMC_ERROR_DB_LOCKED A user key is not loaded in memory (a user is not logged in) - * @retval #CKMC_ERROR_DB_ERROR Failed due to the error with unknown reason + * @retval #CKMC_ERROR_DB_ERROR Failed due to a database error * @retval #CKMC_ERROR_DB_ALIAS_UNKNOWN Alias does not exist * @retval #CKMC_ERROR_PERMISSION_DENIED Failed to access key manager * @@ -157,7 +157,7 @@ int ckmc_get_key(const char *alias, const char *password, ckmc_key_s **ppkey); * @retval #CKMC_ERROR_NONE Successful * @retval #CKMC_ERROR_INVALID_PARAMETER Input parameter is invalid * @retval #CKMC_ERROR_DB_LOCKED A user key is not loaded in memory (a user is not logged in) - * @retval #CKMC_ERROR_DB_ERROR Failed due to the error with unknown reason + * @retval #CKMC_ERROR_DB_ERROR Failed due to a database error * @retval #CKMC_ERROR_DB_ALIAS_UNKNOWN Alias does not exist * @retval #CKMC_ERROR_PERMISSION_DENIED Failed to access key manager * @@ -193,7 +193,7 @@ int ckmc_get_key_alias_list(ckmc_alias_list_s** ppalias_list); * @retval #CKMC_ERROR_DB_LOCKED A user key is not loaded in memory (a user is not logged in) * @retval #CKMC_ERROR_DB_ALIAS_EXISTS Alias already exists * @retval #CKMC_ERROR_INVALID_FORMAT The format of raw_cert is not valid - * @retval #CKMC_ERROR_DB_ERROR Failed due to other DB transaction unexpectedly + * @retval #CKMC_ERROR_DB_ERROR Failed due to a database error * @retval #CKMC_ERROR_PERMISSION_DENIED Failed to access key manager * * @pre User is already logged in and the user key is already loaded into memory in plain text form. @@ -223,7 +223,7 @@ int ckmc_save_cert(const char *alias, const ckmc_cert_s cert, const ckmc_policy_ * @retval #CKMC_ERROR_NONE Successful * @retval #CKMC_ERROR_INVALID_PARAMETER Input parameter is invalid * @retval #CKMC_ERROR_DB_LOCKED A user key is not loaded in memory (a user is not logged in) - * @retval #CKMC_ERROR_DB_ERROR Failed due to the error with unknown reason + * @retval #CKMC_ERROR_DB_ERROR Failed due to a database error * @retval #CKMC_ERROR_DB_ALIAS_UNKNOWN Alias does not exist * @retval #CKMC_ERROR_PERMISSION_DENIED Failed to access key manager * @@ -257,7 +257,7 @@ int ckmc_remove_cert(const char *alias); * @retval #CKMC_ERROR_NONE Successful * @retval #CKMC_ERROR_INVALID_PARAMETER Input parameter is invalid * @retval #CKMC_ERROR_DB_LOCKED A user key is not loaded in memory (a user is not logged in) - * @retval #CKMC_ERROR_DB_ERROR Failed due to the error with unknown reason + * @retval #CKMC_ERROR_DB_ERROR Failed due to a database error * @retval #CKMC_ERROR_DB_ALIAS_UNKNOWN Alias does not exists * @retval #CKMC_ERROR_PERMISSION_DENIED Failed to access key manager * @@ -288,7 +288,7 @@ int ckmc_get_cert(const char *alias, const char *password, ckmc_cert_s **ppcert) * @retval #CKMC_ERROR_NONE Successful * @retval #CKMC_ERROR_INVALID_PARAMETER Input parameter is invalid * @retval #CKMC_ERROR_DB_LOCKED A user key is not loaded in memory (a user is not logged in) - * @retval #CKMC_ERROR_DB_ERROR Failed due to the error with unknown reason + * @retval #CKMC_ERROR_DB_ERROR Failed due to a database error * @retval #CKMC_ERROR_DB_ALIAS_UNKNOWN Alias does not exist * @retval #CKMC_ERROR_PERMISSION_DENIED Failed to access key manager * @@ -303,6 +303,101 @@ int ckmc_get_cert_alias_list(ckmc_alias_list_s** ppalias_list); +/** + * @brief Stores PKCS12's contents inside key manager based on the provided policies. + * All items from the PKCS12 will use the same alias. + * + * @since_tizen 2.3 + * @privlevel public + * @privilege %http://tizen.org/privilege/keymanager + * + * @param[in] alias The name of a data to be stored + * @param[in] pkcs Pointer to the pkcs12 structure to be saved + * @param[in] key_policy The policy about how to store pkcs's private key + * @param[in] cert_policy The policy about how to store pkcs's certificate + * + * @return @c 0 on success, + * otherwise a negative error value + * + * @retval #CKMC_ERROR_NONE Successful + * @retval #CKMC_ERROR_INVALID_PARAMETER Input parameter is invalid + * @retval #CKMC_ERROR_DB_LOCKED A user key is not loaded in memory (a user is not logged in) + * @retval #CKMC_ERROR_DB_ALIAS_EXISTS Alias already exists + * @retval #CKMC_ERROR_DB_ERROR Failed due to a database error + * @retval #CKMC_ERROR_PERMISSION_DENIED Failed to access key manager + * + * @pre User is already logged in and the user key is already loaded into memory in plain text form. + * + * @see ckmc_remove_pkcs12() + * @see ckmc_get_pkcs12() + * @see ckmc_get_data_alias_list() + * @see ckmc_load_from_pkcs12_file2() + * @see #ckmc_pkcs12_s + * @see #ckmc_policy_s + */ +int ckmc_save_pkcs12(const char *alias, const ckmc_pkcs12_s *pkcs, const ckmc_policy_s key_policy, const ckmc_policy_s cert_policy); + +/** + * @brief Removes all pkcs12 contents from key manager. + * + * @since_tizen 2.3 + * @privlevel public + * @privilege %http://tizen.org/privilege/keymanager + * + * @remarks A client can remove only data stored by the client. + * + * @param[in] alias The name of pkcs12 to be removed + * + * @return @c 0 on success, + * otherwise a negative error value + * + * @retval #CKMC_ERROR_NONE Successful + * @retval #CKMC_ERROR_INVALID_PARAMETER Input parameter is invalid + * @retval #CKMC_ERROR_DB_LOCKED A user key is not loaded in memory (a user is not logged in) + * @retval #CKMC_ERROR_DB_ERROR Failed due to a database error + * @retval #CKMC_ERROR_DB_ALIAS_UNKNOWN Alias does not exist + * @retval #CKMC_ERROR_PERMISSION_DENIED Failed to access key manager + * + * @pre User is already logged in and the user key is already loaded into memory in plain text form. + * + * @see ckmc_save_pkcs12() + * @see ckmc_get_pkcs12() + */ +int ckmc_remove_pkcs12(const char *alias); + +/** + * @brief Gets a pkcs12 from key manager. + * + * @since_tizen 2.3 + * @privlevel public + * @privilege %http://tizen.org/privilege/keymanager + * + * @remarks A client can access only data stored by the client. + * @remarks You must destroy the newly created @a pkcs12 by calling ckmc_pkcs12_free() if it is no longer needed. + * + * @param[in] alias The name of a data to retrieve + * @param[out] pkcs12 The pointer to a newly created ckmc_pkcs12_s handle + * + * @return @c 0 on success, + * otherwise a negative error value + * + * @retval #CKMC_ERROR_NONE Successful + * @retval #CKMC_ERROR_INVALID_PARAMETER Input parameter is invalid + * @retval #CKMC_ERROR_DB_LOCKED A user key is not loaded in memory (a user is not logged in) + * @retval #CKMC_ERROR_DB_ERROR Failed due to a database error + * @retval #CKMC_ERROR_DB_ALIAS_UNKNOWN Alias does not exist + * @retval #CKMC_ERROR_PERMISSION_DENIED Failed to access key manager + * + * @pre User is already logged in and the user key is already loaded into memory in plain text form. + * + * @see ckmc_save_pkcs12() + * @see ckmc_remove_pkcs12() + */ +int ckmc_get_pkcs12(const char *alias, ckmc_pkcs12_s **pkcs12); + + + + /** * @brief Stores a data inside key manager based on the provided policy. * @@ -321,7 +416,7 @@ int ckmc_get_cert_alias_list(ckmc_alias_list_s** ppalias_list); * @retval #CKMC_ERROR_INVALID_PARAMETER Input parameter is invalid * @retval #CKMC_ERROR_DB_LOCKED A user key is not loaded in memory (a user is not logged in) * @retval #CKMC_ERROR_DB_ALIAS_EXISTS Alias already exists - * @retval #CKMC_ERROR_DB_ERROR Failed due to other DB transaction unexpectedly + * @retval #CKMC_ERROR_DB_ERROR Failed due to a database error * @retval #CKMC_ERROR_PERMISSION_DENIED Failed to access key manager * * @pre User is already logged in and the user key is already loaded into memory in plain text form. diff --git a/src/include/ckmc/ckmc-type.h b/src/include/ckmc/ckmc-type.h index 0a85f453..b4418240 100644 --- a/src/include/ckmc/ckmc-type.h +++ b/src/include/ckmc/ckmc-type.h @@ -167,6 +167,17 @@ typedef struct __ckmc_cert_list { struct __ckmc_cert_list *next; /**< The pointer pointing to the next ckmc_cert_list_s */ } ckmc_cert_list_s; +/** + * @brief The structure for PKCS12 used in key manager CAPI. + * @since_tizen 2.3 + */ +typedef struct __ckmc_pkcs12 { + ckmc_key_s *priv_key; /**< private key, may be null */ + ckmc_cert_s *cert; /**< certificate, may be null */ + ckmc_cert_list_s *ca_chain; /**< chain certificates list, may be null */ +} ckmc_pkcs12_s; + + /** * @internal * @brief Creates a new @a ckmc_key_s handle and returns it. @@ -259,7 +270,6 @@ void ckmc_buffer_free(ckmc_raw_buffer_s *buffer); * * @see ckmc_cert_free() * @see ckmc_load_cert_from_file() - * @see ckmc_load_from_pkcs12_file * @see #ckmc_cert_s */ int ckmc_cert_new(unsigned char *raw_cert, size_t cert_size, @@ -297,12 +307,42 @@ void ckmc_cert_free(ckmc_cert_s *cert); * @retval #CKMC_ERROR_FILE_ACCESS_DENIED Provided file does not exist or cannot be accessed * * @see ckmc_cert_free() - * @see ckmc_load_from_pkcs12_file() * @see #ckmc_cert_s */ int ckmc_load_cert_from_file(const char *file_path, ckmc_cert_s **cert); /** + * @brief Creates a new @a ckmc_pkcs12_s handle and returns it. + * + * @since_tizen 2.3 + * + * @remarks You must destroy the newly created @a ckmc_pkcs12_s by calling ckmc_pkcs12_free() if it is no longer needed. + * @remarks On success, private_key, cert && ca_cert_list ownership is transferred into newly returned ckmc_pkcs12_s. + * + * @param[in] private_key @a ckmc_key_s handle to the private key (optional) + * @param[in] cert @a ckmc_cert_s handle to the certificate (optional) + * @param[in] ca_cert_list @a ckmc_cert_list_s list of chain certificate handles (optional) + * @param[out] pkcs12_bundle The pointer to a newly created @a ckmc_pkcs12_s handle + * + * @return @c 0 on success, + * otherwise a negative error value + * + * @retval #CKMC_ERROR_INVALID_PARAMETER Input parameter is invalid or private_key, cert and ca_cert_list all are null. + * @retval #CKMC_ERROR_OUT_OF_MEMORY Not enough memory + * + * @see ckmc_pkcs12_free() + * @see ckmc_load_from_pkcs12_file() + * @see ckmc_load_from_pkcs12_file2() + * @see #ckmc_key_s + * @see #ckmc_cert_s + * @see #ckmc_cert_list_s + * @see #ckmc_pkcs12_s + */ +int ckmc_pkcs12_new(ckmc_key_s *private_key, ckmc_cert_s *cert, + ckmc_cert_list_s *ca_cert_list, ckmc_pkcs12_s **pkcs12_bundle); + +/** + * @deprecated, use @a ckmc_load_from_pkcs12_file2() instead * @brief Creates a new @a ckmc_key_s(private key), @a ckmc_cert_s(certificate), and @a ckmc_cert_list_s(CA certificates) handle from a given PKCS#12 file and returns them. * * @since_tizen 2.3 @@ -326,6 +366,8 @@ int ckmc_load_cert_from_file(const char *file_path, ckmc_cert_s **cert); * @retval #CKMC_ERROR_INVALID_FORMAT Invalid PKCS12 file format * @retval #CKMC_ERROR_FILE_ACCESS_DENIED Provided file does not exist or cannot be accessed * + * @see ckmc_pkcs12_new() + * @see ckmc_load_from_pkcs12_file2() * @see ckmc_key_free() * @see ckmc_cert_free() * @see ckmc_cert_list_all_free() @@ -337,6 +379,44 @@ int ckmc_load_from_pkcs12_file(const char *file_path, const char *passphrase, ckmc_key_s **private_key, ckmc_cert_s **cert, ckmc_cert_list_s **ca_cert_list); +/** + * @brief Creates a new @a ckmc_pkcs12_s handle from a given PKCS#12 file and returns it. + * + * @since_tizen 2.3 + * + * @remarks You must destroy the newly created @a ckmc_pkcs12_s by calling ckmc_pkcs12_free() if they are no longer needed. + * + * @param[in] file_path The path of PKCS12 file to be loaded + * @param[in] passphrase The passphrase used to decrypt the PCKS12 file \n + * If PKCS12 file is not encrypted, passphrase can be null. + * @param[out] ca_cert_list The pointer of newly created @a ckmc_cert_list_s handle for CA certificates \n + * It is null if the PKCS12 file does not contain CA certificates. + * + * @return #CKMC_ERROR_NONE on success, + * otherwise a negative error value + * + * @retval #CKMC_ERROR_NONE Successful + * @retval #CKMC_ERROR_OUT_OF_MEMORY Not enough memory space + * @retval #CKMC_ERROR_INVALID_FORMAT Invalid PKCS12 file format + * @retval #CKMC_ERROR_FILE_ACCESS_DENIED Provided file does not exist or cannot be accessed + * + * @see ckmc_pkcs12_free() + * @see #ckmc_pkcs12_s + */ +int ckmc_load_from_pkcs12_file2(const char *file_path, const char *passphrase, ckmc_pkcs12_s **pkcs12_bundle); + +/** + * @brief Destroys the @a ckmc_pkcs12_s handle and releases all its resources. + * + * @since_tizen 2.3 + * + * @param[in] pkcs12 The @a ckmc_pkcs12_s handle to destroy + * + * @see ckmc_pkcs12_new() + * @see ckmc_load_from_pkcs12_file2() + */ +void ckmc_pkcs12_free(ckmc_pkcs12_s *pkcs12); + /** * @internal * @brief Creates a new @a ckmc_alias_list_s handle and returns it. diff --git a/src/manager/client-async/client-manager-async-impl.cpp b/src/manager/client-async/client-manager-async-impl.cpp index 30aa4627..d03776a8 100644 --- a/src/manager/client-async/client-manager-async-impl.cpp +++ b/src/manager/client-async/client-manager-async-impl.cpp @@ -101,6 +101,26 @@ void ManagerAsync::Impl::saveBinaryData(const ManagerAsync::ObserverPtr& observe }, [&observer](int error){ observer->ReceivedError(error); } ); } +void ManagerAsync::Impl::savePKCS12(const ManagerAsync::ObserverPtr& observer, + const Alias &alias, + const PKCS12ShPtr &pkcs, + const Policy &keyPolicy, + const Policy &certPolicy) +{ + try_catch_async([&] { + AliasSupport helper(alias); + sendToStorage(observer, + static_cast(LogicCommand::SAVE_PKCS12), + m_counter, + helper.getName(), + helper.getLabel(), + PKCS12Serializable(*pkcs.get()), + PolicySerializable(keyPolicy), + PolicySerializable(certPolicy)); + + }, [&observer](int error){ observer->ReceivedError(error); } ); +} + void ManagerAsync::Impl::removeAlias(const ManagerAsync::ObserverPtr& observer, const Alias& alias) { @@ -141,6 +161,24 @@ void ManagerAsync::Impl::getBinaryData(const ManagerAsync::ObserverPtr& observer }, [&observer](int error){ observer->ReceivedError(error); } ); } +void ManagerAsync::Impl::getPKCS12(const ManagerAsync::ObserverPtr& observer, + const Alias &alias) +{ + observerCheck(observer); + if (alias.empty()) { + observer->ReceivedError(CKM_API_ERROR_INPUT_PARAM); + return; + } + try_catch_async([&] { + AliasSupport helper(alias); + sendToStorage(observer, + static_cast(LogicCommand::GET_PKCS12), + m_counter, + helper.getName(), + helper.getLabel()); + }, [&observer](int error){ observer->ReceivedError(error); } ); +} + void ManagerAsync::Impl::createSignature(const ObserverPtr& observer, const Alias& privateKeyAlias, const Password& password, diff --git a/src/manager/client-async/client-manager-async-impl.h b/src/manager/client-async/client-manager-async-impl.h index b3aea301..e069704c 100644 --- a/src/manager/client-async/client-manager-async-impl.h +++ b/src/manager/client-async/client-manager-async-impl.h @@ -53,6 +53,12 @@ public: const Alias& alias, const RawBuffer& data, const Policy& policy); + void savePKCS12( + const ObserverPtr& observer, + const Alias &alias, + const PKCS12ShPtr &pkcs, + const Policy &keyPolicy, + const Policy &certPolicy); void createSignature( const ObserverPtr& observer, @@ -98,6 +104,10 @@ public: DBDataType sendDataType, const Password &password); + void getPKCS12( + const ManagerAsync::ObserverPtr& observer, + const Alias &alias); + void getBinaryDataAliasVector( const ManagerAsync::ObserverPtr& observer, DBDataType dataType); diff --git a/src/manager/client-async/client-manager-async.cpp b/src/manager/client-async/client-manager-async.cpp index 75c7684a..9ecaf333 100644 --- a/src/manager/client-async/client-manager-async.cpp +++ b/src/manager/client-async/client-manager-async.cpp @@ -58,6 +58,15 @@ void ManagerAsync::saveData(const ObserverPtr& observer, m_impl->saveData(observer, alias, data, policy); } +void ManagerAsync::savePKCS12(const ObserverPtr& observer, + const Alias &alias, + const PKCS12ShPtr &pkcs, + const Policy &keyPolicy, + const Policy &certPolicy) +{ + m_impl->savePKCS12(observer, alias, pkcs, keyPolicy, certPolicy); +} + void ManagerAsync::removeAlias(const ObserverPtr& observer, const Alias& alias) { m_impl->removeAlias(observer, alias); @@ -82,6 +91,12 @@ void ManagerAsync::getData(const ObserverPtr& observer, m_impl->getBinaryData(observer, alias, DBDataType::BINARY_DATA, password); } +void ManagerAsync::getPKCS12(const ObserverPtr& observer, + const Alias &alias) +{ + m_impl->getPKCS12(observer, alias); +} + void ManagerAsync::getKeyAliasVector(const ObserverPtr& observer) { m_impl->getBinaryDataAliasVector(observer, DBDataType::DB_KEY_FIRST); diff --git a/src/manager/client-async/storage-receiver.cpp b/src/manager/client-async/storage-receiver.cpp index cb9560cc..857bb7e9 100644 --- a/src/manager/client-async/storage-receiver.cpp +++ b/src/manager/client-async/storage-receiver.cpp @@ -55,13 +55,19 @@ void StorageReceiver::parseResponse() switch (static_cast(command)) { case LogicCommand::GET: parseGetCommand(); - break ; + break; + case LogicCommand::GET_PKCS12: + parseGetPKCS12Command(); + break; case LogicCommand::GET_LIST: parseGetListCommand(); break; case LogicCommand::SAVE: parseSaveCommand(); break; + case LogicCommand::SAVE_PKCS12: + parseSavePKCS12Command(); + break; case LogicCommand::REMOVE: parseRemoveCommand(); break; @@ -118,6 +124,21 @@ void StorageReceiver::parseGetCommand() m_observer->ReceivedError(CKM_API_ERROR_BAD_RESPONSE); } +void StorageReceiver::parseGetPKCS12Command() +{ + int retCode; + PKCS12Serializable gotPkcs; + m_buffer.Deserialize(retCode, gotPkcs); + + // check error code + if (retCode != CKM_API_SUCCESS) { + m_observer->ReceivedError(retCode); + return; + } + + m_observer->ReceivedPKCS12(std::make_shared(std::move(gotPkcs))); +} + void StorageReceiver::parseGetListCommand() { int dataType = 0, retCode = 0; @@ -168,6 +189,20 @@ void StorageReceiver::parseSaveCommand() m_observer->ReceivedError(CKM_API_ERROR_BAD_RESPONSE); } +void StorageReceiver::parseSavePKCS12Command() +{ + int retCode = 0; + m_buffer.Deserialize(retCode); + + // check error code + if (retCode != CKM_API_SUCCESS) { + m_observer->ReceivedError(retCode); + return; + } + + m_observer->ReceivedSavePKCS12(); +} + void StorageReceiver::parseRemoveCommand() { int retCode = 0; diff --git a/src/manager/client-async/storage-receiver.h b/src/manager/client-async/storage-receiver.h index 05608923..c838b3d2 100644 --- a/src/manager/client-async/storage-receiver.h +++ b/src/manager/client-async/storage-receiver.h @@ -41,8 +41,10 @@ public: private: void parseGetCommand(); + void parseGetPKCS12Command(); void parseGetListCommand(); void parseSaveCommand(); + void parseSavePKCS12Command(); void parseRemoveCommand(); void parseGetChainCertCommand(); void parseCreateSignatureCommand(); diff --git a/src/manager/client-capi/ckmc-manager.cpp b/src/manager/client-capi/ckmc-manager.cpp index 4a8cf823..0382d35b 100644 --- a/src/manager/client-capi/ckmc-manager.cpp +++ b/src/manager/client-capi/ckmc-manager.cpp @@ -39,19 +39,33 @@ CKM::Password _tostring(const char *str) return CKM::Password(str); } +CKM::KeyShPtr _toCkmKey(const ckmc_key_s *key) +{ + if(key) + { + CKM::RawBuffer buffer(key->raw_key, key->raw_key + key->key_size); + return CKM::Key::create(buffer, _tostring(key->password)); + } + return CKM::KeyShPtr(); +} + CKM::CertificateShPtr _toCkmCertificate(const ckmc_cert_s *cert) { - CKM::RawBuffer buffer(cert->raw_cert, cert->raw_cert + cert->cert_size); - CKM::DataFormat dataFormat = static_cast(static_cast(cert->data_format)); - return CKM::Certificate::create(buffer, dataFormat); + if(cert) + { + CKM::RawBuffer buffer(cert->raw_cert, cert->raw_cert + cert->cert_size); + CKM::DataFormat dataFormat = static_cast(static_cast(cert->data_format)); + return CKM::Certificate::create(buffer, dataFormat); + } + return CKM::CertificateShPtr(); } -ckmc_cert_list_s *_toNewCkmCertList(CKM::CertificateShPtrVector &certVector) +ckmc_cert_list_s *_toNewCkmCertList(const CKM::CertificateShPtrVector &certVector) { int ret; ckmc_cert_list_s *start = NULL; ckmc_cert_list_s *plist = NULL; - CKM::CertificateShPtrVector::iterator it; + CKM::CertificateShPtrVector::const_iterator it; for(it = certVector.begin(); it != certVector.end(); it++) { CKM::RawBuffer rawBuffer = (*it)->getDER(); unsigned char *rawCert = static_cast(malloc(rawBuffer.size())); @@ -285,6 +299,115 @@ int ckmc_get_cert_alias_list(ckmc_alias_list_s** alias_list) { return CKMC_ERROR_NONE; } +KEY_MANAGER_CAPI +int ckmc_save_pkcs12(const char *alias, const ckmc_pkcs12_s *ppkcs, const ckmc_policy_s key_policy, const ckmc_policy_s cert_policy) +{ + CKM::KeyShPtr private_key; + CKM::CertificateShPtr cert; + CKM::CertificateShPtrVector ca_cert_list; + + if(alias==NULL || ppkcs==NULL) { + return CKMC_ERROR_INVALID_PARAMETER; + } + CKM::Alias ckmAlias(alias); + + private_key = _toCkmKey(ppkcs->priv_key); + cert = _toCkmCertificate(ppkcs->cert); + ckmc_cert_list_s *current = NULL; + ckmc_cert_list_s *next = const_cast(ppkcs->ca_chain); + do { + current = next; + next = current->next; + + if(current->cert == NULL){ + continue; + } + + CKM::CertificateShPtr tmpCkmCert = _toCkmCertificate(current->cert); + ca_cert_list.push_back(tmpCkmCert); + }while(next != NULL); + + CKM::Policy keyPolicy(_tostring(key_policy.password), key_policy.extractable); + CKM::Policy certPolicy(_tostring(cert_policy.password), cert_policy.extractable); + + CKM::PKCS12ShPtr pkcs12(new CKM::PKCS12Impl(private_key, cert, ca_cert_list)); + + CKM::ManagerShPtr mgr = CKM::Manager::create(); + int ret = mgr->savePKCS12(ckmAlias, pkcs12, keyPolicy, certPolicy); + + return to_ckmc_error(ret); +} + +KEY_MANAGER_CAPI +int ckmc_remove_pkcs12(const char *alias) +{ + if(alias == NULL) { + return CKMC_ERROR_INVALID_PARAMETER; + } + + CKM::ManagerShPtr mgr = CKM::Manager::create(); + int ret = mgr->removeAlias(alias); + return to_ckmc_error(ret); +} + +KEY_MANAGER_CAPI +int ckmc_get_pkcs12(const char *alias, ckmc_pkcs12_s **pkcs12) +{ + int ret; + CKM::PKCS12ShPtr ShPkcs12; + CKM::PKCS12 *pkcs12Ptr = NULL; + ckmc_key_s *private_key = NULL; + ckmc_cert_s *cert = NULL; + ckmc_cert_list_s *ca_cert_list = 0; + + if(alias == NULL || pkcs12 == NULL) { + return CKMC_ERROR_INVALID_PARAMETER; + } + + CKM::ManagerShPtr mgr = CKM::Manager::create(); + if( (ret = mgr->getPKCS12(alias, ShPkcs12)) != CKM_API_SUCCESS) { + return to_ckmc_error(ret); + } + + pkcs12Ptr = ShPkcs12.get(); + if(!pkcs12Ptr) + return CKMC_ERROR_BAD_RESPONSE; + + if(pkcs12Ptr->getKey()) + { + CKM::KeyShPtr helper = pkcs12Ptr->getKey(); + + unsigned char *rawKey = reinterpret_cast(helper->getDER().data()); + ckmc_key_type_e keyType = static_cast(static_cast(helper->getType())); + ret = ckmc_key_new(rawKey, helper->getDER().size(), keyType, NULL, &private_key); + if(ret != CKMC_ERROR_NONE) + return ret; + } + + if(pkcs12Ptr->getCertificate()) + { + CKM::CertificateShPtr helper = pkcs12Ptr->getCertificate(); + + unsigned char *rawCert = reinterpret_cast(helper->getDER().data()); + ret = ckmc_cert_new(rawCert, helper->getDER().size(), CKMC_FORM_DER, &cert); + if(ret != CKMC_ERROR_NONE) { + ckmc_key_free(private_key); + return ret; + } + } + + ca_cert_list = _toNewCkmCertList(pkcs12Ptr->getCaCertificateShPtrVector()); + + ret = ckmc_pkcs12_new(private_key, cert, ca_cert_list, pkcs12); + if(ret != CKMC_ERROR_NONE) + { + ckmc_key_free(private_key); + ckmc_cert_free(cert); + ckmc_cert_list_free(ca_cert_list); + } + return ret; +} + KEY_MANAGER_CAPI int ckmc_save_data(const char *alias, ckmc_raw_buffer_s data, const ckmc_policy_s policy) { diff --git a/src/manager/client-capi/ckmc-type.cpp b/src/manager/client-capi/ckmc-type.cpp index 15114435..cca44588 100644 --- a/src/manager/client-capi/ckmc-type.cpp +++ b/src/manager/client-capi/ckmc-type.cpp @@ -188,6 +188,43 @@ int ckmc_load_cert_from_file(const char *file_path, ckmc_cert_s **cert) return ret; } +KEY_MANAGER_CAPI +void ckmc_cert_free(ckmc_cert_s *cert) +{ + if(cert == NULL) + return; + + if(cert->raw_cert != NULL) { + memset(cert->raw_cert, 0, cert->cert_size); + free(cert->raw_cert); + } + free(cert); +} + +KEY_MANAGER_CAPI +int ckmc_pkcs12_new(ckmc_key_s *private_key, ckmc_cert_s *cert, + ckmc_cert_list_s *ca_cert_list, ckmc_pkcs12_s **pkcs12_bundle) +{ + ckmc_pkcs12_s *pkcs12; + + if(!pkcs12_bundle || + (private_key==NULL && cert==NULL && (ca_cert_list==NULL || ca_cert_list->cert==NULL))) { + return CKMC_ERROR_INVALID_PARAMETER; + } + + pkcs12 = static_cast(malloc(sizeof(ckmc_pkcs12_s))); + if(pkcs12 == NULL) { + return CKMC_ERROR_OUT_OF_MEMORY; + } + // ownership is transferred into pkcs12 - mentioned in the docs + pkcs12->priv_key = private_key; + pkcs12->cert = cert; + pkcs12->ca_chain = ca_cert_list; + + *pkcs12_bundle = pkcs12; + return CKMC_ERROR_NONE; +} + KEY_MANAGER_CAPI int ckmc_load_from_pkcs12_file(const char *file_path, const char *passphrase, ckmc_key_s **private_key, ckmc_cert_s **ckmcert, ckmc_cert_list_s **ca_cert_list) { @@ -354,17 +391,42 @@ int ckmc_load_from_pkcs12_file(const char *file_path, const char *passphrase, ck return CKMC_ERROR_NONE; } +int ckmc_load_from_pkcs12_file2(const char *file_path, const char *passphrase, ckmc_pkcs12_s **pkcs12_bundle) +{ + int ec; + ckmc_key_s *private_key = 0; + ckmc_cert_s *cert = 0; + ckmc_cert_list_s *ca_cert_list = 0; + + if(!file_path || !pkcs12_bundle) + return CKMC_ERROR_INVALID_PARAMETER; + + ec = ckmc_load_from_pkcs12_file(file_path, passphrase, &private_key, &cert, &ca_cert_list); + if(ec != CKMC_ERROR_NONE) + return ec; + + ec = ckmc_pkcs12_new(private_key, cert, ca_cert_list, pkcs12_bundle); + if(ec != CKMC_ERROR_NONE) + { + ckmc_key_free(private_key); + ckmc_cert_free(cert); + ckmc_cert_list_free(ca_cert_list); + return ec; + } + + return CKMC_ERROR_NONE; +} + KEY_MANAGER_CAPI -void ckmc_cert_free(ckmc_cert_s *cert) +void ckmc_pkcs12_free(ckmc_pkcs12_s *pkcs12) { - if(cert == NULL) + if(pkcs12 == NULL) return; - if(cert->raw_cert != NULL) { - memset(cert->raw_cert, 0, cert->cert_size); - free(cert->raw_cert); - } - free(cert); + ckmc_key_free(pkcs12->priv_key); + ckmc_cert_free(pkcs12->cert); + ckmc_cert_list_free(pkcs12->ca_chain); + free(pkcs12); } KEY_MANAGER_CAPI diff --git a/src/manager/client/client-manager-impl.cpp b/src/manager/client/client-manager-impl.cpp index 28971711..7af969fb 100644 --- a/src/manager/client/client-manager-impl.cpp +++ b/src/manager/client/client-manager-impl.cpp @@ -46,7 +46,7 @@ int ManagerImpl::saveBinaryData( const RawBuffer &rawData, const Policy &policy) { - m_counter++; + int my_counter = ++m_counter; return try_catch([&] { if (alias.empty() || rawData.empty()) @@ -55,7 +55,7 @@ int ManagerImpl::saveBinaryData( MessageBuffer recv; AliasSupport helper(alias); auto send = MessageBuffer::Serialize(static_cast(LogicCommand::SAVE), - m_counter, + my_counter, static_cast(dataType), helper.getName(), helper.getLabel(), @@ -71,9 +71,8 @@ int ManagerImpl::saveBinaryData( int opType; recv.Deserialize(command, counter, retCode, opType); - if (counter != m_counter) { + if (counter != my_counter) return CKM_API_ERROR_UNKNOWN; - } return retCode; }); @@ -106,16 +105,90 @@ int ManagerImpl::saveData(const Alias &alias, const RawBuffer &rawData, const Po return saveBinaryData(alias, DBDataType::BINARY_DATA, rawData, policy); } -int ManagerImpl::removeAlias(const Alias &alias) + +int ManagerImpl::savePKCS12( + const Alias & alias, + const PKCS12ShPtr &pkcs, + const Policy &keyPolicy, + const Policy &certPolicy) { + if (alias.empty() || pkcs.get()==NULL) + return CKM_API_ERROR_INPUT_PARAM; + + int my_counter = ++m_counter; + return try_catch([&] { - if (alias.empty()) - return CKM_API_ERROR_INPUT_PARAM; + MessageBuffer recv; + AliasSupport helper(alias); + auto send = MessageBuffer::Serialize(static_cast(LogicCommand::SAVE_PKCS12), + my_counter, + helper.getName(), + helper.getLabel(), + PKCS12Serializable(*pkcs.get()), + PolicySerializable(keyPolicy), + PolicySerializable(certPolicy)); + + int retCode = m_storageConnection.processRequest(send.Pop(), recv); + if (CKM_API_SUCCESS != retCode) + return retCode; + + int command; + int counter; + recv.Deserialize(command, counter, retCode); + + if (counter != my_counter) + return CKM_API_ERROR_UNKNOWN; + + return retCode; + }); +} + +int ManagerImpl::getPKCS12(const Alias &alias, PKCS12ShPtr &pkcs) +{ + if (alias.empty()) + return CKM_API_ERROR_INPUT_PARAM; + + int my_counter = ++m_counter; + + return try_catch([&] { + MessageBuffer recv; + AliasSupport helper(alias); + auto send = MessageBuffer::Serialize(static_cast(LogicCommand::GET_PKCS12), + my_counter, + helper.getName(), + helper.getLabel()); + int retCode = m_storageConnection.processRequest(send.Pop(), recv); + if (CKM_API_SUCCESS != retCode) + return retCode; + + int command; + int counter; + PKCS12Serializable gotPkcs; + recv.Deserialize(command, counter, retCode, gotPkcs); + + if (counter != my_counter) + return CKM_API_ERROR_UNKNOWN; + + pkcs = std::make_shared(std::move(gotPkcs)); + + return retCode; + }); +} + + +int ManagerImpl::removeAlias(const Alias &alias) +{ + if (alias.empty()) + return CKM_API_ERROR_INPUT_PARAM; + + int my_counter = ++m_counter; + + return try_catch([&] { MessageBuffer recv; AliasSupport helper(alias); auto send = MessageBuffer::Serialize(static_cast(LogicCommand::REMOVE), - m_counter, + my_counter, helper.getName(), helper.getLabel()); @@ -127,9 +200,8 @@ int ManagerImpl::removeAlias(const Alias &alias) int counter; recv.Deserialize(command, counter, retCode); - if (counter != m_counter) { + if (counter != my_counter) return CKM_API_ERROR_UNKNOWN; - } return retCode; }); @@ -142,14 +214,16 @@ int ManagerImpl::getBinaryData( DBDataType &recvDataType, RawBuffer &rawData) { - return try_catch([&] { - if (alias.empty()) - return CKM_API_ERROR_INPUT_PARAM; + if (alias.empty()) + return CKM_API_ERROR_INPUT_PARAM; + + int my_counter = ++m_counter; + return try_catch([&] { MessageBuffer recv; AliasSupport helper(alias); auto send = MessageBuffer::Serialize(static_cast(LogicCommand::GET), - m_counter, + my_counter, static_cast(sendDataType), helper.getName(), helper.getLabel(), @@ -165,9 +239,8 @@ int ManagerImpl::getBinaryData( recv.Deserialize(command, counter, retCode, tmpDataType, rawData); recvDataType = DBDataType(tmpDataType); - if (counter != m_counter) { + if (counter != my_counter) return CKM_API_ERROR_UNKNOWN; - } return retCode; }); @@ -249,11 +322,12 @@ int ManagerImpl::getData(const Alias &alias, const Password &password, RawBuffer int ManagerImpl::getBinaryDataAliasVector(DBDataType dataType, AliasVector &aliasVector) { - return try_catch([&] { + int my_counter = ++m_counter; + return try_catch([&] { MessageBuffer recv; auto send = MessageBuffer::Serialize(static_cast(LogicCommand::GET_LIST), - m_counter, + my_counter, static_cast(dataType)); int retCode = m_storageConnection.processRequest(send.Pop(), recv); @@ -265,7 +339,7 @@ int ManagerImpl::getBinaryDataAliasVector(DBDataType dataType, AliasVector &alia int tmpDataType; LabelNameVector labelNameVector; recv.Deserialize(command, counter, retCode, tmpDataType, labelNameVector); - if ((command != static_cast(LogicCommand::GET_LIST)) || (counter != m_counter)) { + if ((command != static_cast(LogicCommand::GET_LIST)) || (counter != my_counter)) { return CKM_API_ERROR_UNKNOWN; } @@ -352,8 +426,8 @@ int ManagerImpl::createKeyPair( } // proceed with sending request - m_counter++; - int my_counter = m_counter; + int my_counter = ++m_counter; + return try_catch([&] { MessageBuffer recv; @@ -479,8 +553,8 @@ int ManagerImpl::createSignature( const RSAPaddingAlgorithm padding, RawBuffer &signature) { - m_counter++; - int my_counter = m_counter; + int my_counter = ++m_counter; + return try_catch([&] { MessageBuffer recv; @@ -520,10 +594,9 @@ int ManagerImpl::verifySignature( const HashAlgorithm hash, const RSAPaddingAlgorithm padding) { - m_counter++; - int my_counter = m_counter; - return try_catch([&] { + int my_counter = ++m_counter; + return try_catch([&] { MessageBuffer recv; AliasSupport helper(publicKeyOrCertAlias); auto send = MessageBuffer::Serialize(static_cast(LogicCommand::VERIFY_SIGNATURE), @@ -586,8 +659,8 @@ int ManagerImpl::setPermission(const Alias &alias, const Label &accessor, Permission newPermission) { - m_counter++; - int my_counter = m_counter; + int my_counter = ++m_counter; + return try_catch([&] { MessageBuffer recv; AliasSupport helper(alias); diff --git a/src/manager/client/client-manager-impl.h b/src/manager/client/client-manager-impl.h index d5841857..a03113e8 100644 --- a/src/manager/client/client-manager-impl.h +++ b/src/manager/client/client-manager-impl.h @@ -45,6 +45,14 @@ public: int getData(const Alias &alias, const Password &password, RawBuffer &cert); int getDataAliasVector(AliasVector &aliasVector); + int savePKCS12( + const Alias &alias, + const PKCS12ShPtr &pkcs, + const Policy &keyPolicy, + const Policy &certPolicy); + int getPKCS12(const Alias &alias, PKCS12ShPtr &pkcs); + + int removeAlias(const Alias &alias); int createKeyPairRSA( diff --git a/src/manager/common/certificate-impl.cpp b/src/manager/common/certificate-impl.cpp index 316085db..0577958c 100644 --- a/src/manager/common/certificate-impl.cpp +++ b/src/manager/common/certificate-impl.cpp @@ -91,7 +91,8 @@ CertificateImpl::CertificateImpl(CertificateImpl &&second) { CertificateImpl& CertificateImpl::operator=(CertificateImpl &&second) { if (this == &second) return *this; - X509_free(m_x509); + if(m_x509) + X509_free(m_x509); m_x509 = second.m_x509; second.m_x509 = NULL; LogDebug("Certificate moved: " << (void*)m_x509); @@ -101,7 +102,8 @@ CertificateImpl& CertificateImpl::operator=(CertificateImpl &&second) { CertificateImpl& CertificateImpl::operator=(const CertificateImpl &second) { if (this == &second) return *this; - X509_free(m_x509); + if(m_x509) + X509_free(m_x509); m_x509 = X509_dup(second.m_x509); return *this; } @@ -258,7 +260,8 @@ std::string CertificateImpl::getOCSPURL() const { } CertificateImpl::~CertificateImpl() { - X509_free(m_x509); + if(m_x509) + X509_free(m_x509); } CertificateShPtr Certificate::create(const RawBuffer &rawBuffer, DataFormat format) { diff --git a/src/manager/common/certificate-impl.h b/src/manager/common/certificate-impl.h index 679de866..48ae5b7c 100644 --- a/src/manager/common/certificate-impl.h +++ b/src/manager/common/certificate-impl.h @@ -32,7 +32,7 @@ namespace CKM { class CertificateImpl : public Certificate { public: - CertificateImpl(){} + CertificateImpl() : m_x509(NULL) {} explicit CertificateImpl(X509* x509, bool duplicate = true); CertificateImpl(const RawBuffer &data, DataFormat format); CertificateImpl(const CertificateImpl &); diff --git a/src/manager/common/pkcs12-impl.cpp b/src/manager/common/pkcs12-impl.cpp index e8c08c51..d9804d07 100644 --- a/src/manager/common/pkcs12-impl.cpp +++ b/src/manager/common/pkcs12-impl.cpp @@ -38,6 +38,13 @@ typedef std::unique_ptr> BioUniquePtr; } // anonymous namespace +PKCS12Impl::PKCS12Impl(const KeyShPtr &key, const CertificateShPtr &cert, const CertificateShPtrVector &caChain) + : m_pkey(key), + m_cert(cert), + m_ca(caChain) +{ +} + PKCS12Impl::PKCS12Impl(const RawBuffer &buffer, const Password &password) { EVP_PKEY *pkey = NULL; @@ -111,6 +118,38 @@ PKCS12Impl::PKCS12Impl(const RawBuffer &buffer, const Password &password) } } +PKCS12Impl::PKCS12Impl(const PKCS12 &other) + : m_pkey(other.getKey()), + m_cert(other.getCertificate()), + m_ca(other.getCaCertificateShPtrVector()) +{ +} + +PKCS12Impl::PKCS12Impl(PKCS12Impl &&other) + : m_pkey(std::move(other.m_pkey)), + m_cert(std::move(other.m_cert)), + m_ca(std::move(other.m_ca)) +{ +} + +PKCS12Impl::PKCS12Impl(const PKCS12Impl &other) + : m_pkey(other.getKey()), + m_cert(other.getCertificate()), + m_ca(other.getCaCertificateShPtrVector()) +{ +} + +PKCS12Impl& PKCS12Impl::operator=(const PKCS12Impl &other) +{ + if(this != &other) + { + m_pkey = other.getKey(); + m_cert = other.getCertificate(); + m_ca = other.getCaCertificateShPtrVector(); + } + return *this; +} + KeyShPtr PKCS12Impl::getKey() const { return m_pkey; } diff --git a/src/manager/common/pkcs12-impl.h b/src/manager/common/pkcs12-impl.h index b1d1c8f8..6980f5cc 100644 --- a/src/manager/common/pkcs12-impl.h +++ b/src/manager/common/pkcs12-impl.h @@ -28,11 +28,14 @@ namespace CKM { class PKCS12Impl : public PKCS12 { public: - PKCS12Impl(const RawBuffer &buffer, const Password &password); - - PKCS12Impl(const PKCS12Impl &) = delete; - PKCS12Impl(PKCS12Impl &&) = delete; - PKCS12Impl& operator=(const PKCS12Impl &) = delete; + PKCS12Impl() {} + explicit PKCS12Impl(const PKCS12 &); + PKCS12Impl(PKCS12Impl &&); + PKCS12Impl(const PKCS12Impl &); + PKCS12Impl(const RawBuffer &, const Password &); + PKCS12Impl(const KeyShPtr &, const CertificateShPtr &, const CertificateShPtrVector &); + + PKCS12Impl& operator=(const PKCS12Impl &); PKCS12Impl& operator=(PKCS12Impl &&) = delete; virtual KeyShPtr getKey() const; diff --git a/src/manager/common/protocols.cpp b/src/manager/common/protocols.cpp index 67cb36c7..6e800111 100644 --- a/src/manager/common/protocols.cpp +++ b/src/manager/common/protocols.cpp @@ -58,5 +58,78 @@ Permission toPermission(const std::string &input_DB_data) { return Permission::NONE; } + +PKCS12Serializable::PKCS12Serializable() {} +PKCS12Serializable::PKCS12Serializable(const PKCS12 &pkcs) + : PKCS12Impl(pkcs) +{} + +PKCS12Serializable::PKCS12Serializable(IStream &stream) +{ + // key + size_t numKeys; + Deserialization::Deserialize(stream, numKeys); + if(numKeys > 0) { + int keyType; + RawBuffer keyData; + Deserialization::Deserialize(stream, keyType); + Deserialization::Deserialize(stream, keyData); + m_pkey = CKM::Key::create(keyData); + } + + // cert + size_t numCerts; + Deserialization::Deserialize(stream, numCerts); + if(numCerts > 0) { + RawBuffer certData; + Deserialization::Deserialize(stream, certData); + m_cert = CKM::Certificate::create(certData, DataFormat::FORM_DER); + } + + // CA chain + size_t num_CA; + Deserialization::Deserialize(stream, num_CA); + for(size_t i=0; i(isAnyKeyPresent?1:0)); + if(keyPtr) { + Serialization::Serialize(stream, DBDataType(keyPtr->getType())); + Serialization::Serialize(stream, keyPtr->getDER()); + } + + bool isAnyCertPresent = (getCertificate().get()!=NULL); + Serialization::Serialize(stream, static_cast(isAnyCertPresent?1:0)); + if(isAnyCertPresent) { + Serialization::Serialize(stream, getCertificate().get()->getDER()); + } + + // CA chain + Serialization::Serialize(stream, getCaCertificateShPtrVector().size()); + for(auto it : getCaCertificateShPtrVector()) + Serialization::Serialize(stream, it->getDER()); +}; + } // namespace CKM diff --git a/src/manager/common/protocols.h b/src/manager/common/protocols.h index 7487cbe9..1a2bf676 100644 --- a/src/manager/common/protocols.h +++ b/src/manager/common/protocols.h @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -61,7 +62,9 @@ enum class LogicCommand : int { CREATE_SIGNATURE, VERIFY_SIGNATURE, CREATE_KEY_PAIR_DSA, - SET_PERMISSION + SET_PERMISSION, + SAVE_PKCS12, + GET_PKCS12 // for backward compatibility append new at the end }; @@ -83,11 +86,31 @@ public: KEY_AES, CERTIFICATE, BINARY_DATA, + + CHAIN_CERT_0, + CHAIN_CERT_1, + CHAIN_CERT_2, + CHAIN_CERT_3, + CHAIN_CERT_4, + CHAIN_CERT_5, + CHAIN_CERT_6, + CHAIN_CERT_7, + CHAIN_CERT_8, + CHAIN_CERT_9, + CHAIN_CERT_10, + CHAIN_CERT_11, + CHAIN_CERT_12, + CHAIN_CERT_13, + CHAIN_CERT_14, + CHAIN_CERT_15, + // Special types to support database, - DB_FIRST = KEY_RSA_PUBLIC, - DB_LAST = BINARY_DATA, DB_KEY_FIRST = KEY_RSA_PUBLIC, DB_KEY_LAST = KEY_AES, + DB_CHAIN_FIRST = CHAIN_CERT_0, + DB_CHAIN_LAST = CHAIN_CERT_15, + DB_FIRST = KEY_RSA_PUBLIC, + DB_LAST = CHAIN_CERT_15, }; DBDataType() @@ -153,6 +176,22 @@ public: return false; } + bool isChainCert() const { + if (DB_CHAIN_FIRST <= m_dataType && DB_CHAIN_LAST >= m_dataType) + return true; + return false; + } + + static DBDataType getChainDatatype(unsigned int index) + { + DBDataType result(static_cast(index) + DB_CHAIN_FIRST); + + if ( !result.isChainCert() ) + ThrowMsg(Exception::OutOfRange, "Certificate number is out of range"); + + return result; + } + bool isKeyPrivate() const { switch (m_dataType) { case KEY_RSA_PRIVATE: @@ -222,5 +261,16 @@ struct PolicySerializable : public Policy, ISerializable { } }; +struct PKCS12Serializable : public PKCS12Impl, ISerializable { + PKCS12Serializable(); + explicit PKCS12Serializable(const PKCS12 &); + explicit PKCS12Serializable(IStream &); + PKCS12Serializable( + const KeyShPtr &privKey, + const CertificateShPtr &cert, + const CertificateShPtrVector &chainCerts); + void Serialize(IStream &) const; +}; + } // namespace CKM diff --git a/src/manager/service/ckm-logic.cpp b/src/manager/service/ckm-logic.cpp index 0029bf00..649815b9 100644 --- a/src/manager/service/ckm-logic.cpp +++ b/src/manager/service/ckm-logic.cpp @@ -220,17 +220,12 @@ RawBuffer CKMLogic::removeApplicationData(const Label &smackLabel) { return MessageBuffer::Serialize(retCode).Pop(); } -int CKMLogic::saveDataHelper( +int CKMLogic::checkSaveConditions( const Credentials &cred, - DBDataType dataType, + UserData &handler, const Name &name, - const Label &label, - const RawBuffer &key, - const PolicySerializable &policy) + const Label &ownerLabel) { - // use client label if not explicitly provided - const Label &ownerLabel = label.empty() ? cred.smackLabel : label; - // verify name and label are correct if (!isNameValid(name) || !isLabelValid(ownerLabel)) { LogWarning("Invalid parameter passed to key-manager"); @@ -245,17 +240,6 @@ int CKMLogic::saveDataHelper( return access_ec; } - // proceed to data save - DBRow row = { name, cred.smackLabel, - policy.extractable, dataType, DBCMAlgType::NONE, - 0, RawBuffer(), static_cast(key.size()), key, RawBuffer() }; - - if (0 == m_userDataMap.count(cred.uid)) - return CKM_API_ERROR_DB_LOCKED; - - auto &handler = m_userDataMap[cred.uid]; - DBCrypto::Transaction transaction(&handler.database); - // check if not a duplicate if( handler.database.isNameLabelPresent(name, cred.smackLabel) ) return CKM_API_ERROR_DB_ALIAS_EXISTS; @@ -278,63 +262,88 @@ int CKMLogic::saveDataHelper( handler.crypto.pushKey(cred.smackLabel, got_key); } + return CKM_API_SUCCESS; +} + +DBRow CKMLogic::createEncryptedDBRow( + CryptoLogic &crypto, + const Name &name, + const Label &label, + DBDataType dataType, + const RawBuffer &data, + const Policy &policy) const +{ + DBRow row = { name, label, policy.extractable, dataType, DBCMAlgType::NONE, + 0, RawBuffer(), static_cast(data.size()), data, RawBuffer() }; + // do not encrypt data with password during cc_mode on if(m_accessControl.isCCMode()) { - handler.crypto.encryptRow("", row); + crypto.encryptRow("", row); } else { - handler.crypto.encryptRow(policy.password, row); + crypto.encryptRow(policy.password, row); } - - handler.database.saveDBRow(row); - transaction.commit(); - return CKM_API_SUCCESS; + return row; } -void CKMLogic::verifyBinaryData(DBDataType dataType, const RawBuffer &input_data) const +int CKMLogic::verifyBinaryData(DBDataType dataType, const RawBuffer &input_data) const { // verify the data integrity - if (dataType.isKey()) { + if (dataType.isKey()) + { KeyShPtr output_key = CKM::Key::create(input_data); if(output_key.get() == NULL) - ThrowMsg(CKMLogic::Exception::InputDataInvalid, "provided binary data is not valid key data"); - } else if (dataType.isCertificate()) { + { + LogError("provided binary data is not valid key data"); + return CKM_API_ERROR_INPUT_PARAM; + } + } + else if (dataType.isCertificate() || dataType.isChainCert()) + { CertificateShPtr cert = CKM::Certificate::create(input_data, DataFormat::FORM_DER); if(cert.get() == NULL) - ThrowMsg(CKMLogic::Exception::InputDataInvalid, "provided binary data is not valid certificate data"); + { + LogError("provided binary data is not valid certificate data"); + return CKM_API_ERROR_INPUT_PARAM; + } } // TODO: add here BINARY_DATA verification, i.e: max size etc. + return CKM_API_SUCCESS; } RawBuffer CKMLogic::saveData( const Credentials &cred, int commandId, - DBDataType dataType, const Name &name, const Label &label, - const RawBuffer &key, + const RawBuffer &data, + DBDataType dataType, const PolicySerializable &policy) { - int retCode = CKM_API_SUCCESS; - try { - verifyBinaryData(dataType, key); - - retCode = saveDataHelper(cred, dataType, name, label, key, policy); - LogDebug("SaveDataHelper returned: " << retCode); - } catch (const CKMLogic::Exception::InputDataInvalid &e) { - LogError("Provided data invalid: " << e.GetMessage()); - retCode = CKM_API_ERROR_INPUT_PARAM; - } catch (const KeyProvider::Exception::Base &e) { - LogError("KeyProvider failed with message: " << e.GetMessage()); - retCode = CKM_API_ERROR_SERVER_ERROR; - } catch (const CryptoLogic::Exception::Base &e) { - LogError("CryptoLogic failed with message: " << e.GetMessage()); - retCode = CKM_API_ERROR_SERVER_ERROR; - } catch (const DBCrypto::Exception::InternalError &e) { - LogError("DBCrypto failed with message: " << e.GetMessage()); - retCode = CKM_API_ERROR_DB_ERROR; - } catch (const DBCrypto::Exception::TransactionError &e) { - LogError("DBCrypto transaction failed with message " << e.GetMessage()); - retCode = CKM_API_ERROR_DB_ERROR; + int retCode; + if (0 == m_userDataMap.count(cred.uid)) + retCode = CKM_API_ERROR_DB_LOCKED; + else + { + try { + // check if data is correct + retCode = verifyBinaryData(dataType, data); + if(retCode == CKM_API_SUCCESS) + { + retCode = saveDataHelper(cred, name, label, dataType, data, policy); + } + } catch (const KeyProvider::Exception::Base &e) { + LogError("KeyProvider failed with message: " << e.GetMessage()); + retCode = CKM_API_ERROR_SERVER_ERROR; + } catch (const CryptoLogic::Exception::Base &e) { + LogError("CryptoLogic failed with message: " << e.GetMessage()); + retCode = CKM_API_ERROR_SERVER_ERROR; + } catch (const DBCrypto::Exception::InternalError &e) { + LogError("DBCrypto failed with message: " << e.GetMessage()); + retCode = CKM_API_ERROR_DB_ERROR; + } catch (const DBCrypto::Exception::TransactionError &e) { + LogError("DBCrypto transaction failed with message " << e.GetMessage()); + retCode = CKM_API_ERROR_DB_ERROR; + } } auto response = MessageBuffer::Serialize(static_cast(LogicCommand::SAVE), @@ -344,6 +353,89 @@ RawBuffer CKMLogic::saveData( return response.Pop(); } +int CKMLogic::extractPKCS12Data( + CryptoLogic &crypto, + const Name &name, + const Label &ownerLabel, + const PKCS12Serializable &pkcs, + const PolicySerializable &keyPolicy, + const PolicySerializable &certPolicy, + DBRowVector &output) const +{ + // private key is mandatory + if( !pkcs.getKey() ) + return CKM_API_ERROR_INVALID_FORMAT; + Key* keyPtr = pkcs.getKey().get(); + DBDataType keyType = DBDataType(keyPtr->getType()); + RawBuffer keyData = keyPtr->getDER(); + int retCode = verifyBinaryData(keyType, keyData); + if(retCode != CKM_API_SUCCESS) + return retCode; + output.push_back(createEncryptedDBRow(crypto, name, ownerLabel, keyType, keyData, keyPolicy)); + + // certificate is mandatory + if( !pkcs.getCertificate() ) + return CKM_API_ERROR_INVALID_FORMAT; + RawBuffer certData = pkcs.getCertificate().get()->getDER(); + retCode = verifyBinaryData(DBDataType::CERTIFICATE, certData); + if(retCode != CKM_API_SUCCESS) + return retCode; + output.push_back(createEncryptedDBRow(crypto, name, ownerLabel, DBDataType::CERTIFICATE, certData, certPolicy)); + + // CA cert chain + unsigned int cert_index = 0; + for(const auto & ca : pkcs.getCaCertificateShPtrVector()) + { + DBDataType chainDataType = DBDataType::getChainDatatype(cert_index ++); + RawBuffer caCertData = ca->getDER(); + int retCode = verifyBinaryData(chainDataType, caCertData); + if(retCode != CKM_API_SUCCESS) + return retCode; + + output.push_back(createEncryptedDBRow(crypto, name, ownerLabel, chainDataType, caCertData, certPolicy)); + } + + return CKM_API_SUCCESS; +} + +RawBuffer CKMLogic::savePKCS12( + const Credentials &cred, + int commandId, + const Name &name, + const Label &label, + const PKCS12Serializable &pkcs, + const PolicySerializable &keyPolicy, + const PolicySerializable &certPolicy) +{ + int retCode; + if (0 == m_userDataMap.count(cred.uid)) + retCode = CKM_API_ERROR_DB_LOCKED; + else + { + 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 CryptoLogic::Exception::Base &e) { + LogError("CryptoLogic failed with message: " << e.GetMessage()); + retCode = CKM_API_ERROR_SERVER_ERROR; + } catch (const DBCrypto::Exception::InternalError &e) { + LogError("DBCrypto failed with message: " << e.GetMessage()); + retCode = CKM_API_ERROR_DB_ERROR; + } catch (const DBCrypto::Exception::TransactionError &e) { + LogError("DBCrypto transaction failed with message " << e.GetMessage()); + retCode = CKM_API_ERROR_DB_ERROR; + } + } + + auto response = MessageBuffer::Serialize(static_cast(LogicCommand::SAVE_PKCS12), + commandId, + retCode); + return response.Pop(); +} + + int CKMLogic::removeDataHelper( const Credentials &cred, const Name &name, @@ -405,11 +497,11 @@ RawBuffer CKMLogic::removeData( return response.Pop(); } -int CKMLogic::readDataRowHelper(const Name &name, - const Label &ownerLabel, - DBDataType dataType, - DBCrypto & database, - DBRow &row) +int CKMLogic::readSingleRow(const Name &name, + const Label &ownerLabel, + DBDataType dataType, + DBCrypto & database, + DBRow &row) { DBCrypto::DBRowOptional row_optional; if (dataType.isKey()) @@ -436,6 +528,48 @@ int CKMLogic::readDataRowHelper(const Name &name, return CKM_API_SUCCESS; } + +int CKMLogic::readMultiRow(const Name &name, + const Label &ownerLabel, + DBDataType dataType, + DBCrypto & database, + DBRowVector &output) +{ + if (dataType.isKey()) + { + // read all key types + database.getDBRows(name, + ownerLabel, + DBDataType::DB_KEY_FIRST, + DBDataType::DB_KEY_LAST, + output); + } + else if (dataType.isChainCert()) + { + // read all key types + database.getDBRows(name, + ownerLabel, + DBDataType::DB_CHAIN_FIRST, + DBDataType::DB_CHAIN_LAST, + output); + } + else + { + // read anything else + database.getDBRows(name, + ownerLabel, + dataType, + output); + } + + if(!output.size()) { + LogError("No row for given name, label and type"); + return CKM_API_ERROR_DB_ALIAS_UNKNOWN; + } + + return CKM_API_SUCCESS; +} + int CKMLogic::checkDataPermissionsHelper(const Name &name, const Label &ownerLabel, const Label &accessorLabel, @@ -451,6 +585,58 @@ int CKMLogic::checkDataPermissionsHelper(const Name &name, return m_accessControl.canRead(row, PermissionForLabel(accessorLabel, permissionRowOpt)); } +int CKMLogic::readDataHelper( + bool exportFlag, + const Credentials &cred, + DBDataType dataType, + const Name &name, + const Label &label, + const Password &password, + DBRowVector &rows) +{ + if (0 == m_userDataMap.count(cred.uid)) + return CKM_API_ERROR_DB_LOCKED; + + // use client label if not explicitly provided + const Label &ownerLabel = label.empty() ? cred.smackLabel : label; + + if (!isNameValid(name) || !isLabelValid(ownerLabel)) + return CKM_API_ERROR_INPUT_PARAM; + + auto &handler = m_userDataMap[cred.uid]; + + // read rows + DBCrypto::Transaction transaction(&handler.database); + int ec = readMultiRow(name, ownerLabel, dataType, handler.database, rows); + if(CKM_API_SUCCESS != ec) + return ec; + + // all read rows belong to the same owner + DBRow & firstRow = rows.at(0); + + // check access rights + ec = checkDataPermissionsHelper(name, ownerLabel, cred.smackLabel, firstRow, exportFlag, handler.database); + if(CKM_API_SUCCESS != ec) + return ec; + + // decrypt row + if (!handler.crypto.haveKey(firstRow.ownerLabel)) { + RawBuffer key; + auto key_optional = handler.database.getKey(firstRow.ownerLabel); + if(!key_optional) { + LogError("No key for given label in database"); + return CKM_API_ERROR_DB_ERROR; + } + key = *key_optional; + key = handler.keyProvider.getPureDEK(key); + handler.crypto.pushKey(firstRow.ownerLabel, key); + } + for(auto &row : rows) + handler.crypto.decryptRow(password, row); + + return CKM_API_SUCCESS; +} + int CKMLogic::readDataHelper( bool exportFlag, const Credentials &cred, @@ -473,7 +659,7 @@ int CKMLogic::readDataHelper( // read row DBCrypto::Transaction transaction(&handler.database); - int ec = readDataRowHelper(name, ownerLabel, dataType, handler.database, row); + int ec = readSingleRow(name, ownerLabel, dataType, handler.database, row); if(CKM_API_SUCCESS != ec) return ec; @@ -537,6 +723,83 @@ RawBuffer CKMLogic::getData( return response.Pop(); } +int CKMLogic::getPKCS12Helper( + const Credentials &cred, + const Name &name, + const Label &label, + KeyShPtr & privKey, + CertificateShPtr & cert, + CertificateShPtrVector & caChain) +{ + int retCode; + + // read private key (mandatory) + DBRow privKeyRow; + retCode = readDataHelper(true, cred, DBDataType::DB_KEY_FIRST, name, label, CKM::Password(), privKeyRow); + if(retCode != CKM_API_SUCCESS) + return retCode; + privKey = CKM::Key::create(privKeyRow.data); + + // read certificate (mandatory) + DBRow certRow; + retCode = readDataHelper(true, cred, DBDataType::CERTIFICATE, name, label, CKM::Password(), certRow); + if(retCode != CKM_API_SUCCESS) + return retCode; + cert = CKM::Certificate::create(certRow.data, DataFormat::FORM_DER); + + // read CA cert chain (optional) + DBRowVector rawCaChain; + retCode = readDataHelper(true, cred, DBDataType::DB_CHAIN_FIRST, name, label, CKM::Password(), rawCaChain); + if(retCode != CKM_API_SUCCESS && + retCode != CKM_API_ERROR_DB_ALIAS_UNKNOWN) + return retCode; + for(auto &rawCaCert : rawCaChain) + caChain.push_back(CKM::Certificate::create(rawCaCert.data, DataFormat::FORM_DER)); + + // if anything found, return it + if(privKey || cert || caChain.size()>0) + retCode = CKM_API_SUCCESS; + + return retCode; +} + +RawBuffer CKMLogic::getPKCS12( + const Credentials &cred, + int commandId, + const Name &name, + const Label &label) +{ + int retCode; + PKCS12Serializable output; + + try { + KeyShPtr privKey; + CertificateShPtr cert; + CertificateShPtrVector caChain; + retCode = getPKCS12Helper(cred, name, label, privKey, cert, caChain); + + // 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 CryptoLogic::Exception::Base &e) { + LogError("CryptoLogic failed with message: " << e.GetMessage()); + retCode = CKM_API_ERROR_SERVER_ERROR; + } catch (const DBCrypto::Exception::Base &e) { + LogError("DBCrypto failed with message: " << e.GetMessage()); + retCode = CKM_API_ERROR_DB_ERROR; + } + + auto response = MessageBuffer::Serialize(static_cast(LogicCommand::GET_PKCS12), + commandId, + retCode, + output); + return response.Pop(); +} + RawBuffer CKMLogic::getDataList( const Credentials &cred, int commandId, @@ -578,6 +841,65 @@ RawBuffer CKMLogic::getDataList( return response.Pop(); } +int CKMLogic::saveDataHelper( + const Credentials &cred, + const Name &name, + const Label &label, + DBDataType dataType, + const RawBuffer &data, + const PolicySerializable &policy) +{ + auto &handler = m_userDataMap[cred.uid]; + + // use client label if not explicitly provided + const Label &ownerLabel = label.empty() ? cred.smackLabel : label; + + // check if save is possible + DBCrypto::Transaction transaction(&handler.database); + int retCode = checkSaveConditions(cred, handler, name, ownerLabel); + if(retCode != CKM_API_SUCCESS) + return retCode; + + // save the data + DBRow encryptedRow = createEncryptedDBRow(handler.crypto, name, ownerLabel, dataType, data, policy); + handler.database.saveDBRow(encryptedRow); + + transaction.commit(); + return CKM_API_SUCCESS; +} + +int CKMLogic::saveDataHelper( + const Credentials &cred, + const Name &name, + const Label &label, + const PKCS12Serializable &pkcs, + const PolicySerializable &keyPolicy, + const PolicySerializable &certPolicy) +{ + auto &handler = m_userDataMap[cred.uid]; + + // use client label if not explicitly provided + const Label &ownerLabel = label.empty() ? cred.smackLabel : label; + + // check if save is possible + DBCrypto::Transaction transaction(&handler.database); + int retCode = checkSaveConditions(cred, handler, name, ownerLabel); + if(retCode != CKM_API_SUCCESS) + return retCode; + + // extract and encrypt the data + DBRowVector encryptedRows; + retCode = extractPKCS12Data(handler.crypto, name, ownerLabel, pkcs, keyPolicy, certPolicy, encryptedRows); + if(retCode != CKM_API_SUCCESS) + return retCode; + + // save the data + handler.database.saveDBRows(name, ownerLabel, encryptedRows); + transaction.commit(); + + return CKM_API_SUCCESS; +} + int CKMLogic::createKeyPairHelper( const Credentials &cred, @@ -624,23 +946,22 @@ int CKMLogic::createKeyPairHelper( auto &database = m_userDataMap[cred.uid].database; DBCrypto::Transaction transaction(&database); - retCode = saveDataHelper(cred, - DBDataType(prv.getType()), - namePrivate, - labelPrivate, - prv.getDER(), - policyPrivate); + retCode = saveDataHelper(cred, + namePrivate, + labelPrivate, + DBDataType(prv.getType()), + prv.getDER(), + policyPrivate); if (CKM_API_SUCCESS != retCode) return retCode; retCode = saveDataHelper(cred, - DBDataType(pub.getType()), - namePublic, - labelPublic, - pub.getDER(), - policyPublic); - + namePublic, + labelPublic, + DBDataType(pub.getType()), + pub.getDER(), + policyPublic); if (CKM_API_SUCCESS != retCode) return retCode; @@ -754,8 +1075,16 @@ int CKMLogic::getCertificateChainHelper( int ec = readDataHelper(false, cred, DBDataType::CERTIFICATE, i.second, i.first, Password(), row); if (ec != CKM_API_SUCCESS) return ec; - untrustedCertVector.push_back(CertificateImpl(row.data, DataFormat::FORM_DER)); + + // try to read chain certificates (if present) + DBRowVector rawCaChain; + ec = readDataHelper(false, cred, DBDataType::DB_CHAIN_FIRST, i.second, i.first, CKM::Password(), rawCaChain); + if(ec != CKM_API_SUCCESS && + ec != CKM_API_ERROR_DB_ALIAS_UNKNOWN) + return ec; + for(auto &rawCaCert : rawCaChain) + untrustedCertVector.push_back(CertificateImpl(rawCaCert.data, DataFormat::FORM_DER)); } int ec = m_certStore.verifyCertificate(cert, untrustedCertVector, chainVector); @@ -862,16 +1191,18 @@ RawBuffer CKMLogic::verifySignature( DBRow row; KeyImpl key; - retCode = readDataHelper(false, cred, DBDataType::DB_KEY_FIRST, publicKeyOrCertName, ownerLabel, password, row); - + // try certificate first - looking for a public key. + // in case of PKCS, pub key from certificate will be found first + // rather than private key from the same PKCS. + retCode = readDataHelper(false, cred, DBDataType::CERTIFICATE, publicKeyOrCertName, ownerLabel, password, row); if (retCode == CKM_API_SUCCESS) { - key = KeyImpl(row.data); + CertificateImpl cert(row.data, DataFormat::FORM_DER); + key = cert.getKeyImpl(); } else if (retCode == CKM_API_ERROR_DB_ALIAS_UNKNOWN) { - retCode = readDataHelper(false, cred, DBDataType::CERTIFICATE, publicKeyOrCertName, ownerLabel, password, row); + retCode = readDataHelper(false, cred, DBDataType::DB_KEY_FIRST, publicKeyOrCertName, ownerLabel, password, row); if (retCode != CKM_API_SUCCESS) break; - CertificateImpl cert(row.data, DataFormat::FORM_DER); - key = cert.getKeyImpl(); + key = KeyImpl(row.data); } else { break; } diff --git a/src/manager/service/ckm-logic.h b/src/manager/service/ckm-logic.h index 0cbbb2b0..853be0eb 100644 --- a/src/manager/service/ckm-logic.h +++ b/src/manager/service/ckm-logic.h @@ -45,13 +45,6 @@ struct UserData { class CKMLogic { public: - class Exception - { - public: - DECLARE_EXCEPTION_TYPE(CKM::Exception, Base) - DECLARE_EXCEPTION_TYPE(Base, InputDataInvalid); - }; - CKMLogic(); CKMLogic(const CKMLogic &) = delete; CKMLogic(CKMLogic &&) = delete; @@ -80,12 +73,21 @@ public: RawBuffer saveData( const Credentials &cred, int commandId, - DBDataType dataType, const Name &name, const Label &label, - const RawBuffer &key, + const RawBuffer &data, + DBDataType dataType, const PolicySerializable &policy); + RawBuffer savePKCS12( + const Credentials &cred, + int commandId, + const Name &name, + const Label &label, + const PKCS12Serializable &pkcs, + const PolicySerializable &keyPolicy, + const PolicySerializable &certPolicy); + RawBuffer removeData( const Credentials &cred, int commandId, @@ -100,6 +102,12 @@ public: const Label &label, const Password &password); + RawBuffer getPKCS12( + const Credentials &cred, + int commandId, + const Name &name, + const Label &label); + RawBuffer getDataList( const Credentials &cred, int commandId, @@ -163,30 +171,75 @@ public: private: - void verifyBinaryData( + int verifyBinaryData( DBDataType dataType, const RawBuffer &input_data) const; + int checkSaveConditions( + const Credentials &cred, + UserData &handler, + const Name &name, + const Label &label); + int saveDataHelper( const Credentials &cred, - DBDataType dataType, const Name &name, const Label &label, - const RawBuffer &key, + DBDataType dataType, + const RawBuffer &data, const PolicySerializable &policy); + int saveDataHelper( + const Credentials &cred, + const Name &name, + const Label &label, + const PKCS12Serializable &pkcs, + const PolicySerializable &keyPolicy, + const PolicySerializable &certPolicy); + + DBRow createEncryptedDBRow( + CryptoLogic &crypto, + const Name &name, + const Label &label, + DBDataType dataType, + const RawBuffer &data, + const Policy &policy) const; + + int getPKCS12Helper( + const Credentials &cred, + const Name &name, + const Label &label, + KeyShPtr & privKey, + CertificateShPtr & cert, + CertificateShPtrVector & caChain); + + int extractPKCS12Data( + CryptoLogic &crypto, + const Name &name, + const Label &ownerLabel, + const PKCS12Serializable &pkcs, + const PolicySerializable &keyPolicy, + const PolicySerializable &certPolicy, + DBRowVector &output) const; + int removeDataHelper( const Credentials &cred, const Name &name, const Label &ownerLabel); - int readDataRowHelper( + int readSingleRow( const Name &name, const Label &ownerLabel, DBDataType dataType, DBCrypto & database, DBRow &row); + int readMultiRow(const Name &name, + const Label &ownerLabel, + DBDataType dataType, + DBCrypto & database, + DBRowVector &output); + int checkDataPermissionsHelper( const Name &name, const Label &ownerLabel, @@ -204,6 +257,15 @@ private: const Password &password, DBRow &row); + int readDataHelper( + bool exportFlag, + const Credentials &cred, + DBDataType dataType, + const Name &name, + const Label &label, + const Password &password, + DBRowVector &rows); + int createKeyPairHelper( const Credentials &cred, const KeyType key_type, @@ -228,6 +290,7 @@ private: const Label &accessorLabel, const Permission newPermission); + std::map m_userDataMap; CertificateStore m_certStore; AccessControl m_accessControl; diff --git a/src/manager/service/ckm-service.cpp b/src/manager/service/ckm-service.cpp index 61ffa436..722f6ab0 100644 --- a/src/manager/service/ckm-service.cpp +++ b/src/manager/service/ckm-service.cpp @@ -197,12 +197,27 @@ RawBuffer CKMService::processStorage(Credentials &cred, MessageBuffer &buffer) return m_logic->saveData( cred, msgID, - DBDataType(tmpDataType), name, label, rawData, + DBDataType(tmpDataType), policy); } + case LogicCommand::SAVE_PKCS12: + { + RawBuffer rawData; + PKCS12Serializable pkcs; + PolicySerializable keyPolicy, certPolicy; + buffer.Deserialize(name, label, pkcs, keyPolicy, certPolicy); + return m_logic->savePKCS12( + cred, + msgID, + name, + label, + pkcs, + keyPolicy, + certPolicy); + } case LogicCommand::REMOVE: { buffer.Deserialize(name, label); @@ -224,6 +239,15 @@ RawBuffer CKMService::processStorage(Credentials &cred, MessageBuffer &buffer) label, password); } + case LogicCommand::GET_PKCS12: + { + buffer.Deserialize(name, label); + return m_logic->getPKCS12( + cred, + msgID, + name, + label); + } case LogicCommand::GET_LIST: { buffer.Deserialize(tmpDataType); diff --git a/src/manager/service/db-crypto.cpp b/src/manager/service/db-crypto.cpp index f465add8..a98ab790 100644 --- a/src/manager/service/db-crypto.cpp +++ b/src/manager/service/db-crypto.cpp @@ -236,7 +236,26 @@ using namespace DB; "Couldn't check if name and label pair is present"); } - void DBCrypto::saveDBRow(const DBRow &row){ + void DBCrypto::saveDBRows(const Name &name, const Label &owner, const DBRowVector &rows) + { + Try { + // transaction is present in the layer above + NameTable nameTable(this->m_connection); + ObjectTable objectTable(this->m_connection); + nameTable.addRow(name, owner); + for (const auto &i: rows) + objectTable.addRow(i); + return; + } Catch(SqlConnection::Exception::SyntaxError) { + LogError("Couldn't prepare insert statement"); + } Catch(SqlConnection::Exception::InternalError) { + LogError("Couldn't execute insert statement: " << _rethrown_exception.GetMessage()); + } + ThrowMsg(DBCrypto::Exception::InternalError, + "Couldn't save DBRow"); + } + + void DBCrypto::saveDBRow(const DBRow &row) { Try { // transaction is present in the layer above NameTable nameTable(this->m_connection); @@ -359,6 +378,52 @@ using namespace DB; " name " << name << " with owner label " << ownerLabel); } + void DBCrypto::getDBRows( + const Name &name, + const Label &ownerLabel, + DBDataType type, + DBRowVector &output) + { + getDBRows(name, ownerLabel, type, type, output); + } + + void DBCrypto::getDBRows( + const Name &name, + const Label &ownerLabel, + DBDataType typeRangeStart, + DBDataType typeRangeStop, + DBRowVector &output) + { + Try { + SqlConnection::DataCommandUniquePtr selectCommand = + m_connection->PrepareDataCommand(DB_CMD_OBJECT_SELECT_BY_NAME_AND_LABEL); + selectCommand->BindInteger(1, typeRangeStart); + selectCommand->BindInteger(2, typeRangeStop); + + // name table reference + selectCommand->BindString (101, name.c_str()); + selectCommand->BindString (102, ownerLabel.c_str()); + + while(selectCommand->Step()) + { + // extract data + output.push_back(getRow(name, ownerLabel, selectCommand)); + } + return; + } Catch (SqlConnection::Exception::InvalidColumn) { + LogError("Select statement invalid column error"); + } Catch (SqlConnection::Exception::SyntaxError) { + LogError("Couldn't prepare select statement"); + } Catch (SqlConnection::Exception::InternalError) { + LogError("Couldn't execute select statement"); + } + ThrowMsg(DBCrypto::Exception::InternalError, + "Couldn't get row of type <" << + static_cast(typeRangeStart) << "," << + static_cast(typeRangeStop) << ">" << + " name " << name << " with owner label " << ownerLabel); + } + void DBCrypto::listNames( const Label &smackLabel, LabelNameVector& labelNameVector, diff --git a/src/manager/service/db-crypto.h b/src/manager/service/db-crypto.h index 8d5d92c7..4e710c03 100644 --- a/src/manager/service/db-crypto.h +++ b/src/manager/service/db-crypto.h @@ -66,6 +66,11 @@ namespace CKM { void saveDBRow( const DBRow &row); + void saveDBRows( + const Name &name, + const Label &owner, + const DBRowVector &rows); + bool isNameLabelPresent( const Name &name, const Label &owner) const; @@ -81,6 +86,19 @@ namespace CKM { DBDataType typeRangeStart, DBDataType typeRangeStop); + void getDBRows( + const Name &name, + const Label &ownerLabel, + DBDataType type, + DBRowVector &output); + + void getDBRows( + const Name &name, + const Label &ownerLabel, + DBDataType typeRangeStart, + DBDataType typeRangeStop, + DBRowVector &output); + void listNames( const Label &smackLabel, LabelNameVector& labelNameVector, diff --git a/src/manager/service/db-row.h b/src/manager/service/db-row.h index 6f3189b7..f1cb5ec2 100644 --- a/src/manager/service/db-row.h +++ b/src/manager/service/db-row.h @@ -21,6 +21,7 @@ */ #pragma once +#include #include #include @@ -37,5 +38,6 @@ namespace CKM { RawBuffer data; RawBuffer tag; // tag for Aes Gcm algorithm }; + typedef std::vector DBRowVector; } // namespace CKM -- cgit v1.2.3