Add yaca_key_derive_kdf(), define yaca_kdf_e enum 00/82100/6
authorDariusz Michaluk <d.michaluk@samsung.com>
Thu, 28 Jul 2016 08:57:55 +0000 (10:57 +0200)
committerDariusz Michaluk <d.michaluk@samsung.com>
Thu, 4 Aug 2016 10:13:06 +0000 (12:13 +0200)
yaca_key_derive_kdf() implementation/example

Change-Id: Id24036599a71a14c239725a45b51301024365a0b

api/yaca/yaca_key.h
api/yaca/yaca_types.h
examples/key_exchange.c
src/key.c

index 693c4d6..81d0767 100755 (executable)
@@ -350,6 +350,7 @@ void yaca_key_destroy(yaca_key_h key);
  * @retval #YACA_ERROR_OUT_OF_MEMORY Out of memory error
  * @retval #YACA_ERROR_INTERNAL Internal error
  *
+ * @see yaca_key_derive_kdf()
  * @see yaca_simple_calculate_digest()
  * @see yaca_free()
  */
@@ -359,6 +360,49 @@ int yaca_key_derive_dh(const yaca_key_h prv_key,
                        size_t *secret_len);
 
 /**
+ * @brief  Derives a key material from shared secret.
+ *
+ * @since_tizen 3.0
+ *
+ * @remarks  The @a info parameter is ANSI X9.42 OtherInfo or ANSI X9.62 SharedInfo structure,
+ *           more information can be found in ANSI X9.42/62 standard specification
+ *
+ * @remarks  The @a key_material or separate parts of it can be used to import a symmetric key with yaca_key_import()
+ *
+ * @remarks  The @a key_material should be freed using yaca_free()
+ *
+ * @param[in]  kdf                    Key derivation function
+ * @param[in]  algo                   Digest algorithm that should be used in key derivation
+ * @param[in]  secret                 Shared secret
+ * @param[in]  secret_len             Size of the shared secret
+ * @param[in]  info                   Optional additional info, use NULL if not appending extra info
+ * @param[in]  info_len               Length of additional info, use 0 if not using additional info
+ * @param[in]  key_material_bit_len   Length of a key material (in bits) to be generated
+ * @param[out] key_material           Newly generated key material
+ *
+ * @return #YACA_ERROR_NONE on success, negative on error
+ * @retval #YACA_ERROR_NONE Successful
+ * @retval #YACA_ERROR_INVALID_PARAMETER Required parameters have incorrect values (NULL, 0,
+ *                                       invalid algo or kdf)
+ * @retval #YACA_ERROR_OUT_OF_MEMORY Out of memory error
+ * @retval #YACA_ERROR_INTERNAL Internal error
+ *
+ * @see #yaca_kdf_e
+ * @see #yaca_digest_algorithm_e
+ * @see yaca_key_derive_dh()
+ * @see yaca_key_import()
+ * @see yaca_free()
+ */
+int yaca_key_derive_kdf(yaca_kdf_e kdf,
+                        yaca_digest_algorithm_e algo,
+                        const char *secret,
+                        size_t secret_len,
+                        const char *info,
+                        size_t info_len,
+                        size_t key_material_bit_len,
+                        char **key_material);
+
+/**
  * @brief  Derives a key from user password (PKCS #5 a.k.a. pbkdf2 algorithm).
  *
  * @since_tizen 3.0
index 0564f2e..81fcf92 100755 (executable)
@@ -613,6 +613,25 @@ typedef enum {
 } yaca_padding_e;
 
 /**
+ * @brief Enumeration of YACA key derivation functions.
+ *
+ * @since_tizen 3.0
+ */
+typedef enum {
+       /**
+        * ANSI X9.42 key derivation function,
+        * (shared secret derived using Diffie-Helmann key exchange protocol).
+        */
+       YACA_KDF_X942,
+
+       /**
+        * ANSI X9.62 key derivation function,
+        * (shared secret derived using EC Diffie-Helmann key exchange protocol).
+        */
+       YACA_KDF_X962,
+} yaca_kdf_e;
+
+/**
   * @}
   */
 
index 780b838..836cc2a 100644 (file)
@@ -36,10 +36,12 @@ static yaca_key_h exchange_keys(const yaca_key_h pkey)
        int ret;
        char *secret = NULL;
        size_t secret_len;
+       char *key_material = NULL;
 
        yaca_key_h private_key = YACA_KEY_NULL;
        yaca_key_h public_key = YACA_KEY_NULL;
        yaca_key_h params = YACA_KEY_NULL;
