Encryption/decryption API 96/39296/10
authorKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Wed, 1 Apr 2015 09:45:48 +0000 (11:45 +0200)
committerKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Mon, 8 Jun 2015 09:06:22 +0000 (02:06 -0700)
[Issue#] N/A
[Feature] Encryption decryption support
[Problem] N/A
[Cause] N/A
[Solution] API for encryption decryption

[Verification] Succesfull compilation. Run tests
ckm-tests --group=ALGO_PARAMS (all pass)
ckm-tests --group=ENCRYPTION_DECRYPTION (all fail with CKMC_ERROR_UNKNOWN)

Change-Id: I6cbb1fb56ad1d82f8d673ed27d22eade82e4e1d0

src/include/ckmc/ckmc-manager.h
src/include/ckmc/ckmc-type.h
src/manager/client-capi/ckmc-manager.cpp
src/manager/client-capi/ckmc-type.cpp

index ed4113d..7210026 100644 (file)
@@ -1134,6 +1134,82 @@ int ckmc_deny_access(const char *alias, const char *accessor);
  */
 int ckmc_remove_alias(const char *alias);
 
+/**
+ * @brief Encrypts data using selected key and algorithm
+ *
+ * @since_tizen 3.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/keymanager
+ *
+ * @remarks Key identified by @a key_alias should exist
+ *
+ * @param[in] params            Algorithm parameters
+ * @param[in] key_alias         Alias of the key to be used for encryption
+ * @param[in] password          The password used in decrypting a key value. If password of policy
+ *                              is provided in ckmc_save_key(), the same password should be provided
+ * @param[in] decrypted         Data to be encrypted
+ * @param[out] ppencrypted      Encrypted data (some algorithms may return additional information
+ *                              embedded in encrypted data. AES GCM is an example). The caller is
+ *                              responsible for freeing ppencrypted with ckmc_buffer_free().
+ *
+ * @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 the error with unknown reason
+ * @retval #CKMC_ERROR_DB_ALIAS_UNKNOWN     Key with given alias does not exist
+ * @retval #CKMC_ERROR_PERMISSION_DENIED    Failed to access key manager
+ * @retval #CKMC_ERROR_AUTHENTICATION_FAILED
+ *                                          Key decryption failed because password is incorrect.
+ *
+ * @pre User is already logged in and the user key is already loaded into memory in plain text form.
+ */
+int ckmc_encrypt_data(const ckmc_param_list_s *params,
+                      const char *key_alias,
+                      const char *password,
+                      const ckmc_raw_buffer_s decrypted,
+                      ckmc_raw_buffer_s **ppencrypted);
+
+/**
+ * @brief Decrypts data using selected key and algorithm
+ *
+ * @since_tizen 3.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/keymanager
+ *
+ * @remarks Key identified by @a key_alias should exist
+ *
+ * @param[in] params            Algorithm parameters
+ * @param[in] key_alias         Alias of the key to be used for encryption
+ * @param[in] password          The password used in decrypting a key value. If password of policy
+ *                              is provided in ckmc_save_key(), the same password should be provided
+ * @param[in] encrypted         Data to be decrypted (some algorithms may require additional
+ *                              information embedded in encrypted data. AES GCM is an example).
+ * @param[out] ppdecrypted      Decrypted data. The caller is responsible for freeing ppdecrypted
+ *                              with ckmc_buffer_free().
+ *
+ * @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 the error with unknown reason
+ * @retval #CKMC_ERROR_DB_ALIAS_UNKNOWN     Key with given alias does not exist
+ * @retval #CKMC_ERROR_PERMISSION_DENIED    Failed to access key manager
+ * @retval #CKMC_ERROR_AUTHENTICATION_FAILED
+ *                                          Key decryption failed because password is incorrect.
+ *
+ * @pre User is already logged in and the user key is already loaded into memory in plain text form.
+ */
+int ckmc_decrypt_data(const ckmc_param_list_s *params,
+                      const char *key_alias,
+                      const char *password,
+                      const ckmc_raw_buffer_s encrypted,
+                      ckmc_raw_buffer_s **ppdecrypted);
+
 #ifdef __cplusplus
 }
 #endif
