From 04b77abf66cf36be5b411d81311918ea6f59d83d Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Mon, 9 May 2016 16:30:23 +0200 Subject: [PATCH 01/16] Add support to DES encrypt/decrypt. Update documentation. Change-Id: Ide2d1f93cd2deef711a7fdfd2dd922f46f8f3637 --- api/yaca/types.h | 22 ++++++++++++++++++--- src/encrypt.c | 60 +++++++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 63 insertions(+), 19 deletions(-) diff --git a/api/yaca/types.h b/api/yaca/types.h index 5b8c6b6..4363932 100644 --- a/api/yaca/types.h +++ b/api/yaca/types.h @@ -139,24 +139,40 @@ typedef enum { /** * DES encryption. + * - Supported key lengths: @c 64. + * - Supported block cipher modes: + * #YACA_BCM_CBC, + * #YACA_BCM_OFB, + * #YACA_BCM_CFB, + * #YACA_BCM_ECB * - see #yaca_block_cipher_mode_e for details on additional parameters (mandatory). - * - Supported key lengths: @c 56. */ YACA_ENC_UNSAFE_DES, /** * 3DES 2-key encryption. + * - Supported key lengths: @c 128. + * - Supported block cipher modes: + * #YACA_BCM_CBC, + * #YACA_BCM_OFB, + * #YACA_BCM_CFB, + * #YACA_BCM_ECB * - see #yaca_block_cipher_mode_e for details on additional parameters (mandatory). * - Use double DES keys to perform corresponding 2-key 3DES encryption. - * - Supported key lengths: @c 112. + */ YACA_ENC_UNSAFE_3DES_2TDEA, /** * 3DES 3-key encryption. + * - Supported key lengths: @c 192. + * - Supported block cipher modes: + * #YACA_BCM_CBC, + * #YACA_BCM_OFB, + * #YACA_BCM_CFB, + * #YACA_BCM_ECB * - see #yaca_block_cipher_mode_e for details on additional parameters (mandatory). * - Use triple DES keys to perform corresponding 3-key 3DES encryption. - * - Supported key lengths: @c 168. */ YACA_ENC_3DES_3TDEA, diff --git a/src/encrypt.c b/src/encrypt.c index 40aa2ee..ad2334b 100644 --- a/src/encrypt.c +++ b/src/encrypt.c @@ -95,6 +95,10 @@ static const char *encrypt_algo_to_str(yaca_enc_algo_e algo) return "aes"; case YACA_ENC_UNSAFE_DES: return "des"; + case YACA_ENC_UNSAFE_3DES_2TDEA: + return "des-ede"; + case YACA_ENC_3DES_3TDEA: + return "des-ede3"; case YACA_ENC_UNSAFE_RC2: return "rc2"; case YACA_ENC_UNSAFE_RC4: @@ -102,8 +106,6 @@ static const char *encrypt_algo_to_str(yaca_enc_algo_e algo) case YACA_ENC_CAST5: return "cast5"; - case YACA_ENC_UNSAFE_3DES_2TDEA: // TODO: add 3des/2tdea support - case YACA_ENC_3DES_3TDEA: // TODO: add 3des/3tdea support case YACA_ENC_UNSAFE_SKIPJACK: // TODO: add skipjack implementation default: return NULL; @@ -149,8 +151,32 @@ int encrypt_get_algorithm(yaca_enc_algo_e algo, cipher == NULL) return YACA_ERROR_INVALID_ARGUMENT; - ret = snprintf(cipher_name, sizeof(cipher_name), "%s-%zu-%s", algo_name, - key_bits, bcm_name); + switch(algo) + { + case YACA_ENC_AES: + ret = snprintf(cipher_name, sizeof(cipher_name), "%s-%zu-%s", + algo_name, key_bits, bcm_name); + break; + case YACA_ENC_UNSAFE_DES: + ret = snprintf(cipher_name, sizeof(cipher_name), "%s-%s", + algo_name, bcm_name); + break; + case YACA_ENC_UNSAFE_3DES_2TDEA: + case YACA_ENC_3DES_3TDEA: + 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_ENC_UNSAFE_RC2: + case YACA_ENC_UNSAFE_RC4: + case YACA_ENC_CAST5: + case YACA_ENC_UNSAFE_SKIPJACK: + default: + return YACA_ERROR_NOT_IMPLEMENTED; + } + if (ret < 0) return YACA_ERROR_INVALID_ARGUMENT; if ((unsigned)ret >= sizeof(cipher_name)) // output was truncated @@ -179,6 +205,7 @@ static int encrypt_init(yaca_ctx_h *ctx, struct yaca_encrypt_ctx_s *nc; const EVP_CIPHER *cipher; int key_bits; + unsigned char *iv_data = NULL; int iv_bits; int ret; @@ -221,16 +248,17 @@ static int encrypt_init(yaca_ctx_h *ctx, goto err_free; } - liv = key_get_simple(iv); - if (ret != 0 && liv == NULL) { /* cipher requires iv, but none was provided */ - ret = YACA_ERROR_INVALID_ARGUMENT; - goto err_free; - } - - // TODO: handling of algorithms with variable IV length - if (iv_bits != yaca_key_get_bits(iv)) { /* IV length doesn't match cipher */ - ret = YACA_ERROR_INVALID_ARGUMENT; - goto err_free; + if (iv_bits != 0) { /* cipher requires iv*/ + liv = key_get_simple(iv); + if (liv == NULL) { /* iv was not provided */ + ret = YACA_ERROR_INVALID_ARGUMENT; + goto err_free; + } + if (iv_bits != yaca_key_get_bits(iv)) { /* IV length doesn't match cipher */ + ret = YACA_ERROR_INVALID_ARGUMENT; + goto err_free; + } + iv_data = (unsigned char*)liv->d; } nc->cipher_ctx = EVP_CIPHER_CTX_new(); @@ -244,12 +272,12 @@ static int encrypt_init(yaca_ctx_h *ctx, case OP_ENCRYPT: ret = EVP_EncryptInit(nc->cipher_ctx, cipher, (unsigned char*)lkey->d, - (unsigned char*)liv->d); + iv_data); break; case OP_DECRYPT: ret = EVP_DecryptInit(nc->cipher_ctx, cipher, (unsigned char*)lkey->d, - (unsigned char*)liv->d); + iv_data); break; default: ret = YACA_ERROR_INVALID_ARGUMENT; -- 2.7.4 From 2837f2a23d0a01c428142c966ace8aeff78791e2 Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Tue, 10 May 2016 14:57:30 +0200 Subject: [PATCH 02/16] Add support to CAST5 encrypt/decrypt. Update documentation. Change-Id: I645018182fc723190223eac627c665d84da41340 --- api/yaca/types.h | 9 +++++++-- src/encrypt.c | 42 +++++++++++++++++++++++++++++++++++------- 2 files changed, 42 insertions(+), 9 deletions(-) diff --git a/api/yaca/types.h b/api/yaca/types.h index 4363932..3397e86 100644 --- a/api/yaca/types.h +++ b/api/yaca/types.h @@ -192,9 +192,14 @@ typedef enum { /** * CAST5 encryption. + * This is a variable key length cipher. + * Supported key lengths: 40-128 bits in steps of 8 bits. + * - Supported block cipher modes: + * #YACA_BCM_CBC, + * #YACA_BCM_OFB, + * #YACA_BCM_CFB, + * #YACA_BCM_ECB * - see #yaca_block_cipher_mode_e for details on additional parameters (mandatory). - * - The key length is extracted from the key buffer. - * - Supported key lengths: 40-128 bits in steps of 8 bits. */ YACA_ENC_CAST5, diff --git a/src/encrypt.c b/src/encrypt.c index ad2334b..d185c16 100644 --- a/src/encrypt.c +++ b/src/encrypt.c @@ -172,6 +172,9 @@ int encrypt_get_algorithm(yaca_enc_algo_e algo, case YACA_ENC_UNSAFE_RC2: case YACA_ENC_UNSAFE_RC4: case YACA_ENC_CAST5: + ret = snprintf(cipher_name, sizeof(cipher_name), "%s-%s", + algo_name, bcm_name); + break; case YACA_ENC_UNSAFE_SKIPJACK: default: return YACA_ERROR_NOT_IMPLEMENTED; @@ -225,7 +228,6 @@ static int encrypt_init(yaca_ctx_h *ctx, nc->ctx.get_output_length = get_encrypt_output_length; nc->op_type = op_type; - // TODO: handling of algorithms with variable key length ret = yaca_key_get_bits(sym_key); if (ret < 0) goto err_free; @@ -270,14 +272,40 @@ static int encrypt_init(yaca_ctx_h *ctx, switch (op_type) { case OP_ENCRYPT: - ret = EVP_EncryptInit(nc->cipher_ctx, cipher, - (unsigned char*)lkey->d, - iv_data); + ret = EVP_EncryptInit_ex(nc->cipher_ctx, cipher, NULL, NULL, NULL); + if (ret != 1) + break; + + /* Handling of algorithms with variable key length */ + ret = EVP_CIPHER_CTX_set_key_length(nc->cipher_ctx, key_bits / 8); + if (ret != 1) { + ret = YACA_ERROR_INVALID_ARGUMENT; + ERROR_DUMP(ret); + goto err_ctx; + } + + ret = EVP_EncryptInit_ex(nc->cipher_ctx, NULL, NULL, + (unsigned char*)lkey->d, + iv_data); + break; case OP_DECRYPT: - ret = EVP_DecryptInit(nc->cipher_ctx, cipher, - (unsigned char*)lkey->d, - iv_data); + ret = EVP_DecryptInit_ex(nc->cipher_ctx, cipher, NULL, NULL, NULL); + if (ret != 1) + break; + + /* Handling of algorithms with variable key length */ + ret = EVP_CIPHER_CTX_set_key_length(nc->cipher_ctx, key_bits / 8); + if (ret != 1) { + ret = YACA_ERROR_INVALID_ARGUMENT; + ERROR_DUMP(ret); + goto err_ctx; + } + + ret = EVP_DecryptInit_ex(nc->cipher_ctx, NULL, NULL, + (unsigned char*)lkey->d, + iv_data); + break; default: ret = YACA_ERROR_INVALID_ARGUMENT; -- 2.7.4 From 320235dd678e6425ef2e8117067ea6a93bca2c25 Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Wed, 11 May 2016 09:31:30 +0200 Subject: [PATCH 03/16] [FIX] ECB mode does not use an IV, so IV can be YACA_KEY_NULL. Change-Id: I64dbb66346176da764009ffb549451fffa5a5435 --- src/simple.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/simple.c b/src/simple.c index ff7f19e..bb8eeec 100644 --- a/src/simple.c +++ b/src/simple.c @@ -94,7 +94,7 @@ API int yaca_encrypt(yaca_enc_algo_e algo, size_t out_len, lcipher_len, written; if (plain == NULL || plain_len == 0 || cipher == NULL || cipher_len == NULL || - sym_key == YACA_KEY_NULL || iv == YACA_KEY_NULL) + sym_key == YACA_KEY_NULL) return YACA_ERROR_INVALID_ARGUMENT; if (plain_len > INT_MAX) /* TODO: this is because get_output_length returns signed int - perhaps we should change that */ @@ -171,7 +171,7 @@ API int yaca_decrypt(yaca_enc_algo_e algo, size_t out_len, lplain_len, written; if (cipher == NULL || cipher_len == 0 || plain == NULL || plain_len == NULL || - sym_key == YACA_KEY_NULL || iv == YACA_KEY_NULL) + sym_key == YACA_KEY_NULL) return YACA_ERROR_INVALID_ARGUMENT; if (cipher_len > INT_MAX) /* TODO: this is because get_output_length returns signed int - perhaps we should change that */ -- 2.7.4 From 0cb7bca2390db4d2d1e3c0be1d15c2842ed276be Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Wed, 11 May 2016 11:04:43 +0200 Subject: [PATCH 04/16] Add support to RC2/RC4 encrypt/decrypt. Update documentation. Change-Id: I57a54e9581af12ffe73a721c7cae8c3880df94ab --- api/yaca/types.h | 35 +++++++++++++++++++++++++---------- src/encrypt.c | 9 +++++---- 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/api/yaca/types.h b/api/yaca/types.h index 3397e86..7ce9ec9 100644 --- a/api/yaca/types.h +++ b/api/yaca/types.h @@ -100,6 +100,7 @@ typedef enum { YACA_KEY_CURVE_P192 = 192, /**< ECC: P192 curve */ YACA_KEY_CURVE_P256 = 256, /**< ECC: P-256 curve */ YACA_KEY_CURVE_P384 = 384, /**< ECC: SECP-384 curve */ + YACA_KEY_UNSAFE_8BIT = 8, YACA_KEY_UNSAFE_40BIT = 40, YACA_KEY_UNSAFE_64BIT = 64, YACA_KEY_UNSAFE_80BIT = 80, @@ -178,15 +179,23 @@ typedef enum { /** * RC2 encryption. - * - The key length is extracted from the key buffer. + * This is a variable key length cipher. * - Supported key lengths: 8-1024 bits in steps of 8 bits. + * - Additional parameter, effective key bits: #YACA_PARAM_RC2_EFFECTIVE_KEY_BITS, + * by default equals to 128 + * - Supported block cipher modes: + * #YACA_BCM_CBC, + * #YACA_BCM_OFB, + * #YACA_BCM_CFB, + * #YACA_BCM_ECB */ YACA_ENC_UNSAFE_RC2, /** * RC4 encryption. - * - The key length is extracted from the key buffer. + * This is a variable key length cipher. * - Supported key lengths: 40–2048 bits in steps of 8 bits. + * This cipher doesn't support block cipher modes, use #YACA_BCM_NONE instead. */ YACA_ENC_UNSAFE_RC4, @@ -215,6 +224,11 @@ typedef enum { */ typedef enum { /** + * Used when algorithm doesn't support block ciphers modes. + */ + YACA_BCM_NONE, + + /** * ECB block cipher mode. * Encrypts 64 bit at a time. No IV is used. */ @@ -277,17 +291,18 @@ typedef enum { * @brief Non-standard parameters for algorithms */ typedef enum { - YACA_PARAM_PADDING, /**< Padding */ + YACA_PARAM_PADDING, /**< Padding */ - YACA_PARAM_CTR_CNT, /**< CTR Counter bits */ + YACA_PARAM_RC2_EFFECTIVE_KEY_BITS, /**< RC2 effective key bits, 1-1024, 1 bit resolution */ + YACA_PARAM_CTR_CNT, /**< CTR Counter bits */ - YACA_PARAM_GCM_AAD, /**< GCM Additional Authentication Data */ - YACA_PARAM_GCM_TAG, /**< GCM Tag bits */ - YACA_PARAM_GCM_TAG_LEN, /**< GCM Tag length */ + YACA_PARAM_GCM_AAD, /**< GCM Additional Authentication Data */ + YACA_PARAM_GCM_TAG, /**< GCM Tag bits */ + YACA_PARAM_GCM_TAG_LEN, /**< GCM Tag length */ - YACA_PARAM_CCM_AAD, /**< CCM Additional Authentication Data */ - YACA_PARAM_CCM_TAG, /**< CCM Tag bits */ - YACA_PARAM_CCM_TAG_LEN, /**< CCM Tag length */ + YACA_PARAM_CCM_AAD, /**< CCM Additional Authentication Data */ + YACA_PARAM_CCM_TAG, /**< CCM Tag bits */ + YACA_PARAM_CCM_TAG_LEN, /**< CCM Tag length */ } yaca_ex_param_e; /** diff --git a/src/encrypt.c b/src/encrypt.c index d185c16..ec2176f 100644 --- a/src/encrypt.c +++ b/src/encrypt.c @@ -115,6 +115,8 @@ static const char *encrypt_algo_to_str(yaca_enc_algo_e algo) 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: @@ -158,6 +160,8 @@ int encrypt_get_algorithm(yaca_enc_algo_e algo, algo_name, key_bits, bcm_name); break; case YACA_ENC_UNSAFE_DES: + case YACA_ENC_UNSAFE_RC2: + case YACA_ENC_CAST5: ret = snprintf(cipher_name, sizeof(cipher_name), "%s-%s", algo_name, bcm_name); break; @@ -169,11 +173,8 @@ int encrypt_get_algorithm(yaca_enc_algo_e algo, ret = snprintf(cipher_name, sizeof(cipher_name), "%s-%s", algo_name, bcm_name); break; - case YACA_ENC_UNSAFE_RC2: case YACA_ENC_UNSAFE_RC4: - case YACA_ENC_CAST5: - ret = snprintf(cipher_name, sizeof(cipher_name), "%s-%s", - algo_name, bcm_name); + ret = snprintf(cipher_name, sizeof(cipher_name), "%s", algo_name); break; case YACA_ENC_UNSAFE_SKIPJACK: default: -- 2.7.4 From 602946e72763a25f9ea4c19e43f3d3769836833d Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Fri, 13 May 2016 16:45:41 +0200 Subject: [PATCH 05/16] Fix API for get_output_length() Return the value by size_t param instead of signed int return. The return value is used only for error codes from now on. Change-Id: I8c4665342316f35d9aea1d2b3605a1248fc31b17 --- api/yaca/crypto.h | 15 +++++++-------- examples/digest.c | 5 ++--- examples/encrypt.c | 24 ++++++++---------------- examples/encrypt_aes_gcm.c | 31 ++++++++++++++++--------------- examples/seal.c | 8 ++++---- examples/sign.c | 6 +++--- src/crypto.c | 4 ++-- src/digest.c | 5 +++-- src/encrypt.c | 17 ++++++++++++----- src/internal.h | 2 +- src/seal.c | 15 +++++++++++---- src/sign.c | 5 +++-- src/simple.c | 42 +++++++++++++++++++++--------------------- 13 files changed, 93 insertions(+), 86 deletions(-) diff --git a/api/yaca/crypto.h b/api/yaca/crypto.h index 205cce2..ec6ac1b 100644 --- a/api/yaca/crypto.h +++ b/api/yaca/crypto.h @@ -162,29 +162,28 @@ void yaca_ctx_free(yaca_ctx_h ctx); * @brief Returns the output length for a given algorithm. Can only be called * on an initialized context. * - * @param[in] ctx Previously initialized crypto context. - * @param[in] input_len Length of the input data to be processed. + * @param[in] ctx Previously initialized crypto context. + * @param[in] input_len Length of the input data to be processed. + * @param[in] output_len Required length of the output. * * @return negative on error or length of output. */ -// TODO: this function should probably return the value by param of -// size_t type and leave the return int value only to report errors -int yaca_get_output_length(const yaca_ctx_h ctx, size_t input_len); +int yaca_get_output_length(const yaca_ctx_h ctx, size_t input_len, size_t *output_len); /** * @brief Wrapper - returns the length of the digest (for a given context). */ -#define yaca_get_digest_length(ctxa) yaca_get_output_length((ctxa), 0) +#define yaca_get_digest_length(ctxa, output_len) yaca_get_output_length((ctxa), 0, (output_len)) /** * @brief Wrapper - returns the length of the signature (for a given context). */ -#define yaca_get_sign_length(ctxa) yaca_get_output_length((ctxa), 0) +#define yaca_get_sign_length(ctxa, output_len) yaca_get_output_length((ctxa), 0, (output_len)) /** * @brief Wrapper - returns the length of the block (for a given context). */ -#define yaca_get_block_length(ctxa) yaca_get_output_length((ctxa), 0) +#define yaca_get_block_length(ctxa, output_len) yaca_get_output_length((ctxa), 0, (output_len)) /**@}*/ diff --git a/examples/digest.c b/examples/digest.c index 9ee0b41..a5ef093 100644 --- a/examples/digest.c +++ b/examples/digest.c @@ -59,10 +59,9 @@ void digest_advanced(void) if (ret < 0) goto exit_ctx; - // TODO: rename to yaca_digest_get_length?? size_t digest_len; - digest_len = yaca_get_digest_length(ctx); - if (digest_len <= 0) + ret = yaca_get_digest_length(ctx, &digest_len); + if (ret != 0) goto exit_ctx; { diff --git a/examples/encrypt.c b/examples/encrypt.c index 8615abe..6233f7b 100644 --- a/examples/encrypt.c +++ b/examples/encrypt.c @@ -134,18 +134,14 @@ void encrypt_advanced(void) if (ret) goto ex_iv; - ret = yaca_get_block_length(ctx); - if (ret < 0) + ret = yaca_get_block_length(ctx, &block_len); + if (ret != 0) goto ex_ctx; - block_len = ret; - - ret = yaca_get_output_length(ctx, LOREM4096_SIZE); - if (ret < 0) + ret = yaca_get_output_length(ctx, LOREM4096_SIZE, &output_len); + if (ret != 0) goto ex_ctx; - output_len = ret; - /* Calculate max output: size of update + final chunks */ enc_size = output_len + block_len; enc = yaca_malloc(enc_size); @@ -184,18 +180,14 @@ void encrypt_advanced(void) goto ex_of; } - ret = yaca_get_block_length(ctx); - if (ret < 0) + ret = yaca_get_block_length(ctx, &block_len); + if (ret != 0) goto ex_of; - block_len = ret; - - ret = yaca_get_output_length(ctx, LOREM4096_SIZE); - if (ret < 0) + ret = yaca_get_output_length(ctx, LOREM4096_SIZE, &output_len); + if (ret != 0) goto ex_ctx; - output_len = ret; - /* Calculate max output: size of update + final chunks */ dec_size = output_len + block_len; dec = yaca_malloc(dec_size); diff --git a/examples/encrypt_aes_gcm.c b/examples/encrypt_aes_gcm.c index 9bc60fe..23fd4e9 100644 --- a/examples/encrypt_aes_gcm.c +++ b/examples/encrypt_aes_gcm.c @@ -52,7 +52,7 @@ void encrypt_decrypt_aes_gcm(void) size_t aad_len; size_t tag_len; - printf("Plain data (16 of %zu bytes): %.16s\n", (size_t)4096, lorem4096); + printf("Plain data (16 of %zu bytes): %.16s\n", LOREM4096_SIZE, lorem4096); /// Key generation @@ -77,6 +77,8 @@ void encrypt_decrypt_aes_gcm(void) /// Encryption { + size_t len; + ret = yaca_encrypt_init(&ctx, YACA_ENC_AES, YACA_BCM_GCM, key, iv); if (ret < 0) goto clean; @@ -85,21 +87,20 @@ void encrypt_decrypt_aes_gcm(void) if (ret < 0) goto clean; - ret = yaca_encrypt_update(ctx, lorem4096, 4096, NULL, &ciphertext_len); - if (ret != 42) - goto clean;// TODO: what error code? + ret = yaca_get_output_length(ctx, LOREM4096_SIZE, &ciphertext_len); + if (ret != 0) + goto clean; - ret = yaca_get_block_length(ctx); - if (ret < 0) + ret = yaca_get_block_length(ctx, &len); + if (ret != 0) goto clean; - ciphertext_len += ret ; // Add block size for finalize + ciphertext_len += len ; // Add block size for finalize ciphertext = yaca_malloc(ciphertext_len); if (ciphertext == NULL) goto clean; - size_t len; - ret = yaca_encrypt_update(ctx, lorem4096, 4096, ciphertext, &len); + ret = yaca_encrypt_update(ctx, lorem4096, LOREM4096_SIZE, ciphertext, &len); if (ret < 0) goto clean; @@ -132,15 +133,15 @@ void encrypt_decrypt_aes_gcm(void) if (ret < 0) goto clean; - ret = yaca_decrypt_update(ctx, ciphertext, ciphertext_len, NULL, &plaintext_len); - if (ret != 42) - goto clean; // TODO: what error code? + ret = yaca_get_output_length(ctx, ciphertext_len, &plaintext_len); + if (ret != 0) + goto clean; - ret = yaca_get_block_length(ctx); - if (ret < 0) + ret = yaca_get_block_length(ctx, &len); + if (ret != 0) goto clean; - plaintext_len += ret; // Add block size for finalize + plaintext_len += len; // Add block size for finalize plaintext = yaca_malloc(plaintext_len); if (plaintext == NULL) goto clean; diff --git a/examples/seal.c b/examples/seal.c index c75b721..4da8228 100644 --- a/examples/seal.c +++ b/examples/seal.c @@ -65,10 +65,10 @@ void encrypt_seal(void) if (yaca_seal_init(&ctx, key_pub, algo, bcm, key_bits, &aes_key, &iv) != 0) goto ex_pubk; - if ((block_len = yaca_get_block_length(ctx)) <= 0) + if (yaca_get_block_length(ctx, &block_len) != 0) goto ex_ak; - if ((output_len = yaca_get_output_length(ctx, LOREM4096_SIZE)) <= 0) + if (yaca_get_output_length(ctx, LOREM4096_SIZE, &output_len) != 0) goto ex_ak; /* Calculate max output: size of update + final chunks */ @@ -98,10 +98,10 @@ void encrypt_seal(void) if (yaca_open_init(&ctx, key_priv, algo, bcm, key_bits, aes_key, iv) != 0) goto ex_of; - if ((block_len = yaca_get_block_length(ctx)) <= 0) + if (yaca_get_block_length(ctx, &block_len) != 0) goto ex_of; - if ((output_len = yaca_get_output_length(ctx, LOREM4096_SIZE)) <= 0) + if (yaca_get_output_length(ctx, LOREM4096_SIZE, &output_len) != 0) goto ex_of; /* Calculate max output: size of update + final chunks */ diff --git a/examples/sign.c b/examples/sign.c index c5c9a5e..dab16bd 100644 --- a/examples/sign.c +++ b/examples/sign.c @@ -65,7 +65,7 @@ void sign_verify_asym(yaca_key_type_e type, const char *algo) if (yaca_sign_update(ctx, lorem4096, LOREM4096_SIZE) != 0) goto finish; - if ((signature_len = yaca_get_sign_length(ctx)) <= 0) + if (yaca_get_sign_length(ctx, &signature_len) != 0) goto finish; if ((signature = yaca_malloc(signature_len)) == NULL) @@ -123,7 +123,7 @@ void sign_verify_hmac(void) if (yaca_sign_update(ctx, lorem4096, LOREM4096_SIZE) != 0) goto finish; - if ((signature_len = yaca_get_sign_length(ctx)) <= 0) + if (yaca_get_sign_length(ctx, &signature_len) != 0) goto finish; if ((signature = yaca_malloc(signature_len)) == NULL) @@ -176,7 +176,7 @@ void sign_verify_cmac(void) if (yaca_sign_update(ctx, lorem4096, LOREM4096_SIZE)) goto finish; - if ((signature_len = yaca_get_sign_length(ctx)) <= 0) + if (yaca_get_sign_length(ctx, &signature_len) != 0) goto finish; if ((signature = yaca_malloc(signature_len)) == NULL) diff --git a/src/crypto.c b/src/crypto.c index 650bdcf..df5ba7d 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -120,10 +120,10 @@ API void yaca_ctx_free(yaca_ctx_h ctx) } } -API int yaca_get_output_length(const yaca_ctx_h ctx, size_t input_len) +API int yaca_get_output_length(const yaca_ctx_h ctx, size_t input_len, size_t *output_len) { if (ctx == YACA_CTX_NULL) return YACA_ERROR_INVALID_ARGUMENT; - return ctx->get_output_length(ctx, input_len); + return ctx->get_output_length(ctx, input_len, output_len); } diff --git a/src/digest.c b/src/digest.c index b9f4ce4..10d4dbf 100644 --- a/src/digest.c +++ b/src/digest.c @@ -49,14 +49,15 @@ static struct yaca_digest_ctx_s *get_digest_ctx(const yaca_ctx_h ctx) } } -static int get_digest_output_length(const yaca_ctx_h ctx, size_t input_len) +static int get_digest_output_length(const yaca_ctx_h ctx, size_t input_len, size_t *output_len) { struct yaca_digest_ctx_s *c = get_digest_ctx(ctx); if (c == NULL) return YACA_ERROR_INVALID_ARGUMENT; - return EVP_MD_CTX_size(c->mdctx); + *output_len = EVP_MD_CTX_size(c->mdctx); + return 0; } static void destroy_digest_context(yaca_ctx_h ctx) diff --git a/src/encrypt.c b/src/encrypt.c index ec2176f..758fd2b 100644 --- a/src/encrypt.c +++ b/src/encrypt.c @@ -68,7 +68,7 @@ static void destroy_encrypt_ctx(const yaca_ctx_h ctx) nc->cipher_ctx = NULL; } -static int get_encrypt_output_length(const yaca_ctx_h ctx, size_t input_len) +static int get_encrypt_output_length(const yaca_ctx_h ctx, size_t input_len, size_t *output_len) { struct yaca_encrypt_ctx_s *nc = get_encrypt_ctx(ctx); int block_size; @@ -77,14 +77,21 @@ static int get_encrypt_output_length(const yaca_ctx_h ctx, size_t input_len) return YACA_ERROR_INVALID_ARGUMENT; block_size = EVP_CIPHER_CTX_block_size(nc->cipher_ctx); - if (block_size == 0) { + if (block_size <= 0) { ERROR_DUMP(YACA_ERROR_INTERNAL); return YACA_ERROR_INTERNAL; } - if (input_len > 0) - return block_size + input_len - 1; - return block_size; + if (input_len > 0) { + if ((size_t)block_size > SIZE_MAX - input_len + 1) + return YACA_ERROR_TOO_BIG_ARGUMENT; + + *output_len = block_size + input_len - 1; + } else { + *output_len = block_size; + } + + return 0; } static const char *encrypt_algo_to_str(yaca_enc_algo_e algo) diff --git a/src/internal.h b/src/internal.h index 5d1f49a..0aa764a 100644 --- a/src/internal.h +++ b/src/internal.h @@ -46,7 +46,7 @@ struct yaca_ctx_s enum yaca_ctx_type_e type; void (*ctx_destroy)(const yaca_ctx_h ctx); - int (*get_output_length)(const yaca_ctx_h ctx, size_t input_len); + int (*get_output_length)(const yaca_ctx_h ctx, size_t input_len, size_t *output_len); int (*set_param)(yaca_ctx_h ctx, yaca_ex_param_e param, const void *value, size_t value_len); int (*get_param)(const yaca_ctx_h ctx, yaca_ex_param_e param, diff --git a/src/seal.c b/src/seal.c index a5fb2ae..586aac1 100644 --- a/src/seal.c +++ b/src/seal.c @@ -68,7 +68,7 @@ static void destroy_seal_ctx(const yaca_ctx_h ctx) nc->cipher_ctx = NULL; } -static int get_seal_output_length(const yaca_ctx_h ctx, size_t input_len) +static int get_seal_output_length(const yaca_ctx_h ctx, size_t input_len, size_t *output_len) { struct yaca_seal_ctx_s *nc = get_seal_ctx(ctx); int block_size; @@ -83,9 +83,16 @@ static int get_seal_output_length(const yaca_ctx_h ctx, size_t input_len) return YACA_ERROR_INTERNAL; } - if (input_len > 0) - return block_size + input_len - 1; - return block_size; + if (input_len > 0) { + if ((size_t)block_size > SIZE_MAX - input_len + 1) + return YACA_ERROR_TOO_BIG_ARGUMENT; + + *output_len = block_size + input_len - 1; + } else { + *output_len = block_size; + } + + return 0; } static int seal_init(yaca_ctx_h *ctx, diff --git a/src/sign.c b/src/sign.c index b885cc6..e629210 100644 --- a/src/sign.c +++ b/src/sign.c @@ -56,7 +56,7 @@ static struct yaca_sign_ctx_s *get_sign_ctx(const yaca_ctx_h ctx) } } -static int get_sign_output_length(const yaca_ctx_h ctx, size_t input_len) +static int get_sign_output_length(const yaca_ctx_h ctx, size_t input_len, size_t *output_len) { struct yaca_sign_ctx_s *c = get_sign_ctx(ctx); @@ -75,7 +75,8 @@ static int get_sign_output_length(const yaca_ctx_h ctx, size_t input_len) return YACA_ERROR_INVALID_ARGUMENT; } - return len; + *output_len = len; + return 0; } static void destroy_sign_context(yaca_ctx_h ctx) diff --git a/src/simple.c b/src/simple.c index bb8eeec..d82d4f2 100644 --- a/src/simple.c +++ b/src/simple.c @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -52,11 +53,10 @@ API int yaca_digest_calc(yaca_digest_algo_e algo, if (ret < 0) goto err; - ret = yaca_get_digest_length(ctx); - if (ret < 0) + ret = yaca_get_digest_length(ctx, &ldigest_len); + if (ret != 0) goto err; - ldigest_len = ret; ldigest = yaca_malloc(ldigest_len); if (!ldigest) goto err; @@ -97,24 +97,24 @@ API int yaca_encrypt(yaca_enc_algo_e algo, sym_key == YACA_KEY_NULL) return YACA_ERROR_INVALID_ARGUMENT; - if (plain_len > INT_MAX) /* TODO: this is because get_output_length returns signed int - perhaps we should change that */ - return YACA_ERROR_TOO_BIG_ARGUMENT; - ret = yaca_encrypt_init(&ctx, algo, bcm, sym_key, iv); if (ret != 0) return ret; - ret = yaca_get_block_length(ctx); - if (ret <= 0) + ret = yaca_get_block_length(ctx, &lcipher_len); + if (ret != 0) goto err; - lcipher_len = ret; + ret = yaca_get_output_length(ctx, plain_len, &out_len); + if (ret != 0) + goto err; - ret = yaca_get_output_length(ctx, plain_len); - if (ret <= 0) + if (out_len > SIZE_MAX - lcipher_len) { + ret = YACA_ERROR_TOO_BIG_ARGUMENT; goto err; + } - lcipher_len += ret; + lcipher_len += out_len; lcipher = yaca_malloc(lcipher_len); if (lcipher == NULL) @@ -174,24 +174,24 @@ API int yaca_decrypt(yaca_enc_algo_e algo, sym_key == YACA_KEY_NULL) return YACA_ERROR_INVALID_ARGUMENT; - if (cipher_len > INT_MAX) /* TODO: this is because get_output_length returns signed int - perhaps we should change that */ - return YACA_ERROR_TOO_BIG_ARGUMENT; - ret = yaca_decrypt_init(&ctx, algo, bcm, sym_key, iv); if (ret != 0) return ret; - ret = yaca_get_block_length(ctx); - if (ret <= 0) + ret = yaca_get_block_length(ctx, &lplain_len); + if (ret != 0) goto err; - lplain_len = ret; + ret = yaca_get_output_length(ctx, cipher_len, &out_len); + if (ret != 0) + goto err; - ret = yaca_get_output_length(ctx, cipher_len); - if (ret <= 0) + if (out_len > SIZE_MAX - lplain_len) { + ret = YACA_ERROR_TOO_BIG_ARGUMENT; goto err; + } - lplain_len += ret; + lplain_len += out_len; lplain = yaca_malloc(lplain_len); if (!lplain) -- 2.7.4 From 3e2ead07fc1d277395326bbc0a62ef747cd3f337 Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Fri, 13 May 2016 17:51:07 +0200 Subject: [PATCH 06/16] Get rid of few TODOs that no longer apply Change-Id: I0763fba2200770137eb73e9a7c4ee4ff4858e35d --- api/yaca/crypto.h | 4 ---- examples/encrypt.c | 4 ++-- examples/encrypt_aes_gcm.c | 4 ++-- src/sign.c | 6 ++---- 4 files changed, 6 insertions(+), 12 deletions(-) diff --git a/api/yaca/crypto.h b/api/yaca/crypto.h index ec6ac1b..9959df0 100644 --- a/api/yaca/crypto.h +++ b/api/yaca/crypto.h @@ -67,7 +67,6 @@ void yaca_exit(void); * @return NULL on failure, pointer to allocated memory otherwise. * @see yaca_zalloc(), yaca_realloc(), yaca_free() */ -// TODO: this should be a macro to CRYPTO_* void *yaca_malloc(size_t size); /** @@ -78,7 +77,6 @@ void *yaca_malloc(size_t size); * @return NULL on failure, pointer to allocated and zeroed memory otherwise. * @see yaca_malloc(), yaca_realloc(), yaca_free() */ -// TODO: this should be a macro to CRYPTO_* void *yaca_zalloc(size_t size); /** @@ -90,7 +88,6 @@ void *yaca_zalloc(size_t size); * @return NULL on failure, pointer to allocated memory otherwise. * @see yaca_malloc(), yaca_zalloc(), yaca_free() */ -// TODO: this should be a macro to CRYPTO_* void *yaca_realloc(void *addr, size_t size); /** @@ -101,7 +98,6 @@ void *yaca_realloc(void *addr, size_t size); * @see yaca_malloc(), yaca_zalloc(), yaca_realloc() * */ -// TODO: this should be a macro to CRYPTO_* void yaca_free(void *ptr); /** diff --git a/examples/encrypt.c b/examples/encrypt.c index 6233f7b..c253586 100644 --- a/examples/encrypt.c +++ b/examples/encrypt.c @@ -164,7 +164,7 @@ void encrypt_advanced(void) dump_hex(enc, 16, "Encrypted data (16 of %zu bytes): ", enc_size); - yaca_ctx_free(ctx); // TODO: perhaps it should not return value + yaca_ctx_free(ctx); } /// Decryption @@ -233,6 +233,6 @@ int main() encrypt_advanced(); - yaca_exit(); // TODO: what about handing of return value from exit?? + yaca_exit(); return ret; } diff --git a/examples/encrypt_aes_gcm.c b/examples/encrypt_aes_gcm.c index 23fd4e9..9fc1234 100644 --- a/examples/encrypt_aes_gcm.c +++ b/examples/encrypt_aes_gcm.c @@ -118,7 +118,7 @@ void encrypt_decrypt_aes_gcm(void) dump_hex(ciphertext, 16, "Encrypted data (16 of %zu bytes): ", ciphertext_len); - yaca_ctx_free(ctx); // TODO: perhaps it should not return value + yaca_ctx_free(ctx); } /// Decryption @@ -188,6 +188,6 @@ int main() encrypt_decrypt_aes_gcm(); - yaca_exit(); // TODO: what about handing of return value from exit?? + yaca_exit(); return ret; } diff --git a/src/sign.c b/src/sign.c index e629210..7dd2a73 100644 --- a/src/sign.c +++ b/src/sign.c @@ -143,8 +143,7 @@ API int yaca_sign_init(yaca_ctx_h *ctx, if (ret != 0) return ret; - // TODO: use zalloc when available - nc = yaca_malloc(sizeof(struct yaca_sign_ctx_s)); + nc = yaca_zalloc(sizeof(struct yaca_sign_ctx_s)); if (nc == NULL) { ret = YACA_ERROR_OUT_OF_MEMORY; goto free_key; @@ -261,8 +260,7 @@ API int yaca_verify_init(yaca_ctx_h *ctx, if (ret != 0) return ret; - // TODO: use zalloc when available - nc = yaca_malloc(sizeof(struct yaca_sign_ctx_s)); + nc = yaca_zalloc(sizeof(struct yaca_sign_ctx_s)); if (nc == NULL) { ret = YACA_ERROR_OUT_OF_MEMORY; goto free_key; -- 2.7.4 From b1e172ef62a67a70fee37985459facd98775f90d Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Tue, 17 May 2016 15:07:18 +0200 Subject: [PATCH 07/16] Fix assert vs error codes usage in get_sign_output_length() Change-Id: Ieca2200d6f844590ed16b0dc314e56a4572c5dfa --- src/sign.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/sign.c b/src/sign.c index 7dd2a73..3ad2279 100644 --- a/src/sign.c +++ b/src/sign.c @@ -60,9 +60,14 @@ static int get_sign_output_length(const yaca_ctx_h ctx, size_t input_len, size_t { struct yaca_sign_ctx_s *c = get_sign_ctx(ctx); - if (c == NULL || c->mdctx == NULL || c->mdctx->pctx == NULL) + if (c == NULL) return YACA_ERROR_INVALID_ARGUMENT; + assert(c->mdctx != NULL); + + if (c->mdctx->pctx == NULL) + return YACA_ERROR_INTERNAL; + EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(c->mdctx->pctx); if (pkey == NULL) { ERROR_DUMP(YACA_ERROR_INVALID_ARGUMENT); -- 2.7.4 From ad0caccd86a7b35a81729a2ce1348fa597d00086 Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Tue, 17 May 2016 14:19:11 +0200 Subject: [PATCH 08/16] Lower the key bit_len in sign/verify example It takes too long to run the example with 4k key for our purposes. Change-Id: I331782d9cf90f621cf2b009ad4751a952157341f --- examples/sign.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/sign.c b/examples/sign.c index dab16bd..4874131 100644 --- a/examples/sign.c +++ b/examples/sign.c @@ -46,7 +46,7 @@ void sign_verify_asym(yaca_key_type_e type, const char *algo) #endif // GENERATE - if (yaca_key_gen(&prv, type, YACA_KEY_4096BIT) != 0) + if (yaca_key_gen(&prv, type, YACA_KEY_1024BIT) != 0) return; if (yaca_key_extract_public(prv, &pub) != 0) -- 2.7.4 From e800af8e1aee2336baa8b654c239f8a12df74cd5 Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Fri, 13 May 2016 19:16:25 +0200 Subject: [PATCH 09/16] get/set_ctx_param for sign/verify (RSA padding only) Change-Id: I9ce5bde7a43bae619546c9cc5b3e54c4388ca755 --- api/yaca/types.h | 11 +++-- examples/sign.c | 11 +---- src/sign.c | 129 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 135 insertions(+), 16 deletions(-) diff --git a/api/yaca/types.h b/api/yaca/types.h index 7ce9ec9..72d45f4 100644 --- a/api/yaca/types.h +++ b/api/yaca/types.h @@ -310,12 +310,11 @@ typedef enum { */ typedef enum { YACA_PADDING_NONE = 0, /**< total number of data MUST multiple of block size, Default */ - YACA_PADDING_ZEROS, /**< pad with zeros */ - YACA_PADDING_ISO10126, /**< ISO 10126 */ - YACA_PADDING_ANSIX923, /**< ANSI X.923 padding*/ - YACA_PADDING_ANSIX931, /**< ANSI X.931 padding*/ - YACA_PADDING_PKCS1, /**< RSA signature creation */ - YACA_PADDING_PKCS7 /**< Byte padding for symetric algos (RFC 5652), (PKCS5 padding is the same) */ + YACA_PADDING_X931, /**< RSA X9.31 padding*/ + YACA_PADDING_PKCS1, /**< RSA signature/verify operations */ + YACA_PADDING_PKCS1_PSS, /**< RSA signature/verify operations */ + YACA_PADDING_SSLV23, /**< RSA SSLv23 */ + YACA_PADDING_PKCS1_OAEP /**< RSA encrypt/decrypt operations */ } yaca_padding_e; /**@}*/ diff --git a/examples/sign.c b/examples/sign.c index 4874131..faf0131 100644 --- a/examples/sign.c +++ b/examples/sign.c @@ -30,8 +30,6 @@ #include "lorem.h" #include "misc.h" -#define PADDING_IMPLEMENTED 0 - // Signature creation and verification using advanced API void sign_verify_asym(yaca_key_type_e type, const char *algo) { @@ -41,9 +39,7 @@ void sign_verify_asym(yaca_key_type_e type, const char *algo) yaca_ctx_h ctx = YACA_CTX_NULL; yaca_key_h prv = YACA_KEY_NULL; yaca_key_h pub = YACA_KEY_NULL; -#if PADDING_IMPLEMENTED - yaca_padding_e padding = YACA_PADDING_PKCS1; -#endif + yaca_padding_e padding = YACA_PADDING_PKCS1_PSS; // GENERATE if (yaca_key_gen(&prv, type, YACA_KEY_1024BIT) != 0) @@ -56,11 +52,8 @@ void sign_verify_asym(yaca_key_type_e type, const char *algo) if (yaca_sign_init(&ctx, YACA_DIGEST_SHA512, prv) != 0) goto finish; -#if PADDING_IMPLEMENTED - // TODO: yaca_ctx_set_param should take void* not char* if (yaca_ctx_set_param(ctx, YACA_PARAM_PADDING, (char*)(&padding), sizeof(padding)) != 0) goto finish; -#endif if (yaca_sign_update(ctx, lorem4096, LOREM4096_SIZE) != 0) goto finish; @@ -84,10 +77,8 @@ void sign_verify_asym(yaca_key_type_e type, const char *algo) if (yaca_verify_init(&ctx, YACA_DIGEST_SHA512, pub) != 0) goto finish; -#if PADDING_IMPLEMENTED if (yaca_ctx_set_param(ctx, YACA_PARAM_PADDING, (char*)(&padding), sizeof(padding)) != 0) goto finish; -#endif if (yaca_verify_update(ctx, lorem4096, LOREM4096_SIZE) != 0) goto finish; diff --git a/src/sign.c b/src/sign.c index 3ad2279..9573c4c 100644 --- a/src/sign.c +++ b/src/sign.c @@ -17,8 +17,10 @@ */ #include +#include #include +#include #include #include @@ -95,6 +97,129 @@ static void destroy_sign_context(yaca_ctx_h ctx) c->mdctx = NULL; } +int set_sign_param(yaca_ctx_h ctx, yaca_ex_param_e param, const void *value, size_t value_len) +{ + int ret; + struct yaca_sign_ctx_s *c = get_sign_ctx(ctx); + yaca_padding_e padding; + int pad; + EVP_PKEY *pkey; + + if (c == NULL || value == NULL) + return YACA_ERROR_INVALID_ARGUMENT; + + assert(c->mdctx != NULL); + + if (c->mdctx->pctx == NULL) + return YACA_ERROR_INTERNAL; + + /* this function only supports padding */ + if (param != YACA_PARAM_PADDING || value_len != sizeof(yaca_padding_e)) + return YACA_ERROR_INVALID_ARGUMENT; + + padding = *(yaca_padding_e *)(value); + + // TODO: investigate whether it's possible to set + // RSA_NO_PADDING or RSA_SSLV23_PADDING in some cases + switch (padding) { + case YACA_PADDING_X931: + pad = RSA_X931_PADDING; + break; + case YACA_PADDING_PKCS1: + pad = RSA_PKCS1_PADDING; + break; + case YACA_PADDING_PKCS1_PSS: + pad = RSA_PKCS1_PSS_PADDING; + break; + default: + return YACA_ERROR_INVALID_ARGUMENT; + } + + pkey = EVP_PKEY_CTX_get0_pkey(c->mdctx->pctx); + if (pkey == NULL) { + ret = YACA_ERROR_INTERNAL; + ERROR_DUMP(ret); + return ret; + } + + /* padding only works for RSA */ + if (pkey->type != EVP_PKEY_RSA) + return YACA_ERROR_INVALID_ARGUMENT; + + ret = EVP_PKEY_CTX_set_rsa_padding(c->mdctx->pctx, pad); + if (ret <= 0) { + ret = YACA_ERROR_INTERNAL; + ERROR_DUMP(ret); + return ret; + } + + return 0; +} + +int get_sign_param(const yaca_ctx_h ctx, yaca_ex_param_e param, void **value, size_t *value_len) +{ + int ret; + struct yaca_sign_ctx_s *c = get_sign_ctx(ctx); + EVP_PKEY *pkey; + int pad; + yaca_padding_e padding; + + if (c == NULL || value == NULL || value_len == NULL) + return YACA_ERROR_INVALID_ARGUMENT; + + assert(c->mdctx != NULL); + + if (c->mdctx->pctx == NULL) + return YACA_ERROR_INTERNAL; + + /* this function only supports padding */ + if (param != YACA_PARAM_PADDING) + return YACA_ERROR_INVALID_ARGUMENT; + + pkey = EVP_PKEY_CTX_get0_pkey(c->mdctx->pctx); + if (pkey == NULL) { + ret = YACA_ERROR_INTERNAL; + ERROR_DUMP(ret); + return ret; + } + + /* padding only works for RSA */ + if (pkey->type != EVP_PKEY_RSA) + return YACA_ERROR_INVALID_ARGUMENT; + + ret = EVP_PKEY_CTX_get_rsa_padding(c->mdctx->pctx, &pad); + if (ret <= 0) { + ret = YACA_ERROR_INTERNAL; + ERROR_DUMP(ret); + return ret; + } + + switch(pad) { + case RSA_X931_PADDING: + padding = YACA_PADDING_X931; + break; + case RSA_PKCS1_PADDING: + padding = YACA_PADDING_PKCS1; + break; + case RSA_PKCS1_PSS_PADDING: + padding = YACA_PADDING_PKCS1_PSS; + break; + default: + ret = YACA_ERROR_INTERNAL; + ERROR_DUMP(YACA_ERROR_INTERNAL); + return ret; + } + + *value = yaca_malloc(sizeof(yaca_padding_e)); + if (*value == NULL) + return YACA_ERROR_OUT_OF_MEMORY; + + memcpy(*value, &padding, sizeof(yaca_padding_e)); + *value_len = sizeof(yaca_padding_e); + + return 0; +} + static int create_sign_pkey(const yaca_key_h key, EVP_PKEY **pkey) { const struct yaca_key_simple_s *simple_key = key_get_simple(key); @@ -157,6 +282,8 @@ API int yaca_sign_init(yaca_ctx_h *ctx, nc->ctx.type = YACA_CTX_SIGN; nc->ctx.ctx_destroy = destroy_sign_context; nc->ctx.get_output_length = get_sign_output_length; + nc->ctx.set_param = set_sign_param; + nc->ctx.get_param = get_sign_param; switch (key->type) { @@ -274,6 +401,8 @@ API int yaca_verify_init(yaca_ctx_h *ctx, nc->ctx.type = YACA_CTX_SIGN; nc->ctx.ctx_destroy = destroy_sign_context; nc->ctx.get_output_length = NULL; + nc->ctx.set_param = set_sign_param; + nc->ctx.get_param = get_sign_param; switch (key->type) { -- 2.7.4 From 306a32c4cd94b3b9a11abba5c5728bbf2a2ec3c7 Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Wed, 18 May 2016 09:30:36 +0200 Subject: [PATCH 10/16] FIX: SIZE_MAX undeclared. Change-Id: I282d74613fc8f1617575597ae3a26ee4eef385f0 --- src/encrypt.c | 1 + src/seal.c | 1 + 2 files changed, 2 insertions(+) diff --git a/src/encrypt.c b/src/encrypt.c index 758fd2b..4b549f7 100644 --- a/src/encrypt.c +++ b/src/encrypt.c @@ -18,6 +18,7 @@ #include #include +#include #include #include diff --git a/src/seal.c b/src/seal.c index 586aac1..47fe00f 100644 --- a/src/seal.c +++ b/src/seal.c @@ -18,6 +18,7 @@ #include #include +#include #include #include -- 2.7.4 From 84bda780215f0af81b3bb9ee6a9ef8fd5a6414b7 Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Wed, 18 May 2016 10:28:59 +0200 Subject: [PATCH 11/16] Fix API for yaca_get_iv_bits(). Return the value by size_t param instead of signed int return. The return value is used only for error codes from now on. Change-Id: I90afedcffeb37ab315b4f4681323f3d64b7bc9ec --- api/yaca/encrypt.h | 15 ++++++++++----- examples/encrypt.c | 10 ++++------ src/encrypt.c | 14 +++++++++++--- 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/api/yaca/encrypt.h b/api/yaca/encrypt.h index 7806e16..7e81d9b 100644 --- a/api/yaca/encrypt.h +++ b/api/yaca/encrypt.h @@ -148,15 +148,20 @@ int yaca_decrypt_final(yaca_ctx_h ctx, /** * @brief Returns the recomended/default length of the IV for a given encryption configuration. * - * @param[in] algo Encryption algorithm. - * @param[in] bcm Chain mode. - * @param[in] key_bits Key length in bits. + * If returned iv_bits equals 0 that means that for this + * specific algorithm and its parameters IV is not used. * - * @return negative on error or the IV length in bits. + * @param[in] algo Encryption algorithm. + * @param[in] bcm Chain mode. + * @param[in] key_bits Key length in bits. + * @param[out] iv_bits Recommended IV length in bits. + * + * @return 0 on success, negative on error. */ int yaca_get_iv_bits(yaca_enc_algo_e algo, yaca_block_cipher_mode_e bcm, - size_t key_bits); + size_t key_bits, + size_t *iv_bits); /**@}*/ diff --git a/examples/encrypt.c b/examples/encrypt.c index c253586..3e95c86 100644 --- a/examples/encrypt.c +++ b/examples/encrypt.c @@ -44,7 +44,7 @@ void encrypt_simple(void) char *dec_data = NULL; size_t enc_len; size_t dec_len; - int iv_bits; + size_t iv_bits; printf("Simple Encrypt\nPlain data (16 of %zu bytes): %.16s\n", LOREM1024_SIZE, lorem1024); @@ -54,8 +54,7 @@ void encrypt_simple(void) if (ret) return; - iv_bits = yaca_get_iv_bits(algo, bcm, key_bits); - if (iv_bits < 0) + if (yaca_get_iv_bits(algo, bcm, key_bits, &iv_bits) != 0) return; if (iv_bits > 0) { @@ -101,7 +100,7 @@ void encrypt_advanced(void) char *dec = NULL; size_t enc_size; size_t dec_size; - int iv_bits; + size_t iv_bits; printf("Advanced Encrypt\nPlain data (16 of %zu bytes): %.16s\n", LOREM4096_SIZE, lorem4096); @@ -113,8 +112,7 @@ void encrypt_advanced(void) if (ret) return; - iv_bits = yaca_get_iv_bits(algo, bcm, key_bits); - if (iv_bits < 0) + if (yaca_get_iv_bits(algo, bcm, key_bits, &iv_bits) != 0) goto ex_key; if (iv_bits > 0) { diff --git a/src/encrypt.c b/src/encrypt.c index 4b549f7..c41b77a 100644 --- a/src/encrypt.c +++ b/src/encrypt.c @@ -414,8 +414,9 @@ static int encrypt_final(yaca_ctx_h ctx, } API int yaca_get_iv_bits(yaca_enc_algo_e algo, - yaca_block_cipher_mode_e bcm, - size_t key_bits) + yaca_block_cipher_mode_e bcm, + size_t key_bits, + size_t *iv_bits) { const EVP_CIPHER *cipher; int ret; @@ -424,7 +425,14 @@ API int yaca_get_iv_bits(yaca_enc_algo_e algo, if (ret < 0) return ret; - return EVP_CIPHER_iv_length(cipher) * 8; + ret = EVP_CIPHER_iv_length(cipher); + if (ret < 0) { + ERROR_DUMP(YACA_ERROR_INTERNAL); + return YACA_ERROR_INTERNAL; + } + + *iv_bits = ret * 8; + return 0; } API int yaca_encrypt_init(yaca_ctx_h *ctx, -- 2.7.4 From f2f040bd6fa704704190f1e0f423d2c85e06aa43 Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Tue, 17 May 2016 18:48:31 +0200 Subject: [PATCH 12/16] yaca_key import/export API change - passwords Change-Id: Ifcc7c3eca1323cb4418190867bedf1a197b08f73 --- api/yaca/error.h | 3 ++- api/yaca/key.h | 17 ++++++++++++++++- examples/encrypt_aes_gcm.c | 2 +- examples/key_exchange.c | 4 ++-- examples/key_import_export.c | 40 ++++++++++++++++++++-------------------- examples/test.c | 2 +- src/key.c | 2 ++ 7 files changed, 44 insertions(+), 26 deletions(-) diff --git a/api/yaca/error.h b/api/yaca/error.h index 55656bd..acdc2cb 100644 --- a/api/yaca/error.h +++ b/api/yaca/error.h @@ -43,7 +43,8 @@ enum __yaca_error_code { YACA_ERROR_INTERNAL = -3, YACA_ERROR_TOO_BIG_ARGUMENT = -4, YACA_ERROR_OUT_OF_MEMORY = -5, - YACA_ERROR_SIGNATURE_INVALID = -6 + YACA_ERROR_SIGNATURE_INVALID = -6, + YACA_ERROR_PASSWORD_INVALID = -7, }; // TODO disable debug function in release? diff --git a/api/yaca/key.h b/api/yaca/key.h index ce69f21..d6a34d2 100644 --- a/api/yaca/key.h +++ b/api/yaca/key.h @@ -67,16 +67,23 @@ int yaca_key_get_bits(const yaca_key_h key); * format. Additionally it is possible to import public RSA key from * X509 certificate. * + * If the key is encrypted the algorithm will be autodetected and password + * used. If it's not known if the key is encrypted one should pass NULL as + * password and check for the YACA_ERROR_PASSWORD_INVALID return code. + * * @param[out] key Returned key (must be freed with yaca_key_free()). * @param[in] key_type Type of the key. + * @param[in] password null terminated password for the key (can be NULL). * @param[in] data Blob containing the key. * @param[in] data_len Size of the blob. * - * @return 0 on success, negative on error. + * @return 0 on success, YACA_ERROR_PASSWORD_INVALID if wrong password given, + * negative on error. * @see #yaca_key_type_e, yaca_key_export(), yaca_key_free() */ int yaca_key_import(yaca_key_h *key, yaca_key_type_e key_type, + const char *password, const char *data, size_t data_len); @@ -96,9 +103,16 @@ int yaca_key_import(yaca_key_h *key, * - #YACA_KEY_FILE_FORMAT_PEM: used only for asymmetric, PEM file format * - #YACA_KEY_FILE_FORMAT_DER: used only for asymmetric, DER file format * + * If no password is provided the exported key will be unencrypted. Only private + * RSA/DSA exported as PEM can be encrypted. + * + * TODO: document the default encryption algorithm (AES256 for FORMAT_DEFAULT, + * unknown yet for the FORMAT_PKCS8) + * * @param[in] key Key to be exported. * @param[in] key_fmt Format of the key. * @param[in] key_file_fmt Format of the key file. + * @param[in] password Password used for the encryption (can be NULL). * @param[out] data Data, allocated by the library, containing exported key * (must be freed with yaca_free()). * @param[out] data_len Size of the output data. @@ -109,6 +123,7 @@ int yaca_key_import(yaca_key_h *key, int yaca_key_export(const yaca_key_h key, yaca_key_fmt_e key_fmt, yaca_key_file_fmt_e key_file_fmt, + const char *password, char **data, size_t *data_len); diff --git a/examples/encrypt_aes_gcm.c b/examples/encrypt_aes_gcm.c index 9fc1234..86da336 100644 --- a/examples/encrypt_aes_gcm.c +++ b/examples/encrypt_aes_gcm.c @@ -71,7 +71,7 @@ void encrypt_decrypt_aes_gcm(void) goto clean; // generate and export aad? - ret = yaca_key_export(aad_key, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_RAW, &aad, &aad_len); + ret = yaca_key_export(aad_key, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_RAW, NULL, &aad, &aad_len); if (ret < 0) goto clean; diff --git a/examples/key_exchange.c b/examples/key_exchange.c index b3e4f05..9464732 100644 --- a/examples/key_exchange.c +++ b/examples/key_exchange.c @@ -69,7 +69,7 @@ void key_exchange_dh(void) if (1 != fread(buffer, size, 1, fp)) goto clean; - ret = yaca_key_import(&peer_key, YACA_KEY_TYPE_DH_PUB, + ret = yaca_key_import(&peer_key, YACA_KEY_TYPE_DH_PUB, NULL, buffer, size); if (ret < 0) goto clean; @@ -129,7 +129,7 @@ void key_exchange_ecdh(void) if (1 != fread(buffer, size, 1, fp)) goto clean; - ret = yaca_key_import(&peer_key, YACA_KEY_TYPE_ECDH_PUB, buffer, size); + ret = yaca_key_import(&peer_key, YACA_KEY_TYPE_ECDH_PUB, NULL, buffer, size); if (ret < 0) goto clean; diff --git a/examples/key_import_export.c b/examples/key_import_export.c index 1c4db07..9d005c2 100644 --- a/examples/key_import_export.c +++ b/examples/key_import_export.c @@ -46,10 +46,10 @@ int key_import_export_sym(yaca_key_h sym) /* BASE64 */ - ret = yaca_key_export(sym, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_BASE64, &b64, &b64_len); + ret = yaca_key_export(sym, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_BASE64, NULL, &b64, &b64_len); if (ret != 0) return ret; - ret = yaca_key_import(&b64_imported, YACA_KEY_TYPE_SYMMETRIC, b64, b64_len); + ret = yaca_key_import(&b64_imported, YACA_KEY_TYPE_SYMMETRIC, NULL, b64, b64_len); if (ret != 0) goto free; @@ -57,7 +57,7 @@ int key_import_export_sym(yaca_key_h sym) yaca_free(b64); b64 = NULL; - ret = yaca_key_export(b64_imported, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_BASE64, &b64, &b64_len); + ret = yaca_key_export(b64_imported, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_BASE64, NULL, &b64, &b64_len); if (ret != 0) goto free; @@ -66,10 +66,10 @@ int key_import_export_sym(yaca_key_h sym) /* RAW */ - ret = yaca_key_export(sym, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_RAW, &raw, &raw_len); + ret = yaca_key_export(sym, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_RAW, NULL, &raw, &raw_len); if (ret != 0) goto free; - ret = yaca_key_import(&raw_imported, YACA_KEY_TYPE_SYMMETRIC, raw, raw_len); + ret = yaca_key_import(&raw_imported, YACA_KEY_TYPE_SYMMETRIC, NULL, raw, raw_len); if (ret != 0) goto free; @@ -77,7 +77,7 @@ int key_import_export_sym(yaca_key_h sym) yaca_free(raw); raw = NULL; - ret = yaca_key_export(raw_imported, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_RAW, &raw, &raw_len); + ret = yaca_key_export(raw_imported, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_RAW, NULL, &raw, &raw_len); if (ret != 0) goto free; @@ -118,10 +118,10 @@ int key_import_export_asym(yaca_key_h priv, yaca_key_h pub, /* PEM private */ - ret = yaca_key_export(priv, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_PEM, &pem_prv, &pem_prv_len); + ret = yaca_key_export(priv, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_PEM, NULL, &pem_prv, &pem_prv_len); if (ret != 0) return ret; - ret = yaca_key_import(&pem_prv_imported, priv_type, pem_prv, pem_prv_len); + ret = yaca_key_import(&pem_prv_imported, priv_type, NULL, pem_prv, pem_prv_len); if (ret != 0) goto free; @@ -129,7 +129,7 @@ int key_import_export_asym(yaca_key_h priv, yaca_key_h pub, yaca_free(pem_prv); pem_prv = NULL; - ret = yaca_key_export(pem_prv_imported, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_PEM, &pem_prv, &pem_prv_len); + ret = yaca_key_export(pem_prv_imported, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_PEM, NULL, &pem_prv, &pem_prv_len); if (ret != 0) goto free; @@ -138,10 +138,10 @@ int key_import_export_asym(yaca_key_h priv, yaca_key_h pub, /* DER private */ - ret = yaca_key_export(priv, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_DER, &der_prv, &der_prv_len); + ret = yaca_key_export(priv, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_DER, NULL, &der_prv, &der_prv_len); if (ret != 0) goto free; - ret = yaca_key_import(&der_prv_imported, priv_type, der_prv, der_prv_len); + ret = yaca_key_import(&der_prv_imported, priv_type, NULL, der_prv, der_prv_len); if (ret != 0) goto free; @@ -149,7 +149,7 @@ int key_import_export_asym(yaca_key_h priv, yaca_key_h pub, yaca_free(der_prv); der_prv = NULL; - ret = yaca_key_export(der_prv_imported, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_DER, &der_prv, &der_prv_len); + ret = yaca_key_export(der_prv_imported, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_DER, NULL, &der_prv, &der_prv_len); if (ret != 0) goto free; @@ -158,10 +158,10 @@ int key_import_export_asym(yaca_key_h priv, yaca_key_h pub, /* PEM public */ - ret = yaca_key_export(pub, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_PEM, &pem_pub, &pem_pub_len); + ret = yaca_key_export(pub, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_PEM, NULL, &pem_pub, &pem_pub_len); if (ret != 0) goto free; - ret = yaca_key_import(&pem_pub_imported, pub_type, pem_pub, pem_pub_len); + ret = yaca_key_import(&pem_pub_imported, pub_type, NULL, pem_pub, pem_pub_len); if (ret != 0) goto free; @@ -169,7 +169,7 @@ int key_import_export_asym(yaca_key_h priv, yaca_key_h pub, yaca_free(pem_pub); pem_pub = NULL; - ret = yaca_key_export(pem_pub_imported, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_PEM, &pem_pub, &pem_pub_len); + ret = yaca_key_export(pem_pub_imported, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_PEM, NULL, &pem_pub, &pem_pub_len); if (ret != 0) goto free; @@ -178,10 +178,10 @@ int key_import_export_asym(yaca_key_h priv, yaca_key_h pub, /* DER public */ - ret = yaca_key_export(pub, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_DER, &der_pub, &der_pub_len); + ret = yaca_key_export(pub, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_DER, NULL, &der_pub, &der_pub_len); if (ret != 0) goto free; - ret = yaca_key_import(&der_pub_imported, pub_type, der_pub, der_pub_len); + ret = yaca_key_import(&der_pub_imported, pub_type, NULL, der_pub, der_pub_len); if (ret != 0) goto free; @@ -189,7 +189,7 @@ int key_import_export_asym(yaca_key_h priv, yaca_key_h pub, yaca_free(der_pub); der_pub = NULL; - ret = yaca_key_export(der_pub_imported, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_DER, &der_pub, &der_pub_len); + ret = yaca_key_export(der_pub_imported, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_DER, NULL, &der_pub, &der_pub_len); if (ret != 0) goto free; @@ -225,14 +225,14 @@ int key_import_x509(void) return ret; } - ret = yaca_key_import(&rsa_pub_from_cert, YACA_KEY_TYPE_RSA_PUB, pub, pub_len); + ret = yaca_key_import(&rsa_pub_from_cert, YACA_KEY_TYPE_RSA_PUB, NULL, pub, pub_len); if (ret != 0) goto free; yaca_free(pub); pub = NULL; - ret = yaca_key_export(rsa_pub_from_cert, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_PEM, &pub, &pub_len); + ret = yaca_key_export(rsa_pub_from_cert, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_PEM, NULL, &pub, &pub_len); if (ret != 0) goto free; diff --git a/examples/test.c b/examples/test.c index 6f1bdf4..4e6f7f0 100644 --- a/examples/test.c +++ b/examples/test.c @@ -45,7 +45,7 @@ int main(int argc, char* argv[]) printf("done (%d)\n", ret); printf("Exporting key using CryptoAPI.. "); - ret = yaca_key_export(key, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_RAW, &k, &kl); + ret = yaca_key_export(key, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_RAW, NULL, &k, &kl); if (ret < 0) return ret; printf("done (%d)\n", ret); diff --git a/src/key.c b/src/key.c index bb6bc32..c906d5a 100644 --- a/src/key.c +++ b/src/key.c @@ -850,6 +850,7 @@ API int yaca_key_get_bits(const yaca_key_h key) API int yaca_key_import(yaca_key_h *key, yaca_key_type_e key_type, + const char *password, const char *data, size_t data_len) { @@ -881,6 +882,7 @@ API int yaca_key_import(yaca_key_h *key, API int yaca_key_export(const yaca_key_h key, yaca_key_fmt_e key_fmt, yaca_key_file_fmt_e key_file_fmt, + const char *password, char **data, size_t *data_len) { -- 2.7.4 From d528b491ced211becaf512a59ad2fdc7d7cf80d7 Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Wed, 18 May 2016 15:41:11 +0200 Subject: [PATCH 13/16] API changes around key getters. yaca_key_get_bits() - return bits by size_t typed output param yaca_key_get_type() - new getter to get the type of the key Change-Id: I255f3bf3056a50602c1c2bd0a25c177ecf88ee07 --- api/yaca/key.h | 17 ++++++++++++++--- src/encrypt.c | 17 +++++++++++------ src/key.c | 25 +++++++++++++++++++++---- src/seal.c | 10 ++++++++-- 4 files changed, 54 insertions(+), 15 deletions(-) diff --git a/api/yaca/key.h b/api/yaca/key.h index d6a34d2..c58bc60 100644 --- a/api/yaca/key.h +++ b/api/yaca/key.h @@ -44,13 +44,24 @@ extern "C" { // TODO: We need a way to import keys encrypted with hw (or other) keys. New function like yaca_key_load or sth?? /** + * @brief Get key's type. + * + * @param[in] key Key which type we return. + * @param[out] key_type Key type. + * + * @return 0 on success, negative on error. + */ +int yaca_key_get_type(const yaca_key_h key, yaca_key_type_e *key_type); + +/** * @brief Get key's length (in bits). * - * @param[in] key Key which length we return. + * @param[in] key Key which length we return. + * @param[out] key_bits Key length in bits. * - * @return negative on error or key length (in bits). + * @return 0 on success, negative on error. */ -int yaca_key_get_bits(const yaca_key_h key); +int yaca_key_get_bits(const yaca_key_h key, size_t *key_bits); /** * @brief Imports a key. diff --git a/src/encrypt.c b/src/encrypt.c index c41b77a..a4516c3 100644 --- a/src/encrypt.c +++ b/src/encrypt.c @@ -216,9 +216,10 @@ static int encrypt_init(yaca_ctx_h *ctx, const struct yaca_key_simple_s *liv; struct yaca_encrypt_ctx_s *nc; const EVP_CIPHER *cipher; - int key_bits; + size_t key_bits; unsigned char *iv_data = NULL; - int iv_bits; + size_t iv_bits; + size_t iv_bits_check; int ret; if (ctx == NULL || sym_key == YACA_KEY_NULL) @@ -237,10 +238,9 @@ static int encrypt_init(yaca_ctx_h *ctx, nc->ctx.get_output_length = get_encrypt_output_length; nc->op_type = op_type; - ret = yaca_key_get_bits(sym_key); - if (ret < 0) + ret = yaca_key_get_bits(sym_key, &key_bits); + if (ret != 0) goto err_free; - key_bits = ret; ret = encrypt_get_algorithm(algo, bcm, key_bits, &cipher); if (ret != 0) @@ -265,7 +265,12 @@ static int encrypt_init(yaca_ctx_h *ctx, ret = YACA_ERROR_INVALID_ARGUMENT; goto err_free; } - if (iv_bits != yaca_key_get_bits(iv)) { /* IV length doesn't match cipher */ + ret = yaca_key_get_bits(iv, &iv_bits_check); + if (ret != 0) { + ret = YACA_ERROR_INVALID_ARGUMENT; + goto err_free; + } + if (iv_bits != iv_bits_check) { /* IV length doesn't match cipher */ ret = YACA_ERROR_INVALID_ARGUMENT; goto err_free; } diff --git a/src/key.c b/src/key.c index c906d5a..2730c09 100644 --- a/src/key.c +++ b/src/key.c @@ -823,13 +823,29 @@ struct yaca_key_evp_s *key_get_evp(const yaca_key_h key) } } -API int yaca_key_get_bits(const yaca_key_h key) +API int yaca_key_get_type(const yaca_key_h key, yaca_key_type_e *key_type) +{ + const struct yaca_key_s *lkey = (const struct yaca_key_s *)key; + + if (lkey == NULL || key_type == NULL) + return YACA_ERROR_INVALID_ARGUMENT; + + *key_type = lkey->type; + return 0; +} + +API int yaca_key_get_bits(const yaca_key_h key, size_t *key_bits) { const struct yaca_key_simple_s *simple_key = key_get_simple(key); const struct yaca_key_evp_s *evp_key = key_get_evp(key); - if (simple_key != NULL) - return simple_key->bits; + if (key_bits == NULL) + return YACA_ERROR_INVALID_ARGUMENT; + + if (simple_key != NULL) { + *key_bits = simple_key->bits; + return 0; + } if (evp_key != NULL) { int ret; @@ -842,7 +858,8 @@ API int yaca_key_get_bits(const yaca_key_h key) return ret; } - return ret; + *key_bits = ret; + return 0; } return YACA_ERROR_INVALID_ARGUMENT; diff --git a/src/seal.c b/src/seal.c index 47fe00f..bbaa2ca 100644 --- a/src/seal.c +++ b/src/seal.c @@ -222,7 +222,8 @@ static int open_init(yaca_ctx_h *ctx, const struct yaca_key_simple_s *liv; struct yaca_seal_ctx_s *nc; const EVP_CIPHER *cipher; - int iv_bits; + size_t iv_bits; + size_t iv_bits_check; int ret; if (ctx == NULL || prv_key == YACA_KEY_NULL || sym_key == YACA_KEY_NULL) @@ -271,7 +272,12 @@ static int open_init(yaca_ctx_h *ctx, } // TODO: handling of algorithms with variable IV length - if (iv_bits != yaca_key_get_bits(iv)) { /* IV length doesn't match cipher */ + ret = yaca_key_get_bits(iv, &iv_bits_check); + if (ret != 0) { + ret = YACA_ERROR_INVALID_ARGUMENT; + goto err_free; + } + if (iv_bits != iv_bits_check) { /* IV length doesn't match cipher */ ret = YACA_ERROR_INVALID_ARGUMENT; goto err_free; } -- 2.7.4 From 89ae7be7c0fb58432c1ff5f7b0c4c6251ca0cd3d Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Wed, 18 May 2016 17:13:07 +0200 Subject: [PATCH 14/16] API update: add YACA_ERROR_NONE enum value Change-Id: I88b5786a375a7c5c0bda47266ea332a09fb73ae5 --- api/yaca/error.h | 1 + 1 file changed, 1 insertion(+) diff --git a/api/yaca/error.h b/api/yaca/error.h index acdc2cb..64de6f7 100644 --- a/api/yaca/error.h +++ b/api/yaca/error.h @@ -38,6 +38,7 @@ extern "C" { * @brief Error enums */ enum __yaca_error_code { + YACA_ERROR_NONE = 0, YACA_ERROR_INVALID_ARGUMENT = -1, YACA_ERROR_NOT_IMPLEMENTED = -2, YACA_ERROR_INTERNAL = -3, -- 2.7.4 From d3a8562d6c516dd966f543a413659dd64e1a194a Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Mon, 9 May 2016 16:25:03 +0200 Subject: [PATCH 15/16] Rework symmetric encrypt/decrypt example. Change-Id: If8427b9a1374169f28541bc2435ffb0ce4e20cd4 --- examples/encrypt.c | 197 ++++++++++++++++++++++++++--------------------------- 1 file changed, 97 insertions(+), 100 deletions(-) diff --git a/examples/encrypt.c b/examples/encrypt.c index 3e95c86..fe686ce 100644 --- a/examples/encrypt.c +++ b/examples/encrypt.c @@ -24,187 +24,148 @@ #include #include -#include #include +#include #include #include #include "lorem.h" #include "misc.h" -// Symmetric encryption using simple API -void encrypt_simple(void) +void encrypt_simple(const yaca_enc_algo_e algo, + const yaca_block_cipher_mode_e bcm, + const size_t key_bits) { - const yaca_enc_algo_e algo = YACA_ENC_AES; - const yaca_block_cipher_mode_e bcm = YACA_BCM_CBC; - const size_t key_bits = YACA_KEY_256BIT; - int ret; yaca_key_h key = YACA_KEY_NULL; yaca_key_h iv = YACA_KEY_NULL; - char *enc_data = NULL; - char *dec_data = NULL; - size_t enc_len; - size_t dec_len; + + char *enc = NULL; + char *dec = NULL; + size_t enc_size; + size_t dec_size; size_t iv_bits; - printf("Simple Encrypt\nPlain data (16 of %zu bytes): %.16s\n", - LOREM1024_SIZE, lorem1024); + printf("Plain data (16 of %zu bytes): %.16s\n", LOREM4096_SIZE, lorem4096); - ret = yaca_key_derive_pbkdf2("foo bar", "123456789", 10, 1000, - YACA_DIGEST_SHA256, key_bits, &key); - if (ret) + /* Key generation */ + if (yaca_key_derive_pbkdf2("foo bar", "123456789", 10, 1000, + YACA_DIGEST_SHA256, key_bits, &key) != 0) return; if (yaca_get_iv_bits(algo, bcm, key_bits, &iv_bits) != 0) - return; + goto exit; - if (iv_bits > 0) { - ret = yaca_key_gen(&iv, YACA_KEY_TYPE_IV, iv_bits); - if (ret) - goto exit; - } + if (iv_bits > 0 && yaca_key_gen(&iv, YACA_KEY_TYPE_IV, iv_bits) != 0) + goto exit; - ret = yaca_encrypt(algo, bcm, key, iv, lorem1024, LOREM1024_SIZE, - &enc_data, &enc_len); - if (ret) + if (yaca_encrypt(algo, bcm, key, iv, lorem4096, LOREM4096_SIZE, &enc, &enc_size) != 0) goto exit; - dump_hex(enc_data, 16, "Encrypted data (16 of %zu bytes): ", enc_len); + dump_hex(enc, 16, "Encrypted data (16 of %zu bytes): ", enc_size); - ret = yaca_decrypt(algo, bcm, key, iv, enc_data, enc_len, &dec_data, - &dec_len); - if (ret < 0) + if (yaca_decrypt(algo, bcm, key, iv, enc, enc_size, &dec, &dec_size) != 0) goto exit; - printf("Decrypted data (16 of %zu bytes): %.16s\n", dec_len, dec_data); + printf("Decrypted data (16 of %zu bytes): %.16s\n\n", dec_size, dec); + exit: - if (enc_data) - yaca_free(enc_data); - if (dec_data) - yaca_free(dec_data); - if (iv != YACA_KEY_NULL) - yaca_key_free(iv); + + yaca_free(enc); + yaca_free(dec); + yaca_key_free(iv); yaca_key_free(key); } -// Symmetric encryption using advanced API -void encrypt_advanced(void) +void encrypt_advanced(const yaca_enc_algo_e algo, + const yaca_block_cipher_mode_e bcm, + const yaca_key_type_e key_type, + const size_t key_bits) { - const yaca_enc_algo_e algo = YACA_ENC_AES; - const yaca_block_cipher_mode_e bcm = YACA_BCM_CBC; - const size_t key_bits = YACA_KEY_256BIT; - int ret; - yaca_ctx_h ctx; + yaca_ctx_h ctx = YACA_CTX_NULL; yaca_key_h key = YACA_KEY_NULL; yaca_key_h iv = YACA_KEY_NULL; + size_t iv_bits; + char *enc = NULL; char *dec = NULL; size_t enc_size; size_t dec_size; - size_t iv_bits; - printf("Advanced Encrypt\nPlain data (16 of %zu bytes): %.16s\n", - LOREM4096_SIZE, lorem4096); + size_t block_len; + size_t output_len; + size_t out_size; + size_t rem; - /// Key generation + printf("Plain data (16 of %zu bytes): %.16s\n", LOREM4096_SIZE, lorem4096); - ret = yaca_key_derive_pbkdf2("foo bar", "123456789", 10, 1000, - YACA_DIGEST_SHA256, key_bits, &key); - if (ret) + /* Key generation */ + if (yaca_key_gen(&key, key_type, key_bits) != 0) return; if (yaca_get_iv_bits(algo, bcm, key_bits, &iv_bits) != 0) goto ex_key; - if (iv_bits > 0) { - ret = yaca_key_gen(&iv, YACA_KEY_TYPE_IV, iv_bits); - if (ret) - goto ex_key; - } + if (iv_bits > 0 && yaca_key_gen(&iv, YACA_KEY_TYPE_IV, iv_bits) != 0) + goto ex_key; - /// Encryption + /* Encryption */ { - size_t block_len; - size_t output_len; - size_t out_size; - size_t rem; - - ret = yaca_encrypt_init(&ctx, algo, bcm, key, iv); - if (ret) + if (yaca_encrypt_init(&ctx, algo, bcm, key, iv) != 0) goto ex_iv; - ret = yaca_get_block_length(ctx, &block_len); - if (ret != 0) + if (yaca_get_block_length(ctx, &block_len) != 0) goto ex_ctx; - ret = yaca_get_output_length(ctx, LOREM4096_SIZE, &output_len); - if (ret != 0) + if (yaca_get_output_length(ctx, LOREM4096_SIZE, &output_len) != 0) goto ex_ctx; /* Calculate max output: size of update + final chunks */ enc_size = output_len + block_len; - enc = yaca_malloc(enc_size); - if (enc == NULL) + if ((enc = yaca_malloc(enc_size)) == NULL) goto ex_ctx; out_size = enc_size; - ret = yaca_encrypt_update(ctx, lorem4096, LOREM4096_SIZE, enc, - &out_size); - if (ret < 0) + if (yaca_encrypt_update(ctx, lorem4096, LOREM4096_SIZE, enc, &out_size) != 0) goto ex_of; rem = enc_size - out_size; - ret = yaca_encrypt_final(ctx, enc + out_size, &rem); - if (ret < 0) + if (yaca_encrypt_final(ctx, enc + out_size, &rem) != 0) goto ex_of; enc_size = rem + out_size; - dump_hex(enc, 16, "Encrypted data (16 of %zu bytes): ", - enc_size); + dump_hex(enc, 16, "Encrypted data (16 of %zu bytes): ", enc_size); yaca_ctx_free(ctx); + ctx = YACA_CTX_NULL; } - /// Decryption + /* Decryption */ { - size_t block_len; - size_t output_len; - size_t out_size; - size_t rem; - - ret = yaca_decrypt_init(&ctx, algo, bcm, key, iv); - if (ret < 0) { - ctx = YACA_CTX_NULL; + if (yaca_decrypt_init(&ctx, algo, bcm, key, iv) != 0) goto ex_of; - } - ret = yaca_get_block_length(ctx, &block_len); - if (ret != 0) + if (yaca_get_block_length(ctx, &block_len) != 0) goto ex_of; - ret = yaca_get_output_length(ctx, LOREM4096_SIZE, &output_len); - if (ret != 0) - goto ex_ctx; + if (yaca_get_output_length(ctx, LOREM4096_SIZE, &output_len) != 0) + goto ex_of; /* Calculate max output: size of update + final chunks */ dec_size = output_len + block_len; - dec = yaca_malloc(dec_size); - if (dec == NULL) + if ((dec = yaca_malloc(dec_size)) == NULL) goto ex_of; out_size = dec_size; - ret = yaca_decrypt_update(ctx, enc, enc_size, dec, &out_size); - if (ret < 0) + if (yaca_decrypt_update(ctx, enc, enc_size, dec, &out_size) != 0) goto ex_in; rem = dec_size - out_size; - ret = yaca_decrypt_final(ctx, dec + out_size, &rem); - if (ret < 0) + if (yaca_decrypt_final(ctx, dec + out_size, &rem) != 0) goto ex_in; dec_size = rem + out_size; - printf("Decrypted data (16 of %zu bytes): %.16s\n", dec_size, dec); + printf("Decrypted data (16 of %zu bytes): %.16s\n\n", dec_size, dec); } ex_in: @@ -227,10 +188,46 @@ int main() if (ret < 0) return ret; - encrypt_simple(); + yaca_enc_algo_e algo = YACA_ENC_AES; + yaca_block_cipher_mode_e bcm = YACA_BCM_ECB; + yaca_key_type_e key_type = YACA_KEY_TYPE_SYMMETRIC; + size_t key_bits = YACA_KEY_256BIT; + + encrypt_simple(algo, bcm, key_bits); + encrypt_advanced(algo, bcm, key_type,key_bits); - encrypt_advanced(); + algo = YACA_ENC_3DES_3TDEA; + bcm = YACA_BCM_OFB; + key_type = YACA_KEY_TYPE_DES; + key_bits = YACA_KEY_192BIT; + + encrypt_advanced(algo, bcm, key_type,key_bits); + + algo = YACA_ENC_CAST5; + bcm = YACA_BCM_CFB; + key_type = YACA_KEY_TYPE_SYMMETRIC; + key_bits = YACA_KEY_UNSAFE_40BIT; + + encrypt_simple(algo, bcm, key_bits); + encrypt_advanced(algo, bcm, key_type,key_bits); + + algo = YACA_ENC_UNSAFE_RC2; + bcm = YACA_BCM_CBC; + key_type = YACA_KEY_TYPE_SYMMETRIC; + key_bits = YACA_KEY_UNSAFE_8BIT; + + encrypt_simple(algo, bcm, key_bits); + encrypt_advanced(algo, bcm, key_type,key_bits); + + algo = YACA_ENC_UNSAFE_RC4; + bcm = YACA_BCM_NONE; + key_type = YACA_KEY_TYPE_SYMMETRIC; + key_bits = YACA_KEY_2048BIT; + + encrypt_simple(algo, bcm, key_bits); + encrypt_advanced(algo, bcm, key_type,key_bits); yaca_exit(); + return ret; } -- 2.7.4 From 805dc74af5c322ca0199cf67bc30b7fae7f3c070 Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Thu, 12 May 2016 16:46:09 +0200 Subject: [PATCH 16/16] Update AES description. Change-Id: I4172389ae79b2c1028f3035d051f69db0a90804a --- api/yaca/types.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/api/yaca/types.h b/api/yaca/types.h index 72d45f4..282d007 100644 --- a/api/yaca/types.h +++ b/api/yaca/types.h @@ -133,8 +133,17 @@ typedef enum { typedef enum { /** * AES encryption. - * - see #yaca_block_cipher_mode_e for details on additional parameters (mandatory). * - Supported key lengths: @c 128, @c 192 and @c 256. + * - Supported block cipher modes: + * #YACA_BCM_CBC, + * #YACA_BCM_OFB, + * #YACA_BCM_CFB, + * #YACA_BCM_ECB, + * #YACA_BCM_GCM, + * #YACA_BCM_CCM, + * #YACA_BCM_CTR, + * #YACA_BCM_OCB + * - see #yaca_block_cipher_mode_e for details on additional parameters (mandatory). */ YACA_ENC_AES = 0, -- 2.7.4