Add PKCS12 support.
authorMaciej J. Karpiuk <m.karpiuk2@samsung.com>
Fri, 14 Nov 2014 15:08:25 +0000 (16:08 +0100)
committerMaciej J. Karpiuk <m.karpiuk2@samsung.com>
Tue, 17 Feb 2015 10:20:49 +0000 (11:20 +0100)
Change-Id: I389c56611fed80cf27bbbfa279b1c17e55572b14

25 files changed:
src/include/ckm/ckm-manager-async.h
src/include/ckm/ckm-manager.h
src/include/ckmc/ckmc-manager.h
src/include/ckmc/ckmc-type.h
src/manager/client-async/client-manager-async-impl.cpp
src/manager/client-async/client-manager-async-impl.h
src/manager/client-async/client-manager-async.cpp
src/manager/client-async/storage-receiver.cpp
src/manager/client-async/storage-receiver.h
src/manager/client-capi/ckmc-manager.cpp
src/manager/client-capi/ckmc-type.cpp
src/manager/client/client-manager-impl.cpp
src/manager/client/client-manager-impl.h
src/manager/common/certificate-impl.cpp
src/manager/common/certificate-impl.h
src/manager/common/pkcs12-impl.cpp
src/manager/common/pkcs12-impl.h
src/manager/common/protocols.cpp
src/manager/common/protocols.h
src/manager/service/ckm-logic.cpp
src/manager/service/ckm-logic.h
src/manager/service/ckm-service.cpp
src/manager/service/db-crypto.cpp
src/manager/service/db-crypto.h
src/manager/service/db-row.h

index 48bca05..1f0c764 100644 (file)
@@ -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);
index 53363d8..d782169 100644 (file)
@@ -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;
index 3d08fb3..d2be99b 100644 (file)
@@ -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.
index 0a85f45..b441824 100644 (file)
@@ -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.
index 30aa462..d03776a 100644 (file)
@@ -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,
index b3aea30..e069704 100644 (file)
@@ -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);
index 75c7684..9ecaf33 100644 (file)
@@ -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);
index cb9560c..857bb7e 100644 (file)
@@ -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;
index 0560892..c838b3d 100644 (file)
@@ -41,8 +41,10 @@ public:
 
 private:
     void parseGetCommand();
+    void parseGetPKCS12Command();
     void parseGetListCommand();
     void parseSaveCommand();
+    void parseSavePKCS12Command();
     void parseRemoveCommand();
     void parseGetChainCertCommand();
     void parseCreateSignatureCommand();
index 4a8cf82..0382d35 100644 (file)
@@ -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) {
index 1511443..cca4458 100644 (file)
@@ -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
index 2897171..7af969f 100644 (file)
@@ -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);
index d584185..a03113e 100644 (file)
@@ -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(
index 316085d..0577958 100644 (file)
@@ -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) {
index 679de86..48ae5b7 100644 (file)
@@ -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 &);
index e8c08c5..d9804d0 100644 (file)
@@ -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;
 }
index b1d1c8f..6980f5c 100644 (file)
@@ -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;
index 67cb36c..6e80011 100644 (file)
@@ -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
 
index 7487cbe..1a2bf67 100644 (file)
@@ -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
 
index 0029bf0..649815b 100644 (file)
@@ -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;
             }
index 0cbbb2b..853be0e 100644 (file)
@@ -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;
index 61ffa43..722f6ab 100644 (file)
@@ -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);
index f465add..a98ab79 100644 (file)
@@ -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,
index 8d5d92c..4e710c0 100644 (file)
@@ -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,
index 6f3189b..f1cb5ec 100644 (file)
@@ -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