index fbb30ab..9a9669f 100644 (file)
@@ -23,6 +23,7 @@
 #define __TIZEN_CORE_CKMC_TYPE_H
 
 #include <stddef.h>
+#include <stdint.h>
 #include <ckmc/ckmc-error.h>
 
 #define KEY_MANAGER_CAPI __attribute__((visibility("default")))
@@ -218,6 +219,99 @@ typedef struct __ckmc_pkcs12 {
     ckmc_cert_list_s *ca_chain; /**< chain certificates list, may be null */
 } ckmc_pkcs12_s;
 
+/**
+ * @brief Enumeration for crypto algorithm parameters.
+ * @since_tizen 3.0
+ */
+typedef enum __ckmc_param_name {
+    CKMC_PARAM_ALGO_TYPE = 1,
+
+    // encryption & decryption
+    CKMC_PARAM_ED_IV = 101,         /**< 16B buffer (up to 2^64-1 bytes long in case of AES GCM) */
+    CKMC_PARAM_ED_CTR_LEN,          /**< integer */
+    CKMC_PARAM_ED_AAD,              /**< buffer */
+    CKMC_PARAM_ED_TAG_LEN,          /**< integer */
+    CKMC_PARAM_ED_LABEL,            /**< buffer */
+
+    // key generation
+    CKMC_PARAM_GEN_KEY_LEN = 201,   /**< integer */
+    CKMC_PARAM_GEN_EC,              /**< integer - elliptic curve (ckmc_ec_type_e) */
+
+    // sign & verify
+    CKMC_PARAM_SV_HASH_ALGO = 301,  /**< integer - hash algorithm (ckmc_hash_algo_e) */
+    CKMC_PARAM_SV_RSA_PADDING,      /**< integer - RSA padding (ckmc_rsa_padding_algo_e) */
+}ckmc_param_name_e;
+
+/**
+ * @brief Structure for algorithm parameter list.
+ * @since_tizen 3.0
+ */
+struct ckmc_param_list_s;
+
+/**
+ * @brief Enumeration for crypto algorithm types.
+ * @since_tizen 3.0
+ */
+typedef enum __ckmc_algo_type {
+    CKMC_ALGO_AES_CTR = 1,   /**< AES-CTR algorithm
+                                  Supported parameters:
+                                  - CKMC_PARAM_ALGO_TYPE,
+                                  - CKMC_PARAM_ED_IV
+                                  - CKMC_PARAM_ED_CTR_LEN (128 only) */
+
+    CKMC_ALGO_AES_CBC,       /**< AES-CBC algorithm
+                                  Supported parameters:
+                                  - CKMC_PARAM_ALGO_TYPE,
+                                  - CKMC_PARAM_ED_IV */
+
+    CKMC_ALGO_AES_GCM,       /**< AES-GCM algorithm
+                                  Supported parameters:
+                                  - CKMC_PARAM_ALGO_TYPE,
+                                  - CKMC_PARAM_ED_IV
+                                  - CKMC_PARAM_ED_TAG_LEN
+                                  - CKMC_PARAM_ED_AAD */
+
+    CKMC_ALGO_AES_CFB,       /**< AES-CFB algorithm
+                                  Supported parameters:
+                                  - CKMC_PARAM_ALGO_TYPE,
+                                  - CKMC_PARAM_ED_IV */
+
+    CKMC_ALGO_RSA_OAEP,      /**< RSA-OAEP algorithm
+                                  Supported parameters:
+                                  - CKMC_PARAM_ALGO_TYPE,
+                                  - CKMC_PARAM_ED_LABEL */
+
+    CKMC_ALGO_RSA_SV,        /**< RSA algorithm used for signing/verification
+                                  Supported parameters:
+                                  - CKMC_PARAM_ALGO_TYPE,
+                                  - CKMC_PARAM_SV_HASH_ALGO
+                                  - CKMC_PARAM_SV_RSA_PADDING */
+
+    CKMC_ALGO_DSA_SV,        /**< DSA algorithm used for signing/verification
+                                  Supported parameters:
+                                  - CKMC_PARAM_ALGO_TYPE,
+                                  - CKMC_PARAM_SV_HASH_ALGO */
+
+    CKMC_ALGO_ECDSA_SV,      /**< ECDA algorithm used for signing/verification
+                                  Supported parameters:
+                                  - CKMC_PARAM_ALGO_TYPE,
+                                  - CKMC_PARAM_SV_HASH_ALGO */
+
+    CKMC_ALGO_RSA_GEN,       /**< RSA algorithm used for key generation
+                                  Supported parameters:
+                                  - CKMC_PARAM_ALGO_TYPE,
+                                  - CKMC_PARAM_GEN_KEY_LEN */
+
+    CKMC_ALGO_DSA_GEN,       /**< DSA algorithm used for key generation
+                                  Supported parameters:
+                                  - CKMC_PARAM_ALGO_TYPE,
+                                  - CKMC_PARAM_GEN_KEY_LEN */
+
+    CKMC_ALGO_ECDSA_GEN,     /**< ECDA algorithm used for key generation
+                                  Supported parameters:
+                                  - CKMC_PARAM_ALGO_TYPE,
+                                  - CKMC_PARAM_GEN_EC */
+} ckmc_algo_type_e;
 
 /**
  * @internal
@@ -643,6 +737,137 @@ void ckmc_cert_list_free(ckmc_cert_list_s *first);
 void ckmc_cert_list_all_free(ckmc_cert_list_s *first);
 
 /**
+ * @brief Creates new parameter list
+ *
+ * @since_tizen 3.0
+ *
+ * @remarks Caller is responsible for freeing it with ckmc_param_list_free
+ *
+ * @param[in] ppparam_list  Double pointer to the list variable to which the newly created list will
+ *                          be assigned. Last element of the list has param = NULL;
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ *
+ * @retval #CKMC_ERROR_NONE                 Successful
+ * @retval #CKMC_ERROR_INVALID_PARAMETER    Input parameter is invalid
+ *
+ * @see ckmc_param_list_add_integer
+ * @see ckmc_param_list_add_buffer
+ * @see ckmc_param_list_free
+ * @see ckmc_generate_params
+ * @see #ckmc_param_list_s
+ * @see #ckmc_param_name_e
+ */
+int ckmc_param_list_new(ckmc_param_list_s **ppparams);
+
+/**
+ * @brief Adds integer parameter to the list
+ *
+ * @since_tizen 3.0
+ *
+ * @remarks Caller is responsible for ckmc_param_list_s creation.
+ * @remarks Last element of the list has param = NULL;
+ *
+ * @param[in] previous  Any element of the param list.
+ * @param[in] name      Name of parameter to add. Each parameter name has an associated value type:
+ *                      integer or buffer. Passing a buffer parameter name will result in an error
+ * @param[in] value     Value of the parameter in form of a integer.
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ *
+ * @retval #CKMC_ERROR_NONE                 Successful
+ * @retval #CKMC_ERROR_INVALID_PARAMETER    Input parameter is invalid
+ *
+ * @see ckmc_param_list_new
+ * @see ckmc_param_list_add_buffer
+ * @see ckmc_param_list_free
+ * @see ckmc_generate_params
+ * @see #ckmc_param_list_s
+ * @see #ckmc_param_name_e
+ */
+int ckmc_param_list_add_integer(ckmc_param_list_s *params,
+                                ckmc_param_name_e name,
+                                uint64_t value);
+
+/**
+ * @brief Adds buffer parameter to the list
+ *
+ * @since_tizen 3.0
+ *
+ * @remarks Caller is responsible for ckmc_param_list_s creation.
+ * @remarks Last element of the list has param = NULL;
+ *
+ * @param[in] previous  Any element of the param list.
+ * @param[in] name      Name of parameter to add. Each parameter name has an associated value type:
+ *                      integer or buffer. Passing an integer parameter name will result in an error
+ * @param[in] buffer    Value of the parameter in form of a buffer. Caller is responsible for
+ *                      creating and freeing the buffer.
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ *
+ * @retval #CKMC_ERROR_NONE                 Successful
+ * @retval #CKMC_ERROR_INVALID_PARAMETER    Input parameter is invalid
+ *
+ * @see ckmc_param_list_new
+ * @see ckmc_param_list_add_integer
+ * @see ckmc_param_list_free
+ * @see ckmc_generate_params
+ * @see #ckmc_param_list_s
+ * @see #ckmc_param_name_e
+ */
+int ckmc_param_list_add_buffer(ckmc_param_list_s *params,
+                               ckmc_param_name_e name,
+                               const ckmc_raw_buffer_s *buffer);
+
+/**
+ * @brief Frees previously allocated list of algorithm params
+ *
+ * @since_tizen 3.0
+ *
+ * @param[in] first     First element of the list to be freed.
+ *
+ * @see ckmc_param_list_new
+ * @see ckmc_param_list_add_integer
+ * @see ckmc_param_list_add_buffer
+ * @see ckmc_generate_params
+ * @see #ckmc_param_list_s
+ * @see #ckmc_param_name_e
+ */
+void ckmc_param_list_free(ckmc_param_list_s *params);
+
+/**
+ * @brief Generates algorithm parameters for a given algorithm type and adds them to the list.
+ *
+ * @since_tizen 3.0
+ *
+ * @remarks Caller is responsible for ckmc_param_list_s creation and destruction.
+ * @remarks Algorithm parameters used for encryption could be then used for decryption but this
+ *          function should not be used for generating decryption parameters only.
+ * @remarks Algorithm parameters are set to default values. Optional fields are left empty.
+ *          Initialization vectors are randomly generated. Param list passed as ckmc_param_list_s
+ *          will be extended with new params. Caller is responsible for freeing the list
+ *          with ckmc_param_list_free.
+ * @remarks If the function returns error provided param list may contain some of default parameters
+ *
+ * @param[in] type      Type of the algorithm
+ * @param[out] params   List of params to be filled. List should be empty. Otherwise an error will
+ *                      be returned.
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ *
+ * @retval #CKMC_ERROR_NONE                 Successful
+ * @retval #CKMC_ERROR_INVALID_PARAMETER    Input parameter is invalid
+ *
+ * @see ckmc_param_list_new
+ * @see ckmc_param_list_add_integer
+ * @see ckmc_param_list_add_buffer
+ * @see ckmc_param_list_free
+ * @see #ckmc_param_list_s
+ * @see #ckmc_param_name_e
+ */
+int ckmc_generate_params(ckmc_algo_type_e type, ckmc_param_list_s *params);
+
+/**
  * @}
  */
 
