summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMaciej J. Karpiuk <m.karpiuk2@samsung.com>2014-11-14 16:08:25 +0100
committerMaciej J. Karpiuk <m.karpiuk2@samsung.com>2015-02-17 11:20:49 +0100
commitd22ce2b55451a8164775c5945eb158e507a25a4d (patch)
tree89bd9a5639fedea36d5bf9349a62c86c50c9b0dd /src
parentef145d51e7761b2b093300cf2b9e4dde7487abb4 (diff)
downloadkey-manager-d22ce2b55451a8164775c5945eb158e507a25a4d.tar.gz
key-manager-d22ce2b55451a8164775c5945eb158e507a25a4d.tar.bz2
key-manager-d22ce2b55451a8164775c5945eb158e507a25a4d.zip
Add PKCS12 support.
Change-Id: I389c56611fed80cf27bbbfa279b1c17e55572b14
Diffstat (limited to 'src')
-rw-r--r--src/include/ckm/ckm-manager-async.h10
-rw-r--r--src/include/ckm/ckm-manager.h7
-rw-r--r--src/include/ckmc/ckmc-manager.h113
-rw-r--r--src/include/ckmc/ckmc-type.h84
-rw-r--r--src/manager/client-async/client-manager-async-impl.cpp38
-rw-r--r--src/manager/client-async/client-manager-async-impl.h10
-rw-r--r--src/manager/client-async/client-manager-async.cpp15
-rw-r--r--src/manager/client-async/storage-receiver.cpp37
-rw-r--r--src/manager/client-async/storage-receiver.h2
-rw-r--r--src/manager/client-capi/ckmc-manager.cpp133
-rw-r--r--src/manager/client-capi/ckmc-type.cpp76
-rw-r--r--src/manager/client/client-manager-impl.cpp129
-rw-r--r--src/manager/client/client-manager-impl.h8
-rw-r--r--src/manager/common/certificate-impl.cpp9
-rw-r--r--src/manager/common/certificate-impl.h2
-rw-r--r--src/manager/common/pkcs12-impl.cpp39
-rw-r--r--src/manager/common/pkcs12-impl.h13
-rw-r--r--src/manager/common/protocols.cpp73
-rw-r--r--src/manager/common/protocols.h56
-rw-r--r--src/manager/service/ckm-logic.cpp487
-rw-r--r--src/manager/service/ckm-logic.h89
-rw-r--r--src/manager/service/ckm-service.cpp26
-rw-r--r--src/manager/service/db-crypto.cpp67
-rw-r--r--src/manager/service/db-crypto.h18
-rw-r--r--src/manager/service/db-row.h2
25 files changed, 1386 insertions, 157 deletions
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 <ckm/ckm-error.h>
#include <ckm/ckm-key.h>
#include <ckm/ckm-type.h>
+#include <ckm/ckm-pkcs12.h>
// 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 <ckm/ckm-certificate.h>
#include <ckm/ckm-error.h>
#include <ckm/ckm-key.h>
+#include <ckm/ckm-pkcs12.h>
#include <ckm/ckm-type.h>
// 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
*
@@ -304,6 +304,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.
*
* @since_tizen 2.3
@@ -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
@@ -168,6 +168,17 @@ typedef struct __ckmc_cert_list {
} 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()
@@ -338,6 +380,44 @@ int ckmc_load_from_pkcs12_file(const char *file_path, const char *passphrase,
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.
* The alias pointer in the returned @a ckmc_alias_list_s handle points to the provided characters and next is null.
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<int>(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<int>(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<LogicCommand>(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<PKCS12Impl>(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<CKM::DataFormat>(static_cast<int>(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<CKM::DataFormat>(static_cast<int>(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<unsigned char *>(malloc(rawBuffer.size()));
@@ -286,6 +300,115 @@ int ckmc_get_cert_alias_list(ckmc_alias_list_s** alias_list) {
}
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<ckmc_cert_list_s *>(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<unsigned char*>(helper->getDER().data());
+ ckmc_key_type_e keyType = static_cast<ckmc_key_type_e>(static_cast<int>(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<unsigned char*>(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)
{
if(alias == NULL) {
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
@@ -189,6 +189,43 @@ int ckmc_load_cert_from_file(const char *file_path, ckmc_cert_s **cert)
}
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<ckmc_pkcs12_s*>(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)
{
class Pkcs12Converter {
@@ -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<int>(LogicCommand::SAVE),
- m_counter,
+ my_counter,
static_cast<int>(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<int>(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<int>(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<PKCS12Impl>(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<int>(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<int>(LogicCommand::GET),
- m_counter,
+ my_counter,
static_cast<int>(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<int>(LogicCommand::GET_LIST),
- m_counter,
+ my_counter,
static_cast<int>(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<int>(LogicCommand::GET_LIST)) || (counter != m_counter)) {
+ if ((command != static_cast<int>(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<int>(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<BIO, std::function<void(BIO*)>> 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<num_CA; i++)
+ {
+ RawBuffer CAcertData;
+ Deserialization::Deserialize(stream, CAcertData);
+ m_ca.push_back(CKM::Certificate::create(CAcertData, DataFormat::FORM_DER));
+ }
+}
+PKCS12Serializable::PKCS12Serializable(const KeyShPtr &privKey, const CertificateShPtr &cert, const CertificateShPtrVector &chainCerts)
+{
+ m_pkey = privKey;
+ m_cert = cert;
+ m_ca = chainCerts;
+}
+
+void PKCS12Serializable::Serialize(IStream &stream) const
+{
+ // key
+ Key *keyPtr = getKey().get();
+ bool isAnyKeyPresent = (getKey().get()!=NULL);
+
+ // logics if PKCS is correct or not is on the service side.
+ // sending number of keys and certificates to allow proper parsing on the service side.
+ // (what if no key or cert present? attempt to deserialize a not present key/cert would
+ // throw an error and close the connection).
+ Serialization::Serialize(stream, static_cast<size_t>(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<size_t>(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 <string>
#include <ckm/ckm-type.h>
+#include <pkcs12-impl.h>
#include <dpl/exception.h>
#include <dpl/serialization.h>
@@ -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<int>(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<int>(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<int>(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<int>(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<int>(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,
@@ -458,6 +592,58 @@ int CKMLogic::readDataHelper(
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,
+ DBDataType dataType,
+ const Name &name,
+ const Label &label,
+ const Password &password,
DBRow &row)
{
if (0 == m_userDataMap.count(cred.uid))
@@ -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<int>(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<uid_t, UserData> 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<int>(typeRangeStart) << "," <<
+ static_cast<int>(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 <vector>
#include <ckm/ckm-type.h>
#include <protocols.h>
@@ -37,5 +38,6 @@ namespace CKM {
RawBuffer data;
RawBuffer tag; // tag for Aes Gcm algorithm
};
+ typedef std::vector<DBRow> DBRowVector;
} // namespace CKM