+       yaca_key_h aes_key = YACA_KEY_NULL;
 
        ret = yaca_key_extract_parameters(pkey, &params);
        if (ret != YACA_ERROR_NONE)
@@ -58,12 +60,25 @@ static yaca_key_h exchange_keys(const yaca_key_h pkey)
        if (ret != YACA_ERROR_NONE)
                goto exit;
 
+       ret = yaca_key_derive_kdf(YACA_KDF_X962, YACA_DIGEST_SHA512, secret, secret_len,
+                                 NULL, 0, YACA_KEY_LENGTH_192BIT, &key_material);
+       if (ret != YACA_ERROR_NONE)
+               goto exit;
+
+       ret = yaca_key_import(YACA_KEY_TYPE_SYMMETRIC, NULL, key_material, YACA_KEY_LENGTH_192BIT,
+                             &aes_key);
+       if (ret != YACA_ERROR_NONE)
+               goto exit;
+
        dump_hex(secret, secret_len, "\n***** Peer Secret: *****");
+       dump_hex(key_material, YACA_KEY_LENGTH_192BIT, "\n***** Peer AES key: *****");
 
 exit:
        yaca_key_destroy(private_key);
        yaca_key_destroy(params);
+       yaca_key_destroy(aes_key);
        yaca_free(secret);
+       yaca_free(key_material);
 
        return public_key;
 }
@@ -73,10 +88,12 @@ void key_exchange_dh_standard_parameters(void)
        int ret;
        char *secret = NULL;
        size_t secret_len;
+       char *key_material = NULL;
 
        yaca_key_h private_key = YACA_KEY_NULL;
        yaca_key_h public_key = YACA_KEY_NULL;
        yaca_key_h peer_key = YACA_KEY_NULL;
+       yaca_key_h aes_key = YACA_KEY_NULL;
 
        printf("\n***** Diffie Hellman key exchange with standard DH parameters *****");
 
@@ -99,13 +116,26 @@ void key_exchange_dh_standard_parameters(void)
        if (ret != YACA_ERROR_NONE)
                goto exit;
 
+       ret = yaca_key_derive_kdf(YACA_KDF_X962, YACA_DIGEST_SHA512, secret, secret_len,
+                                 NULL, 0, YACA_KEY_LENGTH_192BIT, &key_material);
+       if (ret != YACA_ERROR_NONE)
+               goto exit;
+
+       ret = yaca_key_import(YACA_KEY_TYPE_SYMMETRIC, NULL, key_material, YACA_KEY_LENGTH_192BIT,
+                             &aes_key);
+       if (ret != YACA_ERROR_NONE)
+               goto exit;
+
        dump_hex(secret, secret_len, "\n***** My Secret: *****");
+       dump_hex(key_material, YACA_KEY_LENGTH_192BIT, "\n***** My AES key: *****");
 
 exit:
        yaca_key_destroy(private_key);
        yaca_key_destroy(public_key);
        yaca_key_destroy(peer_key);
+       yaca_key_destroy(aes_key);
        yaca_free(secret);
+       yaca_free(key_material);
 }
 
 void key_exchange_dh_generated_parameters(void)
@@ -113,11 +143,13 @@ void key_exchange_dh_generated_parameters(void)
        int ret;
        char *secret = NULL;
        size_t secret_len;
+       char *key_material = NULL;
 
        yaca_key_h params = YACA_KEY_NULL;
        yaca_key_h private_key = YACA_KEY_NULL;
        yaca_key_h public_key = YACA_KEY_NULL;
        yaca_key_h peer_key = YACA_KEY_NULL;
+       yaca_key_h aes_key = YACA_KEY_NULL;
 
        printf("\n***** Diffie Hellman key exchange with parameters generation *****");
 
@@ -146,14 +178,27 @@ void key_exchange_dh_generated_parameters(void)
        if (ret != YACA_ERROR_NONE)
                goto exit;
 
+       ret = yaca_key_derive_kdf(YACA_KDF_X962, YACA_DIGEST_SHA512, secret, secret_len,
+                                 NULL, 0, YACA_KEY_LENGTH_192BIT, &key_material);
+       if (ret != YACA_ERROR_NONE)
+               goto exit;
+
+       ret = yaca_key_import(YACA_KEY_TYPE_SYMMETRIC, NULL, key_material, YACA_KEY_LENGTH_192BIT,
+                             &aes_key);
+       if (ret != YACA_ERROR_NONE)
+               goto exit;
+
        dump_hex(secret, secret_len, "\n***** My Secret: *****");