index a5bebf4..7a4c8f1 100644 (file)
@@ -816,3 +816,25 @@ int ckmc_remove_alias(const char *alias)
     int ret =  mgr->removeAlias(alias);
     return to_ckmc_error(ret);
 }
+
+KEY_MANAGER_CAPI
+int ckmc_encrypt_data(const ckmc_param_list_s */*params*/,
+                      const char */*key_alias*/,
+                      const char */*password*/,
+                      const ckmc_raw_buffer_s /*decrypted*/,
+                      ckmc_raw_buffer_s **/*ppencrypted*/)
+{
+    // TODO implement it
+    return CKMC_ERROR_UNKNOWN;
+}
+
+KEY_MANAGER_CAPI
+int ckmc_decrypt_data(const ckmc_param_list_s */*params*/,
+                      const char */*key_alias*/,
+                      const char */*password*/,
+                      const ckmc_raw_buffer_s /* encrypted*/,
+                      ckmc_raw_buffer_s **/*ppdecrypted*/)
+{
+    // TODO implement it
+    return CKMC_ERROR_UNKNOWN;
+}
index 7048333..d665dc0 100644 (file)
 #include <openssl/pkcs12.h>
 #include <openssl/evp.h>
 #include <openssl/pem.h>
+#include <fstream>
 
