From 50378da0a263e4bdaaa12f58e9976fb6e4d35f77 Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Thu, 11 Aug 2016 14:21:41 +0200 Subject: [PATCH 01/16] Reorganize API order in header files. Change-Id: I07bc47cfc3b08e157fe9200e2815957aec14713a --- api/yaca/yaca_crypto.h | 26 +++++++++++----------- api/yaca/yaca_key.h | 26 +++++++++++----------- api/yaca/yaca_simple.h | 58 +++++++++++++++++++++++++------------------------- 3 files changed, 55 insertions(+), 55 deletions(-) diff --git a/api/yaca/yaca_crypto.h b/api/yaca/yaca_crypto.h index 5806789..dfdbb8a 100755 --- a/api/yaca/yaca_crypto.h +++ b/api/yaca/yaca_crypto.h @@ -245,19 +245,6 @@ int yaca_context_get_property(const yaca_context_h ctx, size_t *value_len); /** - * @brief Destroys the crypto context. Must be called on all contexts that are - * no longer used. Passing #YACA_CONTEXT_NULL is allowed. - * - * @since_tizen 3.0 - * - * @param[in,out] ctx Crypto context - * - * @see #yaca_context_h - * - */ -void yaca_context_destroy(yaca_context_h ctx); - -/** * @brief Returns the minimum required size of the output buffer for a single crypto function call. * * @since_tizen 3.0 @@ -287,6 +274,19 @@ int yaca_context_get_output_length(const yaca_context_h ctx, size_t *output_len); /** + * @brief Destroys the crypto context. Must be called on all contexts that are + * no longer used. Passing #YACA_CONTEXT_NULL is allowed. + * + * @since_tizen 3.0 + * + * @param[in,out] ctx Crypto context + * + * @see #yaca_context_h + * + */ +void yaca_context_destroy(yaca_context_h ctx); + +/** * @} */ diff --git a/api/yaca/yaca_key.h b/api/yaca/yaca_key.h index b9bf0b1..87e3b30 100755 --- a/api/yaca/yaca_key.h +++ b/api/yaca/yaca_key.h @@ -318,19 +318,6 @@ int yaca_key_extract_public(const yaca_key_h prv_key, yaca_key_h *pub_key); int yaca_key_extract_parameters(const yaca_key_h key, yaca_key_h *params); /** - * @brief Release the key created by the library. Passing YACA_KEY_NULL is allowed. - * - * @since_tizen 3.0 - * - * @param[in,out] key Key to be released - * - * @see yaca_key_import() - * @see yaca_key_export() - * @see yaca_key_generate() - */ -void yaca_key_destroy(yaca_key_h key); - -/** * @brief Derives a shared secret using Diffie-Helmann or EC Diffie-Helmann key exchange protocol. * * @since_tizen 3.0 @@ -437,6 +424,19 @@ int yaca_key_derive_pbkdf2(const char *password, yaca_key_h *key); /** + * @brief Release the key created by the library. Passing YACA_KEY_NULL is allowed. + * + * @since_tizen 3.0 + * + * @param[in,out] key Key to be released + * + * @see yaca_key_import() + * @see yaca_key_export() + * @see yaca_key_generate() + */ +void yaca_key_destroy(yaca_key_h key); + +/** * @} */ diff --git a/api/yaca/yaca_simple.h b/api/yaca/yaca_simple.h index e39e347..487c53d 100755 --- a/api/yaca/yaca_simple.h +++ b/api/yaca/yaca_simple.h @@ -46,35 +46,6 @@ extern "C" { */ /** - * @brief Calculates a digest of a buffer. - * - * @since_tizen 3.0 - * - * @remarks The @a digest should be freed using yaca_free() - * - * @param[in] algo Digest algorithm (select #YACA_DIGEST_SHA256 if unsure) - * @param[in] data Data from which the digest is to be calculated - * @param[in] data_len Length of the data. Can be 0. - * @param[out] digest Message digest, will be allocated by the library - * @param[out] digest_len Length of message digest (depends on algorithm) - * - * @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, - * invalid algo) - * @retval #YACA_ERROR_OUT_OF_MEMORY Out of memory error - * @retval #YACA_ERROR_INTERNAL Internal error - * - * @see #yaca_digest_algorithm_e - * @see yaca_free() - */ -int yaca_simple_calculate_digest(yaca_digest_algorithm_e algo, - const char *data, - size_t data_len, - char **digest, - size_t *digest_len); - -/** * @brief Encrypts data using a symmetric cipher. * * @since_tizen 3.0 @@ -149,6 +120,35 @@ int yaca_simple_decrypt(yaca_encrypt_algorithm_e algo, size_t *plaintext_len); /** + * @brief Calculates a digest of a buffer. + * + * @since_tizen 3.0 + * + * @remarks The @a digest should be freed using yaca_free() + * + * @param[in] algo Digest algorithm (select #YACA_DIGEST_SHA256 if unsure) + * @param[in] data Data from which the digest is to be calculated + * @param[in] data_len Length of the data. Can be 0. + * @param[out] digest Message digest, will be allocated by the library + * @param[out] digest_len Length of message digest (depends on algorithm) + * + * @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, + * invalid algo) + * @retval #YACA_ERROR_OUT_OF_MEMORY Out of memory error + * @retval #YACA_ERROR_INTERNAL Internal error + * + * @see #yaca_digest_algorithm_e + * @see yaca_free() + */ +int yaca_simple_calculate_digest(yaca_digest_algorithm_e algo, + const char *data, + size_t data_len, + char **digest, + size_t *digest_len); + +/** * @brief Creates a signature using asymmetric private key. * * @since_tizen 3.0 -- 2.7.4 From d67c7a089954b3ee369c1f72bfa65ecdb2231295 Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Thu, 11 Aug 2016 16:31:01 +0200 Subject: [PATCH 02/16] Fix: seal/open sym_key_bit_len must be dividable by 8 Fix documentation. Change-Id: I8a4ad8bb9bcd91f17c8318cb5a0db744cbed1c34 --- api/yaca/yaca_seal.h | 4 ++++ src/seal.c | 20 ++++++++++---------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/api/yaca/yaca_seal.h b/api/yaca/yaca_seal.h index 982855c..380e55d 100755 --- a/api/yaca/yaca_seal.h +++ b/api/yaca/yaca_seal.h @@ -49,6 +49,8 @@ extern "C" { * * @remarks The @a ctx should be released using yaca_context_destroy() * + * @remarks The @a pub_key must be #YACA_KEY_TYPE_RSA_PUB + * * @remarks The @a sym_key should be released using yaca_key_destroy() * * @remarks The @a iv should be released using yaca_key_destroy() @@ -152,6 +154,8 @@ int yaca_seal_finalize(yaca_context_h ctx, * * @remarks The @a ctx should be released using yaca_context_destroy() * + * @remarks The @a prv_key must be #YACA_KEY_TYPE_RSA_PRIV + * * @param[out] ctx Newly created context * @param[in] prv_key Private key, part of the pair that was used for the encryption * @param[in] algo Symmetric algorithm that was used for the encryption diff --git a/src/seal.c b/src/seal.c index 504470f..7707e6a 100644 --- a/src/seal.c +++ b/src/seal.c @@ -149,8 +149,8 @@ API int yaca_seal_initialize(yaca_context_h *ctx, const yaca_key_h pub_key, yaca_encrypt_algorithm_e algo, yaca_block_cipher_mode_e bcm, - size_t bit_len, - yaca_key_h *enc_sym_key, + size_t sym_key_bit_len, + yaca_key_h *sym_key, yaca_key_h *iv) { int ret; @@ -160,10 +160,10 @@ 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 || bcm == YACA_BCM_WRAP) + sym_key == NULL || bcm == YACA_BCM_WRAP || sym_key_bit_len % 8 != 0) return YACA_ERROR_INVALID_PARAMETER; - ret = encrypt_get_algorithm(algo, bcm, bit_len, &cipher); + ret = encrypt_get_algorithm(algo, bcm, sym_key_bit_len, &cipher); if (ret != YACA_ERROR_NONE) goto exit; @@ -189,7 +189,7 @@ API int yaca_seal_initialize(yaca_context_h *ctx, if (ret != YACA_ERROR_NONE) goto exit; - *enc_sym_key = lenc_sym_key; + *sym_key = lenc_sym_key; lenc_sym_key = YACA_KEY_NULL; *iv = liv; liv = YACA_KEY_NULL; @@ -224,8 +224,8 @@ API int yaca_open_initialize(yaca_context_h *ctx, const yaca_key_h prv_key, yaca_encrypt_algorithm_e algo, yaca_block_cipher_mode_e bcm, - size_t bit_len, - const yaca_key_h enc_sym_key, + size_t sym_key_bit_len, + const yaca_key_h sym_key, const yaca_key_h iv) { int ret; @@ -233,15 +233,15 @@ 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 || bcm == YACA_BCM_WRAP) + sym_key == YACA_KEY_NULL || bcm == YACA_BCM_WRAP || sym_key_bit_len % 8 != 0) return YACA_ERROR_INVALID_PARAMETER; - ret = encrypt_get_algorithm(algo, bcm, bit_len, &cipher); + ret = encrypt_get_algorithm(algo, bcm, sym_key_bit_len, &cipher); if (ret != YACA_ERROR_NONE) goto exit; /* using private key will make it decrypt the symmetric key */ - ret = seal_encrypt_decrypt_key(prv_key, enc_sym_key, &lsym_key); + ret = seal_encrypt_decrypt_key(prv_key, sym_key, &lsym_key); if (ret != YACA_ERROR_NONE) goto exit; -- 2.7.4 From 9bc39c61d4d1d727fd660567c46b76923e029322 Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Fri, 12 Aug 2016 12:14:40 +0200 Subject: [PATCH 03/16] Fix: Simple API doesn't support GCM and CCM. Change-Id: Ief86239a05aacb5671354f3bb11208afea562c80 --- api/yaca/yaca_simple.h | 4 ++++ src/simple.c | 6 ++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/api/yaca/yaca_simple.h b/api/yaca/yaca_simple.h index 487c53d..96c9d97 100755 --- a/api/yaca/yaca_simple.h +++ b/api/yaca/yaca_simple.h @@ -50,6 +50,8 @@ extern "C" { * * @since_tizen 3.0 * + * @remarks yaca_simple_encrypt() doesn't support #YACA_BCM_GCM and #YACA_BCM_CCM + * * @remarks The @a ciphertext should be freed using yaca_free() * * @param[in] algo Encryption algorithm (select #YACA_ENCRYPT_AES if unsure) @@ -87,6 +89,8 @@ int yaca_simple_encrypt(yaca_encrypt_algorithm_e algo, * * @since_tizen 3.0 * + * @remarks yaca_simple_decrypt() doesn't support #YACA_BCM_GCM and #YACA_BCM_CCM + * * @remarks The @a plaintext should be freed using yaca_free() * * @param[in] algo Decryption algorithm that was used to encrypt the data diff --git a/src/simple.c b/src/simple.c index 4301248..322c123 100644 --- a/src/simple.c +++ b/src/simple.c @@ -99,7 +99,8 @@ API int yaca_simple_encrypt(yaca_encrypt_algorithm_e algo, if (plaintext == NULL || plaintext_len == 0 || ciphertext == NULL || ciphertext_len == NULL || - sym_key == YACA_KEY_NULL) + sym_key == YACA_KEY_NULL || + bcm == YACA_BCM_CCM || bcm == YACA_BCM_GCM) return YACA_ERROR_INVALID_PARAMETER; ret = yaca_encrypt_initialize(&ctx, algo, bcm, sym_key, iv); @@ -172,7 +173,8 @@ API int yaca_simple_decrypt(yaca_encrypt_algorithm_e algo, if (ciphertext == NULL || ciphertext_len == 0 || plaintext == NULL || plaintext_len == NULL || - sym_key == YACA_KEY_NULL) + sym_key == YACA_KEY_NULL || + bcm == YACA_BCM_CCM || bcm == YACA_BCM_GCM) return YACA_ERROR_INVALID_PARAMETER; ret = yaca_decrypt_initialize(&ctx, algo, bcm, sym_key, iv); -- 2.7.4 From 264f9d1a369ba73eadce35c939ec667150990095 Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Fri, 12 Aug 2016 14:51:55 +0200 Subject: [PATCH 04/16] Remove debug function from examples. Remove outdated TODO. Change-Id: I9cc610efec27fd84a95c1bade1b7b59892e781aa --- examples/digest.c | 3 --- examples/encrypt.c | 3 --- examples/encrypt_aes_gcm_ccm.c | 3 --- examples/key_exchange.c | 3 --- examples/key_gen.c | 5 ++--- examples/key_import_export.c | 3 --- examples/key_password.c | 5 ++--- examples/key_wrap.c | 3 --- examples/seal.c | 3 --- examples/sign.c | 3 --- todo.txt | 3 --- 11 files changed, 4 insertions(+), 33 deletions(-) diff --git a/examples/digest.c b/examples/digest.c index bbbccb0..582323e 100644 --- a/examples/digest.c +++ b/examples/digest.c @@ -28,7 +28,6 @@ #include "lorem.h" #include "misc.h" -#include "../src/debug.h" void digest_simple(void) { @@ -81,8 +80,6 @@ exit: int main() { - yaca_debug_set_error_cb(debug_func); - int ret = yaca_initialize(); if (ret != YACA_ERROR_NONE) return ret; diff --git a/examples/encrypt.c b/examples/encrypt.c index 3f6274c..2d5c2c5 100644 --- a/examples/encrypt.c +++ b/examples/encrypt.c @@ -31,7 +31,6 @@ #include "lorem.h" #include "misc.h" -#include "../src/debug.h" void encrypt_simple(const yaca_encrypt_algorithm_e algo, const yaca_block_cipher_mode_e bcm, @@ -182,8 +181,6 @@ exit: int main() { - yaca_debug_set_error_cb(debug_func); - int ret = yaca_initialize(); if (ret != YACA_ERROR_NONE) return ret; diff --git a/examples/encrypt_aes_gcm_ccm.c b/examples/encrypt_aes_gcm_ccm.c index 719ff77..c823d6a 100644 --- a/examples/encrypt_aes_gcm_ccm.c +++ b/examples/encrypt_aes_gcm_ccm.c @@ -30,7 +30,6 @@ #include "lorem.h" #include "misc.h" -#include "../src/debug.h" void encrypt_decrypt_aes_gcm(void) { @@ -321,8 +320,6 @@ exit: int main() { - yaca_debug_set_error_cb(debug_func); - int ret = yaca_initialize(); if (ret != YACA_ERROR_NONE) return ret; diff --git a/examples/key_exchange.c b/examples/key_exchange.c index cc645a9..ee75eac 100644 --- a/examples/key_exchange.c +++ b/examples/key_exchange.c @@ -28,7 +28,6 @@ #include #include "misc.h" -#include "../src/debug.h" /* send own public key and get peer public key */ static yaca_key_h exchange_keys(const yaca_key_h pkey) @@ -167,8 +166,6 @@ exit: int main() { - yaca_debug_set_error_cb(debug_func); - 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; diff --git a/examples/key_gen.c b/examples/key_gen.c index 97ad433..a1ddf36 100644 --- a/examples/key_gen.c +++ b/examples/key_gen.c @@ -17,12 +17,13 @@ */ #include + #include #include #include #include + #include "misc.h" -#include "../src/debug.h" int main() { @@ -30,8 +31,6 @@ int main() yaca_key_h key = YACA_KEY_NULL; yaca_key_h key_params = YACA_KEY_NULL; - yaca_debug_set_error_cb(debug_func); - ret = yaca_initialize(); if (ret != YACA_ERROR_NONE) goto error; diff --git a/examples/key_import_export.c b/examples/key_import_export.c index 9b29011..4a50cb7 100644 --- a/examples/key_import_export.c +++ b/examples/key_import_export.c @@ -28,7 +28,6 @@ #include #include "misc.h" -#include "../src/debug.h" int key_import_export_sym(yaca_key_h sym) { @@ -253,8 +252,6 @@ int main() if (ret != YACA_ERROR_NONE) return ret; - yaca_debug_set_error_cb(debug_func); - ret = yaca_key_generate(YACA_KEY_TYPE_SYMMETRIC, YACA_KEY_LENGTH_1024BIT, &sym); if (ret != YACA_ERROR_NONE) goto exit; diff --git a/examples/key_password.c b/examples/key_password.c index 724e472..7eb46b4 100644 --- a/examples/key_password.c +++ b/examples/key_password.c @@ -18,12 +18,13 @@ #include #include + #include #include #include #include + #include "misc.h" -#include "../src/debug.h" void example_password(const yaca_key_h key, yaca_key_format_e key_fmt, yaca_key_file_format_e key_file_fmt) @@ -81,8 +82,6 @@ int main() int ret; yaca_key_h key = YACA_KEY_NULL; - yaca_debug_set_error_cb(debug_func); - ret = yaca_initialize(); if (ret != YACA_ERROR_NONE) goto exit; diff --git a/examples/key_wrap.c b/examples/key_wrap.c index af8c655..6162397 100644 --- a/examples/key_wrap.c +++ b/examples/key_wrap.c @@ -31,7 +31,6 @@ #include #include "misc.h" -#include "../src/debug.h" void key_wrap_aes(void) { @@ -197,8 +196,6 @@ exit: int main() { - yaca_debug_set_error_cb(debug_func); - int ret = yaca_initialize(); if (ret != YACA_ERROR_NONE) return ret; diff --git a/examples/seal.c b/examples/seal.c index ff1a9e8..7a1aaa0 100644 --- a/examples/seal.c +++ b/examples/seal.c @@ -30,7 +30,6 @@ #include "lorem.h" #include "misc.h" -#include "../src/debug.h" void encrypt_seal(const yaca_encrypt_algorithm_e algo, const yaca_block_cipher_mode_e bcm, @@ -428,8 +427,6 @@ exit: int main() { - yaca_debug_set_error_cb(debug_func); - int ret = yaca_initialize(); if (ret != YACA_ERROR_NONE) return ret; diff --git a/examples/sign.c b/examples/sign.c index a3d88ff..df7ff58 100644 --- a/examples/sign.c +++ b/examples/sign.c @@ -31,7 +31,6 @@ #include "lorem.h" #include "misc.h" -#include "../src/debug.h" /* Signature creation and verification using simple API */ void simple_sign_verify_asym(yaca_key_type_e type, const char *algo) @@ -357,8 +356,6 @@ exit: int main() { - yaca_debug_set_error_cb(debug_func); - int ret = yaca_initialize(); if (ret != YACA_ERROR_NONE) return ret; diff --git a/todo.txt b/todo.txt index 99c60ce..78272ad 100644 --- a/todo.txt +++ b/todo.txt @@ -1,10 +1,7 @@ Global: - Rethink and possibly add verification of output buffer lengths. In other words check whether the user won't cause a buffer overflow. -- Importing/exporting encrypted (passphrased) RSA keys - Support for OCB mode was added in OpenSSL 1.1.0 -- Remove debug function from examples -- yaca_key_wrap(), yaca_key_unwrap() - 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. -- 2.7.4 From 49184d8a67021c68fb38bc6a14fc1862beacf696 Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Wed, 10 Aug 2016 10:44:44 +0200 Subject: [PATCH 05/16] Handle encryption API call order Encryption, decryption, seal & open API functions have to be called in specific order. This commit introduces state change matrices that are used to verify the correct call order. Change-Id: I99029d55bb26af9ec34d7297548c331fbbc41522 --- src/encrypt.c | 152 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- src/internal.h | 14 +++++- 2 files changed, 156 insertions(+), 10 deletions(-) diff --git a/src/encrypt.c b/src/encrypt.c index 070a1f2..0bf6eab 100644 --- a/src/encrypt.c +++ b/src/encrypt.c @@ -117,6 +117,90 @@ static bool is_encryption_op(enum encrypt_op_type_e op_type) return (op_type == OP_ENCRYPT || op_type == OP_SEAL); } +static bool DEFAULT_STATES[STATE_COUNT][STATE_COUNT] = { +/* from \ to INIT, MLEN, AAD, MSG, TAG, TLEN, FIN */ +/* INIT */ { 0, 0, 0, 1, 0, 0, 1 }, +/* MLEN */ { 0, 0, 0, 0, 0, 0, 0 }, +/* AAD */ { 0, 0, 0, 0, 0, 0, 0 }, +/* MSG */ { 0, 0, 0, 1, 0, 0, 1 }, +/* TAG */ { 0, 0, 0, 0, 0, 0, 0 }, +/* TLEN */ { 0, 0, 0, 0, 0, 0, 0 }, +/* FIN */ { 0, 0, 0, 0, 0, 0, 0 }, +}; + +static bool GCM_STATES[2][STATE_COUNT][STATE_COUNT] = { { +/* ENCRYPTION */ +/* from \ to INIT, MLEN, AAD, MSG, TAG, TLEN, FIN */ +/* INIT */ { 0, 0, 1, 1, 0, 0, 1 }, +/* MLEN */ { 0, 0, 0, 0, 0, 0, 0 }, +/* AAD */ { 0, 0, 1, 1, 0, 0, 1 }, +/* MSG */ { 0, 0, 0, 1, 0, 0, 1 }, +/* TAG */ { 0, 0, 0, 0, 0, 0, 0 }, +/* TLEN */ { 0, 0, 0, 0, 0, 0, 0 }, +/* FIN */ { 0, 0, 0, 0, 0, 1, 0 }, +}, { +/* DECRYPTION */ +/* from \ to INIT, MLEN, AAD, MSG, TAG, TLEN, FIN */ +/* INIT */ { 0, 0, 1, 1, 1, 0, 0 }, +/* MLEN */ { 0, 0, 0, 0, 0, 0, 0 }, +/* AAD */ { 0, 0, 1, 1, 1, 0, 0 }, +/* MSG */ { 0, 0, 0, 1, 1, 0, 0 }, +/* TAG */ { 0, 0, 0, 0, 0, 0, 1 }, +/* TLEN */ { 0, 0, 0, 0, 0, 0, 0 }, +/* FIN */ { 0, 0, 0, 0, 0, 0, 0 }, +} }; + +static bool CCM_STATES[2][STATE_COUNT][STATE_COUNT] = { { +/* ENCRYPTION */ +/* from \ to INIT, MLEN, AAD, MSG, TAG, TLEN, FIN */ +/* INIT */ { 0, 1, 0, 1, 0, 1, 0 }, +/* MLEN */ { 0, 0, 1, 0, 0, 0, 0 }, +/* AAD */ { 0, 0, 0, 1, 0, 0, 0 }, +/* MSG */ { 0, 0, 0, 0, 0, 0, 1 }, +/* TAG */ { 0, 0, 0, 0, 0, 0, 0 }, +/* TLEN */ { 0, 1, 0, 1, 0, 0, 0 }, +/* FIN */ { 0, 0, 0, 0, 0, 0, 0 }, +}, { +/* DECRYPTION */ +/* from \ to INIT, MLEN, AAD, MSG, TAG, TLEN, FIN */ +/* INIT */ { 0, 0, 0, 0, 1, 0, 0 }, +/* MLEN */ { 0, 0, 1, 0, 0, 0, 0 }, +/* AAD */ { 0, 0, 0, 1, 0, 0, 0 }, +/* MSG */ { 0, 0, 0, 0, 0, 0, 1 }, +/* TAG */ { 0, 1, 0, 1, 0, 0, 0 }, +/* TLEN */ { 0, 0, 0, 0, 0, 0, 0 }, +/* FIN */ { 0, 0, 0, 0, 0, 0, 0 }, +} }; + +static bool WRAP_STATES[STATE_COUNT][STATE_COUNT] = { +/* from \ to INIT, MLEN, AAD, MSG, TAG, TLEN, FIN */ +/* INIT */ { 0, 0, 0, 1, 0, 0, 1 }, +/* MLEN */ { 0, 0, 0, 0, 0, 0, 0 }, +/* AAD */ { 0, 0, 0, 0, 0, 0, 0 }, +/* MSG */ { 0, 0, 0, 0, 0, 0, 1 }, +/* TAG */ { 0, 0, 0, 0, 0, 0, 0 }, +/* TLEN */ { 0, 0, 0, 0, 0, 0, 0 }, +/* FIN */ { 0, 0, 0, 0, 0, 0, 0 }, +}; + +static bool verify_state_change(struct yaca_encrypt_context_s *c, enum encrypt_context_state_e to) +{ + int mode = EVP_CIPHER_CTX_mode(c->cipher_ctx); + bool encryption = is_encryption_op(c->op_type); + int from = c->state; + + if (mode == EVP_CIPH_CCM_MODE) + return CCM_STATES[encryption ? 0 : 1][from][to]; + else if (mode == EVP_CIPH_GCM_MODE) + return GCM_STATES[encryption ? 0 : 1][from][to]; + else if (mode == EVP_CIPH_WRAP_MODE) + return WRAP_STATES[from][to]; + else + return DEFAULT_STATES[from][to]; + + return false; +} + struct yaca_encrypt_context_s *get_encrypt_context(const yaca_context_h ctx) { if (ctx == YACA_CONTEXT_NULL) @@ -233,7 +317,6 @@ static int encrypt_ctx_create(struct yaca_encrypt_context_s **c, nc->ctx.get_property = get_encrypt_property; nc->op_type = op_type; nc->tag_len = 0; - nc->update_called = false; /* set default tag length for GCM and CCM */ if (mode == EVP_CIPH_GCM_MODE) @@ -525,25 +608,36 @@ int set_encrypt_property(yaca_context_h ctx, if (mode != EVP_CIPH_GCM_MODE) return YACA_ERROR_INVALID_PARAMETER; + if (!verify_state_change(c, STATE_AAD_UPDATED)) + return YACA_ERROR_INVALID_PARAMETER; + if (EVP_CipherUpdate(c->cipher_ctx, NULL, &len, value, value_len) != 1) { ERROR_DUMP(YACA_ERROR_INTERNAL); return YACA_ERROR_INTERNAL; } + c->state = STATE_AAD_UPDATED; break; case YACA_PROPERTY_CCM_AAD: if (mode != EVP_CIPH_CCM_MODE) return YACA_ERROR_INVALID_PARAMETER; + if (!verify_state_change(c, STATE_AAD_UPDATED)) + return YACA_ERROR_INVALID_PARAMETER; + if (EVP_CipherUpdate(c->cipher_ctx, NULL, &len, value, value_len) != 1) { ERROR_DUMP(YACA_ERROR_INTERNAL); return YACA_ERROR_INTERNAL; } + c->state = STATE_AAD_UPDATED; break; case YACA_PROPERTY_GCM_TAG: if (mode != EVP_CIPH_GCM_MODE || is_encryption_op(c->op_type) || value_len == 0 || value_len > INT_MAX) return YACA_ERROR_INVALID_PARAMETER; + if (!verify_state_change(c, STATE_TAG_SET)) + return YACA_ERROR_INVALID_PARAMETER; + if (EVP_CIPHER_CTX_ctrl(c->cipher_ctx, EVP_CTRL_GCM_SET_TAG, value_len, @@ -551,6 +645,7 @@ int set_encrypt_property(yaca_context_h ctx, ERROR_DUMP(YACA_ERROR_INTERNAL); return YACA_ERROR_INTERNAL; } + c->state = STATE_TAG_SET; break; case YACA_PROPERTY_GCM_TAG_LEN: if (value_len != sizeof(size_t) || mode != EVP_CIPH_GCM_MODE || @@ -558,25 +653,44 @@ int set_encrypt_property(yaca_context_h ctx, *(size_t*)value == 0 || *(size_t*)value > INT_MAX) return YACA_ERROR_INVALID_PARAMETER; + if (!verify_state_change(c, STATE_TAG_LENGTH_SET)) + return YACA_ERROR_INVALID_PARAMETER; + c->tag_len = *(size_t*)value; + c->state = STATE_TAG_LENGTH_SET; break; case YACA_PROPERTY_CCM_TAG: if (mode != EVP_CIPH_CCM_MODE || is_encryption_op(c->op_type)) return YACA_ERROR_INVALID_PARAMETER; + if (!verify_state_change(c, STATE_TAG_SET)) + return YACA_ERROR_INVALID_PARAMETER; + ret = encrypt_ctx_set_ccm_tag(c, (char*)value, value_len); + if (ret != YACA_ERROR_NONE) + return ret; + + c->state = STATE_TAG_SET; break; case YACA_PROPERTY_CCM_TAG_LEN: if (value_len != sizeof(size_t) || mode != EVP_CIPH_CCM_MODE || !is_encryption_op(c->op_type)) return YACA_ERROR_INVALID_PARAMETER; + if (!verify_state_change(c, STATE_TAG_LENGTH_SET)) + return YACA_ERROR_INVALID_PARAMETER; + ret = encrypt_ctx_set_ccm_tag_len(c, *(size_t*)value); + if (ret != YACA_ERROR_NONE) + return ret; + + c->state = STATE_TAG_LENGTH_SET; 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) + *(yaca_padding_e*)value != YACA_PADDING_NONE || + c->state == STATE_FINALIZED) return YACA_ERROR_INVALID_PARAMETER; if (EVP_CIPHER_CTX_set_padding(c->cipher_ctx, 0) != 1) { @@ -605,7 +719,10 @@ int get_encrypt_property(const yaca_context_h ctx, yaca_property_e property, switch (property) { case YACA_PROPERTY_GCM_TAG: - if (value_len == NULL || !is_encryption_op(c->op_type) || mode != EVP_CIPH_GCM_MODE) + if (value_len == NULL || + !is_encryption_op(c->op_type) || + mode != EVP_CIPH_GCM_MODE || + (c->state != STATE_TAG_LENGTH_SET && c->state != STATE_FINALIZED)) return YACA_ERROR_INVALID_PARAMETER; assert(c->tag_len <= INT_MAX); @@ -620,7 +737,10 @@ int get_encrypt_property(const yaca_context_h ctx, yaca_property_e property, *value_len = c->tag_len; break; case YACA_PROPERTY_CCM_TAG: - if (value_len == NULL || !is_encryption_op(c->op_type) || mode != EVP_CIPH_CCM_MODE) + if (value_len == NULL || + !is_encryption_op(c->op_type) || + mode != EVP_CIPH_CCM_MODE || + c->state != STATE_FINALIZED) return YACA_ERROR_INVALID_PARAMETER; assert(c->tag_len <= INT_MAX); @@ -762,6 +882,8 @@ int encrypt_initialize(yaca_context_h *ctx, goto exit; } + nc->state = STATE_INITIALIZED; + *ctx = (yaca_context_h)nc; nc = NULL; ret = YACA_ERROR_NONE; @@ -789,11 +911,18 @@ int encrypt_update(yaca_context_h ctx, 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; + enum encrypt_context_state_e target_state; + if (output == NULL && input == NULL) + target_state = STATE_MSG_LENGTH_UPDATED; + else if (output == NULL) + target_state = STATE_AAD_UPDATED; + else if (input == NULL) + return YACA_ERROR_INVALID_PARAMETER; + else + target_state = STATE_MSG_UPDATED; - if (mode == EVP_CIPH_WRAP_MODE && c->update_called == true) - return YACA_ERROR_INVALID_PARAMETER; + if (!verify_state_change(c, target_state)) + 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) { @@ -823,7 +952,8 @@ int encrypt_update(yaca_context_h ctx, } *output_len = loutput_len; - c->update_called = true; + + c->state = target_state; /* Fix for OpenSSL error in 3DES CFB1 */ if ((c->cipher_ctx->flags & EVP_CIPH_FLAG_LENGTH_BITS) != 0) @@ -843,6 +973,9 @@ int encrypt_finalize(yaca_context_h ctx, if (c == NULL || output == NULL || output_len == NULL || op_type != c->op_type) return YACA_ERROR_INVALID_PARAMETER; + if (!verify_state_change(c, STATE_FINALIZED)) + return YACA_ERROR_INVALID_PARAMETER; + 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) @@ -855,6 +988,7 @@ int encrypt_finalize(yaca_context_h ctx, if ((c->cipher_ctx->flags & EVP_CIPH_FLAG_LENGTH_BITS) != 0) *output_len /= 8; + c->state = STATE_FINALIZED; return YACA_ERROR_NONE; } diff --git a/src/internal.h b/src/internal.h index 7c202ec..9e241e3 100644 --- a/src/internal.h +++ b/src/internal.h @@ -67,6 +67,18 @@ struct yaca_backup_context_s { yaca_key_h iv; }; +enum encrypt_context_state_e { + STATE_INITIALIZED = 0, + STATE_MSG_LENGTH_UPDATED, + STATE_AAD_UPDATED, + STATE_MSG_UPDATED, + STATE_TAG_SET, + STATE_TAG_LENGTH_SET, + STATE_FINALIZED, + + STATE_COUNT, +}; + struct yaca_encrypt_context_s { struct yaca_context_s ctx; struct yaca_backup_context_s *backup_ctx; @@ -74,7 +86,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; + enum encrypt_context_state_e state; }; /* Base structure for crypto keys - to be inherited */ -- 2.7.4 From 1f2f1b9dc6bc33428c5c6af22fceb3761bebcb97 Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Wed, 17 Aug 2016 14:29:47 +0200 Subject: [PATCH 06/16] Add missing ERROR_DUMP() for EVP_PKEY_size() Change-Id: Ie03a37e9ad91cc4b3876d177b1a45593598f645b --- src/seal.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/seal.c b/src/seal.c index 7707e6a..83094ce 100644 --- a/src/seal.c +++ b/src/seal.c @@ -100,8 +100,11 @@ static int seal_encrypt_decrypt_key(const yaca_key_h asym_key, return YACA_ERROR_INVALID_PARAMETER; ret = EVP_PKEY_size(lasym_key->evp); - if (ret <= 0) - return YACA_ERROR_INTERNAL; + if (ret <= 0) { + ret = YACA_ERROR_INTERNAL; + ERROR_DUMP(ret); + return ret; + } output_len = ret; -- 2.7.4 From 0e594530adaaf13491176fed6c72fa2df40020b6 Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Thu, 18 Aug 2016 16:27:52 +0200 Subject: [PATCH 07/16] Add GCM tag length verification Change-Id: If3b1c5e33d9a93a2120e8aeddfca024f05355321 --- api/yaca/yaca_types.h | 10 +++++----- src/encrypt.c | 18 ++++++++++++++++-- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/api/yaca/yaca_types.h b/api/yaca/yaca_types.h index 2cf7d50..857710c 100755 --- a/api/yaca/yaca_types.h +++ b/api/yaca/yaca_types.h @@ -478,8 +478,8 @@ typedef enum { * * Supported properties: * - #YACA_PROPERTY_GCM_TAG_LEN = GCM tag length\n - * Supported tag lengths: @c 32, @c 64, @c 96, @c 104, @c 112, @c 120, @c 128, - * (recommended 128 bits tag).\n + * Supported tag lengths: @c 4, @c 8, @c 12, @c 13, @c 14, @c 15, @c 16, + * (recommended 16 bytes 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 @@ -534,7 +534,7 @@ typedef enum { * * Supported properties: * - #YACA_PROPERTY_CCM_TAG_LEN = CCM tag length\n - * Supported tag lengths: 32-128 bits in step of 16 bits (recommended 96 bits tag).\n + * Supported tag lengths: 4-16 bytes in steps of 2 bytes (recommended 12 bytes 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 @@ -603,14 +603,14 @@ typedef enum { YACA_PROPERTY_GCM_AAD, /** GCM Tag. Property type is a buffer (e.g. char*) */ YACA_PROPERTY_GCM_TAG, - /** GCM Tag length. Property type is size_t. */ + /** GCM Tag length in bytes. Property type is size_t. */ YACA_PROPERTY_GCM_TAG_LEN, /** CCM Additional Authentication Data. Property type is a buffer (e.g. char*) */ YACA_PROPERTY_CCM_AAD, /** CCM Tag. Property type is a buffer (e.g. char*) */ YACA_PROPERTY_CCM_TAG, - /** CCM Tag length. Property type is size_t. */ + /** CCM Tag length in bytes. Property type is size_t. */ YACA_PROPERTY_CCM_TAG_LEN } yaca_property_e; diff --git a/src/encrypt.c b/src/encrypt.c index 0bf6eab..7bd94fb 100644 --- a/src/encrypt.c +++ b/src/encrypt.c @@ -201,6 +201,10 @@ static bool verify_state_change(struct yaca_encrypt_context_s *c, enum encrypt_c return false; } +static const size_t VALID_GCM_TAG_LENGTHS[] = { 4, 8, 12, 13, 14, 15, 16 }; +static const size_t VALID_GCM_TAG_LENGTHS_LENGTH = + sizeof(VALID_GCM_TAG_LENGTHS) / sizeof(VALID_GCM_TAG_LENGTHS[0]); + struct yaca_encrypt_context_s *get_encrypt_context(const yaca_context_h ctx) { if (ctx == YACA_CONTEXT_NULL) @@ -656,8 +660,18 @@ int set_encrypt_property(yaca_context_h ctx, if (!verify_state_change(c, STATE_TAG_LENGTH_SET)) return YACA_ERROR_INVALID_PARAMETER; - c->tag_len = *(size_t*)value; - c->state = STATE_TAG_LENGTH_SET; + /* check allowed tag lengths */ + { + size_t tag_len = *(size_t*)value; + for (size_t i = 0; i < VALID_GCM_TAG_LENGTHS_LENGTH; i++) { + if (tag_len == VALID_GCM_TAG_LENGTHS[i]) { + c->tag_len = tag_len; + c->state = STATE_TAG_LENGTH_SET; + return YACA_ERROR_NONE; + } + } + return YACA_ERROR_INVALID_PARAMETER; + } break; case YACA_PROPERTY_CCM_TAG: if (mode != EVP_CIPH_CCM_MODE || is_encryption_op(c->op_type)) -- 2.7.4 From 8d70b1ac7f9084bfade4d6fc2126b74887a15e27 Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Thu, 18 Aug 2016 08:29:39 +0200 Subject: [PATCH 08/16] Removed rsa padding TODO RSA_NO_PADDING can be used when message length exactly matches the length of the asymmetric key. As for now no digest can produce matching output so only plain asymmetric operation without digest supports it. RSA_SSLV23_PADDING can be used in asymmetric encryption only. Change-Id: I9f4b84086bf150994f5eb5cc270203cf8834b683 --- src/sign.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/sign.c b/src/sign.c index 2e5fe25..4233c98 100644 --- a/src/sign.c +++ b/src/sign.c @@ -131,8 +131,6 @@ int set_sign_property(yaca_context_h ctx, 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; -- 2.7.4 From ee618de49c4f7c2afd1dcb0134fbbadcce952384 Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Wed, 24 Aug 2016 10:38:58 +0200 Subject: [PATCH 09/16] Unify key and IV naming and length unit. Change-Id: Iff2bab3a9b7a59c224cff6007a6edda9e30c2d71 --- api/yaca/yaca_crypto.h | 3 +- api/yaca/yaca_encrypt.h | 11 +++---- api/yaca/yaca_key.h | 21 +++++++------ api/yaca/yaca_seal.h | 12 ++++---- api/yaca/yaca_simple.h | 4 +-- api/yaca/yaca_types.h | 78 ++++++++++++++++++++++++++----------------------- 6 files changed, 71 insertions(+), 58 deletions(-) diff --git a/api/yaca/yaca_crypto.h b/api/yaca/yaca_crypto.h index dfdbb8a..58c421d 100755 --- a/api/yaca/yaca_crypto.h +++ b/api/yaca/yaca_crypto.h @@ -221,7 +221,8 @@ int yaca_context_set_property(yaca_context_h ctx, * @remarks The @a value has to be of type appropriate for given property. See #yaca_property_e * for details on corresponding types. * - * @remarks @a value_len can be NULL if returned @a value is a single object (i.e. not an array/buffer) + * @remarks @a value_len can be NULL if returned @a value is a single object + * (i.e. not an array/buffer) * * @param[in] ctx Previously initialized crypto context * @param[in] property Property to be read diff --git a/api/yaca/yaca_encrypt.h b/api/yaca/yaca_encrypt.h index d99db9b..97bfe58 100755 --- a/api/yaca/yaca_encrypt.h +++ b/api/yaca/yaca_encrypt.h @@ -37,17 +37,18 @@ extern "C" { */ /** - * @brief Returns the recommended/default length of the IV for a given encryption configuration. + * @brief Returns the recommended/default length of the Initialization Vector + * for a given encryption configuration. * * @since_tizen 3.0 * * @remarks If returned iv_bit_len equals 0 that means that for this - * specific algorithm and its parameters IV is not used. + * specific algorithm and its parameters Initialization Vector is not used. * * @param[in] algo Encryption algorithm * @param[in] bcm Chain mode * @param[in] key_bit_len Key length in bits - * @param[out] iv_bit_len Recommended IV length in bits + * @param[out] iv_bit_len Recommended Initialization Vector length in bits * * @return #YACA_ERROR_NONE on success, negative on error * @retval #YACA_ERROR_NONE Successful @@ -72,7 +73,7 @@ int yaca_encrypt_get_iv_bit_length(yaca_encrypt_algorithm_e algo, * @param[in] algo Encryption algorithm that will be used * @param[in] bcm Chaining mode that will be used * @param[in] sym_key Symmetric key that will be used - * @param[in] iv Initialization vector that will be used + * @param[in] iv Initialization Vector that will be used * * @return #YACA_ERROR_NONE on success, negative on error * @retval #YACA_ERROR_NONE Successful @@ -161,7 +162,7 @@ int yaca_encrypt_finalize(yaca_context_h ctx, * @param[in] algo Encryption algorithm that was used to encrypt the data * @param[in] bcm Chaining mode that was used to encrypt the data * @param[in] sym_key Symmetric key that was used to encrypt the data - * @param[in] iv Initialization vector that was used to encrypt the data + * @param[in] iv Initialization Vector that was used to encrypt the data * * @return #YACA_ERROR_NONE on success, negative on error * @retval #YACA_ERROR_NONE Successful diff --git a/api/yaca/yaca_key.h b/api/yaca/yaca_key.h index 87e3b30..6f9a0f1 100755 --- a/api/yaca/yaca_key.h +++ b/api/yaca/yaca_key.h @@ -18,7 +18,7 @@ /** * @file yaca_key.h - * @brief Advanced API for the key and IV handling. + * @brief Advanced API for the key and Initialization Vector handling. */ #ifndef YACA_KEY_H @@ -64,7 +64,7 @@ int yaca_key_get_type(const yaca_key_h key, yaca_key_type_e *key_type); * * @since_tizen 3.0 * - * @remarks @a key can be any symmetric (including an IV) or + * @remarks @a key can be any symmetric (including an Initialization Vector) or * asymmetric key (including key generation parameters). * * @remarks For Diffie-Helmann @a key_bit_len returns prime length in bits. Values @@ -98,7 +98,7 @@ int yaca_key_get_bit_length(const yaca_key_h key, size_t *key_bit_len); * @remarks This function imports a key trying to match it to the @a key_type specified. * It should autodetect both the key format and the file format. * - * @remarks For symmetric, IV and DES keys RAW binary format and BASE64 encoded + * @remarks For symmetric, Initialization Vector and DES keys RAW binary format and BASE64 encoded * binary format are supported. * For asymmetric keys PEM and DER file formats are supported. * @@ -154,9 +154,10 @@ int yaca_key_import(yaca_key_type_e key_type, * @remarks This function exports the key to an arbitrary key format and key file format. * * @remarks For key formats two values are allowed: - * - #YACA_KEY_FORMAT_DEFAULT: this is the only option possible in case of symmetric - * keys (or IV), for asymmetric keys it will export to their - * default ASN1 structure format (e.g. PKCS#1, SSLeay, PKCS#3). + * - #YACA_KEY_FORMAT_DEFAULT: this is the only option possible in case of symmetric keys + * (or Initialization Vector), for asymmetric keys it will + * export to their default ASN1 structure format + * (e.g. PKCS#1, SSLeay, PKCS#3). * - #YACA_KEY_FORMAT_PKCS8: this will only work for private asymmetric keys. * * @remarks The following file formats are supported: @@ -207,7 +208,7 @@ int yaca_key_export(const yaca_key_h key, size_t *data_len); /** - * @brief Generates a secure key or key generation parameters (or an initialization vector). + * @brief Generates a secure key or key generation parameters (or an Initialization Vector). * * @since_tizen 3.0 * @@ -323,7 +324,8 @@ int yaca_key_extract_parameters(const yaca_key_h key, yaca_key_h *params); * @since_tizen 3.0 * * @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 + * to produce a symmetric key pass the secret to a key derivation function (KDF) + * or a message digest function * * @remarks The @a secret should be freed with yaca_free() * @@ -355,7 +357,8 @@ int yaca_key_derive_dh(const yaca_key_h prv_key, * @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 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() * diff --git a/api/yaca/yaca_seal.h b/api/yaca/yaca_seal.h index 380e55d..97f8544 100755 --- a/api/yaca/yaca_seal.h +++ b/api/yaca/yaca_seal.h @@ -20,8 +20,9 @@ * @file yaca_seal.h * @brief Advanced API for the asymmetric encryption. * - * @details Seal does more than just encrypt. It first generates the encryption key and IV, - * then encrypts whole message using this key (and selected symmetric algorithm). + * @details Seal does more than just encrypt. It first generates the encryption key and + * Initialization Vector, then encrypts whole message using this key + * (and selected symmetric algorithm). * Finally it encrypts symmetric key with public key. */ @@ -41,7 +42,8 @@ extern "C" { */ /** - * @brief Initializes an asymmetric encryption context and generates symmetric key and IV. + * @brief Initializes an asymmetric encryption context and generates + * symmetric key and Initialization Vector. * * @remarks Generated symmetric key is encrypted with public key, * so can be ONLY used with yaca_open_initialize(). It can be exported, @@ -64,7 +66,7 @@ extern "C" { * @param[in] sym_key_bit_len Symmetric key length (in bits) that will be generated * @param[out] sym_key Generated symmetric key that will be used, * it is encrypted with peer's public key - * @param[out] iv Generated initialization vector that will be used + * @param[out] iv Generated Initialization Vector that will be used * * @return #YACA_ERROR_NONE on success, negative on error * @retval #YACA_ERROR_NONE Successful @@ -163,7 +165,7 @@ int yaca_seal_finalize(yaca_context_h ctx, * @param[in] sym_key_bit_len Symmetric key length (in bits) that was used for the encryption * @param[in] sym_key Symmetric key, encrypted with the public key, * that was used to encrypt the data - * @param[in] iv Initialization vector that was used for the encryption + * @param[in] iv Initialization Vector that was used for the encryption * * @return #YACA_ERROR_NONE on success, negative on error * @retval #YACA_ERROR_NONE Successful diff --git a/api/yaca/yaca_simple.h b/api/yaca/yaca_simple.h index 96c9d97..8f37875 100755 --- a/api/yaca/yaca_simple.h +++ b/api/yaca/yaca_simple.h @@ -57,7 +57,7 @@ extern "C" { * @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 yaca_key.h for key generation functions) - * @param[in] iv Initialization vector + * @param[in] iv Initialization Vector * @param[in] plaintext Plaintext to be encrypted * @param[in] plaintext_len Length of the plaintext * @param[out] ciphertext Encrypted data, will be allocated by the library @@ -96,7 +96,7 @@ int yaca_simple_encrypt(yaca_encrypt_algorithm_e algo, * @param[in] algo Decryption algorithm that was used to encrypt the data * @param[in] bcm Chaining mode that was used to encrypt the data * @param[in] sym_key Symmetric encryption key that was used to encrypt the data - * @param[in] iv Initialization vector that was used to encrypt the data + * @param[in] iv Initialization Vector that was used to encrypt the data * @param[in] ciphertext Ciphertext to be decrypted * @param[in] ciphertext_len Length of ciphertext * @param[out] plaintext Decrypted data, will be allocated by the library diff --git a/api/yaca/yaca_types.h b/api/yaca/yaca_types.h index 857710c..b361d4e 100755 --- a/api/yaca/yaca_types.h +++ b/api/yaca/yaca_types.h @@ -143,7 +143,7 @@ extern "C" { typedef struct yaca_context_s *yaca_context_h; /** - * @brief The handle of a key, an IV or a key generation parameters. + * @brief The handle of a key, an Initialization Vector or a key generation parameters. * * @since_tizen 3.0 */ @@ -178,7 +178,7 @@ typedef enum { } yaca_key_file_format_e; /** - * @brief Enumeration of YACA key types, IV is considered as key. + * @brief Enumeration of YACA key types, Initialization Vector is considered as key. * * @since_tizen 3.0 */ @@ -334,7 +334,7 @@ typedef enum { typedef enum { /** * AES encryption. - * - Supported key lengths: @c 128, @c 192 and @c 256. + * - Supported key lengths: @c 128, @c 192 and @c 256 bits. * - Supported block cipher modes:\n * #YACA_BCM_CBC,\n * #YACA_BCM_OFB,\n @@ -352,7 +352,7 @@ typedef enum { /** * DES encryption. - * - Supported key lengths: @c 64. + * - Supported key lengths: @c 64 bits. * - Supported block cipher modes:\n * #YACA_BCM_CBC,\n * #YACA_BCM_OFB,\n @@ -366,7 +366,7 @@ typedef enum { /** * 3DES 2-key encryption. - * - Supported key lengths: @c 128. + * - Supported key lengths: @c 128 bits. * - Supported block cipher modes:\n * #YACA_BCM_CBC,\n * #YACA_BCM_OFB,\n @@ -379,7 +379,7 @@ typedef enum { /** * 3DES 3-key encryption. - * - Supported key lengths: @c 192. + * - Supported key lengths: @c 192 bits. * - Supported block cipher modes:\n * #YACA_BCM_CBC,\n * #YACA_BCM_OFB,\n @@ -397,7 +397,7 @@ typedef enum { * RC2 encryption. * This is a variable key length cipher. * - Supported key lengths: 8-1024 bits in steps of 8 bits. - * - Effective key bits property by default equals to 128. + * - Effective key bits property by default equals to 128 bits. * - Supported block cipher modes:\n * #YACA_BCM_CBC,\n * #YACA_BCM_OFB,\n @@ -411,15 +411,15 @@ 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. + * - Initialization Vector is not used. + * - This cipher doesn't support block cipher modes, use #YACA_BCM_NONE instead. */ YACA_ENCRYPT_UNSAFE_RC4, /** * CAST5 encryption. * This is a variable key length cipher. - * Supported key lengths: 40-128 bits in steps of 8 bits. + * - Supported key lengths: 40-128 bits in steps of 8 bits. * - Supported block cipher modes:\n * #YACA_BCM_CBC,\n * #YACA_BCM_OFB,\n @@ -438,16 +438,17 @@ typedef enum { typedef enum { /** * Used when algorithm doesn't support block ciphers modes. - * No IV is used. + * Initialization Vector is not used. */ YACA_BCM_NONE, /** * ECB block cipher mode. - * No IV is used. + * Initialization Vector is not 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, + * 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. */ @@ -455,18 +456,19 @@ typedef enum { /** * CTR block cipher mode. - * 16-byte initialization vector for AES, - * 8-byte for other algorithms is mandatory. + * 128-bit Initialization Vector for AES, + * 64-bit for other algorithms is mandatory. */ YACA_BCM_CTR, /** * CBC block cipher mode. - * 16-byte initialization vector for AES, - * 8-byte for other algorithms is mandatory. + * 128-bit Initialization Vector for AES, + * 64-bit 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, + * 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. */ @@ -474,15 +476,15 @@ typedef enum { /** * GCM block cipher mode. - * This is a variable IV length mode (recommended 96 bits IV). + * This is a variable Initialization Vector length mode (recommended 96-bits). * * Supported properties: * - #YACA_PROPERTY_GCM_TAG_LEN = GCM tag length\n * Supported tag lengths: @c 4, @c 8, @c 12, @c 13, @c 14, @c 15, @c 16, * (recommended 16 bytes 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 + * yaca_context_get_property(#YACA_PROPERTY_GCM_TAG) in encryption / seal operation.\n + * 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 @@ -501,42 +503,43 @@ typedef enum { /** * Default CFB block cipher mode. - * 16-byte initialization vector for AES, - * 8-byte for other algorithms is mandatory. + * 128-bit Initialization Vector for AES, + * 64-bit for other algorithms is mandatory. */ YACA_BCM_CFB, /** * 1 bit CFB block cipher mode. - * 16-byte initialization vector for AES, - * 8-byte for other algorithms is mandatory. + * 128-bit Initialization Vector for AES, + * 64-bit for other algorithms is mandatory. */ YACA_BCM_CFB1, /** * 8 bits CFB block cipher mode. - * 16-byte initialization vector for AES, - * 8-byte for other algorithms is mandatory. + * 128-bit Initialization Vector for AES, + * 64-bit for other algorithms is mandatory. */ YACA_BCM_CFB8, /** * OFB block cipher mode. - * 16-byte initialization vector for AES, - * 8-byte for other algorithms is mandatory. + * 128-bit Initialization Vector for AES, + * 64-bit for other algorithms is mandatory. */ YACA_BCM_OFB, /** * CBC-MAC Mode (AES). - * This is a variable IV length mode.\n - * Supported IV lengths: 56-104 bits in steps of 8 bits (recommended 56 bits IV).\n\n + * This is a variable Initialization Vector length mode.\n + * Supported Initialization Vector lengths: 56-104 bits in steps of 8 bits + * (recommended 56-bits).\n\n * * Supported properties: * - #YACA_PROPERTY_CCM_TAG_LEN = CCM tag length\n * Supported tag lengths: 4-16 bytes in steps of 2 bytes (recommended 12 bytes tag).\n * Set after yaca_encrypt_initialize() / yaca_seal_initialize() and before - * yaca_encrypt_update() / yaca_seal_update() in encryption / seal operation. + * yaca_encrypt_update() / yaca_seal_update() in encryption / seal operation.\n * The @a value should be a size_t variable.\n * In decryption / open operation tag length is not set.\n\n * @@ -570,12 +573,15 @@ typedef enum { * * 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. + * 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.\n + * 64-bit Initialization Vector is used.\n + * Wrapped key can be a 128-bit key, a 192-bit key, or a 256-bit key.\n * #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). + * Key used to do the wrapping with #YACA_ENCRYPT_3DES_3TDEA can be a 192-bit DES key only.\n + * Initialization Vector is not used.\n + * Wrapped key can be a 128-bit DES key (two-key), or a 192-bit DES key (three-key).\n * #YACA_ENCRYPT_3DES_3TDEA allows wrapping only one key. * */ -- 2.7.4 From 5d0b7dabadca778984463693e94feae9f8ec1660 Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Mon, 22 Aug 2016 10:55:12 +0200 Subject: [PATCH 10/16] Fix: Key wrapping, block finalizing before update. Change-Id: I8bb6f12c32c7015a6f393f2a76b7884e50c689e9 --- src/encrypt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/encrypt.c b/src/encrypt.c index 7bd94fb..ebe43a4 100644 --- a/src/encrypt.c +++ b/src/encrypt.c @@ -174,7 +174,7 @@ static bool CCM_STATES[2][STATE_COUNT][STATE_COUNT] = { { static bool WRAP_STATES[STATE_COUNT][STATE_COUNT] = { /* from \ to INIT, MLEN, AAD, MSG, TAG, TLEN, FIN */ -/* INIT */ { 0, 0, 0, 1, 0, 0, 1 }, +/* INIT */ { 0, 0, 0, 1, 0, 0, 0 }, /* MLEN */ { 0, 0, 0, 0, 0, 0, 0 }, /* AAD */ { 0, 0, 0, 0, 0, 0, 0 }, /* MSG */ { 0, 0, 0, 0, 0, 0, 1 }, -- 2.7.4 From d14ed38ceca561653603432b2a236efb0ddc9a29 Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Mon, 22 Aug 2016 16:12:16 +0200 Subject: [PATCH 11/16] Unify simple key param names, EC for sign/verify Change-Id: If812d71791c18e7bc798c71a5335f0c498c35ea1 --- api/yaca/yaca_sign.h | 56 +++++++++++++++++++++++++------------------------- api/yaca/yaca_simple.h | 18 ++++++++-------- src/sign.c | 24 +++++++++++----------- src/simple.c | 16 +++++++-------- 4 files changed, 58 insertions(+), 56 deletions(-) diff --git a/api/yaca/yaca_sign.h b/api/yaca/yaca_sign.h index 8daf682..8db0e1e 100755 --- a/api/yaca/yaca_sign.h +++ b/api/yaca/yaca_sign.h @@ -46,13 +46,13 @@ extern "C" { * * @remarks The @a ctx should be released using yaca_context_destroy() * - * @param[out] ctx Newly created context - * @param[in] algo Digest algorithm that will be used - * @param[in] key Private key that will be used, algorithm is deduced based - * on key type, supported key types: - * - #YACA_KEY_TYPE_RSA_PRIV, - * - #YACA_KEY_TYPE_DSA_PRIV, - * - #YACA_KEY_TYPE_EC_PRIV + * @param[out] ctx Newly created context + * @param[in] algo Digest algorithm that will be used + * @param[in] prv_key Private key that will be used, algorithm is deduced based + * on key type, supported key types: + * - #YACA_KEY_TYPE_RSA_PRIV, + * - #YACA_KEY_TYPE_DSA_PRIV, + * - #YACA_KEY_TYPE_EC_PRIV * * @return #YACA_ERROR_NONE on success, negative on error * @retval #YACA_ERROR_NONE Successful @@ -72,7 +72,7 @@ extern "C" { */ int yaca_sign_initialize(yaca_context_h *ctx, yaca_digest_algorithm_e algo, - const yaca_key_h key); + const yaca_key_h prv_key); /** * @brief Initializes a signature context for HMAC. @@ -84,11 +84,11 @@ int yaca_sign_initialize(yaca_context_h *ctx, * * @remarks The @a ctx should be released using yaca_context_destroy() * - * @param[out] ctx Newly created context - * @param[in] algo Digest algorithm that will be used - * @param[in] key Symmetric key that will be used, supported key types: - * - #YACA_KEY_TYPE_SYMMETRIC, - * - #YACA_KEY_TYPE_DES + * @param[out] ctx Newly created context + * @param[in] algo Digest algorithm that will be used + * @param[in] sym_key Symmetric key that will be used, supported key types: + * - #YACA_KEY_TYPE_SYMMETRIC, + * - #YACA_KEY_TYPE_DES * * @return #YACA_ERROR_NONE on success, negative on error * @retval #YACA_ERROR_NONE Successful @@ -106,7 +106,7 @@ int yaca_sign_initialize(yaca_context_h *ctx, */ int yaca_sign_initialize_hmac(yaca_context_h *ctx, yaca_digest_algorithm_e algo, - const yaca_key_h key); + const yaca_key_h sym_key); /** * @brief Initializes a signature context for CMAC. @@ -118,11 +118,11 @@ int yaca_sign_initialize_hmac(yaca_context_h *ctx, * * @remarks The @a ctx should be released using yaca_context_destroy() * - * @param[out] ctx Newly created context - * @param[in] algo Encryption algorithm that will be used - * @param[in] key Symmetric key that will be used, supported key types: - * - #YACA_KEY_TYPE_SYMMETRIC, - * - #YACA_KEY_TYPE_DES + * @param[out] ctx Newly created context + * @param[in] algo Encryption algorithm that will be used + * @param[in] sym_key Symmetric key that will be used, supported key types: + * - #YACA_KEY_TYPE_SYMMETRIC, + * - #YACA_KEY_TYPE_DES * * @return #YACA_ERROR_NONE on success, negative on error * @retval #YACA_ERROR_NONE Successful @@ -140,7 +140,7 @@ int yaca_sign_initialize_hmac(yaca_context_h *ctx, */ int yaca_sign_initialize_cmac(yaca_context_h *ctx, yaca_encrypt_algorithm_e algo, - const yaca_key_h key); + const yaca_key_h sym_key); /** * @brief Feeds the data into the digital signature or MAC algorithm. @@ -204,13 +204,13 @@ int yaca_sign_finalize(yaca_context_h ctx, * * @remarks The @a ctx should be released using yaca_context_destroy() * - * @param[out] ctx Newly created context - * @param[in] algo Digest algorithm that will be used - * @param[in] key Public key that will be used, algorithm is deduced based on - * key type, supported key types: - * - #YACA_KEY_TYPE_RSA_PUB, - * - #YACA_KEY_TYPE_DSA_PUB, - * - #YACA_KEY_TYPE_EC_PUB + * @param[out] ctx Newly created context + * @param[in] algo Digest algorithm that will be used + * @param[in] pub_key Public key that will be used, algorithm is deduced based on + * key type, supported key types: + * - #YACA_KEY_TYPE_RSA_PUB, + * - #YACA_KEY_TYPE_DSA_PUB, + * - #YACA_KEY_TYPE_EC_PUB * * @return #YACA_ERROR_NONE on success, negative on error * @retval #YACA_ERROR_NONE Successful @@ -227,7 +227,7 @@ int yaca_sign_finalize(yaca_context_h ctx, */ int yaca_verify_initialize(yaca_context_h *ctx, yaca_digest_algorithm_e algo, - const yaca_key_h key); + const yaca_key_h pub_key); /** * @brief Feeds the data into the digital signature verification algorithm. diff --git a/api/yaca/yaca_simple.h b/api/yaca/yaca_simple.h index 8f37875..e126074 100755 --- a/api/yaca/yaca_simple.h +++ b/api/yaca/yaca_simple.h @@ -160,10 +160,11 @@ int yaca_simple_calculate_digest(yaca_digest_algorithm_e algo, * @remarks The @a signature should be freed using yaca_free() * * @param[in] algo Digest algorithm that will be used - * @param[in] key Private key that will be used, algorithm is + * @param[in] prv_key Private key that will be used, algorithm is * deduced based on key type, supported key types: * - #YACA_KEY_TYPE_RSA_PRIV, * - #YACA_KEY_TYPE_DSA_PRIV, + * - #YACA_KEY_TYPE_EC_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 library @@ -182,7 +183,7 @@ int yaca_simple_calculate_digest(yaca_digest_algorithm_e algo, * @see yaca_free() */ int yaca_simple_calculate_signature(yaca_digest_algorithm_e algo, - const yaca_key_h key, + const yaca_key_h prv_key, const char *data, size_t data_len, char **signature, @@ -194,10 +195,11 @@ int yaca_simple_calculate_signature(yaca_digest_algorithm_e algo, * @since_tizen 3.0 * * @param[in] algo Digest algorithm that will be used - * @param[in] key Public key that will be used, algorithm is + * @param[in] pub_key Public key that will be used, algorithm is * deduced based on key type, supported key types: * - #YACA_KEY_TYPE_RSA_PUB, * - #YACA_KEY_TYPE_DSA_PUB, + * - #YACA_KEY_TYPE_EC_PUB * @param[in] data Signed data * @param[in] data_len Length of the data * @param[in] signature Message signature @@ -216,7 +218,7 @@ int yaca_simple_calculate_signature(yaca_digest_algorithm_e algo, * @see yaca_simple_calculate_signature() */ int yaca_simple_verify_signature(yaca_digest_algorithm_e algo, - const yaca_key_h key, + const yaca_key_h pub_key, const char *data, size_t data_len, const char *signature, @@ -233,7 +235,7 @@ int yaca_simple_verify_signature(yaca_digest_algorithm_e algo, * @remarks The @a mac should be freed using yaca_free() * * @param[in] algo Digest algorithm that will be used - * @param[in] key Key that will be used, supported key types: + * @param[in] sym_key Key that will be used, supported key types: * - #YACA_KEY_TYPE_SYMMETRIC, * - #YACA_KEY_TYPE_DES * @param[in] data Data to calculate HMAC from @@ -254,7 +256,7 @@ int yaca_simple_verify_signature(yaca_digest_algorithm_e algo, * @see yaca_free() */ int yaca_simple_calculate_hmac(yaca_digest_algorithm_e algo, - const yaca_key_h key, + const yaca_key_h sym_key, const char *data, size_t data_len, char **mac, @@ -271,7 +273,7 @@ int yaca_simple_calculate_hmac(yaca_digest_algorithm_e algo, * @remarks The @a mac should be freed using yaca_free() * * @param[in] algo Encryption algorithm that will be used - * @param[in] key Key that will be used, supported key types: + * @param[in] sym_key Key that will be used, supported key types: * - #YACA_KEY_TYPE_SYMMETRIC, * - #YACA_KEY_TYPE_DES * @param[in] data Data to calculate CMAC from @@ -292,7 +294,7 @@ int yaca_simple_calculate_hmac(yaca_digest_algorithm_e algo, * @see yaca_free() */ int yaca_simple_calculate_cmac(yaca_encrypt_algorithm_e algo, - const yaca_key_h key, + const yaca_key_h sym_key, const char *data, size_t data_len, char **mac, diff --git a/src/sign.c b/src/sign.c index 4233c98..644349d 100644 --- a/src/sign.c +++ b/src/sign.c @@ -236,17 +236,17 @@ int get_sign_property(const yaca_context_h ctx, API int yaca_sign_initialize(yaca_context_h *ctx, yaca_digest_algorithm_e algo, - const yaca_key_h key) + const yaca_key_h prv_key) { struct yaca_sign_context_s *nc = NULL; const EVP_MD *md = NULL; int ret; - const struct yaca_key_evp_s *evp_key = key_get_evp(key); + const struct yaca_key_evp_s *evp_key = key_get_evp(prv_key); if (ctx == NULL || evp_key == NULL) return YACA_ERROR_INVALID_PARAMETER; - switch (key->type) { + switch (prv_key->type) { case YACA_KEY_TYPE_RSA_PRIV: case YACA_KEY_TYPE_DSA_PRIV: case YACA_KEY_TYPE_EC_PRIV: @@ -296,16 +296,16 @@ exit: API int yaca_sign_initialize_hmac(yaca_context_h *ctx, yaca_digest_algorithm_e algo, - const yaca_key_h key) + const yaca_key_h sym_key) { struct yaca_sign_context_s *nc = NULL; EVP_PKEY *pkey = NULL; const EVP_MD *md; int ret; - const struct yaca_key_simple_s *simple_key = key_get_simple(key); + const struct yaca_key_simple_s *simple_key = key_get_simple(sym_key); if (ctx == NULL || simple_key == NULL || - (key->type != YACA_KEY_TYPE_SYMMETRIC && key->type != YACA_KEY_TYPE_DES)) + (sym_key->type != YACA_KEY_TYPE_SYMMETRIC && sym_key->type != YACA_KEY_TYPE_DES)) return YACA_ERROR_INVALID_PARAMETER; ret = yaca_zalloc(sizeof(struct yaca_sign_context_s), (void**)&nc); @@ -360,17 +360,17 @@ exit: API int yaca_sign_initialize_cmac(yaca_context_h *ctx, yaca_encrypt_algorithm_e algo, - const yaca_key_h key) + const yaca_key_h sym_key) { struct yaca_sign_context_s *nc = NULL; CMAC_CTX* cmac_ctx = NULL; const EVP_CIPHER* cipher = NULL; EVP_PKEY *pkey = NULL; int ret; - const struct yaca_key_simple_s *simple_key = key_get_simple(key); + const struct yaca_key_simple_s *simple_key = key_get_simple(sym_key); if (ctx == NULL || simple_key == NULL || - (key->type != YACA_KEY_TYPE_SYMMETRIC && key->type != YACA_KEY_TYPE_DES)) + (sym_key->type != YACA_KEY_TYPE_SYMMETRIC && sym_key->type != YACA_KEY_TYPE_DES)) return YACA_ERROR_INVALID_PARAMETER; ret = yaca_zalloc(sizeof(struct yaca_sign_context_s), (void**)&nc); @@ -487,17 +487,17 @@ API int yaca_sign_finalize(yaca_context_h ctx, API int yaca_verify_initialize(yaca_context_h *ctx, yaca_digest_algorithm_e algo, - const yaca_key_h key) + const yaca_key_h pub_key) { struct yaca_sign_context_s *nc = NULL; const EVP_MD *md = NULL; int ret; - const struct yaca_key_evp_s *evp_key = key_get_evp(key); + const struct yaca_key_evp_s *evp_key = key_get_evp(pub_key); if (ctx == NULL || evp_key == NULL) return YACA_ERROR_INVALID_PARAMETER; - switch (key->type) { + switch (pub_key->type) { case YACA_KEY_TYPE_RSA_PUB: case YACA_KEY_TYPE_DSA_PUB: case YACA_KEY_TYPE_EC_PUB: diff --git a/src/simple.c b/src/simple.c index 322c123..5fabcc8 100644 --- a/src/simple.c +++ b/src/simple.c @@ -265,7 +265,7 @@ static int sign(const yaca_context_h ctx, const char *data, size_t data_len, } API int yaca_simple_calculate_signature(yaca_digest_algorithm_e algo, - const yaca_key_h key, + const yaca_key_h prv_key, const char *data, size_t data_len, char **signature, @@ -278,7 +278,7 @@ API int yaca_simple_calculate_signature(yaca_digest_algorithm_e algo, signature == NULL || signature_len == NULL) return YACA_ERROR_INVALID_PARAMETER; - ret = yaca_sign_initialize(&ctx, algo, key); + ret = yaca_sign_initialize(&ctx, algo, prv_key); if (ret != YACA_ERROR_NONE) return ret; @@ -290,7 +290,7 @@ API int yaca_simple_calculate_signature(yaca_digest_algorithm_e algo, } API int yaca_simple_verify_signature(yaca_digest_algorithm_e algo, - const yaca_key_h key, + const yaca_key_h pub_key, const char *data, size_t data_len, const char *signature, @@ -303,7 +303,7 @@ API int yaca_simple_verify_signature(yaca_digest_algorithm_e algo, signature == NULL || signature_len == 0) return YACA_ERROR_INVALID_PARAMETER; - ret = yaca_verify_initialize(&ctx, algo, key); + ret = yaca_verify_initialize(&ctx, algo, pub_key); if (ret != YACA_ERROR_NONE) return ret; @@ -322,7 +322,7 @@ exit: } API int yaca_simple_calculate_hmac(yaca_digest_algorithm_e algo, - const yaca_key_h key, + const yaca_key_h sym_key, const char *data, size_t data_len, char **mac, @@ -335,7 +335,7 @@ API int yaca_simple_calculate_hmac(yaca_digest_algorithm_e algo, mac == NULL || mac_len == NULL) return YACA_ERROR_INVALID_PARAMETER; - ret = yaca_sign_initialize_hmac(&ctx, algo, key); + ret = yaca_sign_initialize_hmac(&ctx, algo, sym_key); if (ret != YACA_ERROR_NONE) return ret; @@ -347,7 +347,7 @@ API int yaca_simple_calculate_hmac(yaca_digest_algorithm_e algo, } API int yaca_simple_calculate_cmac(yaca_encrypt_algorithm_e algo, - const yaca_key_h key, + const yaca_key_h sym_key, const char *data, size_t data_len, char **mac, @@ -360,7 +360,7 @@ API int yaca_simple_calculate_cmac(yaca_encrypt_algorithm_e algo, mac == NULL || mac_len == NULL) return YACA_ERROR_INVALID_PARAMETER; - ret = yaca_sign_initialize_cmac(&ctx, algo, key); + ret = yaca_sign_initialize_cmac(&ctx, algo, sym_key); if (ret != YACA_ERROR_NONE) return ret; -- 2.7.4 From dd7b1c2ca38fef2199cc577fc210e124ce936a2b Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Wed, 17 Aug 2016 17:23:51 +0200 Subject: [PATCH 12/16] Fix: Check (un)wrapped key length. Change-Id: I6d664586637f94a0bd5f442f14b7a590a0580d8f --- src/encrypt.c | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/src/encrypt.c b/src/encrypt.c index ebe43a4..4cedf96 100644 --- a/src/encrypt.c +++ b/src/encrypt.c @@ -938,13 +938,31 @@ int encrypt_update(yaca_context_h ctx, if (!verify_state_change(c, target_state)) 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; + if (mode == EVP_CIPH_WRAP_MODE) { + if (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; + } + } else if (op_type == OP_DECRYPT) { + 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 + 8)) + return YACA_ERROR_INVALID_PARAMETER; + } else if (type == NID_id_smime_alg_CMS3DESwrap) { + if (input_len != (YACA_KEY_LENGTH_UNSAFE_128BIT / 8 + 16) && + input_len != (YACA_KEY_LENGTH_192BIT / 8 + 16)) + return YACA_ERROR_INVALID_PARAMETER; + } else { + assert(false); + return YACA_ERROR_INTERNAL; + } } else { assert(false); return YACA_ERROR_INTERNAL; -- 2.7.4 From a93f02a84ab8b4629eb4909cc46213d3a2ccd397 Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Thu, 18 Aug 2016 10:35:04 +0200 Subject: [PATCH 13/16] Fix: Allow empty input/output in simple encrypt/decrypt. Change-Id: I44663a1ea50982cc641b30df8a3f4959d6ce4c36 --- api/yaca/yaca_simple.h | 4 +-- src/simple.c | 78 ++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 58 insertions(+), 24 deletions(-) diff --git a/api/yaca/yaca_simple.h b/api/yaca/yaca_simple.h index e126074..e4fd2c3 100755 --- a/api/yaca/yaca_simple.h +++ b/api/yaca/yaca_simple.h @@ -24,8 +24,8 @@ * Design constraints: * - 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. + * - Only digest, signatures 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 */ diff --git a/src/simple.c b/src/simple.c index 5fabcc8..00d9b3c 100644 --- a/src/simple.c +++ b/src/simple.c @@ -95,9 +95,11 @@ API int yaca_simple_encrypt(yaca_encrypt_algorithm_e algo, yaca_context_h ctx; int ret; char *lciphertext = NULL; - size_t out_len, lciphertext_len, written; + size_t out_len = 0; + size_t lciphertext_len = 0; + size_t written = 0; - if (plaintext == NULL || plaintext_len == 0 || + if ((plaintext == NULL && plaintext_len > 0) || (plaintext != NULL && plaintext_len == 0) || ciphertext == NULL || ciphertext_len == NULL || sym_key == YACA_KEY_NULL || bcm == YACA_BCM_CCM || bcm == YACA_BCM_GCM) @@ -107,9 +109,11 @@ API int yaca_simple_encrypt(yaca_encrypt_algorithm_e algo, if (ret != YACA_ERROR_NONE) return ret; - ret = yaca_context_get_output_length(ctx, plaintext_len, &out_len); - if (ret != YACA_ERROR_NONE) - goto exit; + if (plaintext_len > 0) { + ret = yaca_context_get_output_length(ctx, plaintext_len, &out_len); + if (ret != YACA_ERROR_NONE) + goto exit; + } ret = yaca_context_get_output_length(ctx, 0, &lciphertext_len); if (ret != YACA_ERROR_NONE) @@ -127,9 +131,11 @@ API int yaca_simple_encrypt(yaca_encrypt_algorithm_e algo, if (ret != YACA_ERROR_NONE) goto exit; - ret = yaca_encrypt_update(ctx, plaintext, plaintext_len, lciphertext, &out_len); - if (ret != YACA_ERROR_NONE) - goto exit; + if (plaintext_len > 0) { + ret = yaca_encrypt_update(ctx, plaintext, plaintext_len, lciphertext, &out_len); + if (ret != YACA_ERROR_NONE) + goto exit; + } assert(out_len <= lciphertext_len); written = out_len; @@ -139,11 +145,22 @@ API int yaca_simple_encrypt(yaca_encrypt_algorithm_e algo, goto exit; written += out_len; - assert(written <= lciphertext_len && written > 0); + assert(written <= lciphertext_len); - ret = yaca_realloc(written, (void**)&lciphertext); - if (ret != YACA_ERROR_NONE) + if (((bcm == YACA_BCM_CBC || bcm == YACA_BCM_ECB) && written == 0) || + (bcm != YACA_BCM_CBC && bcm != YACA_BCM_ECB && plaintext_len == 0 && written > 0)) { + ret = YACA_ERROR_INTERNAL; goto exit; + } + + if (written > 0) { + ret = yaca_realloc(written, (void**)&lciphertext); + if (ret != YACA_ERROR_NONE) + goto exit; + } else { + yaca_free(lciphertext); + lciphertext = NULL; + } *ciphertext = lciphertext; *ciphertext_len = written; @@ -169,9 +186,12 @@ API int yaca_simple_decrypt(yaca_encrypt_algorithm_e algo, yaca_context_h ctx; int ret; char *lplaintext = NULL; - size_t out_len, lplaintext_len, written; + size_t out_len = 0; + size_t lplaintext_len = 0; + size_t written = 0; - if (ciphertext == NULL || ciphertext_len == 0 || + if ((ciphertext == NULL && ciphertext_len > 0) || (ciphertext != NULL && ciphertext_len == 0) || + ((bcm == YACA_BCM_ECB || bcm == YACA_BCM_CBC) && ciphertext == NULL && ciphertext_len == 0) || plaintext == NULL || plaintext_len == NULL || sym_key == YACA_KEY_NULL || bcm == YACA_BCM_CCM || bcm == YACA_BCM_GCM) @@ -181,9 +201,11 @@ API int yaca_simple_decrypt(yaca_encrypt_algorithm_e algo, if (ret != YACA_ERROR_NONE) return ret; - ret = yaca_context_get_output_length(ctx, ciphertext_len, &out_len); - if (ret != YACA_ERROR_NONE) - goto exit; + if (ciphertext_len > 0) { + ret = yaca_context_get_output_length(ctx, ciphertext_len, &out_len); + if (ret != YACA_ERROR_NONE) + goto exit; + } ret = yaca_context_get_output_length(ctx, 0, &lplaintext_len); if (ret != YACA_ERROR_NONE) @@ -201,9 +223,11 @@ API int yaca_simple_decrypt(yaca_encrypt_algorithm_e algo, if (ret != YACA_ERROR_NONE) goto exit; - ret = yaca_decrypt_update(ctx, ciphertext, ciphertext_len, lplaintext, &out_len); - if (ret != YACA_ERROR_NONE) - goto exit; + if (ciphertext_len > 0) { + ret = yaca_decrypt_update(ctx, ciphertext, ciphertext_len, lplaintext, &out_len); + if (ret != YACA_ERROR_NONE) + goto exit; + } assert(out_len <= lplaintext_len); written = out_len; @@ -213,11 +237,21 @@ API int yaca_simple_decrypt(yaca_encrypt_algorithm_e algo, goto exit; written += out_len; - assert(written <= lplaintext_len && written > 0); + assert(written <= lplaintext_len); - ret = yaca_realloc(written, (void**)&lplaintext); - if (ret != YACA_ERROR_NONE) + if (bcm != YACA_BCM_CBC && bcm != YACA_BCM_ECB && ciphertext_len == 0 && written > 0) { + ret = YACA_ERROR_INTERNAL; goto exit; + } + + if (written > 0) { + ret = yaca_realloc(written, (void**)&lplaintext); + if (ret != YACA_ERROR_NONE) + goto exit; + } else { + yaca_free(lplaintext); + lplaintext = NULL; + } *plaintext = lplaintext; *plaintext_len = written; -- 2.7.4 From ef17161a5fbdb87d7fd3c11a17ce2f00e23ece11 Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Mon, 22 Aug 2016 16:49:39 +0200 Subject: [PATCH 14/16] Effective key length support in RC2. Change-Id: I82f023d3f620336e823738f187d8db4aef09fb61 --- api/yaca/yaca_simple.h | 1 + api/yaca/yaca_types.h | 12 ++++++++++-- src/encrypt.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++- src/internal.h | 1 + 4 files changed, 62 insertions(+), 3 deletions(-) diff --git a/api/yaca/yaca_simple.h b/api/yaca/yaca_simple.h index e4fd2c3..adb4456 100755 --- a/api/yaca/yaca_simple.h +++ b/api/yaca/yaca_simple.h @@ -27,6 +27,7 @@ * - Only digest, signatures and symmetric ciphers are supported * - Disabling PKCS#5 padding for ECB and CBC chaining is not supported * - GCM and CCM chaining is not supported + * - RC2 effective key bits property is not supported * - All outputs are allocated by the library */ diff --git a/api/yaca/yaca_types.h b/api/yaca/yaca_types.h index b361d4e..8bc8b0f 100755 --- a/api/yaca/yaca_types.h +++ b/api/yaca/yaca_types.h @@ -397,7 +397,12 @@ typedef enum { * RC2 encryption. * This is a variable key length cipher. * - Supported key lengths: 8-1024 bits in steps of 8 bits. - * - Effective key bits property by default equals to 128 bits. + * - Effective key bits property by default equals to 128 bits.\n + * Effective key bits can be set using yaca_context_set_property() and + * #YACA_PROPERTY_RC2_EFFECTIVE_KEY_BITS.\n + * It can be set after yaca_encrypt_initialize() / yaca_decrypt_initialize(), and before + * yaca_encrypt_update() / yaca_decrypt_update() in encryption / decryption operation. + * * - Supported block cipher modes:\n * #YACA_BCM_CBC,\n * #YACA_BCM_OFB,\n @@ -617,7 +622,10 @@ typedef enum { /** CCM Tag. Property type is a buffer (e.g. char*) */ YACA_PROPERTY_CCM_TAG, /** CCM Tag length in bytes. Property type is size_t. */ - YACA_PROPERTY_CCM_TAG_LEN + YACA_PROPERTY_CCM_TAG_LEN, + + /** RC2 effective key bits, 1-1024, 1 bit resolution. Property type is size_t. */ + YACA_PROPERTY_RC2_EFFECTIVE_KEY_BITS, } yaca_property_e; /** diff --git a/src/encrypt.c b/src/encrypt.c index 4cedf96..fb5edac 100644 --- a/src/encrypt.c +++ b/src/encrypt.c @@ -506,6 +506,7 @@ static int encrypt_ctx_backup(struct yaca_encrypt_context_s *c, bc->cipher = cipher; bc->sym_key = key_copy(sym_key); bc->iv = key_copy(iv); + bc->padding_none = false; c->backup_ctx = bc; @@ -532,6 +533,13 @@ static int encrypt_ctx_restore(struct yaca_encrypt_context_s *c) ret = encrypt_ctx_init(c, c->backup_ctx->cipher, key->bit_len); assert(ret != YACA_ERROR_INVALID_PARAMETER); + + if (c->backup_ctx->padding_none && EVP_CIPHER_CTX_set_padding(c->cipher_ctx, 0) != 1) { + ret = YACA_ERROR_INTERNAL; + ERROR_DUMP(ret); + return ret; + } + return ret; } @@ -591,6 +599,32 @@ static int encrypt_ctx_set_ccm_tag(struct yaca_encrypt_context_s *c, char *tag, return ret; } +static int encrypt_ctx_set_rc2_effective_key_bits(struct yaca_encrypt_context_s *c, size_t key_bits) +{ + int ret; + + assert(c != NULL); + assert(c->backup_ctx != NULL); + + if (key_bits == 0 || key_bits > 1024) + return YACA_ERROR_INVALID_PARAMETER; + + ret = encrypt_ctx_restore(c); + if (ret != YACA_ERROR_NONE) + return ret; + + ret = EVP_CIPHER_CTX_ctrl(c->cipher_ctx, EVP_CTRL_SET_RC2_KEY_BITS, key_bits, NULL); + if (ret != 1) { + ret = YACA_ERROR_INTERNAL; + ERROR_DUMP(ret); + return ret; + } + + ret = encrypt_ctx_setup(c, c->backup_ctx->sym_key, c->backup_ctx->iv); + assert(ret != YACA_ERROR_INVALID_PARAMETER); + return ret; +} + int set_encrypt_property(yaca_context_h ctx, yaca_property_e property, const void *value, @@ -600,12 +634,14 @@ int set_encrypt_property(yaca_context_h ctx, int len; int ret = YACA_ERROR_NONE; int mode; + int nid; if (c == NULL || value == NULL || value_len == 0) return YACA_ERROR_INVALID_PARAMETER; assert(c->cipher_ctx != NULL); mode = EVP_CIPHER_CTX_mode(c->cipher_ctx); + nid = EVP_CIPHER_nid(c->cipher_ctx->cipher); switch (property) { case YACA_PROPERTY_GCM_AAD: @@ -711,6 +747,16 @@ int set_encrypt_property(yaca_context_h ctx, ERROR_DUMP(YACA_ERROR_INTERNAL); return YACA_ERROR_INTERNAL; } + if (c->backup_ctx != NULL) + c->backup_ctx->padding_none = true; + break; + case YACA_PROPERTY_RC2_EFFECTIVE_KEY_BITS: + if (value_len != sizeof(size_t) || + (nid != NID_rc2_cbc && nid != NID_rc2_ecb && nid != NID_rc2_cfb64 && nid != NID_rc2_ofb64) || + c->state != STATE_INITIALIZED) + return YACA_ERROR_INVALID_PARAMETER; + + ret = encrypt_ctx_set_rc2_effective_key_bits(c, *(size_t*)value); break; default: return YACA_ERROR_INVALID_PARAMETER; @@ -865,6 +911,7 @@ int encrypt_initialize(yaca_context_h *ctx, struct yaca_key_simple_s *lsym_key; int ret; int mode; + int nid; if (ctx == NULL || sym_key == YACA_KEY_NULL) return YACA_ERROR_INVALID_PARAMETER; @@ -890,7 +937,9 @@ int encrypt_initialize(yaca_context_h *ctx, goto exit; mode = EVP_CIPHER_CTX_mode(nc->cipher_ctx); - if (mode == EVP_CIPH_CCM_MODE) { + nid = EVP_CIPHER_nid(nc->cipher_ctx->cipher); + if (mode == EVP_CIPH_CCM_MODE || + nid == NID_rc2_cbc || nid == NID_rc2_ecb || nid == NID_rc2_cfb64 || nid == NID_rc2_ofb64) { ret = encrypt_ctx_backup(nc, cipher, sym_key, iv); if (ret != YACA_ERROR_NONE) goto exit; diff --git a/src/internal.h b/src/internal.h index 9e241e3..107b3a8 100644 --- a/src/internal.h +++ b/src/internal.h @@ -65,6 +65,7 @@ struct yaca_backup_context_s { const EVP_CIPHER *cipher; yaca_key_h sym_key; yaca_key_h iv; + bool padding_none; }; enum encrypt_context_state_e { -- 2.7.4 From 2d53f6d1a35c3baa31ba8f16f097d059d1106725 Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Thu, 25 Aug 2016 16:09:11 +0200 Subject: [PATCH 15/16] Add possibility to restore default encrypt/decrypt padding. Introduce new padding type: YACA_PADDING_PKCS7. Change-Id: I841444c63bfca7a523a2a8df302c8aa38b81e59a --- api/yaca/yaca_types.h | 6 ++++-- src/encrypt.c | 13 ++++++++----- src/internal.h | 2 +- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/api/yaca/yaca_types.h b/api/yaca/yaca_types.h index 8bc8b0f..2032936 100755 --- a/api/yaca/yaca_types.h +++ b/api/yaca/yaca_types.h @@ -451,7 +451,7 @@ typedef enum { * ECB block cipher mode. * Initialization Vector is not used. * - * By default the input data is padded using standard block padding (aka PKCS#5 padding). + * By default the input data is padded using standard block padding (#YACA_PADDING_PKCS7). * 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. @@ -471,7 +471,7 @@ typedef enum { * 128-bit Initialization Vector for AES, * 64-bit for other algorithms is mandatory. * - * By default the input data is padded using standard block padding (aka PKCS#5 padding). + * By default the input data is padded using standard block padding (#YACA_PADDING_PKCS7). * 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. @@ -642,6 +642,8 @@ typedef enum { YACA_PADDING_PKCS1, /** RSA signature/verify operations */ YACA_PADDING_PKCS1_PSS, + /** PKCS #7 padding. Suitable for symmetric encrypt/decrypt operation. */ + YACA_PADDING_PKCS7 } yaca_padding_e; /** diff --git a/src/encrypt.c b/src/encrypt.c index fb5edac..03c515a 100644 --- a/src/encrypt.c +++ b/src/encrypt.c @@ -506,7 +506,7 @@ static int encrypt_ctx_backup(struct yaca_encrypt_context_s *c, bc->cipher = cipher; bc->sym_key = key_copy(sym_key); bc->iv = key_copy(iv); - bc->padding_none = false; + bc->padding = YACA_PADDING_PKCS7; c->backup_ctx = bc; @@ -534,7 +534,8 @@ static int encrypt_ctx_restore(struct yaca_encrypt_context_s *c) ret = encrypt_ctx_init(c, c->backup_ctx->cipher, key->bit_len); assert(ret != YACA_ERROR_INVALID_PARAMETER); - if (c->backup_ctx->padding_none && EVP_CIPHER_CTX_set_padding(c->cipher_ctx, 0) != 1) { + if (c->backup_ctx->padding == YACA_PADDING_NONE && + EVP_CIPHER_CTX_set_padding(c->cipher_ctx, 0) != 1) { ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); return ret; @@ -739,16 +740,18 @@ int set_encrypt_property(yaca_context_h ctx, 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 || + (*(yaca_padding_e*)value != YACA_PADDING_NONE && + *(yaca_padding_e*)value != YACA_PADDING_PKCS7) || c->state == STATE_FINALIZED) return YACA_ERROR_INVALID_PARAMETER; - if (EVP_CIPHER_CTX_set_padding(c->cipher_ctx, 0) != 1) { + yaca_padding_e padding = *(yaca_padding_e*)value; + if (EVP_CIPHER_CTX_set_padding(c->cipher_ctx, padding) != 1) { ERROR_DUMP(YACA_ERROR_INTERNAL); return YACA_ERROR_INTERNAL; } if (c->backup_ctx != NULL) - c->backup_ctx->padding_none = true; + c->backup_ctx->padding = padding; break; case YACA_PROPERTY_RC2_EFFECTIVE_KEY_BITS: if (value_len != sizeof(size_t) || diff --git a/src/internal.h b/src/internal.h index 107b3a8..553e8a1 100644 --- a/src/internal.h +++ b/src/internal.h @@ -65,7 +65,7 @@ struct yaca_backup_context_s { const EVP_CIPHER *cipher; yaca_key_h sym_key; yaca_key_h iv; - bool padding_none; + yaca_padding_e padding; }; enum encrypt_context_state_e { -- 2.7.4 From 96f162115ddbf30990ef00b423345473fb79e855 Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Mon, 29 Aug 2016 15:45:45 +0200 Subject: [PATCH 16/16] RSA low-level API Change-Id: Id0d838d97f613d1c9caf1231efdd961c370f2aab --- api/yaca/yaca_rsa.h | 197 ++++++++++++++++++++++++++++++++++++++++++++++++++ api/yaca/yaca_types.h | 42 ++++++++++- doc/yaca_doc.h | 11 ++- doc/yaca_rsa_doc.h | 32 ++++++++ 4 files changed, 276 insertions(+), 6 deletions(-) create mode 100755 api/yaca/yaca_rsa.h create mode 100755 doc/yaca_rsa_doc.h diff --git a/api/yaca/yaca_rsa.h b/api/yaca/yaca_rsa.h new file mode 100755 index 0000000..621cdff --- /dev/null +++ b/api/yaca/yaca_rsa.h @@ -0,0 +1,197 @@ +/* + * 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 yaca_rsa.h + * @brief Advanced API for low-level RSA operations + */ + +#ifndef YACA_RSA_H +#define YACA_RSA_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @addtogroup CAPI_YACA_RSA_MODULE + * @{ + */ + +/** + * @brief Encrypts data using a RSA public key (low-level encrypt equivalent). + * + * @since_tizen 3.0 + * + * @remarks The @a ciphertext should be freed using yaca_free() + * + * @remarks The key used has to be of a #YACA_KEY_TYPE_RSA_PUB type + * + * @remarks The maximum length of plaintext depends on the key length and padding method, + * see #yaca_padding_e for details + * + * @remarks The @a plaintext can be NULL but then the @a plaintext_len must be 0 + * + * @param[in] padding Padding method + * @param[in] pub_key Public RSA key (see yaca_key.h for key generation functions) + * @param[in] plaintext Plaintext to be encrypted + * @param[in] plaintext_len Length of the plaintext + * @param[out] ciphertext Encrypted data, will be allocated by the library + * @param[out] ciphertext_len Length of the encrypted data (may be larger than decrypted) + * + * @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 padding, pub_key or plaintext_len) + * @retval #YACA_ERROR_OUT_OF_MEMORY Out of memory error + * @retval #YACA_ERROR_INTERNAL Internal error + * + * @see #yaca_key_type_e + * @see #yaca_padding_e + * @see yaca_rsa_private_decrypt() + * @see yaca_free() + */ +int yaca_rsa_public_encrypt(yaca_padding_e padding, + const yaca_key_h pub_key, + const char *plaintext, + size_t plaintext_len, + char **ciphertext, + size_t *ciphertext_len); + +/** + * @brief Decrypts data using a RSA private key (low-level decrypt equivalent). + * + * @since_tizen 3.0 + * + * @remarks The @a plaintext should be freed using yaca_free() + * + * @remarks The key used has to be of a #YACA_KEY_TYPE_RSA_PRIV type + * + * @param[in] padding Padding method + * @param[in] prv_key Private RSA key matching the public one used to encrypt the data + * @param[in] ciphertext Ciphertext to be decrypted + * @param[in] ciphertext_len Length of ciphertext + * @param[out] plaintext Decrypted data, will be allocated by the library + * @param[out] plaintext_len Length of the decrypted data + * + * @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 padding or prv_key), padding check failed + * @retval #YACA_ERROR_OUT_OF_MEMORY Out of memory error + * @retval #YACA_ERROR_INTERNAL Internal error + * + * @see #yaca_key_type_e + * @see #yaca_padding_e + * @see yaca_rsa_public_encrypt() + * @see yaca_free() + */ +int yaca_rsa_private_decrypt(yaca_padding_e padding, + const yaca_key_h prv_key, + const char *ciphertext, + size_t ciphertext_len, + char **plaintext, + size_t *plaintext_len); + +/** + * @brief Encrypts data using a RSA private key (low-level sign equivalent). + * + * @since_tizen 3.0 + * + * @remarks The @a ciphertext should be freed using yaca_free() + * + * @remarks The key used has to be of a #YACA_KEY_TYPE_RSA_PRIV type + * + * @remarks The maximum length of plaintext depends on the key length and padding method, + * see #yaca_padding_e for details + * + * @remarks The @a plaintext can be NULL but then the @a plaintext_len must be 0 + * + * @param[in] padding Padding method + * @param[in] prv_key Private RSA key (see yaca_key.h for key generation functions) + * @param[in] plaintext Plaintext to be encrypted + * @param[in] plaintext_len Length of the plaintext + * @param[out] ciphertext Encrypted data, will be allocated by the library + * @param[out] ciphertext_len Length of the encrypted data (may be larger than decrypted) + * + * @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 padding, prv_key or message_len) + * @retval #YACA_ERROR_OUT_OF_MEMORY Out of memory error + * @retval #YACA_ERROR_INTERNAL Internal error + * + * @see #yaca_key_type_e + * @see #yaca_padding_e + * @see yaca_rsa_public_decrypt() + * @see yaca_free() + */ +int yaca_rsa_private_encrypt(yaca_padding_e padding, + const yaca_key_h prv_key, + const char *plaintext, + size_t plaintext_len, + char **ciphertext, + size_t *ciphertext_len); + +/** + * @brief Decrypts data using a RSA public key (low-level verify equivalent). + * + * @since_tizen 3.0 + * + * @remarks The @a plaintext should be freed using yaca_free() + * + * @remarks The key used has to be of a #YACA_KEY_TYPE_RSA_PUB type + * + * @param[in] padding Padding method + * @param[in] pub_key Public RSA key matching the private one used to encrypt the data + * @param[in] ciphertext Ciphertext to be decrypted + * @param[in] ciphertext_len Length of ciphertext + * @param[out] plaintext Decrypted data, will be allocated by the library + * @param[out] plaintext_len Length of the decrypted data + * + * @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 padding or pub_key), padding check failed + * @retval #YACA_ERROR_OUT_OF_MEMORY Out of memory error + * @retval #YACA_ERROR_INTERNAL Internal error + * + * @see #yaca_key_type_e + * @see #yaca_padding_e + * @see yaca_rsa_private_encrypt() + * @see yaca_free() + */ +int yaca_rsa_public_decrypt(yaca_padding_e padding, + const yaca_key_h pub_key, + const char *ciphertext, + size_t ciphertext_len, + char **plaintext, + size_t *plaintext_len); + +/** + * @} + */ + +#ifdef __cplusplus +} /* extern */ +#endif + +#endif /* YACA_RSA_H */ diff --git a/api/yaca/yaca_types.h b/api/yaca/yaca_types.h index 2032936..bdd7f9e 100755 --- a/api/yaca/yaca_types.h +++ b/api/yaca/yaca_types.h @@ -634,14 +634,48 @@ typedef enum { * @since_tizen 3.0 */ typedef enum { - /** The total number of data bytes MUST be a multiple of block size */ + /** + * No padding at all. This method assumes that the input data already has a proper length for + * a given cryptographic operation (e.g. it has been padded by the client). Suitable for + * symmetric encrypt/decrypt operations as well as low-level RSA operations. + */ YACA_PADDING_NONE = 0, - /** RSA X9.31 padding */ + + /** + * X9.31 padding. Suitable for RSA sign/verify operation. Not supported in low-level + * RSA operations. + */ YACA_PADDING_X931, - /** RSA signature/verify operations */ + + /** + * PKCS #1 v1.5 padding. Suitable for RSA sign/verify and low-level RSA operations. + * For low-level operations the input must be at least 12 bytes shorter than the key length. + */ YACA_PADDING_PKCS1, - /** RSA signature/verify operations */ + + /** + * PKCS #1 PSS padding. Suitable for RSA sign/verify operations. Not supported in low-level + * RSA operations. + */ YACA_PADDING_PKCS1_PSS, + + /** + * EME-OAEP as defined in PKCS #1 v2.0 with SHA-1, MGF1 and an empty encoding parameter. + * Suitable for low-level RSA public_encrypt/private_decrypt operations. For low-level + * operations the input must be at least 42 bytes shorter than the key length. + */ + YACA_PADDING_PKCS1_OAEP, + + /** + * PKCS #1 v1.5 padding with an SSL-specific modification that denotes that the party + * is SSL3 capable. It is used for rollback attack detection in SSLv3. If during decryption it + * turns out that both parties are using #YACA_PADDING_PKCS1_SSL23 (both are communicating + * using SSL2 and both are SSL3 capable) it is treated as a rollback attack and an error is + * returned. Suitable for low-level RSA public_encrypt/private_decrypt operations. For + * low-level operations the input must be at least 12 bytes shorter than the key length. + */ + YACA_PADDING_PKCS1_SSLV23, + /** PKCS #7 padding. Suitable for symmetric encrypt/decrypt operation. */ YACA_PADDING_PKCS7 } yaca_padding_e; diff --git a/doc/yaca_doc.h b/doc/yaca_doc.h index 4b9751d..d8b3ae3 100755 --- a/doc/yaca_doc.h +++ b/doc/yaca_doc.h @@ -18,10 +18,11 @@ /** * @ingroup CAPI_SECURITY_FRAMEWORK * @defgroup CAPI_YACA_MODULE YACA - * @brief The YACA (Yet Another Crypto Api) provides a crypto function such as key management, data integrity and data en/decryption. + * @brief The YACA (Yet Another Crypto Api) provides a crypto functions such as key management, data integrity, data en/decryption and low-level RSA operations. * Key management provides APIs for generating secured key,importing a key trying to match it to the key_type specified and exporting a key to arbitrary format. * Data Integrity provides Advanced/Simpled API for the integrity handling - HMAC, CMAC, message digests and digital signature. * Data en/decryption provides Advanced/Simpled APIs for en/decrypting and sealing/opening a data. + * RSA module provides advanced APIs for low-level encryption/decryption operations with asymmetric RSA keys. * * @section CAPI_YACA_MODULE_OVERVIEW Overview * @@ -42,17 +43,23 @@ * * * + * + * + * + * *
@ref CAPI_YACA_SIMPLE_MODULE Provides simple APIs for cryptographic operations.
@ref CAPI_YACA_RSA_MODULE Provides APIs for low-level RSA operations.
* * The yaca provides a crypto function such as key management, integrity handling and data en/decryption. * Key management provides APIs for generating secured key, importing a key trying to match it to the key type specified and exporting a key to arbitrary format. * Data Integrity provides Advanced/Simpled API for the integrity handling - HMAC, CMAC, message digest and digital signature. * Data en/decryption provides Advanced/Simpled APIs for en/decrypting a data and creating a IV. + * RSA module provides advanced APIs for low-level encryption/decryption operations with asymmetric RSA keys. * - * The yaca provides 3 types of API. + * The yaca provides 4 types of API. * - key management APIs : These APIs provides generating key using random number or password, importing a key trying to match it to the key_type specified and exporting a key to arbitrary format. * - data en/decryption APIs : These APIs provides Advanced/Simpled API for the data encryption. * - integrity APIs : These APIs provides creating a signature using asymmetric private key, verifying a signature using asymmetric public key, calculating a HMAC/CMAC of given message using symmetric key and calculating message digests of given message without key. + * - low-level RSA API : These APIs allow for low-level encryption/decryption operations with asymmetric RSA keys. * * */ diff --git a/doc/yaca_rsa_doc.h b/doc/yaca_rsa_doc.h new file mode 100755 index 0000000..4012e68 --- /dev/null +++ b/doc/yaca_rsa_doc.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ +#ifndef __TIZEN_CORE_YACA_RSA_DOC_H__ +#define __TIZEN_CORE_YACA_RSA_DOC_H__ +/** + * @ingroup CAPI_YACA_MODULE + * @defgroup CAPI_YACA_RSA_MODULE YACA Low-level RSA + * @brief Provides APIs for low-level RSA operations. + * + * @section CAPI_YACA_RSA_MODULE_HEADER Required Header + * \#include \n + * + * @section CAPI_YACA_RSA_MODULE_OVERVIEW Overview + * It provides advanced APIs for low-level encryption/decryption operations + * with asymmetric RSA keys. + * + */ + +#endif /* __TIZEN_CORE_YACA_RSA_DOC_H__ */ -- 2.7.4