From 621c2df6d2005b367b5eb2e5100ead43394708ec Mon Sep 17 00:00:00 2001 From: Mateusz Kulikowski Date: Wed, 13 Apr 2016 14:44:40 +0200 Subject: [PATCH 01/16] examples: Add LOREM*_SIZE Add macros containing sizes of lorem* strings. Change-Id: I2514f9fc03d55561530fac9ec856f404f9aa987b Signed-off-by: Mateusz Kulikowski --- examples/lorem.c | 10 ++++++---- examples/lorem.h | 18 ++++++++++++++---- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/examples/lorem.c b/examples/lorem.c index ac6955f..d6f9f42 100644 --- a/examples/lorem.c +++ b/examples/lorem.c @@ -21,12 +21,14 @@ * @brief Lorem Ipsum */ -const char *lorem8 = "Lorem i"; -const char *lorem16 = "Lorem ipsum dol"; -const char *lorem1024 = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec non dolor tincidunt, vehicula erat non, pulvinar nisl. Suspendisse gravida commodo hendrerit. Sed ex magna, aliquet malesuada lectus ut, porttitor tincidunt ante. Nulla facilisi. Morbi nec scelerisque risus. Sed a gravida sapien. Cras sed neque bibendum, dapibus lectus sed, porta nulla. Morbi tristique velit lacus, at luctus turpis mollis sed. Nam quis sapien eu magna cursus venenatis. Phasellus et vestibulum urna, non pellentesque ex. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Etiam pretium aliquam porta.\ +#include "lorem.h" + +const char lorem8[LOREM8_SIZE] = "Lorem i"; +const char lorem16[LOREM16_SIZE] = "Lorem ipsum dol"; +const char lorem1024[LOREM1024_SIZE] = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec non dolor tincidunt, vehicula erat non, pulvinar nisl. Suspendisse gravida commodo hendrerit. Sed ex magna, aliquet malesuada lectus ut, porttitor tincidunt ante. Nulla facilisi. Morbi nec scelerisque risus. Sed a gravida sapien. Cras sed neque bibendum, dapibus lectus sed, porta nulla. Morbi tristique velit lacus, at luctus turpis mollis sed. Nam quis sapien eu magna cursus venenatis. Phasellus et vestibulum urna, non pellentesque ex. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Etiam pretium aliquam porta.\ Morbi magna metus, commodo in fermentum id, mattis pretium mauris. Donec sed rhoncus justo. Duis fringilla sem quis velit dignissim bibendum. Sed porta efficitur ipsum, in dignissim magna molestie eu. Sed elementum maximus risus. Quisque cursus urna lectus, sit amet fringilla purus tempor eu. Praesent tincidunt dolor sit amet dolor vulputate, et molestie tellus euismod. Proin suscipit dictum amet."; -const char *lorem4096 = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus congue semper ipsum, ac convallis magna rhoncus sit amet. Donec pellentesque maximus convallis. Mauris ut egestas sem. Maecenas efficitur suscipit auctor. Nunc malesuada laoreet porttitor. Donec gravida tortor nisi, in mattis lectus porta ut. Integer vehicula eros et tellus placerat, nec fermentum justo aliquet.\ +const char lorem4096[LOREM4096_SIZE] = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus congue semper ipsum, ac convallis magna rhoncus sit amet. Donec pellentesque maximus convallis. Mauris ut egestas sem. Maecenas efficitur suscipit auctor. Nunc malesuada laoreet porttitor. Donec gravida tortor nisi, in mattis lectus porta ut. Integer vehicula eros et tellus placerat, nec fermentum justo aliquet.\ Maecenas metus massa, ultrices et ultricies sed, imperdiet nec dolor. Nam eget massa eros. Proin vitae laoreet metus, at scelerisque massa. Nullam convallis dolor id nisl iaculis, a gravida risus pretium. Proin non nunc eget nibh fermentum dignissim. Nullam tristique, odio eget rutrum sagittis, tortor purus cursus nunc, nec iaculis quam nunc ac metus. Cras ut tortor a eros porta vehicula non at lectus. Aliquam volutpat quis nisi ut mattis. Curabitur semper vehicula ultrices. Aenean cursus laoreet venenatis. Aenean vulputate, nisl id facilisis fringilla, neque velit posuere libero, et viverra tortor felis vitae urna. Sed in congue nunc. Fusce molestie tempor pharetra. Cras sodales pulvinar nunc non sollicitudin.\ Maecenas vehicula metus ac tristique ultricies. Suspendisse potenti. Pellentesque suscipit egestas augue, sed dictum orci. Pellentesque eu lorem ultricies, vestibulum est in, bibendum turpis. Proin placerat tincidunt metus, eget volutpat dolor. Pellentesque varius leo eget velit lobortis, sit amet congue orci bibendum. Aliquam vitae posuere lorem. Donec sed convallis diam. Quisque aliquam interdum purus, eu ornare ex ullamcorper iaculis. In sit amet nisl eu nisl ultricies dapibus. Aenean finibus efficitur elit ut sodales. Nam sit amet auctor sem, eu iaculis nunc. Vivamus mattis arcu a viverra faucibus. In dignissim, nisi sit amet consectetur tempus, lorem dui fringilla augue, sit amet lacinia lectus sapien efficitur odio.\ Nullam et egestas enim. Nam sit amet mi malesuada, dapibus felis quis, viverra mauris. Ut quis enim eu neque porta vehicula. Etiam ullamcorper vitae turpis vehicula blandit. Maecenas blandit tristique semper. Aliquam at sagittis enim. Donec quis molestie urna. Duis ut urna blandit, pellentesque magna ultrices, dignissim mi. Morbi fermentum ex massa, ut facilisis est tincidunt vel. Nam sed erat in lacus molestie mattis quis ut leo. Phasellus tempus elit urna, eget sagittis purus volutpat sed. Suspendisse aliquam, sem vel gravida lobortis, tortor orci ornare nisi, sed mollis ligula sem nec risus. In a ex nibh. Praesent odio est, molestie sed vestibulum id, varius sit amet lectus. Donec vel diam efficitur, tristique ligula a, aliquet felis. Nullam sit amet neque tellus.\ diff --git a/examples/lorem.h b/examples/lorem.h index 1b7ceb5..1b02d19 100644 --- a/examples/lorem.h +++ b/examples/lorem.h @@ -24,12 +24,22 @@ #ifndef LOREM_H #define LOREM_H +#include + /** Test strings, sizes include null-termination */ -extern const char *lorem8; -extern const char *lorem16; -extern const char *lorem1024; -extern const char *lorem4096; +extern const char lorem8[]; +extern const char lorem16[]; +extern const char lorem1024[]; +extern const char lorem4096[]; + +/** + * Sizes of test strings + */ +#define LOREM8_SIZE ((size_t)8) +#define LOREM16_SIZE ((size_t)16) +#define LOREM1024_SIZE ((size_t)1024) +#define LOREM4096_SIZE ((size_t)4096) #endif -- 2.7.4 From 7979a7584e6e0898ec68dddde6d495edad6db5c8 Mon Sep 17 00:00:00 2001 From: Mateusz Kulikowski Date: Wed, 13 Apr 2016 14:45:16 +0200 Subject: [PATCH 02/16] crypto.h: rename yaca_get_iv_length() to yaca_get_iv_bits() Function returns IV length in bits - rename it to avoid confusion. Change-Id: I58f565e1ca96321856f099d55ec456f23be1dbe0 Signed-off-by: Mateusz Kulikowski --- api/yaca/crypto.h | 10 +++++----- src/crypto.c | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/api/yaca/crypto.h b/api/yaca/crypto.h index 66d77e6..1b9feab 100644 --- a/api/yaca/crypto.h +++ b/api/yaca/crypto.h @@ -163,17 +163,17 @@ int yaca_get_output_length(const yaca_ctx_h ctx, size_t input_len); #define yaca_get_block_length(ctxa) yaca_get_output_length((ctxa), 0) /** - * @brief yaca_get_iv_length Returns the recomended/default length of the IV for a given encryption configuration. + * @brief yaca_get_iv_bits Returns the recomended/default length of the IV for a given encryption configuration. * * @param[in] algo Encryption algorithm. * @param[in] bcm Chain mode. * @param[in] key_bits Key length in bits (@see crypto_key_len_e). * - * @return negative on error (@see error.h) or the IV length. + * @return negative on error (@see error.h) or the IV length in bits. */ -int yaca_get_iv_length(yaca_enc_algo_e algo, - yaca_block_cipher_mode_e bcm, - size_t key_bits); +int yaca_get_iv_bits(yaca_enc_algo_e algo, + yaca_block_cipher_mode_e bcm, + size_t key_bits); /**@}*/ diff --git a/src/crypto.c b/src/crypto.c index af73404..9081bcf 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -108,9 +108,9 @@ API int yaca_get_output_length(const yaca_ctx_h ctx, size_t input_len) return ctx->get_output_length(ctx, input_len); } -API int yaca_get_iv_length(yaca_enc_algo_e algo, - yaca_block_cipher_mode_e bcm, - size_t key_bits) +API int yaca_get_iv_bits(yaca_enc_algo_e algo, + yaca_block_cipher_mode_e bcm, + size_t key_bits) { return YACA_ERROR_NOT_IMPLEMENTED; } -- 2.7.4 From 144545c77f8b73340d9f684a8ccea404692a777f Mon Sep 17 00:00:00 2001 From: Mateusz Kulikowski Date: Mon, 11 Apr 2016 11:58:52 +0200 Subject: [PATCH 03/16] Encrypt example update - Handle outputs allocation properly - Calculate IV lengths - Generate IV properly Change-Id: I3ae9c15dac9fa36bb308846fc4c33c61296ca819 Signed-off-by: Mateusz Kulikowski --- examples/encrypt.c | 134 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 89 insertions(+), 45 deletions(-) diff --git a/examples/encrypt.c b/examples/encrypt.c index 8ca1bc1..f428713 100644 --- a/examples/encrypt.c +++ b/examples/encrypt.c @@ -33,6 +33,9 @@ // Symmetric encryption using simple API void encrypt_simple(void) { + const yaca_enc_algo_e algo = YACA_ENC_AES; + const yaca_block_cipher_mode_e bcm = YACA_BCM_CBC; + const size_t key_bits = YACA_KEY_256BIT; int ret; yaca_key_h key = YACA_KEY_NULL; yaca_key_h iv = YACA_KEY_NULL; @@ -40,30 +43,35 @@ void encrypt_simple(void) char *dec_data = NULL; size_t enc_len; size_t dec_len; + int iv_bits; - printf("Plain data (16 of %zu bytes): %.16s\n", (size_t)1024, lorem1024); + printf("Simple Encrypt\nPlain data (16 of %zu bytes): %.16s\n", + LOREM1024_SIZE, lorem1024); - ret = yaca_key_derive_pbkdf2("foo bar", "123456789", 10, - 1000, YACA_DIGEST_SHA256, - YACA_KEY_256BIT, &key); + ret = yaca_key_derive_pbkdf2("foo bar", "123456789", 10, 1000, + YACA_DIGEST_SHA256, key_bits, &key); if (ret) return; - ret = yaca_key_gen(&iv, YACA_KEY_TYPE_IV, YACA_KEY_IV_256BIT); - if (ret) - goto exit; + iv_bits = yaca_get_iv_bits(algo, bcm, key_bits); + if (iv_bits < 0) + return; + + if (iv_bits > 0) { + ret = yaca_key_gen(&iv, YACA_KEY_TYPE_IV, iv_bits); + if (ret) + goto exit; + } - ret = yaca_encrypt(YACA_ENC_AES, YACA_BCM_CBC, - key, iv, lorem1024, 1024, &enc_data, &enc_len); + ret = yaca_encrypt(algo, bcm, key, iv, lorem1024, LOREM1024_SIZE, + &enc_data, &enc_len); if (ret) goto exit; dump_hex(enc_data, 16, "Encrypted data (16 of %zu bytes): ", enc_len); - ret = yaca_decrypt(YACA_ENC_AES, YACA_BCM_CBC, - key, iv, - enc_data, enc_len, - &dec_data, &dec_len); + ret = yaca_decrypt(algo, bcm, key, iv, enc_data, enc_len, &dec_data, + &dec_len); if (ret < 0) goto exit; @@ -81,6 +89,9 @@ exit: // Symmetric encryption using advanced API void encrypt_advanced(void) { + const yaca_enc_algo_e algo = YACA_ENC_AES; + const yaca_block_cipher_mode_e bcm = YACA_BCM_CBC; + const size_t key_bits = YACA_KEY_256BIT; int ret; yaca_ctx_h ctx; yaca_key_h key = YACA_KEY_NULL; @@ -89,86 +100,113 @@ void encrypt_advanced(void) char *dec = NULL; size_t enc_size; size_t dec_size; + int iv_bits; - printf("Plain data (16 of %zu bytes): %.16s\n", (size_t)4096, lorem1024); + printf("Advanced Encrypt\nPlain data (16 of %zu bytes): %.16s\n", + LOREM4096_SIZE, lorem4096); /// Key generation - ret = yaca_key_derive_pbkdf2("foo bar", "123456789", 10, - 1000, YACA_DIGEST_SHA256, - YACA_KEY_256BIT, &key); + ret = yaca_key_derive_pbkdf2("foo bar", "123456789", 10, 1000, + YACA_DIGEST_SHA256, key_bits, &key); if (ret) return; - ret = yaca_key_gen(&iv, YACA_KEY_TYPE_SYMMETRIC, YACA_KEY_IV_256BIT); - if (ret) + iv_bits = yaca_get_iv_bits(algo, bcm, key_bits); + if (iv_bits < 0) goto ex_key; + if (iv_bits > 0) { + ret = yaca_key_gen(&iv, YACA_KEY_TYPE_IV, iv_bits); + if (ret) + goto ex_key; + } + /// Encryption { - ret = yaca_encrypt_init(&ctx, YACA_ENC_AES, YACA_BCM_CBC, - key, iv); + size_t block_len; + size_t output_len; + size_t out_size; + size_t rem; + + ret = yaca_encrypt_init(&ctx, algo, bcm, key, iv); if (ret) goto ex_iv; - ret = yaca_encrypt_update(ctx, lorem4096, 4096, NULL, &enc_size); - if (ret != 42) - goto ex_ctx;// TODO: what error code? - ret = yaca_get_block_length(ctx); if (ret < 0) goto ex_ctx; - enc_size += ret ; // Add block size for finalize + block_len = ret; + + ret = yaca_get_output_length(ctx, LOREM4096_SIZE); + if (ret < 0) + goto ex_ctx; + + output_len = ret; + + /* Calculate max output: size of update + final chunks */ + enc_size = output_len + block_len; enc = yaca_malloc(enc_size); if (enc == NULL) goto ex_ctx; - size_t out_size = enc_size; - ret = yaca_encrypt_update(ctx, lorem4096, 4096, enc, &out_size); + out_size = enc_size; + ret = yaca_encrypt_update(ctx, lorem4096, LOREM4096_SIZE, enc, + &out_size); if (ret < 0) goto ex_of; - size_t rem = enc_size - out_size; + rem = enc_size - out_size; ret = yaca_encrypt_final(ctx, enc + out_size, &rem); if (ret < 0) goto ex_of; enc_size = rem + out_size; - dump_hex(enc, 16, "Encrypted data (16 of %zu bytes): ", enc_size); + dump_hex(enc, 16, "Encrypted data (16 of %zu bytes): ", + enc_size); yaca_ctx_free(ctx); // TODO: perhaps it should not return value } /// Decryption { - ret = yaca_decrypt_init(&ctx, YACA_ENC_AES, YACA_BCM_CBC, - key, iv); + size_t block_len; + size_t output_len; + size_t out_size; + size_t rem; + + ret = yaca_decrypt_init(&ctx, algo, bcm, key, iv); if (ret < 0) { - yaca_free(enc); - goto ex_iv; + ctx = YACA_CTX_NULL; + goto ex_of; } - ret = yaca_decrypt_update(ctx, enc, enc_size, NULL, &dec_size); - if (ret != 42) - goto ex_of; // TODO: what error code? - ret = yaca_get_block_length(ctx); if (ret < 0) goto ex_of; - dec_size += ret; // Add block size for finalize + block_len = ret; + + ret = yaca_get_output_length(ctx, LOREM4096_SIZE); + if (ret < 0) + goto ex_ctx; + + output_len = ret; + + /* Calculate max output: size of update + final chunks */ + dec_size = output_len + block_len; dec = yaca_malloc(dec_size); if (dec == NULL) goto ex_of; - size_t out_size = dec_size; + out_size = dec_size; ret = yaca_decrypt_update(ctx, enc, enc_size, dec, &out_size); if (ret < 0) goto ex_in; - size_t rem = dec_size - out_size; + rem = dec_size - out_size; ret = yaca_encrypt_final(ctx, dec + out_size, &rem); if (ret < 0) goto ex_in; @@ -214,6 +252,9 @@ void encrypt_seal(void) /// Encrypt a.k.a. seal { + size_t out_size; + size_t rem; + ret = yaca_seal_init(&ctx, key_pub, YACA_ENC_AES, YACA_BCM_CBC, &aes_key, &iv); @@ -234,12 +275,12 @@ void encrypt_seal(void) goto ex_ak; // Seal and finalize - size_t out_size = enc_size; + out_size = enc_size; ret = yaca_seal_update(ctx, lorem4096, 4096, enc, &out_size); if (ret < 0) goto ex_of; - size_t rem = enc_size - out_size; + rem = enc_size - out_size; ret = yaca_seal_final(ctx, enc + out_size, &rem); if (ret < 0) goto ex_of; @@ -253,6 +294,9 @@ void encrypt_seal(void) /// Decrypt a.k.a. open { + size_t out_size; + size_t rem; + ret = yaca_open_init(&ctx, key_priv, YACA_ENC_AES, YACA_BCM_CBC, aes_key, iv); @@ -275,12 +319,12 @@ void encrypt_seal(void) goto ex_of; // Seal and finalize - size_t out_size = enc_size; + out_size = enc_size; ret = yaca_open_update(ctx, enc, enc_size, dec, &out_size); if (ret < 0) goto ex_in; - size_t rem = dec_size - out_size; + rem = dec_size - out_size; ret = yaca_open_final(ctx, dec + out_size, &rem); if (ret < 0) goto ex_in; -- 2.7.4 From 455ddca22cb754e2a344b506a2fbbd28b0211c5d Mon Sep 17 00:00:00 2001 From: Mateusz Kulikowski Date: Mon, 11 Apr 2016 12:40:18 +0200 Subject: [PATCH 04/16] simple: Handle encrypt/decrypt block sizes properly - Calculate output block sizes properly - Resize output allocations to size output Change-Id: I58cc4530f9b832375c20c79c9883910adaaccc67 Signed-off-by: Mateusz Kulikowski --- src/simple.c | 62 ++++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 46 insertions(+), 16 deletions(-) diff --git a/src/simple.c b/src/simple.c index ce1d5f3..ff7f19e 100644 --- a/src/simple.c +++ b/src/simple.c @@ -90,6 +90,7 @@ API int yaca_encrypt(yaca_enc_algo_e algo, yaca_ctx_h ctx; int ret; char *lcipher; + char *rcipher; size_t out_len, lcipher_len, written; if (plain == NULL || plain_len == 0 || cipher == NULL || cipher_len == NULL || @@ -100,21 +101,28 @@ API int yaca_encrypt(yaca_enc_algo_e algo, return YACA_ERROR_TOO_BIG_ARGUMENT; ret = yaca_encrypt_init(&ctx, algo, bcm, sym_key, iv); - if (ret < 0) + if (ret != 0) return ret; - ret = yaca_get_output_length(ctx, plain_len); - if (ret < 0) + ret = yaca_get_block_length(ctx); + if (ret <= 0) goto err; lcipher_len = ret; + + ret = yaca_get_output_length(ctx, plain_len); + if (ret <= 0) + goto err; + + lcipher_len += ret; + lcipher = yaca_malloc(lcipher_len); if (lcipher == NULL) goto err; out_len = lcipher_len; ret = yaca_encrypt_update(ctx, plain, plain_len, lcipher, &out_len); - if (ret < 0) + if (ret != 0) goto err_free; assert (out_len <= lcipher_len); @@ -122,15 +130,22 @@ API int yaca_encrypt(yaca_enc_algo_e algo, written = out_len; out_len = lcipher_len - written; ret = yaca_encrypt_final(ctx, lcipher + written, &out_len); - if (ret < 0) + if (ret != 0) goto err_free; - assert (out_len + written == lcipher_len); + written += out_len; + assert (written <= lcipher_len); + + rcipher = yaca_realloc(lcipher, written); + if (rcipher == NULL) { + ret = YACA_ERROR_OUT_OF_MEMORY; + goto err_free; + } yaca_ctx_free(ctx); - *cipher = lcipher; - *cipher_len = lcipher_len; + *cipher = rcipher; + *cipher_len = written; return 0; err_free: @@ -152,6 +167,7 @@ API int yaca_decrypt(yaca_enc_algo_e algo, yaca_ctx_h ctx; int ret; char *lplain; + char *rplain; size_t out_len, lplain_len, written; if (cipher == NULL || cipher_len == 0 || plain == NULL || plain_len == NULL || @@ -162,21 +178,28 @@ API int yaca_decrypt(yaca_enc_algo_e algo, return YACA_ERROR_TOO_BIG_ARGUMENT; ret = yaca_decrypt_init(&ctx, algo, bcm, sym_key, iv); - if (ret < 0) + if (ret != 0) return ret; - ret = yaca_get_output_length(ctx, cipher_len); - if (ret < 0) + ret = yaca_get_block_length(ctx); + if (ret <= 0) goto err; lplain_len = ret; + + ret = yaca_get_output_length(ctx, cipher_len); + if (ret <= 0) + goto err; + + lplain_len += ret; + lplain = yaca_malloc(lplain_len); if (!lplain) goto err; out_len = lplain_len; ret = yaca_decrypt_update(ctx, cipher, cipher_len, lplain, &out_len); - if (ret < 0) + if (ret != 0) goto err_free; assert(out_len <= lplain_len); @@ -184,15 +207,22 @@ API int yaca_decrypt(yaca_enc_algo_e algo, written = out_len; out_len = lplain_len - written; ret = yaca_decrypt_final(ctx, lplain + written, &out_len); - if (ret < 0) + if (ret != 0) goto err_free; - assert(out_len + written == lplain_len); + written += out_len; + assert(written <= lplain_len); + + rplain = yaca_realloc(lplain, written); + if (rplain == NULL) { + ret = YACA_ERROR_OUT_OF_MEMORY; + goto err_free; + } yaca_ctx_free(ctx); - *plain = lplain; - *plain_len = lplain_len; + *plain = rplain; + *plain_len = written; return 0; err_free: -- 2.7.4 From c06a90476453190abfe4b143094c91719a0ce9e0 Mon Sep 17 00:00:00 2001 From: Mateusz Kulikowski Date: Mon, 11 Apr 2016 15:27:21 +0200 Subject: [PATCH 05/16] internal.h: add YACA_CTX_ENCRYPT It is context for encryption Change-Id: Icb8ebbb9804edca48cab3d6523a9e27c3ab30fe1 Signed-off-by: Mateusz Kulikowski --- src/internal.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/internal.h b/src/internal.h index deeff97..504fb6d 100644 --- a/src/internal.h +++ b/src/internal.h @@ -35,7 +35,8 @@ enum yaca_ctx_type_e { YACA_CTX_INVALID = 0, YACA_CTX_DIGEST, - YACA_CTX_SIGN + YACA_CTX_SIGN, + YACA_CTX_ENCRYPT, }; /* Base structure for crypto contexts - to be inherited */ -- 2.7.4 From 9b3d768ceec9e8f051f6f140361a82c231b6a063 Mon Sep 17 00:00:00 2001 From: Mateusz Kulikowski Date: Mon, 11 Apr 2016 15:31:50 +0200 Subject: [PATCH 06/16] encrypt: add get_symmetric_algorithm Implement function to map yaca algorithm enums to EVP_CIPHER. It is currently not very fast, and doesn't handle all algorithms/modes supported by yaca. Change-Id: I34c9a78044561b7fdcdc9e23632e45ff745e7f34 Signed-off-by: Mateusz Kulikowski --- src/encrypt.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/src/encrypt.c b/src/encrypt.c index ca8fa1d..596a1a4 100644 --- a/src/encrypt.c +++ b/src/encrypt.c @@ -20,12 +20,90 @@ #include #include +#include #include #include #include "internal.h" +static const char *symmetric_algo_to_str(yaca_enc_algo_e algo) +{ + switch(algo) + { + case YACA_ENC_AES: + return "aes"; + case YACA_ENC_UNSAFE_DES: + return "des"; + case YACA_ENC_UNSAFE_RC2: + return "rc2"; + case YACA_ENC_UNSAFE_RC4: + return "rc4"; + case YACA_ENC_CAST5: + return "cast5"; + + case YACA_ENC_UNSAFE_3DES_2TDEA: // TODO: add 3des/2tdea support + case YACA_ENC_3DES_3TDEA: // TODO: add 3des/3tdea support + case YACA_ENC_UNSAFE_SKIPJACK: // TODO: add skipjack implementation + default: + return NULL; + } +} + +static const char *bcm_to_str(yaca_block_cipher_mode_e bcm) +{ + switch (bcm) { + case YACA_BCM_ECB: + return "ecb"; + case YACA_BCM_CBC: + return "cbc"; + case YACA_BCM_CTR: + return "ctr"; + case YACA_BCM_GCM: + return "gcm"; + case YACA_BCM_CFB: + return "cfb"; + case YACA_BCM_OFB: + return "ofb"; + case YACA_BCM_OCB: + return "ocb"; + case YACA_BCM_CCM: + return "ccm"; + default: + return NULL; + } +} + +int get_symmetric_algorithm(yaca_enc_algo_e algo, + yaca_block_cipher_mode_e bcm, + unsigned key_bits, + const EVP_CIPHER **cipher) +{ + char cipher_name[32]; + const char *algo_name = symmetric_algo_to_str(algo); + const char *bcm_name = bcm_to_str(bcm); + const EVP_CIPHER *lcipher; + int ret; + + if (algo_name == NULL || bcm_name == NULL || key_bits == 0 || + cipher == NULL) + return YACA_ERROR_INVALID_ARGUMENT; + + ret = snprintf(cipher_name, sizeof(cipher_name), "%s-%d-%s", algo_name, + key_bits, bcm_name); + if (ret < 0) + return YACA_ERROR_INVALID_ARGUMENT; + if ((unsigned)ret >= sizeof(cipher_name)) // output was truncated + return YACA_ERROR_INVALID_ARGUMENT; + + lcipher = EVP_get_cipherbyname(cipher_name); + if (lcipher == NULL) + return YACA_ERROR_OPENSSL_FAILURE; // TODO: yaca_get_error_code_from_openssl(ret); + + *cipher = lcipher; + return 0; +} + API int yaca_encrypt_init(yaca_ctx_h *ctx, yaca_enc_algo_e algo, yaca_block_cipher_mode_e bcm, -- 2.7.4 From d9a512a7d78824e32106717770071f38dba97615 Mon Sep 17 00:00:00 2001 From: Mateusz Kulikowski Date: Mon, 11 Apr 2016 15:33:39 +0200 Subject: [PATCH 07/16] Implement yaca_get_iv_bits() Move code to encrypt* as it's encryption related. Change-Id: Id9b5072e3fb220aaffcc0f1aad5f2b0893fa06ed Signed-off-by: Mateusz Kulikowski --- api/yaca/crypto.h | 13 ------------- api/yaca/encrypt.h | 13 +++++++++++++ src/crypto.c | 7 ------- src/encrypt.c | 14 ++++++++++++++ 4 files changed, 27 insertions(+), 20 deletions(-) diff --git a/api/yaca/crypto.h b/api/yaca/crypto.h index 1b9feab..cd30ff2 100644 --- a/api/yaca/crypto.h +++ b/api/yaca/crypto.h @@ -162,19 +162,6 @@ int yaca_get_output_length(const yaca_ctx_h ctx, size_t input_len); */ #define yaca_get_block_length(ctxa) yaca_get_output_length((ctxa), 0) -/** - * @brief yaca_get_iv_bits Returns the recomended/default length of the IV for a given encryption configuration. - * - * @param[in] algo Encryption algorithm. - * @param[in] bcm Chain mode. - * @param[in] key_bits Key length in bits (@see crypto_key_len_e). - * - * @return negative on error (@see error.h) or the IV length in bits. - */ -int yaca_get_iv_bits(yaca_enc_algo_e algo, - yaca_block_cipher_mode_e bcm, - size_t key_bits); - /**@}*/ #ifdef __cplusplus diff --git a/api/yaca/encrypt.h b/api/yaca/encrypt.h index 38e565f..e94fb37 100644 --- a/api/yaca/encrypt.h +++ b/api/yaca/encrypt.h @@ -247,6 +247,19 @@ int yaca_open_final(yaca_ctx_h ctx, char *plain, size_t *plain_len); +/** + * @brief yaca_get_iv_bits Returns the recomended/default length of the IV for a given encryption configuration. + * + * @param[in] algo Encryption algorithm. + * @param[in] bcm Chain mode. + * @param[in] key_bits Key length in bits (@see crypto_key_len_e). + * + * @return negative on error (@see error.h) or the IV length in bits. + */ +int yaca_get_iv_bits(yaca_enc_algo_e algo, + yaca_block_cipher_mode_e bcm, + size_t key_bits); + /**@}*/ #ifdef __cplusplus diff --git a/src/crypto.c b/src/crypto.c index 9081bcf..4a49071 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -107,10 +107,3 @@ API int yaca_get_output_length(const yaca_ctx_h ctx, size_t input_len) return ctx->get_output_length(ctx, input_len); } - -API int yaca_get_iv_bits(yaca_enc_algo_e algo, - yaca_block_cipher_mode_e bcm, - size_t key_bits) -{ - return YACA_ERROR_NOT_IMPLEMENTED; -} diff --git a/src/encrypt.c b/src/encrypt.c index 596a1a4..bfd730d 100644 --- a/src/encrypt.c +++ b/src/encrypt.c @@ -104,6 +104,20 @@ int get_symmetric_algorithm(yaca_enc_algo_e algo, return 0; } +API int yaca_get_iv_bits(yaca_enc_algo_e algo, + yaca_block_cipher_mode_e bcm, + size_t key_bits) +{ + const EVP_CIPHER *cipher; + int ret; + + ret = get_symmetric_algorithm(algo, bcm, key_bits, &cipher); + if (ret < 0) + return ret; + + return EVP_CIPHER_iv_length(cipher) * 8; +} + API int yaca_encrypt_init(yaca_ctx_h *ctx, yaca_enc_algo_e algo, yaca_block_cipher_mode_e bcm, -- 2.7.4 From 31eb3c7613d4f96d309d781e64929cfef366b07b Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Mon, 11 Apr 2016 15:10:17 +0200 Subject: [PATCH 08/16] Add package with examples. Change-Id: Idd9fee1bdc3588721fb74f1dca3ff570e827a757 --- CMakeLists.txt | 8 ++++++++ examples/CMakeLists.txt | 5 +++++ packaging/yaca.spec | 25 ++++++++++++++++++------- 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a42b702..0c2f401 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -90,6 +90,14 @@ IF(NOT DEFINED BIN_INSTALL_DIR) SET(BIN_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}") ENDIF(NOT DEFINED BIN_INSTALL_DIR) +IF(NOT DEFINED SHARE_INSTALL_PREFIX) + SET(SHARE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}/share") +ENDIF(NOT DEFINED SHARE_INSTALL_PREFIX) + +IF(NOT DEFINED EXAMPLES_DIR) + SET(EXAMPLES_DIR "${SHARE_INSTALL_PREFIX}/${PROJECT_NAME}/examples") +ENDIF(NOT DEFINED EXAMPLES_DIR) + ADD_SUBDIRECTORY(${SRC_FOLDER}) #ADD_SUBDIRECTORY(${TEST_FOLDER}) ADD_SUBDIRECTORY(${EXAMPLES_FOLDER}) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 160ec0e..6413bad 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -45,6 +45,8 @@ FUNCTION(BUILD_EXAMPLE EXAMPLE_NAME SOURCE_FILE) WORLD_READ WORLD_EXECUTE ) + INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${SOURCE_FILE} + DESTINATION ${EXAMPLES_DIR}) ENDFUNCTION(BUILD_EXAMPLE) BUILD_EXAMPLE("yaca-example-digest" digest.c) @@ -53,3 +55,6 @@ BUILD_EXAMPLE("yaca-example-encrypt-gcm" encrypt_aes_gcm.c) BUILD_EXAMPLE("yaca-example-sign" sign.c) BUILD_EXAMPLE("yaca-example-key-exchange" key_exchange.c) BUILD_EXAMPLE("yaca-example-test" test.c) + +INSTALL(FILES ${COMMON_SOURCES} + DESTINATION ${EXAMPLES_DIR}) diff --git a/packaging/yaca.spec b/packaging/yaca.spec index bfef0c7..126018c 100644 --- a/packaging/yaca.spec +++ b/packaging/yaca.spec @@ -13,10 +13,13 @@ Requires(postun): /sbin/ldconfig %description The package provides Yet Another Crypto API. +%post -p /sbin/ldconfig + +%postun -p /sbin/ldconfig + %files -%defattr(644,root,root,755) %{_libdir}/libyaca.so.0 -%attr(755,root,root) %{_libdir}/libyaca.so.%{version} +%{_libdir}/libyaca.so.%{version} %prep %setup -q @@ -33,10 +36,6 @@ make -k %{?jobs:-j%jobs} %clean rm -rf %{buildroot} -%post -n yaca -p /sbin/ldconfig - -%postun -n yaca -p /sbin/ldconfig - ## Devel Package ############################################################### %package devel Summary: Yet Another Crypto API development files @@ -47,7 +46,19 @@ Requires: yaca = %{version}-%{release} The package provides Yet Another Crypto API development files. %files devel -%defattr(644,root,root,755) %{_libdir}/libyaca.so %{_includedir}/yaca %{_libdir}/pkgconfig/yaca.pc + +## Examples Package ############################################################ +%package examples +Summary: Yet Another Crypto API example files +Group: Security/Other +Requires: yaca = %{version}-%{release} + +%description examples +The package provides Yet Another Crypto API example files. + +%files examples +%{_bindir}/yaca-example* +%{_datadir}/%{name}/examples -- 2.7.4 From 4db7c072c298f0b816a8fe079279fb9a104d653d Mon Sep 17 00:00:00 2001 From: Mateusz Kulikowski Date: Mon, 11 Apr 2016 15:35:20 +0200 Subject: [PATCH 09/16] Implement limited symmetric cipher support Change-Id: I5b130e3e1d41cfcce1f730f3d1b316c088432677 Signed-off-by: Mateusz Kulikowski --- src/encrypt.c | 260 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 247 insertions(+), 13 deletions(-) diff --git a/src/encrypt.c b/src/encrypt.c index bfd730d..d195800 100644 --- a/src/encrypt.c +++ b/src/encrypt.c @@ -17,17 +17,75 @@ */ #include +#include #include #include #include #include +#include #include +#include #include "internal.h" -static const char *symmetric_algo_to_str(yaca_enc_algo_e algo) +enum encrypt_op_type { + OP_ENCRYPT = 0, + OP_DECRYPT = 1 +}; + +struct yaca_encrypt_ctx_s +{ + struct yaca_ctx_s ctx; + + EVP_CIPHER_CTX *cipher_ctx; + enum encrypt_op_type op_type; /* Operation context was created for */ +}; + +static struct yaca_encrypt_ctx_s *get_encrypt_ctx(const yaca_ctx_h ctx) +{ + if (ctx == YACA_CTX_NULL) + return NULL; + + switch (ctx->type) + { + case YACA_CTX_ENCRYPT: + return (struct yaca_encrypt_ctx_s *)ctx; + default: + return NULL; + } +} + +static void destroy_encrypt_ctx(const yaca_ctx_h ctx) +{ + struct yaca_encrypt_ctx_s *nc = get_encrypt_ctx(ctx); + + if (nc == NULL) + return; + + EVP_CIPHER_CTX_free(nc->cipher_ctx); + nc->cipher_ctx = NULL; +} + +static int get_encrypt_output_length(const yaca_ctx_h ctx, size_t input_len) +{ + struct yaca_encrypt_ctx_s *nc = get_encrypt_ctx(ctx); + int block_size; + + if (nc == NULL || nc->cipher_ctx == NULL) + return YACA_ERROR_INVALID_ARGUMENT; + + block_size = EVP_CIPHER_CTX_block_size(nc->cipher_ctx); + if (block_size == 0) + return YACA_ERROR_OPENSSL_FAILURE; // TODO: extract openssl error here + + if (input_len > 0) + return block_size + input_len - 1; + return block_size; +} + +static const char *encrypt_algo_to_str(yaca_enc_algo_e algo) { switch(algo) { @@ -74,13 +132,13 @@ static const char *bcm_to_str(yaca_block_cipher_mode_e bcm) } } -int get_symmetric_algorithm(yaca_enc_algo_e algo, - yaca_block_cipher_mode_e bcm, - unsigned key_bits, - const EVP_CIPHER **cipher) +int get_encrypt_algorithm(yaca_enc_algo_e algo, + yaca_block_cipher_mode_e bcm, + unsigned key_bits, + const EVP_CIPHER **cipher) { char cipher_name[32]; - const char *algo_name = symmetric_algo_to_str(algo); + const char *algo_name = encrypt_algo_to_str(algo); const char *bcm_name = bcm_to_str(bcm); const EVP_CIPHER *lcipher; int ret; @@ -104,6 +162,178 @@ int get_symmetric_algorithm(yaca_enc_algo_e algo, return 0; } +static int encrypt_init(yaca_ctx_h *ctx, + yaca_enc_algo_e algo, + yaca_block_cipher_mode_e bcm, + const yaca_key_h sym_key, + const yaca_key_h iv, + enum encrypt_op_type op_type) +{ + const struct yaca_key_simple_s *lkey; + const struct yaca_key_simple_s *liv; + struct yaca_encrypt_ctx_s *nc; + const EVP_CIPHER *cipher; + int key_bits; + int iv_bits; + int ret; + + if (ctx == NULL || sym_key == YACA_KEY_NULL) + return YACA_ERROR_INVALID_ARGUMENT; + + lkey = key_get_simple(sym_key); + if (lkey == NULL) + return YACA_ERROR_INVALID_ARGUMENT; + + nc = yaca_malloc(sizeof(struct yaca_encrypt_ctx_s)); + if (nc == NULL) + return YACA_ERROR_OUT_OF_MEMORY; + + memset(nc, 0, sizeof(struct yaca_encrypt_ctx_s)); + + nc->ctx.type = YACA_CTX_ENCRYPT; + nc->ctx.ctx_destroy = destroy_encrypt_ctx; + nc->ctx.get_output_length = get_encrypt_output_length; + nc->op_type = op_type; + + // TODO: handling of algorithms with variable key length + ret = yaca_key_get_length(sym_key); + if (ret < 0) + goto err_free; + key_bits = ret; + + ret = get_encrypt_algorithm(algo, bcm, key_bits, &cipher); + if (ret != 0) + goto err_free; + + ret = EVP_CIPHER_iv_length(cipher); + if (ret < 0) + goto err_free; + + iv_bits = ret * 8; + if (iv_bits == 0 && iv != NULL) { /* 0 -> cipher doesn't use iv, but it was provided */ + ret = YACA_ERROR_INVALID_ARGUMENT; + goto err_free; + } + + liv = key_get_simple(iv); + if (ret != 0 && liv == NULL) { /* cipher requires iv, but none was provided */ + ret = YACA_ERROR_INVALID_ARGUMENT; + goto err_free; + } + + // TODO: handling of algorithms with variable IV length + if (iv_bits != yaca_key_get_length(iv)) { /* IV length doesn't match cipher */ + ret = YACA_ERROR_INVALID_ARGUMENT; + goto err_free; + } + + nc->cipher_ctx = EVP_CIPHER_CTX_new(); + if (nc->cipher_ctx == NULL) { + ret = YACA_ERROR_OPENSSL_FAILURE; // TODO: yaca_get_error_code_from_openssl(ret); + goto err_free; + } + + switch (op_type) { + case OP_ENCRYPT: + ret = EVP_EncryptInit(nc->cipher_ctx, cipher, + (unsigned char*)lkey->d, + (unsigned char*)liv->d); + break; + case OP_DECRYPT: + ret = EVP_DecryptInit(nc->cipher_ctx, cipher, + (unsigned char*)lkey->d, + (unsigned char*)liv->d); + break; + default: + ret = YACA_ERROR_INVALID_ARGUMENT; + goto err_ctx; + } + + if (ret != 1) { + ret = YACA_ERROR_OPENSSL_FAILURE; // TODO: yaca_get_error_code_from_openssl(ret); + goto err_ctx; + } + + *ctx = (yaca_ctx_h)nc; + return 0; + +err_ctx: + EVP_CIPHER_CTX_free(nc->cipher_ctx); +err_free: + yaca_free(nc); + return ret; +} + +static int encrypt_update(yaca_ctx_h ctx, + const unsigned char *input, + size_t input_len, + unsigned char *output, + size_t *output_len, + enum encrypt_op_type op_type) +{ + struct yaca_encrypt_ctx_s *c = get_encrypt_ctx(ctx); + int ret; + int loutput_len; + + if (c == NULL || input == NULL || input_len == 0 || + output == NULL || output_len == NULL || op_type != c->op_type) + return YACA_ERROR_INVALID_ARGUMENT; + + loutput_len = *output_len; + + switch (op_type) { + case OP_ENCRYPT: + ret = EVP_EncryptUpdate(c->cipher_ctx, output, &loutput_len, + input, input_len); + break; + case OP_DECRYPT: + ret = EVP_DecryptUpdate(c->cipher_ctx, output, &loutput_len, + input, input_len); + break; + default: + return YACA_ERROR_INVALID_ARGUMENT; + } + + if (ret != 1) + return YACA_ERROR_OPENSSL_FAILURE; // TODO: yaca_get_error_code_from_openssl(ret); + + *output_len = loutput_len; + return 0; +} + +static int encrypt_final(yaca_ctx_h ctx, + unsigned char *output, + size_t *output_len, + enum encrypt_op_type op_type) +{ + struct yaca_encrypt_ctx_s *c = get_encrypt_ctx(ctx); + int ret; + int loutput_len; + + if (c == NULL || output == NULL || output_len == NULL || + op_type != c->op_type) + return YACA_ERROR_INVALID_ARGUMENT; + + loutput_len = *output_len; + + switch (op_type) { + case OP_ENCRYPT: + ret = EVP_EncryptFinal(c->cipher_ctx, output, &loutput_len); + break; + case OP_DECRYPT: + ret = EVP_DecryptFinal(c->cipher_ctx, output, &loutput_len); + break; + default: + return YACA_ERROR_INVALID_ARGUMENT; + } + + if (ret != 1) + return YACA_ERROR_OPENSSL_FAILURE; // TODO: yaca_get_error_code_from_openssl(ret); + + *output_len = loutput_len; + return 0; +} + API int yaca_get_iv_bits(yaca_enc_algo_e algo, yaca_block_cipher_mode_e bcm, size_t key_bits) @@ -111,7 +341,7 @@ API int yaca_get_iv_bits(yaca_enc_algo_e algo, const EVP_CIPHER *cipher; int ret; - ret = get_symmetric_algorithm(algo, bcm, key_bits, &cipher); + ret = get_encrypt_algorithm(algo, bcm, key_bits, &cipher); if (ret < 0) return ret; @@ -124,7 +354,7 @@ API int yaca_encrypt_init(yaca_ctx_h *ctx, const yaca_key_h sym_key, const yaca_key_h iv) { - return YACA_ERROR_NOT_IMPLEMENTED; + return encrypt_init(ctx, algo, bcm, sym_key, iv, OP_ENCRYPT); } API int yaca_encrypt_update(yaca_ctx_h ctx, @@ -133,14 +363,16 @@ API int yaca_encrypt_update(yaca_ctx_h ctx, char *cipher, size_t *cipher_len) { - return YACA_ERROR_NOT_IMPLEMENTED; + return encrypt_update(ctx, (const unsigned char*)plain, plain_len, + (unsigned char*)cipher, cipher_len, OP_ENCRYPT); } API int yaca_encrypt_final(yaca_ctx_h ctx, char *cipher, size_t *cipher_len) { - return YACA_ERROR_NOT_IMPLEMENTED; + return encrypt_final(ctx, (unsigned char*)cipher, + cipher_len, OP_ENCRYPT); } API int yaca_decrypt_init(yaca_ctx_h *ctx, @@ -149,7 +381,7 @@ API int yaca_decrypt_init(yaca_ctx_h *ctx, const yaca_key_h sym_key, const yaca_key_h iv) { - return YACA_ERROR_NOT_IMPLEMENTED; + return encrypt_init(ctx, algo, bcm, sym_key, iv, OP_DECRYPT); } API int yaca_decrypt_update(yaca_ctx_h ctx, @@ -158,14 +390,16 @@ API int yaca_decrypt_update(yaca_ctx_h ctx, char *plain, size_t *plain_len) { - return YACA_ERROR_NOT_IMPLEMENTED; + return encrypt_update(ctx, (const unsigned char*)cipher, cipher_len, + (unsigned char*)plain, plain_len, OP_DECRYPT); } API int yaca_decrypt_final(yaca_ctx_h ctx, char *plain, size_t *plain_len) { - return YACA_ERROR_NOT_IMPLEMENTED; + return encrypt_final(ctx,(unsigned char*)plain, plain_len, + OP_DECRYPT); } API int yaca_seal_init(yaca_ctx_h *ctx, -- 2.7.4 From 0482f46764d70b38f6d6376132893d6cee80e9ba Mon Sep 17 00:00:00 2001 From: Mateusz Kulikowski Date: Mon, 11 Apr 2016 15:46:33 +0200 Subject: [PATCH 10/16] yaca: add yaca_zalloc This allocator will be mostly used to allocate contexts/keys. Change-Id: I5c3a5efcda5a243503ac80502c221157e18eaa2a Signed-off-by: Mateusz Kulikowski --- api/yaca/crypto.h | 10 ++++++++++ src/crypto.c | 9 +++++++++ 2 files changed, 19 insertions(+) diff --git a/api/yaca/crypto.h b/api/yaca/crypto.h index cd30ff2..309d2f9 100644 --- a/api/yaca/crypto.h +++ b/api/yaca/crypto.h @@ -68,6 +68,16 @@ void yaca_exit(void); void *yaca_malloc(size_t size); /** + * @brief yaca_zalloc Allocates the zeroed memory. + * + * @param[in] size Size of the allocation (bytes). + * + * @return NULL on failure, pointer to allocated and zeroed memory otherwise. + */ +// TODO: this should be a macro to CRYPTO_* +void *yaca_zalloc(size_t size); + +/** * @brief yaca_realloc Re-allocates the memory. * * @param[in] addr Address of the memory to be reallocated. diff --git a/src/crypto.c b/src/crypto.c index 4a49071..550abf0 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -17,6 +17,7 @@ */ #include +#include #include #include @@ -54,6 +55,14 @@ API void *yaca_malloc(size_t size) return OPENSSL_malloc(size); } +API void *yaca_zalloc(size_t size) +{ + void *blob = OPENSSL_malloc(size); + if (blob != NULL) + memset(blob, 0, size); + return blob; +} + API void *yaca_realloc(void *addr, size_t size) { return OPENSSL_realloc(addr, size); -- 2.7.4 From e62df1be79c2a82447e66461840327342231cf39 Mon Sep 17 00:00:00 2001 From: Mateusz Kulikowski Date: Mon, 11 Apr 2016 15:50:50 +0200 Subject: [PATCH 11/16] Use crypto_zalloc for internal structure allocations. Change-Id: I3a3f738cf238c362ac33e3aa01c3a37d263140f9 Signed-off-by: Mateusz Kulikowski --- src/digest.c | 2 +- src/encrypt.c | 4 +--- src/key.c | 10 +++++----- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/digest.c b/src/digest.c index 93a2535..9c50748 100644 --- a/src/digest.c +++ b/src/digest.c @@ -121,7 +121,7 @@ API int yaca_digest_init(yaca_ctx_h *ctx, yaca_digest_algo_e algo) if (ctx == NULL) return YACA_ERROR_INVALID_ARGUMENT; - nc = yaca_malloc(sizeof(struct yaca_digest_ctx_s)); + nc = yaca_zalloc(sizeof(struct yaca_digest_ctx_s)); if (nc == NULL) return YACA_ERROR_OUT_OF_MEMORY; diff --git a/src/encrypt.c b/src/encrypt.c index d195800..24e9117 100644 --- a/src/encrypt.c +++ b/src/encrypt.c @@ -184,12 +184,10 @@ static int encrypt_init(yaca_ctx_h *ctx, if (lkey == NULL) return YACA_ERROR_INVALID_ARGUMENT; - nc = yaca_malloc(sizeof(struct yaca_encrypt_ctx_s)); + nc = yaca_zalloc(sizeof(struct yaca_encrypt_ctx_s)); if (nc == NULL) return YACA_ERROR_OUT_OF_MEMORY; - memset(nc, 0, sizeof(struct yaca_encrypt_ctx_s)); - nc->ctx.type = YACA_CTX_ENCRYPT; nc->ctx.ctx_destroy = destroy_encrypt_ctx; nc->ctx.get_output_length = get_encrypt_output_length; diff --git a/src/key.c b/src/key.c index 6ba3c9e..f5aa42c 100644 --- a/src/key.c +++ b/src/key.c @@ -137,7 +137,7 @@ API int yaca_key_import(yaca_key_h *key, if (data_len > SIZE_MAX - sizeof(struct yaca_key_simple_s)) return YACA_ERROR_TOO_BIG_ARGUMENT; - nk = yaca_malloc(sizeof(struct yaca_key_simple_s) + data_len); + nk = yaca_zalloc(sizeof(struct yaca_key_simple_s) + data_len); if (nk == NULL) return YACA_ERROR_OUT_OF_MEMORY; @@ -232,7 +232,7 @@ API int yaca_key_gen(yaca_key_h *sym_key, if (key_byte_len > SIZE_MAX - sizeof(struct yaca_key_simple_s)) return YACA_ERROR_TOO_BIG_ARGUMENT; - nk = yaca_malloc(sizeof(struct yaca_key_simple_s) + key_byte_len); + nk = yaca_zalloc(sizeof(struct yaca_key_simple_s) + key_byte_len); if (nk == NULL) return YACA_ERROR_OUT_OF_MEMORY; @@ -269,11 +269,11 @@ API int yaca_key_gen_pair(yaca_key_h *prv_key, if (key_type != YACA_KEY_TYPE_PAIR_RSA) return YACA_ERROR_NOT_IMPLEMENTED; - nk_prv = yaca_malloc(sizeof(struct yaca_key_evp_s)); + nk_prv = yaca_zalloc(sizeof(struct yaca_key_evp_s)); if (nk_prv == NULL) return YACA_ERROR_OUT_OF_MEMORY; - nk_pub = yaca_malloc(sizeof(struct yaca_key_evp_s)); + nk_pub = yaca_zalloc(sizeof(struct yaca_key_evp_s)); if (nk_pub == NULL) { ret = YACA_ERROR_OUT_OF_MEMORY; goto free_prv; @@ -414,7 +414,7 @@ API int yaca_key_derive_pbkdf2(const char *password, if (key_byte_len > SIZE_MAX - sizeof(struct yaca_key_simple_s)) return YACA_ERROR_TOO_BIG_ARGUMENT; - nk = yaca_malloc(sizeof(struct yaca_key_simple_s) + key_byte_len); + nk = yaca_zalloc(sizeof(struct yaca_key_simple_s) + key_byte_len); if (nk == NULL) return YACA_ERROR_OUT_OF_MEMORY; -- 2.7.4 From 40c0aefda7679310c150f24fcb88b9177cf56485 Mon Sep 17 00:00:00 2001 From: Mateusz Kulikowski Date: Mon, 11 Apr 2016 15:51:51 +0200 Subject: [PATCH 12/16] Add yaca_ctx_get|set_param prototypes. Change-Id: I714a47663e742bc8c3eeb446483eee0a58a8a056 Signed-off-by: Mateusz Kulikowski --- src/crypto.c | 16 ++++++++++++++-- src/internal.h | 4 ++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/crypto.c b/src/crypto.c index 550abf0..a90d0d9 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -92,13 +92,25 @@ API int yaca_rand_bytes(char *data, size_t data_len) API int yaca_ctx_set_param(yaca_ctx_h ctx, yaca_ex_param_e param, const void *value, size_t value_len) { - return YACA_ERROR_NOT_IMPLEMENTED; + if (ctx == YACA_CTX_NULL) + return YACA_ERROR_INVALID_ARGUMENT; + + if (ctx->set_param == NULL) + return YACA_ERROR_NOT_SUPPORTED; + + return ctx->set_param(ctx, param, value, value_len); } API int yaca_ctx_get_param(const yaca_ctx_h ctx, yaca_ex_param_e param, void **value, size_t *value_len) { - return YACA_ERROR_NOT_IMPLEMENTED; + if (ctx == YACA_CTX_NULL) + return YACA_ERROR_INVALID_ARGUMENT; + + if (ctx->get_param == NULL) + return YACA_ERROR_NOT_SUPPORTED; + + return ctx->get_param(ctx, param, value, value_len); } API void yaca_ctx_free(yaca_ctx_h ctx) diff --git a/src/internal.h b/src/internal.h index 504fb6d..25f0edc 100644 --- a/src/internal.h +++ b/src/internal.h @@ -46,6 +46,10 @@ struct yaca_ctx_s void (*ctx_destroy)(const yaca_ctx_h ctx); int (*get_output_length)(const yaca_ctx_h ctx, size_t input_len); + int (*set_param)(yaca_ctx_h ctx, yaca_ex_param_e param, + const void *value, size_t value_len); + int (*get_param)(const yaca_ctx_h ctx, yaca_ex_param_e param, + void **value, size_t *value_len); }; -- 2.7.4 From d167d69d481326aae3ab570605b236724800d199 Mon Sep 17 00:00:00 2001 From: Mateusz Kulikowski Date: Mon, 11 Apr 2016 15:52:33 +0200 Subject: [PATCH 13/16] yaca_ctx_free: Cause exception on missing destructor. ctx->ctx_destriy is mandatory for all contexts. Add assert to verify that. Change-Id: I1a1b5b5c7eb50eb5cea440ad74d410aeb2cdda59 Signed-off-by: Mateusz Kulikowski --- src/crypto.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/crypto.c b/src/crypto.c index a90d0d9..2ffb10c 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -116,6 +116,7 @@ API int yaca_ctx_get_param(const yaca_ctx_h ctx, yaca_ex_param_e param, API void yaca_ctx_free(yaca_ctx_h ctx) { if (ctx != YACA_CTX_NULL) { + assert(ctx->ctx_destroy != NULL); ctx->ctx_destroy(ctx); yaca_free(ctx); } -- 2.7.4 From 9b0e0ce18c07687c33f47a296c6cd8dc9f7098b5 Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Thu, 14 Apr 2016 16:52:58 +0200 Subject: [PATCH 14/16] Nullify destroyed pointer. Change-Id: I40384227010a733499b05bf6b587a1ec125505df --- src/digest.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/digest.c b/src/digest.c index 9c50748..2a5f01d 100644 --- a/src/digest.c +++ b/src/digest.c @@ -67,6 +67,7 @@ static void destroy_digest_context(yaca_ctx_h ctx) return; EVP_MD_CTX_destroy(c->mdctx); + c->mdctx = NULL; } int digest_get_algorithm(yaca_digest_algo_e algo, const EVP_MD **md) -- 2.7.4 From 28e28e9ea9ef82981c5da5d941e20e6c3ffc827d Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Mon, 18 Apr 2016 12:35:32 +0200 Subject: [PATCH 15/16] Split symmetric/asymmetric encryption Change-Id: Iab1755771de9cdb8d2b2902cf6b6a1adcb343ade --- api/yaca/encrypt.h | 112 --------------------------------- api/yaca/seal.h | 150 ++++++++++++++++++++++++++++++++++++++++++++ examples/CMakeLists.txt | 1 + examples/encrypt.c | 122 ------------------------------------ examples/seal.c | 162 ++++++++++++++++++++++++++++++++++++++++++++++++ src/encrypt.c | 52 ---------------- src/seal.c | 83 +++++++++++++++++++++++++ 7 files changed, 396 insertions(+), 286 deletions(-) create mode 100644 api/yaca/seal.h create mode 100644 examples/seal.c create mode 100644 src/seal.c diff --git a/api/yaca/encrypt.h b/api/yaca/encrypt.h index e94fb37..8c52fc9 100644 --- a/api/yaca/encrypt.h +++ b/api/yaca/encrypt.h @@ -135,118 +135,6 @@ int yaca_decrypt_final(yaca_ctx_h ctx, char *plain, size_t *plain_len); -/**@}*/ - -/** - * @defgroup Advanced-Encryption-Asymmetric Advanced API for the asymmetric encryption. - * - * TODO: extended description and examples. - * - * TODO: 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). - * Finally it encrypts symmetric key with public key. - * - * @{ - */ - -/** - * @brief yaca_seal_init Initializes an asymmetric encryption context. - * - * @param[out] ctx Newly created context (must be freed with @see yaca_ctx_free). - * @param[in] pub_key Public key of the peer that will receive the encrypted data. - * @param[in] algo Symmetric algorithm that will be used. - * @param[in] bcm Block chaining mode for the symmetric algorithm. - * @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. - * - * @return 0 on success, negative on error (@see error.h). - */ -int yaca_seal_init(yaca_ctx_h *ctx, - const yaca_key_h pub_key, - yaca_enc_algo_e algo, - yaca_block_cipher_mode_e bcm, - yaca_key_h *sym_key, - yaca_key_h *iv); - -/** - * @brief yaca_seal_update Encrypts piece of the data. - * - * @param[in,out] ctx Context created by @see yaca_seal_init. - * @param[in] plain Plain text to be encrypted. - * @param[in] plain_len Length of the plain text. - * @param[out] cipher Buffer for the encrypted data (must be allocated by client, @see yaca_get_output_length). - * @param[out] cipher_len Length of the encrypted data, actual number of bytes written will be returned here. - * - * @return 0 on success, negative on error (@see error.h). - */ -int yaca_seal_update(yaca_ctx_h ctx, - const char *plain, - size_t plain_len, - char *cipher, - size_t *cipher_len); - -/** - * @brief yaca_seal_final Encrypts the final piece of the data. - * - * @param[in,out] ctx A valid seal context. - * @param[out] cipher Final piece of the encrypted data (must be allocated by client, @see yaca_get_block_length). - * @param[out] cipher_len Length of the final piece, actual number of bytes written will be returned here. - * - * @return 0 on success, negative on error (@see error.h). - */ -int yaca_seal_final(yaca_ctx_h ctx, - char *cipher, - size_t *cipher_len); - -/** - * @brief yaca_open_init Initializes an asymmetric decryption context. - * - * @param[out] ctx Newly created context. Must be freed by @see yaca_ctx_free. - * @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. - * @param[in] bcm Block chaining mode for the symmetric algorithm. - * @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. - * - * @return 0 on success, negative on error (@see error.h). - */ -int yaca_open_init(yaca_ctx_h *ctx, - const yaca_key_h prv_key, - yaca_enc_algo_e algo, - yaca_block_cipher_mode_e bcm, - const yaca_key_h sym_key, - const yaca_key_h iv); - -/** - * @brief yaca_open_update Decrypts piece of the data. - * - * @param[in,out] ctx Context created by @see yaca_open_init. - * @param[in] cipher Cipher text to be decrypted. - * @param[in] cipher_len Length of the cipher text. - * @param[out] plain Buffer for the decrypted data (must be allocated by client, @see yaca_get_output_length). - * @param[out] plain_len Length of the decrypted data, actual number of bytes written will be returned here. - * - * @return 0 on success, negative on error (@see error.h). - */ -int yaca_open_update(yaca_ctx_h ctx, - const char *cipher, - size_t cipher_len, - char *plain, - size_t *plain_len); - -/** - * @brief yaca_open_final Decrypts last chunk of sealed message. - * - * @param[in,out] ctx A valid open context. - * @param[out] plain Final piece of the decrypted data (must be allocated by client, @see yaca_get_block_length). - * @param[out] plain_len Length of the final piece, actual number of bytes written will be returned here. - * - * @return 0 on success, negative on error (@see error.h). - */ -int yaca_open_final(yaca_ctx_h ctx, - char *plain, - size_t *plain_len); - /** * @brief yaca_get_iv_bits Returns the recomended/default length of the IV for a given encryption configuration. * diff --git a/api/yaca/seal.h b/api/yaca/seal.h new file mode 100644 index 0000000..aa1a10b --- /dev/null +++ b/api/yaca/seal.h @@ -0,0 +1,150 @@ +/* + * 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 seal.h + * @brief + */ + +#ifndef SEAL_H +#define SEAL_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup Advanced-Encryption-Asymmetric Advanced API for the asymmetric encryption. + * + * TODO: extended description and examples. + * + * TODO: 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). + * Finally it encrypts symmetric key with public key. + * + * @{ + */ + +/** + * @brief yaca_seal_init Initializes an asymmetric encryption context. + * + * @param[out] ctx Newly created context (must be freed with @see yaca_ctx_free). + * @param[in] pub_key Public key of the peer that will receive the encrypted data. + * @param[in] algo Symmetric algorithm that will be used. + * @param[in] bcm Block chaining mode for the symmetric algorithm. + * @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. + * + * @return 0 on success, negative on error (@see error.h). + */ +int yaca_seal_init(yaca_ctx_h *ctx, + const yaca_key_h pub_key, + yaca_enc_algo_e algo, + yaca_block_cipher_mode_e bcm, + yaca_key_h *sym_key, + yaca_key_h *iv); + +/** + * @brief yaca_seal_update Encrypts piece of the data. + * + * @param[in,out] ctx Context created by @see yaca_seal_init. + * @param[in] plain Plain text to be encrypted. + * @param[in] plain_len Length of the plain text. + * @param[out] cipher Buffer for the encrypted data (must be allocated by client, @see yaca_get_output_length). + * @param[out] cipher_len Length of the encrypted data, actual number of bytes written will be returned here. + * + * @return 0 on success, negative on error (@see error.h). + */ +int yaca_seal_update(yaca_ctx_h ctx, + const char *plain, + size_t plain_len, + char *cipher, + size_t *cipher_len); + +/** + * @brief yaca_seal_final Encrypts the final piece of the data. + * + * @param[in,out] ctx A valid seal context. + * @param[out] cipher Final piece of the encrypted data (must be allocated by client, @see yaca_get_block_length). + * @param[out] cipher_len Length of the final piece, actual number of bytes written will be returned here. + * + * @return 0 on success, negative on error (@see error.h). + */ +int yaca_seal_final(yaca_ctx_h ctx, + char *cipher, + size_t *cipher_len); + +/** + * @brief yaca_open_init Initializes an asymmetric decryption context. + * + * @param[out] ctx Newly created context. Must be freed by @see yaca_ctx_free. + * @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. + * @param[in] bcm Block chaining mode for the symmetric algorithm. + * @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. + * + * @return 0 on success, negative on error (@see error.h). + */ +int yaca_open_init(yaca_ctx_h *ctx, + const yaca_key_h prv_key, + yaca_enc_algo_e algo, + yaca_block_cipher_mode_e bcm, + const yaca_key_h sym_key, + const yaca_key_h iv); + +/** + * @brief yaca_open_update Decrypts piece of the data. + * + * @param[in,out] ctx Context created by @see yaca_open_init. + * @param[in] cipher Cipher text to be decrypted. + * @param[in] cipher_len Length of the cipher text. + * @param[out] plain Buffer for the decrypted data (must be allocated by client, @see yaca_get_output_length). + * @param[out] plain_len Length of the decrypted data, actual number of bytes written will be returned here. + * + * @return 0 on success, negative on error (@see error.h). + */ +int yaca_open_update(yaca_ctx_h ctx, + const char *cipher, + size_t cipher_len, + char *plain, + size_t *plain_len); + +/** + * @brief yaca_open_final Decrypts last chunk of sealed message. + * + * @param[in,out] ctx A valid open context. + * @param[out] plain Final piece of the decrypted data (must be allocated by client, @see yaca_get_block_length). + * @param[out] plain_len Length of the final piece, actual number of bytes written will be returned here. + * + * @return 0 on success, negative on error (@see error.h). + */ +int yaca_open_final(yaca_ctx_h ctx, + char *plain, + size_t *plain_len); + +/**@}*/ + +#ifdef __cplusplus +} /* extern */ +#endif + +#endif /* SEAL_H */ diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 6413bad..cda1c9c 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -51,6 +51,7 @@ ENDFUNCTION(BUILD_EXAMPLE) BUILD_EXAMPLE("yaca-example-digest" digest.c) BUILD_EXAMPLE("yaca-example-encrypt" encrypt.c) +BUILD_EXAMPLE("yaca-example-seal" seal.c) BUILD_EXAMPLE("yaca-example-encrypt-gcm" encrypt_aes_gcm.c) BUILD_EXAMPLE("yaca-example-sign" sign.c) BUILD_EXAMPLE("yaca-example-key-exchange" key_exchange.c) diff --git a/examples/encrypt.c b/examples/encrypt.c index f428713..eb8f3ce 100644 --- a/examples/encrypt.c +++ b/examples/encrypt.c @@ -228,126 +228,6 @@ ex_key: yaca_key_free(key); } -void encrypt_seal(void) -{ - int ret; - yaca_ctx_h ctx = YACA_CTX_NULL; - yaca_key_h key_pub = YACA_KEY_NULL; - yaca_key_h key_priv = YACA_KEY_NULL; - yaca_key_h aes_key = YACA_KEY_NULL; - yaca_key_h iv = YACA_KEY_NULL; - - char *enc = NULL; - char *dec = NULL; - size_t enc_size; - size_t dec_size; - - printf("Plain data (16 of %zu bytes): %.16s\n", (size_t)4096, lorem1024); - - /// Generate key pair - ret = yaca_key_gen_pair(&key_priv, &key_pub, - YACA_KEY_TYPE_PAIR_RSA, - YACA_KEY_2048BIT); - if (ret) return; - - /// Encrypt a.k.a. seal - { - size_t out_size; - size_t rem; - - ret = yaca_seal_init(&ctx, key_pub, - YACA_ENC_AES, YACA_BCM_CBC, - &aes_key, &iv); - if (ret < 0) - goto ex_pk; - - ret = yaca_seal_update(ctx, lorem4096, 4096, NULL, &enc_size); - if (ret < 0) - goto ex_ak; - - ret = yaca_get_block_length(ctx); - if (ret < 0) - goto ex_ak; - - enc_size = enc_size + ret; - enc = yaca_malloc(enc_size); - if (enc == NULL) - goto ex_ak; - - // Seal and finalize - out_size = enc_size; - ret = yaca_seal_update(ctx, lorem4096, 4096, enc, &out_size); - if (ret < 0) - goto ex_of; - - rem = enc_size - out_size; - ret = yaca_seal_final(ctx, enc + out_size, &rem); - if (ret < 0) - goto ex_of; - - enc_size = rem + out_size; - - dump_hex(enc, 16, "Encrypted data (16 of %zu bytes): ", enc_size); - - yaca_ctx_free(ctx); // TODO: perhaps it should not return value - } - - /// Decrypt a.k.a. open - { - size_t out_size; - size_t rem; - - ret = yaca_open_init(&ctx, key_priv, - YACA_ENC_AES, YACA_BCM_CBC, - aes_key, iv); - if (ret < 0) { - yaca_free(enc); - goto ex_ak; - } - - ret = yaca_open_update(ctx, enc, enc_size, NULL, &dec_size); - if (ret < 0) - goto ex_of; - - ret = yaca_get_block_length(ctx); - if (ret < 0) - goto ex_of; - - dec_size = dec_size + ret; - dec = yaca_malloc(dec_size); - if (dec == NULL) - goto ex_of; - - // Seal and finalize - out_size = enc_size; - ret = yaca_open_update(ctx, enc, enc_size, dec, &out_size); - if (ret < 0) - goto ex_in; - - rem = dec_size - out_size; - ret = yaca_open_final(ctx, dec + out_size, &rem); - if (ret < 0) - goto ex_in; - - dec_size = rem + out_size; - - printf("Decrypted data (16 of %zu bytes): %.16s\n", (size_t)dec_size, dec); - - yaca_ctx_free(ctx); // TODO: perhaps it should not return value - } - -ex_in: - yaca_free(dec); -ex_of: - yaca_free(enc); -ex_ak: - yaca_key_free(aes_key); - yaca_key_free(iv); -ex_pk: - yaca_key_free(key_pub); - yaca_key_free(key_priv); -} - int main() { int ret = yaca_init(); @@ -358,8 +238,6 @@ int main() encrypt_advanced(); - encrypt_seal(); - yaca_exit(); // TODO: what about handing of return value from exit?? return ret; } diff --git a/examples/seal.c b/examples/seal.c new file mode 100644 index 0000000..a96dfd0 --- /dev/null +++ b/examples/seal.c @@ -0,0 +1,162 @@ +/* + * 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 seal.c + * @brief + */ + +#include + +#include +#include +#include +#include "lorem.h" +#include "misc.h" + +void encrypt_seal(void) +{ + int ret; + yaca_ctx_h ctx = YACA_CTX_NULL; + yaca_key_h key_pub = YACA_KEY_NULL; + yaca_key_h key_priv = YACA_KEY_NULL; + yaca_key_h aes_key = YACA_KEY_NULL; + yaca_key_h iv = YACA_KEY_NULL; + + char *enc = NULL; + char *dec = NULL; + size_t enc_size; + size_t dec_size; + + printf("Plain data (16 of %zu bytes): %.16s\n", (size_t)4096, lorem1024); + + /// Generate key pair + ret = yaca_key_gen_pair(&key_priv, &key_pub, + YACA_KEY_TYPE_PAIR_RSA, + YACA_KEY_2048BIT); + if (ret) return; + + /// Encrypt a.k.a. seal + { + size_t out_size; + size_t rem; + + ret = yaca_seal_init(&ctx, key_pub, + YACA_ENC_AES, YACA_BCM_CBC, + &aes_key, &iv); + if (ret < 0) + goto ex_pk; + + ret = yaca_seal_update(ctx, lorem4096, 4096, NULL, &enc_size); + if (ret < 0) + goto ex_ak; + + ret = yaca_get_block_length(ctx); + if (ret < 0) + goto ex_ak; + + enc_size = enc_size + ret; + enc = yaca_malloc(enc_size); + if (enc == NULL) + goto ex_ak; + + // Seal and finalize + out_size = enc_size; + ret = yaca_seal_update(ctx, lorem4096, 4096, enc, &out_size); + if (ret < 0) + goto ex_of; + + rem = enc_size - out_size; + ret = yaca_seal_final(ctx, enc + out_size, &rem); + if (ret < 0) + goto ex_of; + + enc_size = rem + out_size; + + dump_hex(enc, 16, "Encrypted data (16 of %zu bytes): ", enc_size); + + yaca_ctx_free(ctx); // TODO: perhaps it should not return value + } + + /// Decrypt a.k.a. open + { + size_t out_size; + size_t rem; + + ret = yaca_open_init(&ctx, key_priv, + YACA_ENC_AES, YACA_BCM_CBC, + aes_key, iv); + if (ret < 0) { + yaca_free(enc); + goto ex_ak; + } + + ret = yaca_open_update(ctx, enc, enc_size, NULL, &dec_size); + if (ret < 0) + goto ex_of; + + ret = yaca_get_block_length(ctx); + if (ret < 0) + goto ex_of; + + dec_size = dec_size + ret; + dec = yaca_malloc(dec_size); + if (dec == NULL) + goto ex_of; + + // Seal and finalize + out_size = enc_size; + ret = yaca_open_update(ctx, enc, enc_size, dec, &out_size); + if (ret < 0) + goto ex_in; + + rem = dec_size - out_size; + ret = yaca_open_final(ctx, dec + out_size, &rem); + if (ret < 0) + goto ex_in; + + dec_size = rem + out_size; + + printf("Decrypted data (16 of %zu bytes): %.16s\n", (size_t)dec_size, dec); + + yaca_ctx_free(ctx); // TODO: perhaps it should not return value + } + +ex_in: + yaca_free(dec); +ex_of: + yaca_free(enc); +ex_ak: + yaca_key_free(aes_key); + yaca_key_free(iv); +ex_pk: + yaca_key_free(key_pub); + yaca_key_free(key_priv); +} + +int main() +{ + int ret = yaca_init(); + if (ret < 0) + return ret; + + encrypt_seal(); + + yaca_exit(); // TODO: what about handing of return value from exit?? + return ret; +} diff --git a/src/encrypt.c b/src/encrypt.c index 24e9117..5aeecf7 100644 --- a/src/encrypt.c +++ b/src/encrypt.c @@ -399,55 +399,3 @@ API int yaca_decrypt_final(yaca_ctx_h ctx, return encrypt_final(ctx,(unsigned char*)plain, plain_len, OP_DECRYPT); } - -API int yaca_seal_init(yaca_ctx_h *ctx, - const yaca_key_h pub_key, - yaca_enc_algo_e algo, - yaca_block_cipher_mode_e bcm, - yaca_key_h *sym_key, - yaca_key_h *iv) -{ - return YACA_ERROR_NOT_IMPLEMENTED; -} - -API int yaca_seal_update(yaca_ctx_h ctx, - const char *plain, - size_t plain_len, - char *cipher, - size_t *cipher_len) -{ - return YACA_ERROR_NOT_IMPLEMENTED; -} - -API int yaca_seal_final(yaca_ctx_h ctx, - char *cipher, - size_t *cipher_len) -{ - return YACA_ERROR_NOT_IMPLEMENTED; -} - -API int yaca_open_init(yaca_ctx_h *ctx, - const yaca_key_h prv_key, - yaca_enc_algo_e algo, - yaca_block_cipher_mode_e bcm, - const yaca_key_h sym_key, - const yaca_key_h iv) -{ - return YACA_ERROR_NOT_IMPLEMENTED; -} - -API int yaca_open_update(yaca_ctx_h ctx, - const char *cipher, - size_t cipher_len, - char *plain, - size_t *plain_len) -{ - return YACA_ERROR_NOT_IMPLEMENTED; -} - -API int yaca_open_final(yaca_ctx_h ctx, - char *plain, - size_t *plain_len) -{ - return YACA_ERROR_NOT_IMPLEMENTED; -} diff --git a/src/seal.c b/src/seal.c new file mode 100644 index 0000000..fb5b50e --- /dev/null +++ b/src/seal.c @@ -0,0 +1,83 @@ +/* + * 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 + */ + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include "internal.h" + +API int yaca_seal_init(yaca_ctx_h *ctx, + const yaca_key_h pub_key, + yaca_enc_algo_e algo, + yaca_block_cipher_mode_e bcm, + yaca_key_h *sym_key, + yaca_key_h *iv) +{ + return YACA_ERROR_NOT_IMPLEMENTED; +} + +API int yaca_seal_update(yaca_ctx_h ctx, + const char *plain, + size_t plain_len, + char *cipher, + size_t *cipher_len) +{ + return YACA_ERROR_NOT_IMPLEMENTED; +} + +API int yaca_seal_final(yaca_ctx_h ctx, + char *cipher, + size_t *cipher_len) +{ + return YACA_ERROR_NOT_IMPLEMENTED; +} + +API int yaca_open_init(yaca_ctx_h *ctx, + const yaca_key_h prv_key, + yaca_enc_algo_e algo, + yaca_block_cipher_mode_e bcm, + const yaca_key_h sym_key, + const yaca_key_h iv) +{ + return YACA_ERROR_NOT_IMPLEMENTED; +} + +API int yaca_open_update(yaca_ctx_h ctx, + const char *cipher, + size_t cipher_len, + char *plain, + size_t *plain_len) +{ + return YACA_ERROR_NOT_IMPLEMENTED; +} + +API int yaca_open_final(yaca_ctx_h ctx, + char *plain, + size_t *plain_len) +{ + return YACA_ERROR_NOT_IMPLEMENTED; +} -- 2.7.4 From 7e63a71279fe8fcdc74e66c7ca17c1056d610e15 Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Mon, 18 Apr 2016 16:56:42 +0200 Subject: [PATCH 16/16] yaca_seal_init() needs key length to generate EVP_CIPHER Change-Id: I65f40910983d5d8928174807dbdc7c622eee70d8 --- api/yaca/seal.h | 14 ++++++++------ examples/seal.c | 2 +- src/seal.c | 1 + 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/api/yaca/seal.h b/api/yaca/seal.h index aa1a10b..a080247 100644 --- a/api/yaca/seal.h +++ b/api/yaca/seal.h @@ -46,12 +46,13 @@ extern "C" { /** * @brief yaca_seal_init Initializes an asymmetric encryption context. * - * @param[out] ctx Newly created context (must be freed with @see yaca_ctx_free). - * @param[in] pub_key Public key of the peer that will receive the encrypted data. - * @param[in] algo Symmetric algorithm that will be used. - * @param[in] bcm Block chaining mode for the symmetric algorithm. - * @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] ctx Newly created context (must be freed with @see yaca_ctx_free). + * @param[in] pub_key Public key of the peer that will receive the encrypted data. + * @param[in] algo Symmetric algorithm that will be used. + * @param[in] bcm Block chaining mode for the symmetric algorithm. + * @param[in] sym_key_bits 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. * * @return 0 on success, negative on error (@see error.h). */ @@ -59,6 +60,7 @@ int yaca_seal_init(yaca_ctx_h *ctx, const yaca_key_h pub_key, yaca_enc_algo_e algo, yaca_block_cipher_mode_e bcm, + yaca_key_bits_e sym_key_bits, yaca_key_h *sym_key, yaca_key_h *iv); diff --git a/examples/seal.c b/examples/seal.c index a96dfd0..e2377a1 100644 --- a/examples/seal.c +++ b/examples/seal.c @@ -57,7 +57,7 @@ void encrypt_seal(void) size_t rem; ret = yaca_seal_init(&ctx, key_pub, - YACA_ENC_AES, YACA_BCM_CBC, + YACA_ENC_AES, YACA_BCM_CBC, YACA_KEY_192BIT, &aes_key, &iv); if (ret < 0) goto ex_pk; diff --git a/src/seal.c b/src/seal.c index fb5b50e..7b9308a 100644 --- a/src/seal.c +++ b/src/seal.c @@ -34,6 +34,7 @@ API int yaca_seal_init(yaca_ctx_h *ctx, const yaca_key_h pub_key, yaca_enc_algo_e algo, yaca_block_cipher_mode_e bcm, + yaca_key_bits_e sym_key_bits, yaca_key_h *sym_key, yaca_key_h *iv) { -- 2.7.4