From: Dariusz Michaluk Date: Thu, 28 Jul 2016 08:57:55 +0000 (+0200) Subject: Add yaca_key_derive_kdf(), define yaca_kdf_e enum X-Git-Tag: accepted/tizen/common/20160901.143419~35^2~8 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=fa419fb02cb4a27cf33952e2f4db328754ddc694;p=platform%2Fcore%2Fsecurity%2Fyaca.git Add yaca_key_derive_kdf(), define yaca_kdf_e enum yaca_key_derive_kdf() implementation/example Change-Id: Id24036599a71a14c239725a45b51301024365a0b --- diff --git a/api/yaca/yaca_key.h b/api/yaca/yaca_key.h index 693c4d6..81d0767 100755 --- a/api/yaca/yaca_key.h +++ b/api/yaca/yaca_key.h @@ -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 diff --git a/api/yaca/yaca_types.h b/api/yaca/yaca_types.h index 0564f2e..81fcf92 100755 --- a/api/yaca/yaca_types.h +++ b/api/yaca/yaca_types.h @@ -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; + +/** * @} */ diff --git a/examples/key_exchange.c b/examples/key_exchange.c index 780b838..836cc2a 100644 --- a/examples/key_exchange.c +++ b/examples/key_exchange.c @@ -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, ¶ms); 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() diff --git a/src/key.c b/src/key.c index a0c6943..136a333 100644 --- 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,