+namespace {
 
-const char * const ckmc_label_name_separator    = CKM::LABEL_NAME_SEPARATOR;
-const char * const ckmc_label_shared_owner      = CKM::LABEL_SYSTEM_DB;
+const size_t DEFAULT_IV_LEN = 16;
+const size_t DEFAULT_IV_LEN_BITS = 8*DEFAULT_IV_LEN;
+const size_t DEFAULT_KEY_LEN_BITS = 4096;
+
+int _ckmc_random_buffer(ckmc_raw_buffer_s **buffer, size_t len)
+{
+    if(!buffer)
+        return CKMC_ERROR_INVALID_PARAMETER;
+
+    char* data = static_cast<char*>(malloc(len*sizeof(char)));
+    if(!data)
+        return CKMC_ERROR_OUT_OF_MEMORY;
+
+    std::ifstream is("/dev/urandom", std::ifstream::binary);
+    if(!is) {
+        free(data);
+        return CKMC_ERROR_FILE_SYSTEM;
+    }
+
+    is.read(data, len);
+    if (static_cast<std::streamsize>(len) != is.gcount()) {
+        free(data);
+        return CKMC_ERROR_FILE_SYSTEM;
+    }
+
+    return ckmc_buffer_new(reinterpret_cast<unsigned char*>(data), len, buffer);
+}
 
+int _ckmc_load_cert_from_x509(X509 *xCert, ckmc_cert_s **cert)
+{
+    if(xCert == NULL) {
+        return CKMC_ERROR_INVALID_FORMAT;
+    }
 
-int _ckmc_load_cert_from_x509(X509 *xCert, ckmc_cert_s **cert);
+    BIO *bcert = BIO_new(BIO_s_mem());
+
+    i2d_X509_bio(bcert, xCert);
+
+    CKM::RawBuffer output(8196);
+    int size = BIO_read(bcert, output.data(), output.size());
+    BIO_free_all(bcert);
+    if (size <= 0) {
+        return CKMC_ERROR_INVALID_FORMAT;
+    }
+    output.resize(size);
+
+    return ckmc_cert_new(output.data(), output.size(), CKMC_FORM_DER, cert);
+}
+
+} // namespace anonymous
+
+
+const char * const ckmc_label_name_separator    = CKM::LABEL_NAME_SEPARATOR;
+const char * const ckmc_label_shared_owner      = CKM::LABEL_SYSTEM_DB;
 
 KEY_MANAGER_CAPI
 int ckmc_key_new(unsigned char *raw_key, size_t key_size, ckmc_key_type_e key_type, char *password, ckmc_key_s **ppkey)
