From ac7449e73ef8d8db7e35bb923113a160bc93778d Mon Sep 17 00:00:00 2001 From: Mateusz Forc Date: Fri, 29 Jul 2016 10:13:57 +0200 Subject: [PATCH 01/16] FIX: Correct IV length for Block Cipher Modes in doc Change-Id: Id05bb379c27ffc6d37e3911e2b21bd621aa137c6 --- api/yaca/yaca_types.h | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/api/yaca/yaca_types.h b/api/yaca/yaca_types.h index e8802c3..c675a12 100755 --- a/api/yaca/yaca_types.h +++ b/api/yaca/yaca_types.h @@ -276,13 +276,15 @@ typedef enum { /** * CTR block cipher mode. - * 16-byte initialization vector is mandatory. + * 16-byte initialization vector for AES, + * 8-byte for other algorithms is mandatory. */ YACA_BCM_CTR, /** * CBC block cipher mode. - * 16-byte initialization vector is mandatory. + * 16-byte initialization vector for AES, + * 8-byte for other algorithms is mandatory. */ YACA_BCM_CBC, @@ -316,25 +318,29 @@ typedef enum { /** * Default CFB block cipher mode. - * 16-byte initialization vector is mandatory. + * 16-byte initialization vector for AES, + * 8-byte for other algorithms is mandatory. */ YACA_BCM_CFB, /** * 1 bit CFB block cipher mode. - * 16-byte initialization vector is mandatory. + * 16-byte initialization vector for AES, + * 8-byte for other algorithms is mandatory. */ YACA_BCM_CFB1, /** * 8 bits CFB block cipher mode. - * 16-byte initialization vector is mandatory. + * 16-byte initialization vector for AES, + * 8-byte for other algorithms is mandatory. */ YACA_BCM_CFB8, /** * OFB block cipher mode. - * 16-byte initialization vector is mandatory. + * 16-byte initialization vector for AES, + * 8-byte for other algorithms is mandatory. */ YACA_BCM_OFB, -- 2.7.4 From 4581e7ed408caa4324a7fa2a3b6a577f6c7ca09e Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Fri, 15 Jul 2016 18:09:25 +0200 Subject: [PATCH 02/16] Key wrapping implementation/example Change-Id: Ifedb332212bffa4c0934f57d9d51b12537fe1d1f --- api/yaca/yaca_types.h | 27 +++++- examples/CMakeLists.txt | 1 + examples/key_wrap.c | 212 ++++++++++++++++++++++++++++++++++++++++++++++++ src/encrypt.c | 122 ++++++++++++++++++++++------ src/internal.h | 2 + src/seal.c | 4 +- 6 files changed, 337 insertions(+), 31 deletions(-) create mode 100644 examples/key_wrap.c diff --git a/api/yaca/yaca_types.h b/api/yaca/yaca_types.h index f5d9854..0564f2e 100755 --- a/api/yaca/yaca_types.h +++ b/api/yaca/yaca_types.h @@ -344,7 +344,8 @@ typedef enum { * #YACA_BCM_ECB,\n * #YACA_BCM_GCM,\n * #YACA_BCM_CCM,\n - * #YACA_BCM_CTR + * #YACA_BCM_CTR,\n + * #YACA_BCM_WRAP * - see #yaca_block_cipher_mode_e for details on additional properties (mandatory). */ YACA_ENCRYPT_AES = 0, @@ -385,7 +386,8 @@ typedef enum { * #YACA_BCM_CFB,\n * #YACA_BCM_CFB1,\n * #YACA_BCM_CFB8,\n - * #YACA_BCM_ECB + * #YACA_BCM_ECB,\n + * #YACA_BCM_WRAP * - see #yaca_block_cipher_mode_e for details on additional properties (mandatory). * - Use triple DES keys to perform corresponding 3-key 3DES encryption. */ @@ -540,7 +542,26 @@ typedef enum { * @see examples/encrypt_aes_gcm_ccm.c * @see examples/seal.c */ - YACA_BCM_CCM + YACA_BCM_CCM, + + /** + * Used with #YACA_ENCRYPT_AES or #YACA_ENCRYPT_3DES_3TDEA to perform a key wrapping + * (key material symmetric encryption). + * + * Only a single yaca_encrypt_update() / yaca_decrypt_update() is allowed. + * + * Usage in yaca_seal_initialize() / yaca_open_finalize() is forbidden. + * + * Key used to do the wrapping with #YACA_ENCRYPT_AES can be a 128-bit key, a 192-bit key, or a 256-bit key. + * Wrapped key can be a 128-bit key, a 192-bit key, or a 256-bit key. + * #YACA_ENCRYPT_AES allows wrapping multiple keys together. + * + * Key used to do the wrapping with #YACA_ENCRYPT_3DES_3TDEA can be a 192 bit DES key only. + * Wrapped key can be a 128-bit DES key (two-key), or a 192-bit DES key (three-key). + * #YACA_ENCRYPT_3DES_3TDEA allows wrapping only one key. + * + */ + YACA_BCM_WRAP } yaca_block_cipher_mode_e; diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index bcc54e4..12cd956 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -52,6 +52,7 @@ BUILD_EXAMPLE("yaca-example-key-gen" key_gen.c) BUILD_EXAMPLE("yaca-example-key-exchange" key_exchange.c) BUILD_EXAMPLE("yaca-example-key-impexp" key_import_export.c) BUILD_EXAMPLE("yaca-example-key-password" key_password.c) +BUILD_EXAMPLE("yaca-example-key-wrap" key_wrap.c) INSTALL(FILES ${COMMON_SOURCES} DESTINATION ${EXAMPLES_DIR}) diff --git a/examples/key_wrap.c b/examples/key_wrap.c new file mode 100644 index 0000000..af8c655 --- /dev/null +++ b/examples/key_wrap.c @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Krzysztof Jackiewicz + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +/** + * @file key_wrap.c + * @brief + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include "misc.h" +#include "../src/debug.h" + +void key_wrap_aes(void) +{ + int ret; + yaca_key_h sym_key = YACA_KEY_NULL; + yaca_key_h iv = YACA_KEY_NULL; + yaca_key_h aes_key = YACA_KEY_NULL; + + size_t iv_bit_len; + char *key_data = NULL; + size_t key_data_len; + char *wrapped_key = NULL; + size_t wrapped_key_len; + + printf("\n***** AES key wrapping ******\n"); + + ret = yaca_key_generate(YACA_KEY_TYPE_SYMMETRIC, YACA_KEY_LENGTH_256BIT, &aes_key); + if (ret != YACA_ERROR_NONE) + goto exit; + + ret = yaca_key_generate(YACA_KEY_TYPE_SYMMETRIC, YACA_KEY_LENGTH_192BIT, &sym_key); + if (ret != YACA_ERROR_NONE) + goto exit; + + ret = yaca_encrypt_get_iv_bit_length(YACA_ENCRYPT_AES, + YACA_BCM_WRAP, + YACA_KEY_LENGTH_192BIT, + &iv_bit_len); + if (ret != YACA_ERROR_NONE) + goto exit; + + if (iv_bit_len > 0) { + ret = yaca_key_generate(YACA_KEY_TYPE_IV, iv_bit_len, &iv); + if (ret != YACA_ERROR_NONE) + goto exit; + } + + /* Key wrapping */ + { + ret = yaca_key_export(aes_key, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_RAW, NULL, + &key_data, &key_data_len); + if (ret != YACA_ERROR_NONE) + goto exit; + + ret = yaca_simple_encrypt(YACA_ENCRYPT_AES, YACA_BCM_WRAP, sym_key, iv, + key_data, key_data_len, + &wrapped_key, &wrapped_key_len); + if (ret != YACA_ERROR_NONE) + goto exit; + + dump_hex(key_data, key_data_len, "***** Unwrapped key:*****"); + dump_hex(wrapped_key, wrapped_key_len, "***** Wrapped key:*****"); + } + + yaca_free(key_data); + key_data = NULL; + yaca_key_destroy(aes_key); + aes_key = YACA_KEY_NULL; + + /* Key unwrapping */ + { + ret = yaca_simple_decrypt(YACA_ENCRYPT_AES, YACA_BCM_WRAP, sym_key, iv, + wrapped_key, wrapped_key_len, + &key_data, &key_data_len); + if (ret != YACA_ERROR_NONE) + goto exit; + + ret = yaca_key_import(YACA_KEY_TYPE_SYMMETRIC, NULL, key_data, key_data_len, &aes_key); + if (ret != YACA_ERROR_NONE) + goto exit; + + dump_hex(key_data, key_data_len, "***** Unwrapped key:*****"); + } + +exit: + yaca_key_destroy(aes_key); + yaca_key_destroy(sym_key); + yaca_key_destroy(iv); + yaca_free(key_data); + yaca_free(wrapped_key); +} + +void key_wrap_des(void) +{ + int ret; + yaca_key_h sym_key = YACA_KEY_NULL; + yaca_key_h iv = YACA_KEY_NULL; + yaca_key_h des_key = YACA_KEY_NULL; + + size_t iv_bit_len; + char *key_data = NULL; + size_t key_data_len; + char *wrapped_key = NULL; + size_t wrapped_key_len; + + printf("\n***** 3DES key wrapping ******\n"); + + ret = yaca_key_generate(YACA_KEY_TYPE_DES, YACA_KEY_LENGTH_192BIT, &des_key); + if (ret != YACA_ERROR_NONE) + goto exit; + + ret = yaca_key_generate(YACA_KEY_TYPE_DES, YACA_KEY_LENGTH_192BIT, &sym_key); + if (ret != YACA_ERROR_NONE) + goto exit; + + ret = yaca_encrypt_get_iv_bit_length(YACA_ENCRYPT_3DES_3TDEA, + YACA_BCM_WRAP, + YACA_KEY_LENGTH_192BIT, + &iv_bit_len); + if (ret != YACA_ERROR_NONE) + goto exit; + + if (iv_bit_len > 0) { + ret = yaca_key_generate(YACA_KEY_TYPE_IV, iv_bit_len, &iv); + if (ret != YACA_ERROR_NONE) + goto exit; + } + + /* Key wrapping */ + { + ret = yaca_key_export(des_key, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_RAW, NULL, + &key_data, &key_data_len); + if (ret != YACA_ERROR_NONE) + goto exit; + + ret = yaca_simple_encrypt(YACA_ENCRYPT_3DES_3TDEA, YACA_BCM_WRAP, sym_key, iv, + key_data, key_data_len, + &wrapped_key, &wrapped_key_len); + if (ret != YACA_ERROR_NONE) + goto exit; + + dump_hex(key_data, key_data_len, "***** Unwrapped key:*****"); + dump_hex(wrapped_key, wrapped_key_len, "***** Wrapped key:*****"); + } + + yaca_free(key_data); + key_data = NULL; + yaca_key_destroy(des_key); + des_key = YACA_KEY_NULL; + + /* Key unwrapping */ + { + ret = yaca_simple_decrypt(YACA_ENCRYPT_3DES_3TDEA, YACA_BCM_WRAP, sym_key, iv, + wrapped_key, wrapped_key_len, + &key_data, &key_data_len); + if (ret != YACA_ERROR_NONE) + goto exit; + + ret = yaca_key_import(YACA_KEY_TYPE_DES, NULL, key_data, key_data_len, &des_key); + if (ret != YACA_ERROR_NONE) + goto exit; + + dump_hex(key_data, key_data_len, "***** Unwrapped key:*****"); + } + +exit: + yaca_key_destroy(des_key); + yaca_key_destroy(sym_key); + yaca_key_destroy(iv); + yaca_free(key_data); + yaca_free(wrapped_key); +} + +int main() +{ + yaca_debug_set_error_cb(debug_func); + + int ret = yaca_initialize(); + if (ret != YACA_ERROR_NONE) + return ret; + + key_wrap_aes(); + key_wrap_des(); + + yaca_cleanup(); + return ret; +} + diff --git a/src/encrypt.c b/src/encrypt.c index 08880da..4fa6965 100644 --- a/src/encrypt.c +++ b/src/encrypt.c @@ -58,34 +58,34 @@ struct yaca_encrypt_context_s *get_encrypt_context(const yaca_context_h ctx) void destroy_encrypt_context(const yaca_context_h ctx) { - struct yaca_encrypt_context_s *nc = get_encrypt_context(ctx); + struct yaca_encrypt_context_s *c = get_encrypt_context(ctx); - if (nc == NULL) + if (c == NULL) return; - if (nc->backup_ctx != NULL) { - yaca_key_destroy(nc->backup_ctx->iv); - yaca_key_destroy(nc->backup_ctx->sym_key); - yaca_free(nc->backup_ctx); - nc->backup_ctx = NULL; + if (c->backup_ctx != NULL) { + yaca_key_destroy(c->backup_ctx->iv); + yaca_key_destroy(c->backup_ctx->sym_key); + yaca_free(c->backup_ctx); + c->backup_ctx = NULL; } - EVP_CIPHER_CTX_free(nc->cipher_ctx); - nc->cipher_ctx = NULL; + EVP_CIPHER_CTX_free(c->cipher_ctx); + c->cipher_ctx = NULL; } int get_encrypt_output_length(const yaca_context_h ctx, size_t input_len, size_t *output_len) { assert(output_len != NULL); - struct yaca_encrypt_context_s *nc = get_encrypt_context(ctx); + struct yaca_encrypt_context_s *c = get_encrypt_context(ctx); int block_size; - if (nc == NULL) + if (c == NULL) return YACA_ERROR_INVALID_PARAMETER; - assert(nc->cipher_ctx != NULL); + assert(c->cipher_ctx != NULL); - block_size = EVP_CIPHER_CTX_block_size(nc->cipher_ctx); + block_size = EVP_CIPHER_CTX_block_size(c->cipher_ctx); if (block_size <= 0) { ERROR_DUMP(YACA_ERROR_INTERNAL); return YACA_ERROR_INTERNAL; @@ -105,6 +105,33 @@ int get_encrypt_output_length(const yaca_context_h ctx, size_t input_len, size_t return YACA_ERROR_NONE; } +int get_wrap_output_length(const yaca_context_h ctx, size_t input_len, size_t *output_len) +{ + assert(output_len != NULL); + + struct yaca_encrypt_context_s *c = get_encrypt_context(ctx); + if (c == NULL) + return YACA_ERROR_INVALID_PARAMETER; + assert(c->cipher_ctx != NULL); + + int type = EVP_CIPHER_type(c->cipher_ctx->cipher); + + if (input_len > 0) { + if (type == NID_id_aes128_wrap || type == NID_id_aes192_wrap || type == NID_id_aes256_wrap) { + *output_len = input_len + 8; + } else if (type == NID_id_smime_alg_CMS3DESwrap) { + *output_len = input_len + 16; + } else { + assert(false); + return YACA_ERROR_INTERNAL; + } + } else { + *output_len = 0; + } + + return YACA_ERROR_NONE; +} + static int encrypt_ctx_create(struct yaca_encrypt_context_s **c, enum encrypt_op_type_e op_type, const EVP_CIPHER *cipher) @@ -120,16 +147,19 @@ static int encrypt_ctx_create(struct yaca_encrypt_context_s **c, if (ret != YACA_ERROR_NONE) return ret; + mode = EVP_CIPHER_flags(cipher) & EVP_CIPH_MODE; + nc->ctx.type = YACA_CONTEXT_ENCRYPT; nc->backup_ctx = NULL; nc->ctx.context_destroy = destroy_encrypt_context; - nc->ctx.get_output_length = get_encrypt_output_length; + nc->ctx.get_output_length = (mode == EVP_CIPH_WRAP_MODE) ? + get_wrap_output_length : + get_encrypt_output_length; nc->ctx.set_property = set_encrypt_property; nc->ctx.get_property = get_encrypt_property; nc->op_type = op_type; nc->tag_len = 0; - - mode = EVP_CIPHER_flags(cipher) & EVP_CIPH_MODE; + nc->update_called = false; /* set default tag length for GCM and CCM */ if (mode == EVP_CIPH_GCM_MODE) @@ -144,6 +174,9 @@ static int encrypt_ctx_create(struct yaca_encrypt_context_s **c, goto exit; } + if (mode == EVP_CIPH_WRAP_MODE) + EVP_CIPHER_CTX_set_flags(nc->cipher_ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW); + *c = nc; nc = NULL; @@ -564,6 +597,8 @@ static const char *bcm_to_str(yaca_block_cipher_mode_e bcm) return "ofb"; case YACA_BCM_CCM: return "ccm"; + case YACA_BCM_WRAP: + return "wrap"; default: return NULL; } @@ -587,8 +622,12 @@ int encrypt_get_algorithm(yaca_encrypt_algorithm_e algo, switch (algo) { case YACA_ENCRYPT_AES: - ret = snprintf(cipher_name, sizeof(cipher_name), "%s-%zu-%s", - algo_name, key_bit_len, bcm_name); + if (bcm == YACA_BCM_WRAP) + ret = snprintf(cipher_name, sizeof(cipher_name), "id-%s%zu-%s", + algo_name, key_bit_len, bcm_name); + else + ret = snprintf(cipher_name, sizeof(cipher_name), "%s-%zu-%s", + algo_name, key_bit_len, bcm_name); break; case YACA_ENCRYPT_UNSAFE_DES: case YACA_ENCRYPT_UNSAFE_RC2: @@ -597,9 +636,17 @@ int encrypt_get_algorithm(yaca_encrypt_algorithm_e algo, algo_name, bcm_name); break; case YACA_ENCRYPT_UNSAFE_3DES_2TDEA: + if (bcm == YACA_BCM_ECB) + ret = snprintf(cipher_name, sizeof(cipher_name), "%s", algo_name); + else + ret = snprintf(cipher_name, sizeof(cipher_name), "%s-%s", + algo_name, bcm_name); + break; case YACA_ENCRYPT_3DES_3TDEA: if (bcm == YACA_BCM_ECB) ret = snprintf(cipher_name, sizeof(cipher_name), "%s", algo_name); + else if (bcm == YACA_BCM_WRAP) + ret = snprintf(cipher_name, sizeof(cipher_name), "id-smime-alg-CMS3DESwrap"); else ret = snprintf(cipher_name, sizeof(cipher_name), "%s-%s", algo_name, bcm_name); @@ -728,14 +775,34 @@ int encrypt_update(yaca_context_h ctx, struct yaca_encrypt_context_s *c = get_encrypt_context(ctx); int ret; int loutput_len; + int mode; + int type; if (c == NULL || input_len == 0 || output_len == NULL || op_type != c->op_type) return YACA_ERROR_INVALID_PARAMETER; - if (EVP_CIPHER_CTX_mode(c->cipher_ctx) != EVP_CIPH_CCM_MODE) - if (input == NULL || output == NULL) + mode = EVP_CIPHER_CTX_mode(c->cipher_ctx); + type = EVP_CIPHER_type(c->cipher_ctx->cipher); + + if (mode != EVP_CIPH_CCM_MODE && (input == NULL || output == NULL)) + return YACA_ERROR_INVALID_PARAMETER; + + if (mode == EVP_CIPH_WRAP_MODE && c->update_called == true) return YACA_ERROR_INVALID_PARAMETER; + if (mode == EVP_CIPH_WRAP_MODE && op_type == OP_ENCRYPT) { + if (type == NID_id_aes128_wrap || type == NID_id_aes192_wrap || type == NID_id_aes256_wrap) { + if (input_len % 8 != 0 || input_len < (YACA_KEY_LENGTH_UNSAFE_128BIT / 8)) + return YACA_ERROR_INVALID_PARAMETER; + } else if (type == NID_id_smime_alg_CMS3DESwrap) { + if (input_len != (YACA_KEY_LENGTH_UNSAFE_128BIT / 8) && input_len != (YACA_KEY_LENGTH_192BIT / 8)) + return YACA_ERROR_INVALID_PARAMETER; + } else { + assert(false); + return YACA_ERROR_INTERNAL; + } + } + ret = EVP_CipherUpdate(c->cipher_ctx, output, &loutput_len, input, input_len); if (ret != 1 || loutput_len < 0) { ret = YACA_ERROR_INTERNAL; @@ -744,6 +811,7 @@ int encrypt_update(yaca_context_h ctx, } *output_len = loutput_len; + c->update_called = true; return YACA_ERROR_NONE; } @@ -753,16 +821,18 @@ int encrypt_finalize(yaca_context_h ctx, { struct yaca_encrypt_context_s *c = get_encrypt_context(ctx); int ret; - int loutput_len; + int loutput_len = 0; if (c == NULL || output == NULL || output_len == NULL || op_type != c->op_type) return YACA_ERROR_INVALID_PARAMETER; - ret = EVP_CipherFinal(c->cipher_ctx, output, &loutput_len); - if (ret != 1 || loutput_len < 0) { - ret = YACA_ERROR_INTERNAL; - ERROR_DUMP(ret); - return ret; + if (EVP_CIPHER_CTX_mode(c->cipher_ctx) != EVP_CIPH_WRAP_MODE) { + ret = EVP_CipherFinal(c->cipher_ctx, output, &loutput_len); + if (ret != 1 || loutput_len < 0) { + ret = YACA_ERROR_INTERNAL; + ERROR_DUMP(ret); + return ret; + } } *output_len = loutput_len; diff --git a/src/internal.h b/src/internal.h index b6e2321..7c202ec 100644 --- a/src/internal.h +++ b/src/internal.h @@ -25,6 +25,7 @@ #define YACA_INTERNAL_H #include +#include #include #include @@ -73,6 +74,7 @@ struct yaca_encrypt_context_s { EVP_CIPHER_CTX *cipher_ctx; enum encrypt_op_type_e op_type; /* Operation context was created for */ size_t tag_len; + bool update_called; }; /* Base structure for crypto keys - to be inherited */ diff --git a/src/seal.c b/src/seal.c index 623d2e8..504470f 100644 --- a/src/seal.c +++ b/src/seal.c @@ -160,7 +160,7 @@ API int yaca_seal_initialize(yaca_context_h *ctx, yaca_key_h lenc_sym_key = YACA_KEY_NULL; if (pub_key == YACA_KEY_NULL || pub_key->type != YACA_KEY_TYPE_RSA_PUB || - enc_sym_key == NULL) + enc_sym_key == NULL || bcm == YACA_BCM_WRAP) return YACA_ERROR_INVALID_PARAMETER; ret = encrypt_get_algorithm(algo, bcm, bit_len, &cipher); @@ -233,7 +233,7 @@ API int yaca_open_initialize(yaca_context_h *ctx, yaca_key_h lsym_key = YACA_KEY_NULL; if (prv_key == YACA_KEY_NULL || prv_key->type != YACA_KEY_TYPE_RSA_PRIV || - enc_sym_key == YACA_KEY_NULL) + enc_sym_key == YACA_KEY_NULL || bcm == YACA_BCM_WRAP) return YACA_ERROR_INVALID_PARAMETER; ret = encrypt_get_algorithm(algo, bcm, bit_len, &cipher); -- 2.7.4 From 37e93ef83facf435ff4f8e90f734180782b3658a Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Wed, 20 Jul 2016 12:07:36 +0200 Subject: [PATCH 03/16] Change yaca_key_derive_dh() API Return buffer with shared secret instead of yaca_key_h. Shared secret should not be used as a key. Change-Id: I55de2b330deb06dd6b15902bf5f4ea9fe45e4359 --- api/yaca/yaca_key.h | 22 ++++++++++++++-------- examples/CMakeLists.txt | 2 +- src/key.c | 27 ++++++++++++++------------- 3 files changed, 29 insertions(+), 22 deletions(-) diff --git a/api/yaca/yaca_key.h b/api/yaca/yaca_key.h index b8714b1..693c4d6 100755 --- a/api/yaca/yaca_key.h +++ b/api/yaca/yaca_key.h @@ -330,27 +330,33 @@ int yaca_key_extract_parameters(const yaca_key_h key, yaca_key_h *params); void yaca_key_destroy(yaca_key_h key); /** - * @brief Derives a key using Diffie-Helmann or EC Diffie-Helmann key exchange protocol. + * @brief Derives a shared secret using Diffie-Helmann or EC Diffie-Helmann key exchange protocol. * * @since_tizen 3.0 * - * @remarks The @a sym_key should be released using yaca_key_destroy() + * @remarks The @a secret should not be used as a symmetric key, + * to produce a symmetric key pass the secret to a key derivation function (KDF) or a message digest function * - * @param[in] prv_key Our private key - * @param[in] pub_key Peer public key - * @param[out] sym_key Shared secret, that can be used as a symmetric key + * @remarks The @a secret should be freed with yaca_free() + * + * @param[in] prv_key Our private key + * @param[in] pub_key Peer public key + * @param[out] secret Generated shared secret + * @param[out] secret_len Size of the shared secret * * @return #YACA_ERROR_NONE on success, negative on error * @retval #YACA_ERROR_NONE Successful - * @retval #YACA_ERROR_INVALID_PARAMETER Required parameters have incorrect values + * @retval #YACA_ERROR_INVALID_PARAMETER Required parameters have incorrect values (invalid key) * @retval #YACA_ERROR_OUT_OF_MEMORY Out of memory error * @retval #YACA_ERROR_INTERNAL Internal error * - * @see yaca_key_destroy() + * @see yaca_simple_calculate_digest() + * @see yaca_free() */ int yaca_key_derive_dh(const yaca_key_h prv_key, const yaca_key_h pub_key, - yaca_key_h *sym_key); + char **secret, + size_t *secret_len); /** * @brief Derives a key from user password (PKCS #5 a.k.a. pbkdf2 algorithm). diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 12cd956..7cad03a 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -49,7 +49,7 @@ BUILD_EXAMPLE("yaca-example-seal" seal.c) BUILD_EXAMPLE("yaca-example-encrypt-gcm-ccm" encrypt_aes_gcm_ccm.c) BUILD_EXAMPLE("yaca-example-sign" sign.c) BUILD_EXAMPLE("yaca-example-key-gen" key_gen.c) -BUILD_EXAMPLE("yaca-example-key-exchange" key_exchange.c) +#BUILD_EXAMPLE("yaca-example-key-exchange" key_exchange.c) BUILD_EXAMPLE("yaca-example-key-impexp" key_import_export.c) BUILD_EXAMPLE("yaca-example-key-password" key_password.c) BUILD_EXAMPLE("yaca-example-key-wrap" key_wrap.c) diff --git a/src/key.c b/src/key.c index 462ace9..a0c6943 100644 --- a/src/key.c +++ b/src/key.c @@ -1748,16 +1748,17 @@ API void yaca_key_destroy(yaca_key_h key) API int yaca_key_derive_dh(const yaca_key_h prv_key, const yaca_key_h pub_key, - yaca_key_h *sym_key) + char **secret, + size_t *secret_len) { int ret; struct yaca_key_evp_s *lprv_key = key_get_evp(prv_key); struct yaca_key_evp_s *lpub_key = key_get_evp(pub_key); - struct yaca_key_simple_s *nk = NULL; - size_t nk_len; EVP_PKEY_CTX *ctx; + char *data = NULL; + size_t data_len; - if (lprv_key == NULL || lpub_key == NULL || sym_key == NULL || + if (lprv_key == NULL || lpub_key == NULL || secret == NULL || secret_len == NULL || (!(lprv_key->key.type == YACA_KEY_TYPE_DH_PRIV && lpub_key->key.type == YACA_KEY_TYPE_DH_PUB) && @@ -1786,38 +1787,38 @@ API int yaca_key_derive_dh(const yaca_key_h prv_key, goto exit; } - ret = EVP_PKEY_derive(ctx, NULL, &nk_len); + ret = EVP_PKEY_derive(ctx, NULL, &data_len); if (ret != 1) { ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); goto exit; } - if (nk_len == 0 || nk_len > SIZE_MAX / 8) { + if (data_len == 0 || data_len > SIZE_MAX / 8) { ret = YACA_ERROR_INVALID_PARAMETER; goto exit; } - ret = yaca_zalloc(sizeof(struct yaca_key_simple_s) + nk_len, (void**)&nk); + ret = yaca_zalloc(data_len, (void**)&data); if (ret != YACA_ERROR_NONE) goto exit; - ret = EVP_PKEY_derive(ctx, (unsigned char*)nk->d, &nk_len); + ret = EVP_PKEY_derive(ctx, (unsigned char*)data, &data_len); if (ret != 1) { ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); goto exit; } - nk->bit_len = nk_len * 8; - nk->key.type = YACA_KEY_TYPE_SYMMETRIC; - *sym_key = (yaca_key_h)nk; - nk = NULL; + *secret = data; + data = NULL; + *secret_len = data_len; + ret = YACA_ERROR_NONE; exit: EVP_PKEY_CTX_free(ctx); - yaca_free(nk); + yaca_free(data); return ret; } -- 2.7.4 From cde36079e054683dd47428a9443a7bd4543e3cad Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Thu, 28 Jul 2016 10:53:10 +0200 Subject: [PATCH 04/16] Rework key derivation example Change-Id: I2beb8f49298b87dd9b0917d2d9fbb1b98619bb6e --- examples/CMakeLists.txt | 2 +- examples/key_exchange.c | 158 +++++++++++++++++++++++++++++++----------------- 2 files changed, 103 insertions(+), 57 deletions(-) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 7cad03a..12cd956 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -49,7 +49,7 @@ BUILD_EXAMPLE("yaca-example-seal" seal.c) BUILD_EXAMPLE("yaca-example-encrypt-gcm-ccm" encrypt_aes_gcm_ccm.c) BUILD_EXAMPLE("yaca-example-sign" sign.c) BUILD_EXAMPLE("yaca-example-key-gen" key_gen.c) -#BUILD_EXAMPLE("yaca-example-key-exchange" key_exchange.c) +BUILD_EXAMPLE("yaca-example-key-exchange" key_exchange.c) BUILD_EXAMPLE("yaca-example-key-impexp" key_import_export.c) BUILD_EXAMPLE("yaca-example-key-password" key_password.c) BUILD_EXAMPLE("yaca-example-key-wrap" key_wrap.c) diff --git a/examples/key_exchange.c b/examples/key_exchange.c index c825090..780b838 100644 --- a/examples/key_exchange.c +++ b/examples/key_exchange.c @@ -30,21 +30,22 @@ #include "misc.h" #include "../src/debug.h" -void key_exchange_dh(void) +/* send own public key and get peer public key */ +static yaca_key_h exchange_keys(const yaca_key_h pkey) { int ret; + char *secret = NULL; + size_t secret_len; 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 secret = YACA_KEY_NULL; + yaca_key_h params = YACA_KEY_NULL; - FILE *fp = NULL; - char *buffer = NULL; - long size; + ret = yaca_key_extract_parameters(pkey, ¶ms); + if (ret != YACA_ERROR_NONE) + goto exit; - /* generate private, public key */ - ret = yaca_key_generate(YACA_KEY_TYPE_DH_PRIV, YACA_KEY_LENGTH_2048BIT, &private_key); + ret = yaca_key_generate_from_parameters(params, &private_key); if (ret != YACA_ERROR_NONE) goto exit; @@ -52,60 +53,82 @@ void key_exchange_dh(void) if (ret != YACA_ERROR_NONE) goto exit; - /* get peer public key */ - // TODO: read key from file to buffer can be replaced with read_file() from misc.h - fp = fopen("key.pub", "r"); - if (!fp) goto exit; + /* derive secret */ + ret = yaca_key_derive_dh(private_key, pkey, &secret, &secret_len); + if (ret != YACA_ERROR_NONE) + goto exit; - fseek(fp, 0L, SEEK_END); - size = ftell(fp); - rewind(fp); + dump_hex(secret, secret_len, "\n***** Peer Secret: *****"); - /* allocate memory for entire content */ - if (yaca_malloc(size + 1, (void**)&buffer) != YACA_ERROR_NONE) - goto exit; +exit: + yaca_key_destroy(private_key); + yaca_key_destroy(params); + yaca_free(secret); - /* copy the file into the buffer */ - if (1 != fread(buffer, size, 1, fp)) + return public_key; +} + +void key_exchange_dh_standard_parameters(void) +{ + int ret; + char *secret = NULL; + size_t secret_len; + + yaca_key_h private_key = YACA_KEY_NULL; + yaca_key_h public_key = YACA_KEY_NULL; + yaca_key_h peer_key = YACA_KEY_NULL; + + printf("\n***** Diffie Hellman key exchange with standard DH parameters *****"); + + /* generate private, public key */ + ret = yaca_key_generate(YACA_KEY_TYPE_DH_PRIV, YACA_KEY_LENGTH_DH_RFC_2048_256, &private_key); + if (ret != YACA_ERROR_NONE) goto exit; - ret = yaca_key_import(YACA_KEY_TYPE_DH_PUB, NULL, - buffer, size, &peer_key); + ret = yaca_key_extract_public(private_key, &public_key); if (ret != YACA_ERROR_NONE) goto exit; + /* get peer public key */ + peer_key = exchange_keys(public_key); + if (peer_key == YACA_KEY_NULL) + goto exit; + /* derive secret */ - ret = yaca_key_derive_dh(private_key, peer_key, &secret); + ret = yaca_key_derive_dh(private_key, peer_key, &secret, &secret_len); if (ret != YACA_ERROR_NONE) goto exit; + dump_hex(secret, secret_len, "\n***** My Secret: *****"); + exit: yaca_key_destroy(private_key); yaca_key_destroy(public_key); yaca_key_destroy(peer_key); - yaca_key_destroy(secret); - if (fp != NULL) - fclose(fp); - yaca_free(buffer); + yaca_free(secret); } -// TODO ECDH is not supported yet -#if 0 -void key_exchange_ecdh(void) +void key_exchange_dh_generated_parameters(void) { int ret; + char *secret = NULL; + size_t secret_len; + 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 secret = YACA_KEY_NULL; - FILE *fp = NULL; - char *buffer = NULL; - long size; + printf("\n***** Diffie Hellman key exchange with parameters generation *****"); - /* generate private, public key */ - ret = yaca_key_generate(YACA_KEY_TYPE_EC_PRIV, YACA_KEY_CURVE_P256, &private_key); + /* generate parameters */ + ret = yaca_key_generate(YACA_KEY_TYPE_DH_PARAMS, + YACA_KEY_LENGTH_DH_GENERATOR_2 | 1024, ¶ms); + if (ret != YACA_ERROR_NONE) + goto exit; + + /* generate private, public key */ + ret = yaca_key_generate_from_parameters(params, &private_key); if (ret != YACA_ERROR_NONE) goto exit; @@ -114,42 +137,64 @@ void key_exchange_ecdh(void) goto exit; /* get peer public key */ - // TODO: read key from file to buffer can be replaced with read_file() from misc.h - fp = fopen("key.pub", "r"); - if (fp == NULL) + peer_key = exchange_keys(public_key); + if (peer_key == YACA_KEY_NULL) goto exit; - fseek(fp, 0L, SEEK_END); - size = ftell(fp); - rewind(fp); - - /* allocate memory for entire content */ - if (yaca_malloc(size + 1, (void**)&buffer) != YACA_ERROR_NONE) + /* derive secret */ + ret = yaca_key_derive_dh(private_key, peer_key, &secret, &secret_len); + if (ret != YACA_ERROR_NONE) goto exit; - /* copy the file into the buffer */ - if (1 != fread(buffer, size, 1, fp)) + dump_hex(secret, secret_len, "\n***** My Secret: *****"); + +exit: + yaca_key_destroy(params); + yaca_key_destroy(private_key); + yaca_key_destroy(public_key); + yaca_key_destroy(peer_key); + yaca_free(secret); +} + +void key_exchange_ecdh(void) +{ + int ret; + char *secret = NULL; + size_t secret_len; + + yaca_key_h private_key = YACA_KEY_NULL; + yaca_key_h public_key = YACA_KEY_NULL; + yaca_key_h peer_key = YACA_KEY_NULL; + + printf("\n***** Elliptic Curve Diffie Hellman key exchange *****"); + + /* generate private, public key */ + ret = yaca_key_generate(YACA_KEY_TYPE_EC_PRIV, YACA_KEY_LENGTH_EC_PRIME256V1, &private_key); + if (ret != YACA_ERROR_NONE) goto exit; - ret = yaca_key_import(YACA_KEY_TYPE_EC_PUB, NULL, buffer, size, &peer_key); + ret = yaca_key_extract_public(private_key, &public_key); if (ret != YACA_ERROR_NONE) goto exit; + /* get peer public key */ + peer_key = exchange_keys(public_key); + if (peer_key == YACA_KEY_NULL) + goto exit; + /* derive secret */ - ret = yaca_key_derive_dh(private_key, peer_key, &secret); + ret = yaca_key_derive_dh(private_key, peer_key, &secret, &secret_len); if (ret != YACA_ERROR_NONE) goto exit; + dump_hex(secret, secret_len, "\n***** My Secret: *****"); + exit: yaca_key_destroy(private_key); yaca_key_destroy(public_key); yaca_key_destroy(peer_key); - yaca_key_destroy(secret); - if (fp != NULL) - fclose(fp); - yaca_free(buffer); + yaca_free(secret); } -#endif int main() { @@ -159,8 +204,9 @@ int main() if (ret != YACA_ERROR_NONE) return ret; - key_exchange_dh(); - //key_exchange_ecdh(); + key_exchange_dh_standard_parameters(); + key_exchange_dh_generated_parameters(); + key_exchange_ecdh(); yaca_cleanup(); return ret; -- 2.7.4 From fa419fb02cb4a27cf33952e2f4db328754ddc694 Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Thu, 28 Jul 2016 10:57:55 +0200 Subject: [PATCH 05/16] Add yaca_key_derive_kdf(), define yaca_kdf_e enum yaca_key_derive_kdf() implementation/example Change-Id: Id24036599a71a14c239725a45b51301024365a0b --- api/yaca/yaca_key.h | 44 +++++++++++++++++++++++++++++++++++ api/yaca/yaca_types.h | 19 +++++++++++++++ examples/key_exchange.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++ src/key.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 184 insertions(+) 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, -- 2.7.4 From 1cc57e574a498f8d0ff09abe0fb696862cc3ec75 Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Mon, 1 Aug 2016 14:35:06 +0200 Subject: [PATCH 06/16] Add possibility to disabling encrypt/decrypt padding. Change-Id: I42bbd36013b6d39917f6946f35d533dc4f0dbd8e --- api/yaca/yaca_simple.h | 3 ++- api/yaca/yaca_types.h | 14 ++++++++++++-- src/debug.c | 2 ++ src/encrypt.c | 18 +++++++++++++----- 4 files changed, 29 insertions(+), 8 deletions(-) diff --git a/api/yaca/yaca_simple.h b/api/yaca/yaca_simple.h index 34a238c..e151397 100755 --- a/api/yaca/yaca_simple.h +++ b/api/yaca/yaca_simple.h @@ -25,6 +25,7 @@ * - All operations are single-shot (no streaming possible) * - Context is not used * - For now only digest and symmetric ciphers are supported + * - Disabling PKCS#5 padding for ECB and CBC chaining is not supported. * - GCM and CCM chaining is not supported * - All outputs are allocated by the library */ @@ -82,7 +83,7 @@ int yaca_simple_calculate_digest(yaca_digest_algorithm_e algo, * * @param[in] algo Encryption algorithm (select #YACA_ENCRYPT_AES if unsure) * @param[in] bcm Chaining mode (select #YACA_BCM_CBC if unsure) - * @param[in] sym_key Symmetric encryption key (see key.h for key generation functions) + * @param[in] sym_key Symmetric encryption key (see yaca_key.h for key generation functions) * @param[in] iv Initialization vector * @param[in] plaintext Plaintext to be encrypted * @param[in] plaintext_len Length of the plaintext diff --git a/api/yaca/yaca_types.h b/api/yaca/yaca_types.h index 81fcf92..8a3b1b9 100755 --- a/api/yaca/yaca_types.h +++ b/api/yaca/yaca_types.h @@ -441,7 +441,12 @@ typedef enum { /** * ECB block cipher mode. - * Encrypts 64 bit at a time. No IV is used. + * No IV is used. + * + * By default the input data is padded using standard block padding (aka PKCS#5 padding). + * Padding can be disabled using yaca_context_set_property() and #YACA_PROPERTY_PADDING, #YACA_PADDING_NONE, + * then the total length of data passed until *_finalize() MUST be a multiple of block size. + * #YACA_PROPERTY_PADDING can be set at the latest before the *_finalize() call. */ YACA_BCM_ECB, @@ -454,6 +459,11 @@ typedef enum { /** * CBC block cipher mode. * 16-byte initialization vector is mandatory. + * + * By default the input data is padded using standard block padding (aka PKCS#5 padding). + * Padding can be disabled using yaca_context_set_property() and #YACA_PROPERTY_PADDING, #YACA_PADDING_NONE, + * then the total length of data passed until *_finalize() MUST be a multiple of block size. + * #YACA_PROPERTY_PADDING can be set at the latest before the *_finalize() call. */ YACA_BCM_CBC, @@ -575,7 +585,7 @@ typedef enum { */ typedef enum { /** - * Padding for the sign/verify operation. Property type is #yaca_padding_e. + * Padding for the encrypt/decrypt or sign/verify operation. Property type is #yaca_padding_e. * * This property can be set at the latest before the *_finalize() call. */ diff --git a/src/debug.c b/src/debug.c index 9e5164b..7f9d470 100644 --- a/src/debug.c +++ b/src/debug.c @@ -127,6 +127,8 @@ int error_handle(const char *file, int line, const char *function) case ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_COMMAND_NOT_SUPPORTED): case ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_READ_BIO, PEM_R_NO_START_LINE): case ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_NOT_ENOUGH_DATA): + case ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_ENCRYPTFINAL_EX, EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH): + case ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_DECRYPTFINAL_EX, EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH): ret = YACA_ERROR_INVALID_PARAMETER; break; case ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_GET_OBJECT, ASN1_R_TOO_LONG): diff --git a/src/encrypt.c b/src/encrypt.c index 4fa6965..d1c756c 100644 --- a/src/encrypt.c +++ b/src/encrypt.c @@ -494,6 +494,17 @@ int set_encrypt_property(yaca_context_h ctx, ret = encrypt_ctx_set_ccm_tag_len(c, *(size_t*)value); break; + case YACA_PROPERTY_PADDING: + if ((mode != EVP_CIPH_ECB_MODE && mode != EVP_CIPH_CBC_MODE) || + value_len != sizeof(yaca_padding_e) || + *(yaca_padding_e*)value != YACA_PADDING_NONE) + return YACA_ERROR_INVALID_PARAMETER; + + if (EVP_CIPHER_CTX_set_padding(c->cipher_ctx, 0) != 1) { + ERROR_DUMP(YACA_ERROR_INTERNAL); + return YACA_ERROR_INTERNAL; + } + break; default: return YACA_ERROR_INVALID_PARAMETER; } @@ -828,11 +839,8 @@ int encrypt_finalize(yaca_context_h ctx, if (EVP_CIPHER_CTX_mode(c->cipher_ctx) != EVP_CIPH_WRAP_MODE) { ret = EVP_CipherFinal(c->cipher_ctx, output, &loutput_len); - if (ret != 1 || loutput_len < 0) { - ret = YACA_ERROR_INTERNAL; - ERROR_DUMP(ret); - return ret; - } + if (ret != 1 || loutput_len < 0) + return ERROR_HANDLE(); } *output_len = loutput_len; -- 2.7.4 From 999b823f8dcc9a8e465a34741e082807492d3ff8 Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Fri, 5 Aug 2016 12:08:23 +0200 Subject: [PATCH 07/16] Fix for bug in OpenSSL's 3DES CFB1 implementation OpenSSL 3DES CFB1 implementation assumes that the size of input data is in bits. It is indeed possible to use bits instead of bytes by setting an EVP_CIPHER_CTX flag EVP_CIPH_FLAG_LENGTH_BITS. However, this flag is not being checked in the implementation. The fix has been already applied to OpenSSL but not yet released. This commit causes EVP_CIPH_FLAG_LENGTH_BITS flag to be set always when 3DES CFB1 is used. It also performes conversion between bit and byte units if needed. It's a temporary fix and should also work with fixed OpenSSL. Anyway, as soon as the fix in OpenSSL is released this commit should be reverted. Change-Id: I97807f0afeecace86adb974e08e6f00fa66f22de --- src/encrypt.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/encrypt.c b/src/encrypt.c index ac53d66..d1b0698 100644 --- a/src/encrypt.c +++ b/src/encrypt.c @@ -269,6 +269,11 @@ static int encrypt_ctx_setup(struct yaca_encrypt_context_s *c, if (ret != YACA_ERROR_NONE) return ret; + /* Fix for OpenSSL error in 3DES CFB1 */ + int nid = EVP_CIPHER_CTX_nid(c->cipher_ctx); + if (nid == NID_des_ede3_cfb1) + EVP_CIPHER_CTX_set_flags(c->cipher_ctx, EVP_CIPH_FLAG_LENGTH_BITS); + if (liv != NULL) iv_data = (unsigned char*)liv->d; @@ -746,6 +751,13 @@ int encrypt_update(yaca_context_h ctx, if (input == NULL || output == NULL) return YACA_ERROR_INVALID_PARAMETER; + /* Fix for OpenSSL error in 3DES CFB1 */ + if ((c->cipher_ctx->flags & EVP_CIPH_FLAG_LENGTH_BITS) != 0) { + if (input_len > INT_MAX / 8) + return YACA_ERROR_INVALID_PARAMETER; + input_len *= 8; + } + ret = EVP_CipherUpdate(c->cipher_ctx, output, &loutput_len, input, input_len); if (ret != 1 || loutput_len < 0) { ret = YACA_ERROR_INTERNAL; @@ -754,6 +766,11 @@ int encrypt_update(yaca_context_h ctx, } *output_len = loutput_len; + + /* Fix for OpenSSL error in 3DES CFB1 */ + if ((c->cipher_ctx->flags & EVP_CIPH_FLAG_LENGTH_BITS) != 0) + *output_len /= 8; + return YACA_ERROR_NONE; } @@ -776,6 +793,11 @@ int encrypt_finalize(yaca_context_h ctx, } *output_len = loutput_len; + + /* Fix for OpenSSL error in 3DES CFB1 */ + if ((c->cipher_ctx->flags & EVP_CIPH_FLAG_LENGTH_BITS) != 0) + *output_len /= 8; + return YACA_ERROR_NONE; } -- 2.7.4 From 209afea7ec7b47dbe72e437b3f585d2d733c1b14 Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Thu, 4 Aug 2016 13:43:48 +0200 Subject: [PATCH 08/16] Fix documentation: RC4 doesn't use IV Change-Id: I9ab587999821709d02e4d9928ffb64a1fffa7ec4 --- api/yaca/yaca_types.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/api/yaca/yaca_types.h b/api/yaca/yaca_types.h index c675a12..5464d89 100755 --- a/api/yaca/yaca_types.h +++ b/api/yaca/yaca_types.h @@ -232,6 +232,7 @@ typedef enum { * #YACA_BCM_OFB,\n * #YACA_BCM_CFB,\n * #YACA_BCM_ECB + * - see #yaca_block_cipher_mode_e for details on additional properties (mandatory). */ YACA_ENCRYPT_UNSAFE_RC2, @@ -239,6 +240,7 @@ typedef enum { * RC4 encryption. * This is a variable key length cipher. * - Supported key lengths: 40–2048 bits in steps of 8 bits. + * No IV is used. * This cipher doesn't support block cipher modes, use #YACA_BCM_NONE instead. */ YACA_ENCRYPT_UNSAFE_RC4, @@ -265,6 +267,7 @@ typedef enum { typedef enum { /** * Used when algorithm doesn't support block ciphers modes. + * No IV is used. */ YACA_BCM_NONE, -- 2.7.4 From b5e2a62346b425d6b4e7c3c22cccdf149888d6ca Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Fri, 5 Aug 2016 17:35:13 +0200 Subject: [PATCH 09/16] Fix codestyle Change-Id: I1d34fa7eedc8c8de720245f0a70b0926df24c0a9 --- api/yaca/yaca_types.h | 4 ++-- src/crypto.c | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/api/yaca/yaca_types.h b/api/yaca/yaca_types.h index 17cddc9..a022ce3 100755 --- a/api/yaca/yaca_types.h +++ b/api/yaca/yaca_types.h @@ -462,8 +462,8 @@ typedef enum { /** * CBC block cipher mode. - * 16-byte initialization vector for AES, - * 8-byte for other algorithms is mandatory. + * 16-byte initialization vector for AES, + * 8-byte for other algorithms is mandatory. * * By default the input data is padded using standard block padding (aka PKCS#5 padding). * Padding can be disabled using yaca_context_set_property() and #YACA_PROPERTY_PADDING, #YACA_PADDING_NONE, diff --git a/src/crypto.c b/src/crypto.c index 32f1d70..87c153c 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -83,8 +83,7 @@ API int yaca_initialize(void) pthread_mutex_lock(&init_mutex); { - if (threads_cnt == 0) - { + if (threads_cnt == 0) { assert(mutexes == NULL); OPENSSL_init(); -- 2.7.4 From dc1956b77ab425d975c604fdbebb0323ffdeb51d Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Tue, 9 Aug 2016 17:36:24 +0200 Subject: [PATCH 10/16] Support EC keys for sign/verify operations Change-Id: I78bf6112e31de78aacb6902d3bd5c9e978cfcd32 --- src/sign.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/sign.c b/src/sign.c index 2576501..2e5fe25 100644 --- a/src/sign.c +++ b/src/sign.c @@ -251,9 +251,8 @@ API int yaca_sign_initialize(yaca_context_h *ctx, switch (key->type) { case YACA_KEY_TYPE_RSA_PRIV: case YACA_KEY_TYPE_DSA_PRIV: - break; case YACA_KEY_TYPE_EC_PRIV: - //TODO NOT_IMPLEMENTED + break; default: return YACA_ERROR_INVALID_PARAMETER; } @@ -503,9 +502,8 @@ API int yaca_verify_initialize(yaca_context_h *ctx, switch (key->type) { case YACA_KEY_TYPE_RSA_PUB: case YACA_KEY_TYPE_DSA_PUB: - break; case YACA_KEY_TYPE_EC_PUB: - //TODO NOT_IMPLEMENTED + break; default: return YACA_ERROR_INVALID_PARAMETER; } -- 2.7.4 From 2ac300b8e7063c1a2de88039bbbeae8869df37f8 Mon Sep 17 00:00:00 2001 From: Mateusz Forc Date: Tue, 9 Aug 2016 11:27:36 +0200 Subject: [PATCH 11/16] Fix documentation: Tag length is not set in decrypt / open Change-Id: I3d9c65847b82011d9ec48d3324aec0944d79c80a --- api/yaca/yaca_types.h | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/api/yaca/yaca_types.h b/api/yaca/yaca_types.h index a022ce3..2cf7d50 100755 --- a/api/yaca/yaca_types.h +++ b/api/yaca/yaca_types.h @@ -482,7 +482,8 @@ typedef enum { * (recommended 128 bits tag).\n * Set after yaca_encrypt_finalize() / yaca_seal_finalize() and before * yaca_context_get_property(#YACA_PROPERTY_GCM_TAG) - * in encryption / seal operation. The @a value should be a size_t variable.\n\n + * in encryption / seal operation. The @a value should be a size_t variable.\n + * In decryption / open operation tag length is not set.\n\n * * - #YACA_PROPERTY_GCM_TAG = GCM tag\n * Get after yaca_encrypt_finalize() / yaca_seal_finalize() in encryption / seal operation.\n @@ -495,8 +496,6 @@ typedef enum { * yaca_decrypt_update() / yaca_open_update() in decryption / open operation.\n\n * * @see yaca_context_set_property() - * @see examples/encrypt_aes_gcm_ccm.c - * @see examples/seal.c */ YACA_BCM_GCM, @@ -538,7 +537,8 @@ typedef enum { * Supported tag lengths: 32-128 bits in step of 16 bits (recommended 96 bits tag).\n * Set after yaca_encrypt_initialize() / yaca_seal_initialize() and before * yaca_encrypt_update() / yaca_seal_update() in encryption / seal operation. - * The @a value should be a size_t variable. \n\n + * The @a value should be a size_t variable.\n + * In decryption / open operation tag length is not set.\n\n * * - #YACA_PROPERTY_CCM_TAG = CCM tag\n * Get after yaca_encrypt_finalize() / yaca_seal_finalize() in encryption / seal operation.\n @@ -558,8 +558,7 @@ typedef enum { * Set after yaca_decrypt_initialize() / yaca_open_initialize() and before * yaca_decrypt_update() / yaca_open_update() in decryption / open operation.\n\n * - * @see examples/encrypt_aes_gcm_ccm.c - * @see examples/seal.c + * @see yaca_context_set_property() */ YACA_BCM_CCM, -- 2.7.4 From ebbf8b0723c30ece0d7ae849ec182a643e1eeab0 Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Mon, 8 Aug 2016 10:45:19 +0200 Subject: [PATCH 12/16] Fix: yaca_key_derive_dh() different parameters error Change-Id: Ia13fae08c15aa134c1fd84e3ae33e9a7f89d421c --- src/debug.c | 1 + src/key.c | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/debug.c b/src/debug.c index 7f9d470..0dbed34 100644 --- a/src/debug.c +++ b/src/debug.c @@ -129,6 +129,7 @@ int error_handle(const char *file, int line, const char *function) case ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_NOT_ENOUGH_DATA): case ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_ENCRYPTFINAL_EX, EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH): case ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_DECRYPTFINAL_EX, EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH): + case ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_DERIVE_SET_PEER, EVP_R_DIFFERENT_PARAMETERS): ret = YACA_ERROR_INVALID_PARAMETER; break; case ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_GET_OBJECT, ASN1_R_TOO_LONG): diff --git a/src/key.c b/src/key.c index 136a333..a79010c 100644 --- a/src/key.c +++ b/src/key.c @@ -1782,8 +1782,7 @@ API int yaca_key_derive_dh(const yaca_key_h prv_key, ret = EVP_PKEY_derive_set_peer(ctx, lpub_key->evp); if (ret != 1) { - ret = YACA_ERROR_INTERNAL; - ERROR_DUMP(ret); + ret = ERROR_HANDLE(); goto exit; } -- 2.7.4 From 275b1d2f4c45201b1a68a0fd297df717736482f7 Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Tue, 9 Aug 2016 14:57:50 +0200 Subject: [PATCH 13/16] Change yaca_key_derive_kdf() API Key material length should be in bytes. Fix key exchange example. Change-Id: I6b408a45d963d806f9abbb50056ed08da3a979fc --- api/yaca/yaca_key.h | 18 ++-- examples/key_exchange.c | 214 ++++++++++++++++++------------------------------ src/key.c | 10 +-- 3 files changed, 95 insertions(+), 147 deletions(-) diff --git a/api/yaca/yaca_key.h b/api/yaca/yaca_key.h index 81d0767..8cf4b93 100755 --- a/api/yaca/yaca_key.h +++ b/api/yaca/yaca_key.h @@ -371,14 +371,14 @@ int yaca_key_derive_dh(const yaca_key_h prv_key, * * @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 + * @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_len Length of a key material 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 @@ -399,7 +399,7 @@ int yaca_key_derive_kdf(yaca_kdf_e kdf, size_t secret_len, const char *info, size_t info_len, - size_t key_material_bit_len, + size_t key_material_len, char **key_material); /** diff --git a/examples/key_exchange.c b/examples/key_exchange.c index 836cc2a..cc645a9 100644 --- a/examples/key_exchange.c +++ b/examples/key_exchange.c @@ -36,12 +36,18 @@ static yaca_key_h exchange_keys(const yaca_key_h pkey) int ret; char *secret = NULL; size_t secret_len; + char *temp_material = NULL; + size_t temp_material_len; char *key_material = NULL; + size_t key_material_len; + char *iv_material = NULL; + size_t iv_material_len; 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; + yaca_key_h iv = YACA_KEY_NULL; ret = yaca_key_extract_parameters(pkey, ¶ms); if (ret != YACA_ERROR_NONE) @@ -60,47 +66,57 @@ static yaca_key_h exchange_keys(const yaca_key_h pkey) if (ret != YACA_ERROR_NONE) goto exit; + key_material_len = YACA_KEY_LENGTH_192BIT / 8; + iv_material_len = YACA_KEY_LENGTH_IV_128BIT / 8; + temp_material_len = key_material_len + iv_material_len; ret = yaca_key_derive_kdf(YACA_KDF_X962, YACA_DIGEST_SHA512, secret, secret_len, - NULL, 0, YACA_KEY_LENGTH_192BIT, &key_material); + NULL, 0, temp_material_len, &temp_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); + key_material = temp_material; + iv_material = temp_material + key_material_len; + + ret = yaca_key_import(YACA_KEY_TYPE_SYMMETRIC, NULL, key_material, key_material_len, &aes_key); + if (ret != YACA_ERROR_NONE) + goto exit; + + ret = yaca_key_import(YACA_KEY_TYPE_IV, NULL, iv_material, iv_material_len, &iv); 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: *****"); + dump_hex(key_material, key_material_len, "\n***** Peer AES key: *****"); + dump_hex(iv_material, iv_material_len, "\n***** Peer IV: *****"); exit: yaca_key_destroy(private_key); yaca_key_destroy(params); yaca_key_destroy(aes_key); + yaca_key_destroy(iv); yaca_free(secret); - yaca_free(key_material); + yaca_free(temp_material); return public_key; } -void key_exchange_dh_standard_parameters(void) +void key_derivation(const yaca_key_h private_key) { int ret; char *secret = NULL; size_t secret_len; + char *temp_material = NULL; + size_t temp_material_len; char *key_material = NULL; + size_t key_material_len; + char *iv_material = NULL; + size_t iv_material_len; - 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 *****"); - - /* generate private, public key */ - ret = yaca_key_generate(YACA_KEY_TYPE_DH_PRIV, YACA_KEY_LENGTH_DH_RFC_2048_256, &private_key); - if (ret != YACA_ERROR_NONE) - goto exit; + yaca_key_h iv = YACA_KEY_NULL; ret = yaca_key_extract_public(private_key, &public_key); if (ret != YACA_ERROR_NONE) @@ -116,158 +132,90 @@ void key_exchange_dh_standard_parameters(void) if (ret != YACA_ERROR_NONE) goto exit; + key_material_len = YACA_KEY_LENGTH_192BIT / 8; + iv_material_len = YACA_KEY_LENGTH_IV_128BIT / 8; + temp_material_len = key_material_len + iv_material_len; 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) -{ - 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 *****"); + NULL, 0, temp_material_len, &temp_material); - /* generate parameters */ - ret = yaca_key_generate(YACA_KEY_TYPE_DH_PARAMS, - YACA_KEY_LENGTH_DH_GENERATOR_2 | 1024, ¶ms); if (ret != YACA_ERROR_NONE) goto exit; - /* generate private, public key */ - ret = yaca_key_generate_from_parameters(params, &private_key); - if (ret != YACA_ERROR_NONE) - goto exit; + key_material = temp_material; + iv_material = temp_material + key_material_len; - ret = yaca_key_extract_public(private_key, &public_key); + ret = yaca_key_import(YACA_KEY_TYPE_SYMMETRIC, NULL, key_material, key_material_len, &aes_key); if (ret != YACA_ERROR_NONE) goto exit; - /* get peer public key */ - peer_key = exchange_keys(public_key); - if (peer_key == YACA_KEY_NULL) - goto exit; - - /* derive secret */ - ret = yaca_key_derive_dh(private_key, peer_key, &secret, &secret_len); - 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); + ret = yaca_key_import(YACA_KEY_TYPE_IV, NULL, iv_material, iv_material_len, &iv); 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: *****"); + dump_hex(key_material, key_material_len, "\n***** My AES key: *****"); + dump_hex(iv_material, iv_material_len, "\n***** My IV: *****"); 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_key_destroy(iv); yaca_free(secret); - yaca_free(key_material); + yaca_free(temp_material); } -void key_exchange_ecdh(void) +int main() { - 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 *****"); - - /* generate private, public key */ - ret = yaca_key_generate(YACA_KEY_TYPE_EC_PRIV, YACA_KEY_LENGTH_EC_PRIME256V1, &private_key); - if (ret != YACA_ERROR_NONE) - goto exit; - - ret = yaca_key_extract_public(private_key, &public_key); - if (ret != YACA_ERROR_NONE) - goto exit; + yaca_debug_set_error_cb(debug_func); - /* get peer public key */ - peer_key = exchange_keys(public_key); - if (peer_key == YACA_KEY_NULL) - goto exit; + yaca_key_h ecdh_key = YACA_KEY_NULL; + yaca_key_h dh_params = YACA_KEY_NULL; + yaca_key_h dh_key_from_params = YACA_KEY_NULL; + yaca_key_h dh_key = YACA_KEY_NULL; - /* derive secret */ - ret = yaca_key_derive_dh(private_key, peer_key, &secret, &secret_len); + int ret = yaca_initialize(); if (ret != YACA_ERROR_NONE) - goto exit; + return ret; - 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; + printf("\n***** Elliptic Curve Diffie Hellman key exchange and key/iv derivation *****"); + { + ret = yaca_key_generate(YACA_KEY_TYPE_EC_PRIV, YACA_KEY_LENGTH_EC_PRIME256V1, &ecdh_key); + 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; + key_derivation(ecdh_key); + } - dump_hex(secret, secret_len, "\n***** My Secret: *****"); - dump_hex(key_material, YACA_KEY_LENGTH_192BIT, "\n***** My AES key: *****"); + printf("\n***** Diffie Hellman Diffie Hellman key exchange and key/iv derivation *****"); + { + ret = yaca_key_generate(YACA_KEY_TYPE_DH_PARAMS, + YACA_KEY_LENGTH_DH_GENERATOR_2 | 1024, &dh_params); + if (ret != YACA_ERROR_NONE) + goto exit; -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); -} + ret = yaca_key_generate_from_parameters(dh_params, &dh_key_from_params); + if (ret != YACA_ERROR_NONE) + goto exit; -int main() -{ - yaca_debug_set_error_cb(debug_func); + key_derivation(dh_key_from_params); + } - int ret = yaca_initialize(); - if (ret != YACA_ERROR_NONE) - return ret; + printf("\n***** Diffie Hellman Diffie Hellman key exchange and key/iv derivation *****"); + { + ret = yaca_key_generate(YACA_KEY_TYPE_DH_PRIV, YACA_KEY_LENGTH_DH_RFC_2048_256, &dh_key); + if (ret != YACA_ERROR_NONE) + goto exit; - key_exchange_dh_standard_parameters(); - key_exchange_dh_generated_parameters(); - key_exchange_ecdh(); + key_derivation(dh_key); + } +exit: + yaca_key_destroy(ecdh_key); + yaca_key_destroy(dh_params); + yaca_key_destroy(dh_key_from_params); + yaca_key_destroy(dh_key); yaca_cleanup(); + return ret; } diff --git a/src/key.c b/src/key.c index a79010c..92bc8a3 100644 --- a/src/key.c +++ b/src/key.c @@ -1827,7 +1827,7 @@ API int yaca_key_derive_kdf(yaca_kdf_e kdf, size_t secret_len, const char *info, size_t info_len, - size_t key_material_bit_len, + size_t key_material_len, char **key_material) { int ret; @@ -1836,10 +1836,10 @@ API int yaca_key_derive_kdf(yaca_kdf_e kdf, if (secret == NULL || secret_len == 0 || (info == NULL && info_len > 0) || (info != NULL && info_len == 0) || - key_material_bit_len == 0 || key_material == NULL) + key_material_len == 0 || key_material == NULL) return YACA_ERROR_INVALID_PARAMETER; - ret = yaca_zalloc(key_material_bit_len, (void**)&out); + ret = yaca_zalloc(key_material_len, (void**)&out); if (ret != YACA_ERROR_NONE) return ret; @@ -1849,7 +1849,7 @@ API int yaca_key_derive_kdf(yaca_kdf_e kdf, switch (kdf) { case YACA_KDF_X942: - ret = DH_KDF_X9_42((unsigned char*)out, key_material_bit_len, + ret = DH_KDF_X9_42((unsigned char*)out, key_material_len, (unsigned char*)secret, secret_len, OBJ_nid2obj(NID_id_smime_alg_ESDH), (unsigned char*)info, info_len, md); if (ret != 1 || out == NULL) { @@ -1859,7 +1859,7 @@ API int yaca_key_derive_kdf(yaca_kdf_e kdf, } break; case YACA_KDF_X962: - ret = ECDH_KDF_X9_62((unsigned char*)out, key_material_bit_len, + ret = ECDH_KDF_X9_62((unsigned char*)out, key_material_len, (unsigned char*)secret, secret_len, (unsigned char*)info, info_len, md); if (ret != 1 || out == NULL) { -- 2.7.4 From 49ca825cf81e710e0c9df5ceb49a7f2419ede688 Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Mon, 8 Aug 2016 15:01:15 +0200 Subject: [PATCH 14/16] Static encrypt/digest algo list Change-Id: I81e416d21ab22d119c6ec6ad9f79834ef151b2a2 --- src/digest.c | 52 ++++++++------- src/encrypt.c | 203 ++++++++++++++++++++++++++-------------------------------- 2 files changed, 116 insertions(+), 139 deletions(-) diff --git a/src/digest.c b/src/digest.c index fa342bb..0d7b426 100644 --- a/src/digest.c +++ b/src/digest.c @@ -31,6 +31,20 @@ #include "internal.h" +static const struct { + yaca_digest_algorithm_e algo; + const EVP_MD *(*digest)(void); +} MESSAGE_DIGESTS[] = { + {YACA_DIGEST_MD5, EVP_md5}, + {YACA_DIGEST_SHA1, EVP_sha1}, + {YACA_DIGEST_SHA224, EVP_sha224}, + {YACA_DIGEST_SHA256, EVP_sha256}, + {YACA_DIGEST_SHA384, EVP_sha384}, + {YACA_DIGEST_SHA512, EVP_sha512}, +}; + +static const size_t MESSAGE_DIGESTS_SIZE = sizeof(MESSAGE_DIGESTS) / sizeof(MESSAGE_DIGESTS[0]); + struct yaca_digest_context_s { struct yaca_context_s ctx; @@ -83,36 +97,20 @@ static void destroy_digest_context(yaca_context_h ctx) int digest_get_algorithm(yaca_digest_algorithm_e algo, const EVP_MD **md) { - int ret = YACA_ERROR_NONE; + int ret; + size_t i; - if (!md) - return YACA_ERROR_INVALID_PARAMETER; + assert(md != NULL); *md = NULL; - - switch (algo) { - case YACA_DIGEST_MD5: - *md = EVP_md5(); - break; - case YACA_DIGEST_SHA1: - *md = EVP_sha1(); - break; - case YACA_DIGEST_SHA224: - *md = EVP_sha224(); - break; - case YACA_DIGEST_SHA256: - *md = EVP_sha256(); - break; - case YACA_DIGEST_SHA384: - *md = EVP_sha384(); - break; - case YACA_DIGEST_SHA512: - *md = EVP_sha512(); - break; - default: - ret = YACA_ERROR_INVALID_PARAMETER; - break; - } + ret = YACA_ERROR_INVALID_PARAMETER; + + for (i = 0; i < MESSAGE_DIGESTS_SIZE; ++i) + if (MESSAGE_DIGESTS[i].algo == algo) { + *md = MESSAGE_DIGESTS[i].digest(); + ret = YACA_ERROR_NONE; + break; + } if (ret == YACA_ERROR_NONE && *md == NULL) { ret = YACA_ERROR_INTERNAL; diff --git a/src/encrypt.c b/src/encrypt.c index a58bcdf..070a1f2 100644 --- a/src/encrypt.c +++ b/src/encrypt.c @@ -38,6 +38,80 @@ static const size_t DEFAULT_GCM_TAG_LEN = 16; static const size_t DEFAULT_CCM_TAG_LEN = 12; +static const struct { + yaca_encrypt_algorithm_e algo; + yaca_block_cipher_mode_e bcm; + size_t key_bit_len; + const EVP_CIPHER *(*cipher)(void); +} ENCRYPTION_CIPHERS[] = { + {YACA_ENCRYPT_AES, YACA_BCM_CBC, 128, EVP_aes_128_cbc}, + {YACA_ENCRYPT_AES, YACA_BCM_CCM, 128, EVP_aes_128_ccm}, + {YACA_ENCRYPT_AES, YACA_BCM_CFB, 128, EVP_aes_128_cfb}, + {YACA_ENCRYPT_AES, YACA_BCM_CFB1, 128, EVP_aes_128_cfb1}, + {YACA_ENCRYPT_AES, YACA_BCM_CFB8, 128, EVP_aes_128_cfb8}, + {YACA_ENCRYPT_AES, YACA_BCM_CTR, 128, EVP_aes_128_ctr}, + {YACA_ENCRYPT_AES, YACA_BCM_ECB, 128, EVP_aes_128_ecb}, + {YACA_ENCRYPT_AES, YACA_BCM_GCM, 128, EVP_aes_128_gcm}, + {YACA_ENCRYPT_AES, YACA_BCM_OFB, 128, EVP_aes_128_ofb}, + {YACA_ENCRYPT_AES, YACA_BCM_WRAP, 128, EVP_aes_128_wrap}, + + {YACA_ENCRYPT_AES, YACA_BCM_CBC, 192, EVP_aes_192_cbc}, + {YACA_ENCRYPT_AES, YACA_BCM_CCM, 192, EVP_aes_192_ccm}, + {YACA_ENCRYPT_AES, YACA_BCM_CFB, 192, EVP_aes_192_cfb}, + {YACA_ENCRYPT_AES, YACA_BCM_CFB1, 192, EVP_aes_192_cfb1}, + {YACA_ENCRYPT_AES, YACA_BCM_CFB8, 192, EVP_aes_192_cfb8}, + {YACA_ENCRYPT_AES, YACA_BCM_CTR, 192, EVP_aes_192_ctr}, + {YACA_ENCRYPT_AES, YACA_BCM_ECB, 192, EVP_aes_192_ecb}, + {YACA_ENCRYPT_AES, YACA_BCM_GCM, 192, EVP_aes_192_gcm}, + {YACA_ENCRYPT_AES, YACA_BCM_OFB, 192, EVP_aes_192_ofb}, + {YACA_ENCRYPT_AES, YACA_BCM_WRAP, 192, EVP_aes_192_wrap}, + + {YACA_ENCRYPT_AES, YACA_BCM_CBC, 256, EVP_aes_256_cbc}, + {YACA_ENCRYPT_AES, YACA_BCM_CCM, 256, EVP_aes_256_ccm}, + {YACA_ENCRYPT_AES, YACA_BCM_CFB, 256, EVP_aes_256_cfb}, + {YACA_ENCRYPT_AES, YACA_BCM_CFB1, 256, EVP_aes_256_cfb1}, + {YACA_ENCRYPT_AES, YACA_BCM_CFB8, 256, EVP_aes_256_cfb8}, + {YACA_ENCRYPT_AES, YACA_BCM_CTR, 256, EVP_aes_256_ctr}, + {YACA_ENCRYPT_AES, YACA_BCM_ECB, 256, EVP_aes_256_ecb}, + {YACA_ENCRYPT_AES, YACA_BCM_GCM, 256, EVP_aes_256_gcm}, + {YACA_ENCRYPT_AES, YACA_BCM_OFB, 256, EVP_aes_256_ofb}, + {YACA_ENCRYPT_AES, YACA_BCM_WRAP, 256, EVP_aes_256_wrap}, + + {YACA_ENCRYPT_UNSAFE_DES, YACA_BCM_CBC, -1, EVP_des_cbc}, + {YACA_ENCRYPT_UNSAFE_DES, YACA_BCM_CFB, -1, EVP_des_cfb}, + {YACA_ENCRYPT_UNSAFE_DES, YACA_BCM_CFB1, -1, EVP_des_cfb1}, + {YACA_ENCRYPT_UNSAFE_DES, YACA_BCM_CFB8, -1, EVP_des_cfb8}, + {YACA_ENCRYPT_UNSAFE_DES, YACA_BCM_ECB, -1, EVP_des_ecb}, + {YACA_ENCRYPT_UNSAFE_DES, YACA_BCM_OFB, -1, EVP_des_ofb}, + + {YACA_ENCRYPT_UNSAFE_3DES_2TDEA, YACA_BCM_CBC, -1, EVP_des_ede_cbc}, + {YACA_ENCRYPT_UNSAFE_3DES_2TDEA, YACA_BCM_CFB, -1, EVP_des_ede_cfb}, + {YACA_ENCRYPT_UNSAFE_3DES_2TDEA, YACA_BCM_ECB, -1, EVP_des_ede_ecb}, + {YACA_ENCRYPT_UNSAFE_3DES_2TDEA, YACA_BCM_OFB, -1, EVP_des_ede_ofb}, + + {YACA_ENCRYPT_3DES_3TDEA, YACA_BCM_CBC, -1, EVP_des_ede3_cbc}, + {YACA_ENCRYPT_3DES_3TDEA, YACA_BCM_CFB, -1, EVP_des_ede3_cfb}, + {YACA_ENCRYPT_3DES_3TDEA, YACA_BCM_CFB1, -1, EVP_des_ede3_cfb1}, + {YACA_ENCRYPT_3DES_3TDEA, YACA_BCM_CFB8, -1, EVP_des_ede3_cfb8}, + {YACA_ENCRYPT_3DES_3TDEA, YACA_BCM_ECB, -1, EVP_des_ede3_ecb}, + {YACA_ENCRYPT_3DES_3TDEA, YACA_BCM_OFB, -1, EVP_des_ede3_ofb}, + {YACA_ENCRYPT_3DES_3TDEA, YACA_BCM_WRAP, -1, EVP_des_ede3_wrap}, + + {YACA_ENCRYPT_UNSAFE_RC2, YACA_BCM_CBC, -1, EVP_rc2_cbc}, + {YACA_ENCRYPT_UNSAFE_RC2, YACA_BCM_CFB, -1, EVP_rc2_cfb}, + {YACA_ENCRYPT_UNSAFE_RC2, YACA_BCM_ECB, -1, EVP_rc2_ecb}, + {YACA_ENCRYPT_UNSAFE_RC2, YACA_BCM_OFB, -1, EVP_rc2_ofb}, + + {YACA_ENCRYPT_UNSAFE_RC4, YACA_BCM_NONE, -1, EVP_rc4}, + + {YACA_ENCRYPT_CAST5, YACA_BCM_CBC, -1, EVP_cast5_cbc}, + {YACA_ENCRYPT_CAST5, YACA_BCM_CFB, -1, EVP_cast5_cfb}, + {YACA_ENCRYPT_CAST5, YACA_BCM_ECB, -1, EVP_cast5_ecb}, + {YACA_ENCRYPT_CAST5, YACA_BCM_OFB, -1, EVP_cast5_ofb}, +}; + +static const size_t ENCRYPTION_CIPHERS_SIZE = sizeof(ENCRYPTION_CIPHERS) / sizeof(ENCRYPTION_CIPHERS[0]); + static bool is_encryption_op(enum encrypt_op_type_e op_type) { return (op_type == OP_ENCRYPT || op_type == OP_SEAL); @@ -568,58 +642,6 @@ int get_encrypt_property(const yaca_context_h ctx, yaca_property_e property, return YACA_ERROR_NONE; } -static const char *encrypt_algo_to_str(yaca_encrypt_algorithm_e algo) -{ - switch (algo) { - case YACA_ENCRYPT_AES: - return "aes"; - case YACA_ENCRYPT_UNSAFE_DES: - return "des"; - case YACA_ENCRYPT_UNSAFE_3DES_2TDEA: - return "des-ede"; - case YACA_ENCRYPT_3DES_3TDEA: - return "des-ede3"; - case YACA_ENCRYPT_UNSAFE_RC2: - return "rc2"; - case YACA_ENCRYPT_UNSAFE_RC4: - return "rc4"; - case YACA_ENCRYPT_CAST5: - return "cast5"; - default: - return NULL; - } -} - -static const char *bcm_to_str(yaca_block_cipher_mode_e bcm) -{ - switch (bcm) { - case YACA_BCM_NONE: - return "none"; - case YACA_BCM_ECB: - return "ecb"; - case YACA_BCM_CBC: - return "cbc"; - case YACA_BCM_CTR: - return "ctr"; - case YACA_BCM_GCM: - return "gcm"; - case YACA_BCM_CFB: - return "cfb"; - case YACA_BCM_CFB1: - return "cfb1"; - case YACA_BCM_CFB8: - return "cfb8"; - case YACA_BCM_OFB: - return "ofb"; - case YACA_BCM_CCM: - return "ccm"; - case YACA_BCM_WRAP: - return "wrap"; - default: - return NULL; - } -} - static int check_key_bit_length_for_algo(yaca_encrypt_algorithm_e algo, size_t key_bit_len) { assert(key_bit_len % 8 == 0); @@ -669,79 +691,36 @@ int encrypt_get_algorithm(yaca_encrypt_algorithm_e algo, size_t key_bit_len, const EVP_CIPHER **cipher) { - char cipher_name[32]; - const char *algo_name = encrypt_algo_to_str(algo); - const char *bcm_name = bcm_to_str(bcm); - const EVP_CIPHER *lcipher; int ret; + size_t i; assert(cipher != NULL); - if (algo_name == NULL || bcm_name == NULL || key_bit_len == 0) - return YACA_ERROR_INVALID_PARAMETER; - ret = check_key_bit_length_for_algo(algo, key_bit_len); if (ret != YACA_ERROR_NONE) return ret; - switch (algo) { - case YACA_ENCRYPT_AES: - if (bcm == YACA_BCM_WRAP) - ret = snprintf(cipher_name, sizeof(cipher_name), "id-%s%zu-%s", - algo_name, key_bit_len, bcm_name); - else - ret = snprintf(cipher_name, sizeof(cipher_name), "%s-%zu-%s", - algo_name, key_bit_len, bcm_name); - break; - case YACA_ENCRYPT_UNSAFE_DES: - case YACA_ENCRYPT_UNSAFE_RC2: - case YACA_ENCRYPT_CAST5: - ret = snprintf(cipher_name, sizeof(cipher_name), "%s-%s", - algo_name, bcm_name); - break; - case YACA_ENCRYPT_UNSAFE_3DES_2TDEA: - if (bcm == YACA_BCM_ECB) - ret = snprintf(cipher_name, sizeof(cipher_name), "%s", algo_name); - else - ret = snprintf(cipher_name, sizeof(cipher_name), "%s-%s", - algo_name, bcm_name); - break; - case YACA_ENCRYPT_3DES_3TDEA: - if (bcm == YACA_BCM_ECB) - ret = snprintf(cipher_name, sizeof(cipher_name), "%s", algo_name); - else if (bcm == YACA_BCM_WRAP) - ret = snprintf(cipher_name, sizeof(cipher_name), "id-smime-alg-CMS3DESwrap"); - else - ret = snprintf(cipher_name, sizeof(cipher_name), "%s-%s", - algo_name, bcm_name); - break; - case YACA_ENCRYPT_UNSAFE_RC4: - if (bcm != YACA_BCM_NONE) - ret = YACA_ERROR_INVALID_PARAMETER; - else - ret = snprintf(cipher_name, sizeof(cipher_name), "%s", algo_name); - break; - default: - return YACA_ERROR_INVALID_PARAMETER; - } - - if (ret < 0) - return YACA_ERROR_INVALID_PARAMETER; - if ((unsigned)ret >= sizeof(cipher_name)) /* output was truncated */ - return YACA_ERROR_INVALID_PARAMETER; + *cipher = NULL; + ret = YACA_ERROR_INVALID_PARAMETER; + + for (i = 0; i < ENCRYPTION_CIPHERS_SIZE; ++i) + if (ENCRYPTION_CIPHERS[i].algo == algo && + ENCRYPTION_CIPHERS[i].bcm == bcm && + (ENCRYPTION_CIPHERS[i].key_bit_len == key_bit_len || + ENCRYPTION_CIPHERS[i].key_bit_len == (size_t)-1)) { + *cipher = ENCRYPTION_CIPHERS[i].cipher(); + ret = YACA_ERROR_NONE; + break; + } - lcipher = EVP_get_cipherbyname(cipher_name); - if (lcipher == NULL) { - ret = YACA_ERROR_INVALID_PARAMETER; - ERROR_CLEAR(); - return ret; + if (ret == YACA_ERROR_NONE && *cipher == NULL) { + ret = YACA_ERROR_INTERNAL; + ERROR_DUMP(ret); } - *cipher = lcipher; - return YACA_ERROR_NONE; + return ret; } - int encrypt_initialize(yaca_context_h *ctx, const EVP_CIPHER *cipher, const yaca_key_h sym_key, -- 2.7.4 From 4678c0a60d048e9b38aa12941fbfc7582f479d2f Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Thu, 11 Aug 2016 12:35:56 +0200 Subject: [PATCH 15/16] Add missing 'library' in function description Change-Id: Ic4d7da6a0201e4cc131737b56d5903abb9fb137a --- api/yaca/yaca_simple.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/yaca/yaca_simple.h b/api/yaca/yaca_simple.h index e151397..e39e347 100755 --- a/api/yaca/yaca_simple.h +++ b/api/yaca/yaca_simple.h @@ -162,7 +162,7 @@ int yaca_simple_decrypt(yaca_encrypt_algorithm_e algo, * - #YACA_KEY_TYPE_DSA_PRIV, * @param[in] data Data to be signed * @param[in] data_len Length of the data - * @param[out] signature Message signature, will be allocated by the + * @param[out] signature Message signature, will be allocated by the library * @param[out] signature_len Length of the signature * * @return #YACA_ERROR_NONE on success, negative on error -- 2.7.4 From c7aa00cd3c539af51107b31137e808581a897383 Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Thu, 11 Aug 2016 17:10:49 +0200 Subject: [PATCH 16/16] Use PKCS5 v2 in PKCS8 encrypted export Change-Id: Ia8f28768aca7b669e44b8b61c84625e5c811c033 --- api/yaca/yaca_key.h | 3 ++- src/key.c | 10 +++++----- todo.txt | 1 - 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/api/yaca/yaca_key.h b/api/yaca/yaca_key.h index 8cf4b93..b9bf0b1 100755 --- a/api/yaca/yaca_key.h +++ b/api/yaca/yaca_key.h @@ -172,7 +172,8 @@ int yaca_key_import(yaca_key_type_e key_type, * * @remarks Encryption is obligatory for #YACA_KEY_FORMAT_PKCS8 format (for both, PEM and DER * file formats). If no password is provided the #YACA_ERROR_INVALID_PARAMETER will - * be returned. The encryption algorithm used in this case is PBE with DES-CBC. + * be returned. The encryption algorithm used in this case is AES-256-CBC. The key is + * generated from password using PBKDF2 with HMAC-SHA1 function and 2048 iterations. * * @remarks Encryption is not supported for the symmetric, public keys and key generation * parameters in all their supported formats. If a password is provided in such diff --git a/src/key.c b/src/key.c index 92bc8a3..35ca37e 100644 --- a/src/key.c +++ b/src/key.c @@ -809,7 +809,7 @@ static int export_evp_pkcs8_bio(struct yaca_key_evp_s *evp_key, assert(mem != NULL); int ret; - int nid = NID_pbeWithMD5AndDES_CBC; + const EVP_CIPHER *enc = EVP_aes_256_cbc();; /* PKCS8 export requires a password */ if (password == NULL) @@ -824,8 +824,8 @@ static int export_evp_pkcs8_bio(struct yaca_key_evp_s *evp_key, case YACA_KEY_TYPE_DSA_PRIV: case YACA_KEY_TYPE_DH_PRIV: case YACA_KEY_TYPE_EC_PRIV: - ret = PEM_write_bio_PKCS8PrivateKey_nid(mem, evp_key->evp, nid, - NULL, 0, NULL, (void*)password); + ret = PEM_write_bio_PKCS8PrivateKey(mem, evp_key->evp, enc, + NULL, 0, NULL, (void*)password); break; default: @@ -841,8 +841,8 @@ static int export_evp_pkcs8_bio(struct yaca_key_evp_s *evp_key, case YACA_KEY_TYPE_DSA_PRIV: case YACA_KEY_TYPE_DH_PRIV: case YACA_KEY_TYPE_EC_PRIV: - ret = i2d_PKCS8PrivateKey_nid_bio(mem, evp_key->evp, nid, - NULL, 0, NULL, (void*)password); + ret = i2d_PKCS8PrivateKey_bio(mem, evp_key->evp, enc, + NULL, 0, NULL, (void*)password); break; default: diff --git a/todo.txt b/todo.txt index c33b5d7..99c60ce 100644 --- a/todo.txt +++ b/todo.txt @@ -8,4 +8,3 @@ Global: - We need a way to import keys encrypted with hw (or other) keys. New function like yaca_key_load or sth? - Add extended description and examples in documentation. -- Check PKCS8 with PKCS5 2.0 (EVP cipher instead of PBE) -- 2.7.4