+       dump_hex(key_material, YACA_KEY_LENGTH_192BIT, "\n***** My AES key: *****");
 
 exit:
        yaca_key_destroy(params);
        yaca_key_destroy(private_key);
        yaca_key_destroy(public_key);
        yaca_key_destroy(peer_key);
+       yaca_key_destroy(aes_key);
        yaca_free(secret);
+       yaca_free(key_material);
 }
 
 void key_exchange_ecdh(void)
@@ -161,10 +206,12 @@ void key_exchange_ecdh(void)
        int ret;
        char *secret = NULL;
        size_t secret_len;
+       char *key_material = NULL;
 
        yaca_key_h private_key = YACA_KEY_NULL;
        yaca_key_h public_key = YACA_KEY_NULL;
        yaca_key_h peer_key = YACA_KEY_NULL;
+       yaca_key_h aes_key = YACA_KEY_NULL;
 
        printf("\n***** Elliptic Curve Diffie Hellman key exchange *****");
 
@@ -187,13 +234,26 @@ void key_exchange_ecdh(void)
        if (ret != YACA_ERROR_NONE)
                goto exit;
 
+       ret = yaca_key_derive_kdf(YACA_KDF_X962, YACA_DIGEST_SHA512, secret, secret_len,
+                                 NULL, 0, YACA_KEY_LENGTH_192BIT, &key_material);
+       if (ret != YACA_ERROR_NONE)
+               goto exit;
+
+       ret = yaca_key_import(YACA_KEY_TYPE_SYMMETRIC, NULL, key_material, YACA_KEY_LENGTH_192BIT,
+                             &aes_key);
+       if (ret != YACA_ERROR_NONE)
+               goto exit;
+
        dump_hex(secret, secret_len, "\n***** My Secret: *****");
+       dump_hex(key_material, YACA_KEY_LENGTH_192BIT, "\n***** My AES key: *****");
 
 exit:
        yaca_key_destroy(private_key);
        yaca_key_destroy(public_key);
        yaca_key_destroy(peer_key);
+       yaca_key_destroy(aes_key);
        yaca_free(secret);
+       yaca_free(key_material);
 }
 
 int main()
index a0c6943..136a333 100644 (file)
--- a/src/key.c
+++ b/src/key.c
@@ -1822,6 +1822,67 @@ exit:
        return ret;
 }
 
+API int yaca_key_derive_kdf(yaca_kdf_e kdf,
+                            yaca_digest_algorithm_e algo,
+                            const char *secret,
+                            size_t secret_len,
+                            const char *info,
+                            size_t info_len,
+                            size_t key_material_bit_len,
+                            char **key_material)
+{
+       int ret;
+       char *out = NULL;
+       const EVP_MD *md;
+
+       if (secret == NULL || secret_len == 0 ||
+           (info == NULL && info_len > 0) || (info != NULL && info_len == 0) ||
+           key_material_bit_len == 0 || key_material == NULL)
+               return YACA_ERROR_INVALID_PARAMETER;
+
+       ret = yaca_zalloc(key_material_bit_len, (void**)&out);
+       if (ret != YACA_ERROR_NONE)
+               return ret;
+
+       ret = digest_get_algorithm(algo, &md);
+       if (ret != YACA_ERROR_NONE)
+               goto exit;
+
+       switch (kdf) {
+       case YACA_KDF_X942:
+               ret = DH_KDF_X9_42((unsigned char*)out, key_material_bit_len,
+                                  (unsigned char*)secret, secret_len,
+                                  OBJ_nid2obj(NID_id_smime_alg_ESDH), (unsigned char*)info, info_len, md);
+               if (ret != 1 || out == NULL) {
+                       ret = YACA_ERROR_INTERNAL;
+                       ERROR_DUMP(ret);
+                       goto exit;
+               }
+               break;
+       case YACA_KDF_X962:
+               ret = ECDH_KDF_X9_62((unsigned char*)out, key_material_bit_len,
+                                    (unsigned char*)secret, secret_len,
+                                    (unsigned char*)info, info_len, md);
+               if (ret != 1 || out == NULL) {
+                       ret = YACA_ERROR_INTERNAL;
+                       ERROR_DUMP(ret);
+                       goto exit;
+               }
+               break;
+       default:
+               ret = YACA_ERROR_INVALID_PARAMETER;
+               goto exit;
+       }
+
+       *key_material = out;
+       out = NULL;
+       ret = YACA_ERROR_NONE;
+
+exit:
+       yaca_free(out);
+       return ret;
+}
+
 API int yaca_key_derive_pbkdf2(const char *password,
                                const char *salt,
                                size_t salt_len,