@@ -541,24 +592,94 @@ void ckmc_cert_list_all_free(ckmc_cert_list_s *first)
     }
 }
 
-int _ckmc_load_cert_from_x509(X509 *xCert, ckmc_cert_s **cert)
+KEY_MANAGER_CAPI
+int ckmc_param_list_new(ckmc_param_list_s **ppparams)
 {
-    if(xCert == NULL) {
-        return CKMC_ERROR_INVALID_FORMAT;
-    }
+    if (!ppparams)
+        return CKMC_ERROR_INVALID_PARAMETER;
 
-    BIO *bcert = BIO_new(BIO_s_mem());
+    *ppparams = reinterpret_cast<ckmc_param_list_s*>(new(std::nothrow)(CKM::CryptoAlgorithm));
+    if (!*ppparams)
+        return CKMC_ERROR_OUT_OF_MEMORY;
+    return CKMC_ERROR_NONE;
+}
 
-    i2d_X509_bio(bcert, xCert);
+KEY_MANAGER_CAPI
+int ckmc_param_list_add_integer(ckmc_param_list_s *params,
+                                ckmc_param_name_e name,
+                                uint64_t value)
+{
+    if (!params)
+        return CKMC_ERROR_INVALID_PARAMETER;
 
-    CKM::RawBuffer output(8196);
-    int size = BIO_read(bcert, output.data(), output.size());
-    BIO_free_all(bcert);
-    if (size <= 0) {
-        return CKMC_ERROR_INVALID_FORMAT;
-    }
-    output.resize(size);
+    CKM::CryptoAlgorithm* algo = reinterpret_cast<CKM::CryptoAlgorithm*>(params);
+    bool ret = algo->addParam(static_cast<CKM::ParamName>(name), value);
+    return (ret ? CKMC_ERROR_NONE : CKMC_ERROR_INVALID_PARAMETER);
+}
 
-    return ckmc_cert_new(output.data(), output.size(), CKMC_FORM_DER, cert);
+KEY_MANAGER_CAPI
+int ckmc_param_list_add_buffer(ckmc_param_list_s *params,
+                               ckmc_param_name_e name,
+                               const ckmc_raw_buffer_s *buffer)
+{
+    if (!params || !buffer || !buffer->data || buffer->size == 0)
+        return CKMC_ERROR_INVALID_PARAMETER;
+
+    CKM::CryptoAlgorithm* algo = reinterpret_cast<CKM::CryptoAlgorithm*>(params);
+    CKM::RawBuffer b(buffer->data, buffer->data + buffer->size);
+    bool ret =  algo->addParam(static_cast<CKM::ParamName>(name), b);
+    return (ret ? CKMC_ERROR_NONE : CKMC_ERROR_INVALID_PARAMETER);
 }
 
+KEY_MANAGER_CAPI
+void ckmc_param_list_free(ckmc_param_list_s *params)
+{
+    CKM::CryptoAlgorithm* algo = reinterpret_cast<CKM::CryptoAlgorithm*>(params);
+    delete algo;
+}
+
+KEY_MANAGER_CAPI
+int ckmc_generate_params(ckmc_algo_type_e type, ckmc_param_list_s *params)
+{
+    // return error if params are NULL
+    if(params == NULL)
+        return CKMC_ERROR_INVALID_PARAMETER;
+
+    ckmc_raw_buffer_s* buffer = NULL;
+    int ret = CKMC_ERROR_NONE;
+    switch(type)
+    {
+    case CKMC_ALGO_AES_CTR:
+        ret = ckmc_param_list_add_integer(params, CKMC_PARAM_ED_CTR_LEN, DEFAULT_IV_LEN_BITS);
+        // no break on purpose
+    case CKMC_ALGO_AES_CBC:
+    case CKMC_ALGO_AES_GCM:
+    case CKMC_ALGO_AES_CFB:
+        if (ret == CKMC_ERROR_NONE)
+            ret = _ckmc_random_buffer(&buffer, DEFAULT_IV_LEN);
+        if (ret == CKMC_ERROR_NONE)
+            ret = ckmc_param_list_add_buffer(params, CKMC_PARAM_ED_IV, buffer);
+        else
+            ckmc_buffer_free(buffer);
+        break;
+    case CKMC_ALGO_RSA_OAEP:
+        break;
+    case CKMC_ALGO_RSA_SV:
+    case CKMC_ALGO_DSA_SV:
+    case CKMC_ALGO_ECDSA_SV:
+        // no hash, no padding by default
+        break;
+    case CKMC_ALGO_RSA_GEN:
+    case CKMC_ALGO_DSA_GEN:
+        ret = ckmc_param_list_add_integer(params, CKMC_PARAM_GEN_KEY_LEN, DEFAULT_KEY_LEN_BITS);
+        break;
+    case CKMC_ALGO_ECDSA_GEN:
+        ret = ckmc_param_list_add_integer(params, CKMC_PARAM_GEN_EC, CKMC_EC_PRIME192V1);
+        break;
+    default:
+        return CKMC_ERROR_INVALID_PARAMETER;
+    }
+    if (ret == CKMC_ERROR_NONE)
+        return ckmc_param_list_add_integer(params, CKMC_PARAM_ALGO_TYPE, type);
+    return ret;
+}