From d79b648a81a8ea217105f20d3ba2bc106a2d4abc Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Wed, 8 Jun 2016 11:05:59 +0200 Subject: [PATCH 01/16] Use C89 style for comments. Minor codestyle and comments cleanup. Change-Id: I014b52d96ddc10ba9186ac0bd692b112ba10aefe --- examples/key_exchange.c | 15 ++++++++------- examples/misc.h | 9 +-------- examples/sign.c | 46 +++++++++++++++++++++++----------------------- src/digest.c | 2 +- src/encrypt.c | 2 +- src/key.c | 2 +- src/sign.c | 4 ++-- 7 files changed, 37 insertions(+), 43 deletions(-) diff --git a/examples/key_exchange.c b/examples/key_exchange.c index 4f93eff..eb9beae 100644 --- a/examples/key_exchange.c +++ b/examples/key_exchange.c @@ -45,7 +45,7 @@ void key_exchange_dh(void) char *buffer = NULL; long size; - // generate private, public key + /* generate private, public key */ ret = yaca_key_generate(YACA_KEY_TYPE_DH_PRIV, YACA_KEY_LENGTH_2048BIT, &private_key); if (ret != YACA_ERROR_NONE) goto exit; @@ -54,8 +54,8 @@ void key_exchange_dh(void) if (ret != YACA_ERROR_NONE) goto exit; - // get peer public key from file - // add helper to read key from file to buffer? + /* get peer public key */ + // TODO: read key from file to buffer can be replaced with read_file() from misc.h fp = fopen("key.pub", "r"); if (!fp) goto exit; @@ -76,7 +76,7 @@ void key_exchange_dh(void) if (ret != YACA_ERROR_NONE) goto exit; - // derive secret + /* derive secret */ ret = yaca_key_derive_dh(private_key, peer_key, &secret); if (ret != YACA_ERROR_NONE) goto exit; @@ -107,7 +107,7 @@ void key_exchange_ecdh(void) char *buffer = NULL; long size; - // generate private, public key + /* generate private, public key */ ret = yaca_key_generate(YACA_KEY_TYPE_EC_PRIV, YACA_KEY_CURVE_P256, &private_key); if (ret != YACA_ERROR_NONE) goto exit; @@ -116,7 +116,8 @@ void key_exchange_ecdh(void) if (ret != YACA_ERROR_NONE) goto exit; - // get peer public key from file + /* get peer public key */ + // TODO: read key from file to buffer can be replaced with read_file() from misc.h fp = fopen("key.pub", "r"); if (fp == NULL) goto exit; @@ -137,7 +138,7 @@ void key_exchange_ecdh(void) if (ret != YACA_ERROR_NONE) goto exit; - // derive secret + /* derive secret */ ret = yaca_key_derive_dh(private_key, peer_key, &secret); if (ret != YACA_ERROR_NONE) goto exit; diff --git a/examples/misc.h b/examples/misc.h index b2e1cbd..843aba2 100644 --- a/examples/misc.h +++ b/examples/misc.h @@ -26,14 +26,7 @@ #include -// Various helper functions - - -// Dumps dump_size of buf. -// As a "heading" displays fmt message (formatted like printf) -void dump_hex(const char *buf, - size_t dump_size, - const char *fmt, ...); +void dump_hex(const char *buf, size_t dump_size, const char *fmt, ...); void debug_func(const char *buf); diff --git a/examples/sign.c b/examples/sign.c index 60057b4..a3d88ff 100644 --- a/examples/sign.c +++ b/examples/sign.c @@ -33,7 +33,7 @@ #include "misc.h" #include "../src/debug.h" -// Signature creation and verification using simple API +/* Signature creation and verification using simple API */ void simple_sign_verify_asym(yaca_key_type_e type, const char *algo) { char *signature = NULL; @@ -42,14 +42,14 @@ void simple_sign_verify_asym(yaca_key_type_e type, const char *algo) yaca_key_h prv = YACA_KEY_NULL; yaca_key_h pub = YACA_KEY_NULL; - // GENERATE + /* GENERATE */ if (yaca_key_generate(type, YACA_KEY_LENGTH_1024BIT, &prv) != YACA_ERROR_NONE) return; if (yaca_key_extract_public(prv, &pub) != YACA_ERROR_NONE) goto exit; - // SIGN + /* SIGN */ if (yaca_simple_calculate_signature(YACA_DIGEST_SHA512, prv, lorem4096, @@ -60,7 +60,7 @@ void simple_sign_verify_asym(yaca_key_type_e type, const char *algo) dump_hex(signature, signature_len, "[Simple API] %s Signature of lorem4096:", algo); - // VERIFY + /* VERIFY */ if (yaca_simple_verify_signature(YACA_DIGEST_SHA512, pub, lorem4096, @@ -85,11 +85,11 @@ void simple_sign_verify_hmac(void) yaca_key_h key = YACA_KEY_NULL; - // GENERATE + /* GENERATE */ if (yaca_key_generate(YACA_KEY_TYPE_SYMMETRIC, YACA_KEY_LENGTH_256BIT, &key) != YACA_ERROR_NONE) return; - // SIGN + /* SIGN */ if (yaca_simple_calculate_hmac(YACA_DIGEST_SHA512, key, lorem4096, @@ -100,7 +100,7 @@ void simple_sign_verify_hmac(void) dump_hex(signature1, signature_len, "[Simple API] HMAC Signature of lorem4096:"); - // VERIFY + /* VERIFY */ if (yaca_simple_calculate_hmac(YACA_DIGEST_SHA512, key, lorem4096, @@ -128,11 +128,11 @@ void simple_sign_verify_cmac(void) yaca_key_h key = YACA_KEY_NULL; - // GENERATE + /* GENERATE */ if (yaca_key_generate(YACA_KEY_TYPE_SYMMETRIC, YACA_KEY_LENGTH_256BIT, &key)) return; - // SIGN + /* SIGN */ if (yaca_simple_calculate_cmac(YACA_ENCRYPT_AES, key, lorem4096, @@ -144,7 +144,7 @@ void simple_sign_verify_cmac(void) dump_hex(signature1, signature_len, "[Simple API] CMAC Signature of lorem4096:"); - // VERIFY + /* VERIFY */ if (yaca_simple_calculate_cmac(YACA_ENCRYPT_AES, key, lorem4096, @@ -164,7 +164,7 @@ exit: yaca_key_destroy(key); } -// Signature creation and verification using advanced API +/* Signature creation and verification using advanced API */ void sign_verify_asym(yaca_key_type_e type, const char *algo) { char *signature = NULL; @@ -175,14 +175,14 @@ void sign_verify_asym(yaca_key_type_e type, const char *algo) yaca_key_h pub = YACA_KEY_NULL; yaca_padding_e padding = YACA_PADDING_PKCS1_PSS; - // GENERATE + /* GENERATE */ if (yaca_key_generate(type, YACA_KEY_LENGTH_1024BIT, &prv) != YACA_ERROR_NONE) return; if (yaca_key_extract_public(prv, &pub) != YACA_ERROR_NONE) goto exit; - // SIGN + /* SIGN */ if (yaca_sign_initialize(&ctx, YACA_DIGEST_SHA512, prv) != YACA_ERROR_NONE) goto exit; @@ -203,11 +203,11 @@ void sign_verify_asym(yaca_key_type_e type, const char *algo) dump_hex(signature, signature_len, "[Advanced API] %s Signature of lorem4096:", algo); - // CLEANUP + /* CLEANUP */ yaca_context_destroy(ctx); ctx = YACA_CONTEXT_NULL; - // VERIFY + /* VERIFY */ if (yaca_verify_initialize(&ctx, YACA_DIGEST_SHA512, pub) != YACA_ERROR_NONE) goto exit; @@ -238,11 +238,11 @@ void sign_verify_hmac(void) yaca_context_h ctx = YACA_CONTEXT_NULL; yaca_key_h key = YACA_KEY_NULL; - // GENERATE + /* GENERATE */ if (yaca_key_generate(YACA_KEY_TYPE_SYMMETRIC, YACA_KEY_LENGTH_256BIT, &key) != YACA_ERROR_NONE) return; - // SIGN + /* SIGN */ if (yaca_sign_initialize_hmac(&ctx, YACA_DIGEST_SHA512, key) != YACA_ERROR_NONE) goto exit; @@ -260,11 +260,11 @@ void sign_verify_hmac(void) dump_hex(signature1, signature_len, "[Advanced API] HMAC Signature of lorem4096:"); - // CLEANUP + /* CLEANUP */ yaca_context_destroy(ctx); ctx = YACA_CONTEXT_NULL; - // VERIFY + /* VERIFY */ if (yaca_sign_initialize_hmac(&ctx, YACA_DIGEST_SHA512, key) != YACA_ERROR_NONE) goto exit; @@ -301,11 +301,11 @@ void sign_verify_cmac(void) yaca_context_h ctx = YACA_CONTEXT_NULL; yaca_key_h key = YACA_KEY_NULL; - // GENERATE + /* GENERATE */ if (yaca_key_generate(YACA_KEY_TYPE_SYMMETRIC, YACA_KEY_LENGTH_256BIT, &key)) return; - // SIGN + /* SIGN */ if (yaca_sign_initialize_cmac(&ctx, YACA_ENCRYPT_AES, key) != YACA_ERROR_NONE) goto exit; @@ -323,11 +323,11 @@ void sign_verify_cmac(void) dump_hex(signature1, signature_len, "[Advanced API] CMAC Signature of lorem4096:"); - // CLEANUP + /* CLEANUP */ yaca_context_destroy(ctx); ctx = YACA_CONTEXT_NULL; - // VERIFY + /* VERIFY */ if (yaca_sign_initialize_cmac(&ctx, YACA_ENCRYPT_AES, key) != YACA_ERROR_NONE) goto exit; diff --git a/src/digest.c b/src/digest.c index d5d7278..0191e96 100644 --- a/src/digest.c +++ b/src/digest.c @@ -190,7 +190,7 @@ API int yaca_digest_finalize(yaca_context_h ctx, char *digest, size_t *digest_le if (c == NULL || digest == NULL || digest_len == NULL) return YACA_ERROR_INVALID_PARAMETER; - if (*digest_len == 0 || *digest_len > UINT_MAX) // DigestFinal accepts uint + if (*digest_len == 0 || *digest_len > UINT_MAX) /* DigestFinal accepts UINT */ return YACA_ERROR_INVALID_PARAMETER; ret = EVP_DigestFinal_ex(c->mdctx, (unsigned char*)digest, &len); diff --git a/src/encrypt.c b/src/encrypt.c index 324e829..a53a442 100644 --- a/src/encrypt.c +++ b/src/encrypt.c @@ -291,7 +291,7 @@ int encrypt_get_algorithm(yaca_encrypt_algorithm_e algo, if (ret < 0) return YACA_ERROR_INVALID_PARAMETER; - if ((unsigned)ret >= sizeof(cipher_name)) // output was truncated + if ((unsigned)ret >= sizeof(cipher_name)) /* output was truncated */ return YACA_ERROR_INVALID_PARAMETER; lcipher = EVP_get_cipherbyname(cipher_name); diff --git a/src/key.c b/src/key.c index 2ba9b9e..8f02b3c 100644 --- a/src/key.c +++ b/src/key.c @@ -846,7 +846,7 @@ int gen_evp_dsa(struct yaca_key_evp_s **out, size_t key_bits) /* Openssl generates 512-bit key for key lengths smaller than 512. It also * rounds key size to multiplication of 64. */ - if(key_bits < 512 || key_bits % 64 != 0) + if (key_bits < 512 || key_bits % 64 != 0) return YACA_ERROR_INVALID_PARAMETER; int ret; diff --git a/src/sign.c b/src/sign.c index 9da9385..afaaec0 100644 --- a/src/sign.c +++ b/src/sign.c @@ -386,7 +386,7 @@ API int yaca_sign_initialize_cmac(yaca_context_h *ctx, if (ret != YACA_ERROR_NONE) goto exit; - // create and initialize low level CMAC context + /* create and initialize low level CMAC context */ cmac_ctx = CMAC_CTX_new(); if (cmac_ctx == NULL) { ret = YACA_ERROR_INTERNAL; @@ -400,7 +400,7 @@ API int yaca_sign_initialize_cmac(yaca_context_h *ctx, goto exit; } - // create key and assign CMAC context to it + /* create key and assign CMAC context to it */ pkey = EVP_PKEY_new(); if (pkey == NULL) { ret = YACA_ERROR_INTERNAL; -- 2.7.4 From 0067abaaf14e845e491b0b5a9d9f57820a4e52cd Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Wed, 8 Jun 2016 11:18:18 +0200 Subject: [PATCH 02/16] Remove no-unused-parameter compilation flag. Fix some errors. Change-Id: Ic091bff6f4936608cfb6d9a32b20e93fc59849b8 --- CMakeLists.txt | 2 -- examples/key_password.c | 2 +- src/crypto.c | 2 +- src/digest.c | 4 +++- src/internal.h | 1 + src/key.c | 2 +- src/sign.c | 2 +- 7 files changed, 8 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e2b5e35..7b9cb1b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,8 +59,6 @@ ADD_DEFINITIONS("-fPIC") # Position Independent Code ADD_DEFINITIONS("-Werror") # Make all warnings into errors ADD_DEFINITIONS("-Wall") # Generate all warnings ADD_DEFINITIONS("-Wextra") # Generate even more extra warnings -# TODO Remove 'no-unused-parameter' after API implementation -ADD_DEFINITIONS("-Wno-unused-parameter") # Supress unused parameter warning ADD_DEFINITIONS("-pedantic") # Be pedantic ADD_DEFINITIONS("-pedantic-errors") # Make pedantic warnings into errors ADD_DEFINITIONS(-DPROJECT_SOURCE_DIR="${PROJECT_SOURCE_DIR}") diff --git a/examples/key_password.c b/examples/key_password.c index 829797c..ef40fa2 100644 --- a/examples/key_password.c +++ b/examples/key_password.c @@ -76,7 +76,7 @@ exit: yaca_key_destroy(lkey); } -int main(int argc, char *argv[]) +int main() { int ret; yaca_key_h key = YACA_KEY_NULL; diff --git a/src/crypto.c b/src/crypto.c index 99fa1db..fc48c9e 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -37,7 +37,7 @@ static pthread_mutex_t *mutexes = NULL; -static void locking_callback(int mode, int type, const char *file, int line) +static void locking_callback(int mode, int type, UNUSED const char *file, UNUSED int line) { /* Ignore NULL mutexes and lock/unlock error codes as we can't do anything * about them. */ diff --git a/src/digest.c b/src/digest.c index 0191e96..235a0a2 100644 --- a/src/digest.c +++ b/src/digest.c @@ -50,7 +50,9 @@ static struct yaca_digest_ctx_s *get_digest_ctx(const yaca_context_h ctx) } } -static int get_digest_output_length(const yaca_context_h ctx, size_t input_len, size_t *output_len) +static int get_digest_output_length(const yaca_context_h ctx, + UNUSED size_t input_len, + size_t *output_len) { struct yaca_digest_ctx_s *c = get_digest_ctx(ctx); diff --git a/src/internal.h b/src/internal.h index d9cea2e..62aa8fd 100644 --- a/src/internal.h +++ b/src/internal.h @@ -32,6 +32,7 @@ #include #define API __attribute__ ((visibility("default"))) +#define UNUSED __attribute__((unused)) enum yaca_ctx_type_e { YACA_CTX_INVALID = 0, diff --git a/src/key.c b/src/key.c index 8f02b3c..7abd5ff 100644 --- a/src/key.c +++ b/src/key.c @@ -42,7 +42,7 @@ /* This callback only exists to block the default OpenSSL one and * allow us to check for a proper error code when the key is encrypted */ -int password_dummy_cb(char *buf, int size, int rwflag, void *u) +int password_dummy_cb(char *buf, UNUSED int size, UNUSED int rwflag, UNUSED void *u) { const char empty[] = ""; diff --git a/src/sign.c b/src/sign.c index afaaec0..7be2005 100644 --- a/src/sign.c +++ b/src/sign.c @@ -64,7 +64,7 @@ static struct yaca_sign_ctx_s *get_sign_ctx(const yaca_context_h ctx) } static int get_sign_output_length(const yaca_context_h ctx, - size_t input_len, + UNUSED size_t input_len, size_t *output_len) { struct yaca_sign_ctx_s *c = get_sign_ctx(ctx); -- 2.7.4 From d3e4c7fe363f7344c2c9494a23a04880562bc11d Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Wed, 8 Jun 2016 11:58:03 +0200 Subject: [PATCH 03/16] Update readme.txt after API changes. Change-Id: Icc18e8370c02e8d9aba507924b4f39bf45dad7f7 --- readme.txt | 40 ++++++++++++++++++---------------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/readme.txt b/readme.txt index b0fe7f2..664632f 100644 --- a/readme.txt +++ b/readme.txt @@ -2,39 +2,35 @@ YACA - Yet Another Crypto API Basic information: -Code Style (for now): - Tabs (8-chars) + spaces; - $ astyle -T8 +Code Style: + Tizen coding style (doc/coding-rules.txt) Project structure: - api/ - Public API (headers) - - demos/ - Demo applications - doc/ - Documentation - examples/ - Usage examples - - src/ - source - - test/ - tests + api/yaca/ - Public API (headers) + doc/ - Documentation + examples/ - Usage examples + packaging/ - RPM spec file + src/ - Source General design: - All memory allocated by API should be freed with yaca_free() - - Contexts and keys should be freed with yaca_ctx_free()/yaca_key_free() - - Function names: yaca__; Ex: yaca_verify_init() - - Simplified/Simple functions don't have part - - Enums: YACA__; Ex: YACA_KEY_256BIT + - Contexts and keys should be freed with yaca_context_destroy()/yaca_key_destroy() + - Function names: yaca__; Ex: yaca_verify_initialize() + - Simplified/Simple functions don't have part, but have prefix + - Enums: YACA__; Ex: YACA_KEY_LENGTH_256BIT - Objects (context, key) end with _h - - Most functions return 0 on success, negative values on error + - Functions returns YACA_ERROR_NONE on success, negative values on error Simplified API: - - Is located in simple.h - - Currently, to use it - some functions from crypto.h and key.h are needed - - Symmetric ciphers (except for GCM) and message digests are only operations that are supported + - Is located in yaca_simple.h + - Currently, to use it - some functions from yaca_crypto.h and yaca_key.h are needed + - Symmetric ciphers (except for GCM and CCM), + message digests and signatures are only operations that are supported - All operations are single-shot and output is allocated by library API: - 1) All contexts are created by appropriate init() functions - 2) Keys are created by generate or import functions + - All contexts are created by appropriate _initialize() functions + - Keys are created by generate or import functions Examples: - It is possible to compile-check examples with "make" command -- 2.7.4 From b2091efc9c1b7b88993171c4b11baf8974b91990 Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Wed, 8 Jun 2016 13:03:39 +0200 Subject: [PATCH 04/16] ACR: Seal/open sym_key_bits parameter should be size_t. Change-Id: I18de46fcd5991cc0e18f8e292c3d95e72c3a611c --- api/yaca/yaca_seal.h | 6 ++++-- src/seal.c | 8 ++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/api/yaca/yaca_seal.h b/api/yaca/yaca_seal.h index f6e3df7..784a494 100644 --- a/api/yaca/yaca_seal.h +++ b/api/yaca/yaca_seal.h @@ -68,6 +68,7 @@ extern "C" { * * @see #yaca_encrypt_algorithm_e * @see #yaca_block_cipher_mode_e + * @see #yaca_key_bit_length_e * @see yaca_seal_update() * @see yaca_seal_finalize() * @see yaca_key_destroy() @@ -77,7 +78,7 @@ 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, - yaca_key_bit_length_e sym_key_bit_len, + size_t sym_key_bit_len, yaca_key_h *sym_key, yaca_key_h *iv); @@ -158,6 +159,7 @@ int yaca_seal_finalize(yaca_context_h ctx, * * @see #yaca_encrypt_algorithm_e * @see #yaca_block_cipher_mode_e + * @see #yaca_key_bit_length_e * @see yaca_open_update() * @see yaca_open_finalize() * @see yaca_context_destroy() @@ -166,7 +168,7 @@ 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, - yaca_key_bit_length_e sym_key_bit_len, + size_t sym_key_bit_len, const yaca_key_h sym_key, const yaca_key_h iv); diff --git a/src/seal.c b/src/seal.c index 0859e14..50b977d 100644 --- a/src/seal.c +++ b/src/seal.c @@ -100,7 +100,7 @@ static int seal_init(yaca_context_h *ctx, const yaca_key_h pub_key, yaca_encrypt_algorithm_e algo, yaca_block_cipher_mode_e bcm, - yaca_key_bit_length_e sym_key_bits, + size_t sym_key_bits, yaca_key_h *sym_key, yaca_key_h *iv) { @@ -215,7 +215,7 @@ static int open_init(yaca_context_h *ctx, const yaca_key_h prv_key, yaca_encrypt_algorithm_e algo, yaca_block_cipher_mode_e bcm, - yaca_key_bit_length_e sym_key_bits, + size_t sym_key_bits, const yaca_key_h sym_key, const yaca_key_h iv) { @@ -383,7 +383,7 @@ 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, - yaca_key_bit_length_e sym_key_bit_len, + size_t sym_key_bit_len, yaca_key_h *sym_key, yaca_key_h *iv) { @@ -418,7 +418,7 @@ 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, - yaca_key_bit_length_e sym_key_bit_len, + size_t sym_key_bit_len, const yaca_key_h sym_key, const yaca_key_h iv) { -- 2.7.4 From a491b32a3af598bee5edefbfce7dc08cd9d6aa39 Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Wed, 8 Jun 2016 18:02:22 +0200 Subject: [PATCH 05/16] Check for known errors first Known errors can be marked as fatal at the same time, but we still want to know a specific error code in such case. Check for them first. If they are not specific, only then check for generic fatal codes. Change-Id: I16ddcb201fdbb91daf1ef61590d949d7be847927 --- src/debug.c | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/src/debug.c b/src/debug.c index 306f7cd..3223da1 100644 --- a/src/debug.c +++ b/src/debug.c @@ -114,11 +114,26 @@ void error_dump(const char *file, int line, const char *function, int code) int error_handle(const char *file, int line, const char *function) { - int ret; + int ret = YACA_ERROR_NONE; unsigned long err = ERR_peek_error(); + if (err == 0) + return YACA_ERROR_INTERNAL; + + /* known errors */ + switch (err) { + case ERR_PACK(ERR_LIB_RSA, RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_KEYBITS): + case ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_COMMAND_NOT_SUPPORTED): + ret = YACA_ERROR_INVALID_PARAMETER; + break; + case ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_DO_HEADER, PEM_R_BAD_DECRYPT): + case ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_DECRYPTFINAL_EX, EVP_R_BAD_DECRYPT): + ret = YACA_ERROR_INVALID_PASSWORD; + break; + } + /* fatal errors */ - if (ERR_FATAL_ERROR(err) > 0) { + if (ret == YACA_ERROR_NONE && ERR_FATAL_ERROR(err) > 0) { switch (ERR_GET_REASON(err)) { case ERR_R_MALLOC_FAILURE: ret = YACA_ERROR_OUT_OF_MEMORY; @@ -129,27 +144,17 @@ int error_handle(const char *file, int line, const char *function) break; case ERR_R_INTERNAL_ERROR: case ERR_R_DISABLED: - default: ret = YACA_ERROR_INTERNAL; - } - } - /* known errors */ - else { - switch (err) { - case ERR_PACK(ERR_LIB_RSA, RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_KEYBITS): - case ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_COMMAND_NOT_SUPPORTED): - ret = YACA_ERROR_INVALID_PARAMETER; - break; - case ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_DO_HEADER, PEM_R_BAD_DECRYPT): - case ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_DECRYPTFINAL_EX, EVP_R_BAD_DECRYPT): - ret = YACA_ERROR_INVALID_PASSWORD; break; - default: - error_dump(file, line, function, YACA_ERROR_INTERNAL); - ret = YACA_ERROR_INTERNAL; } } + /* neither known nor fatal, unknown */ + if (ret == YACA_ERROR_NONE) { + error_dump(file, line, function, YACA_ERROR_INTERNAL); + ret = YACA_ERROR_INTERNAL; + } + /* remove all errors from queue */ ERR_clear_error(); return ret; -- 2.7.4 From 7728bb8e070f6b39e4c9e644d32d00f39a4254dd Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Wed, 8 Jun 2016 18:03:32 +0200 Subject: [PATCH 06/16] Use ERROR_HANDLE() to check for invalid passwords Change-Id: I3d0449474e5b9240dedb7fe784a507541e705c2a --- src/debug.c | 4 +++- src/key.c | 28 ++++++---------------------- 2 files changed, 9 insertions(+), 23 deletions(-) diff --git a/src/debug.c b/src/debug.c index 3223da1..2f277d0 100644 --- a/src/debug.c +++ b/src/debug.c @@ -124,10 +124,12 @@ int error_handle(const char *file, int line, const char *function) switch (err) { case ERR_PACK(ERR_LIB_RSA, RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_KEYBITS): case ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_COMMAND_NOT_SUPPORTED): + case ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_READ_BIO, PEM_R_NO_START_LINE): + case ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_CHECK_TLEN, ASN1_R_WRONG_TAG): ret = YACA_ERROR_INVALID_PARAMETER; break; - case ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_DO_HEADER, PEM_R_BAD_DECRYPT): case ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_DECRYPTFINAL_EX, EVP_R_BAD_DECRYPT): + case ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_DO_HEADER, PEM_R_BAD_DECRYPT): ret = YACA_ERROR_INVALID_PASSWORD; break; } diff --git a/src/key.c b/src/key.c index 7abd5ff..3a70534 100644 --- a/src/key.c +++ b/src/key.c @@ -237,18 +237,6 @@ exit: return ret; } -bool check_import_wrong_pass() -{ - unsigned long err = ERR_peek_error(); - unsigned long err_bad_password_1 = ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_DO_HEADER, PEM_R_BAD_DECRYPT); - unsigned long err_bad_password_2 = ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_DECRYPTFINAL_EX, EVP_R_BAD_DECRYPT); - - if (err == err_bad_password_1 || err == err_bad_password_2) - return true; - - return false; -} - int import_evp(yaca_key_h *key, yaca_key_type_e key_type, const char *password, @@ -295,31 +283,28 @@ int import_evp(yaca_key_h *key, if (pkey == NULL && !wrong_pass) { BIO_reset(src); pkey = PEM_read_bio_PrivateKey(src, NULL, cb, (void*)password); - if (check_import_wrong_pass()) + if (ERROR_HANDLE() == YACA_ERROR_INVALID_PASSWORD) wrong_pass = true; private = true; - ERROR_CLEAR(); } if (pkey == NULL && !wrong_pass) { BIO_reset(src); pkey = PEM_read_bio_PUBKEY(src, NULL, cb, (void*)password); - if (check_import_wrong_pass()) + if (ERROR_HANDLE() == YACA_ERROR_INVALID_PASSWORD) wrong_pass = true; private = false; - ERROR_CLEAR(); } if (pkey == NULL && !wrong_pass) { BIO_reset(src); X509 *x509 = PEM_read_bio_X509(src, NULL, cb, (void*)password); - if (check_import_wrong_pass()) + if (ERROR_HANDLE() == YACA_ERROR_INVALID_PASSWORD) wrong_pass = true; if (x509 != NULL) pkey = X509_get_pubkey(x509); X509_free(x509); private = false; - ERROR_CLEAR(); } } /* Possible DER */ @@ -327,24 +312,23 @@ int import_evp(yaca_key_h *key, if (pkey == NULL && !wrong_pass) { BIO_reset(src); pkey = d2i_PKCS8PrivateKey_bio(src, NULL, cb, (void*)password); - if (check_import_wrong_pass()) + if (ERROR_HANDLE() == YACA_ERROR_INVALID_PASSWORD) wrong_pass = true; private = true; - ERROR_CLEAR(); } if (pkey == NULL && !wrong_pass) { BIO_reset(src); pkey = d2i_PrivateKey_bio(src, NULL); - private = true; ERROR_CLEAR(); + private = true; } if (pkey == NULL && !wrong_pass) { BIO_reset(src); pkey = d2i_PUBKEY_bio(src, NULL); - private = false; ERROR_CLEAR(); + private = false; } } -- 2.7.4 From cdb06a4616f8d0c54d8ac974d9d9b35dd31d03a9 Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Wed, 8 Jun 2016 14:50:16 +0200 Subject: [PATCH 07/16] ACR: Cleanup TODO's and descriptions in API headers. Change-Id: I48fd3df7fa2a530dab80a7037e4a4d6087b7e949 --- api/yaca/yaca_crypto.h | 1 - api/yaca/yaca_digest.h | 1 - api/yaca/yaca_encrypt.h | 5 ++--- api/yaca/yaca_key.h | 34 ++++++++++++++++------------------ api/yaca/yaca_seal.h | 7 +++---- api/yaca/yaca_sign.h | 14 ++++++-------- api/yaca/yaca_simple.h | 24 +++++++++++------------- api/yaca/yaca_types.h | 17 ++++++++--------- todo.txt | 1 + 9 files changed, 47 insertions(+), 57 deletions(-) diff --git a/api/yaca/yaca_crypto.h b/api/yaca/yaca_crypto.h index 652913c..e93d0f1 100644 --- a/api/yaca/yaca_crypto.h +++ b/api/yaca/yaca_crypto.h @@ -34,7 +34,6 @@ extern "C" { /** * @defgroup Non-Crypto Yet Another Crypto API - non crypto related functions. * - * TODO: extended description and examples. * * @{ */ diff --git a/api/yaca/yaca_digest.h b/api/yaca/yaca_digest.h index 4c72af5..622928b 100644 --- a/api/yaca/yaca_digest.h +++ b/api/yaca/yaca_digest.h @@ -34,7 +34,6 @@ extern "C" { /** * @defgroup Advanced-Digest Advanced API for the message digests. * - * TODO: extended description and examples. * * @{ */ diff --git a/api/yaca/yaca_encrypt.h b/api/yaca/yaca_encrypt.h index ab50c39..c87d048 100644 --- a/api/yaca/yaca_encrypt.h +++ b/api/yaca/yaca_encrypt.h @@ -34,7 +34,6 @@ extern "C" { /** * @defgroup Advanced-Encryption-Symmetric Advanced API for the symmetric encryption. * - * TODO: extended description and examples. * * @{ */ @@ -44,8 +43,8 @@ extern "C" { * * @since_tizen 3.0 * - * @remarks If returned iv_bits equals 0 that means that for this - * specific algorithm and its parameters IV is not used. + * @remarks If returned iv_bit_len equals 0 that means that for this + * specific algorithm and its parameters IV is not used. * * @param[in] algo Encryption algorithm * @param[in] bcm Chain mode diff --git a/api/yaca/yaca_key.h b/api/yaca/yaca_key.h index 3dad4f4..5f0aa1b 100644 --- a/api/yaca/yaca_key.h +++ b/api/yaca/yaca_key.h @@ -34,7 +34,6 @@ extern "C" { /** * @defgroup Key Advanced API for the key and IV handling. * - * TODO: extended description and examples. * * @{ */ @@ -80,21 +79,21 @@ int yaca_key_get_bit_length(const yaca_key_h key, size_t *key_bit_len); * * @since_tizen 3.0 * - * @remarks This function imports a key trying to match it to the key_type specified. - * It should autodetect both the key format and the file format. + * @remarks This function imports a key trying to match it to the 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 - * binary format are supported. - * For asymmetric keys PEM and DER file formats are supported. + * @remarks For symmetric, IV and DES keys RAW binary format and BASE64 encoded + * binary format are supported. + * For asymmetric keys PEM and DER file formats are supported. * - * @remarks Asymmetric keys can be in PKCS#1 or SSleay key formats (for RSA and - * DSA respectively). Asymmetric private keys can also be in PKCS#8 - * format. Additionally it is possible to import public RSA key from - * X509 certificate. + * @remarks Asymmetric keys can be in PKCS#1 or SSleay key formats (for RSA and + * DSA respectively). Asymmetric private keys can also be in PKCS#8 + * format. Additionally it is possible to import public RSA key from + * X509 certificate. * - * @remarks If the key is encrypted the algorithm will be autodetected and password - * used. If it's not known if the key is encrypted one should pass NULL as - * password and check for the #YACA_ERROR_INVALID_PASSWORD return code. + * @remarks If the key is encrypted the algorithm will be autodetected and password + * used. If it's not known if the key is encrypted one should pass NULL as + * password and check for the #YACA_ERROR_INVALID_PASSWORD return code. * * @param[in] key_type Type of the key * @param[in] password null terminated password for the key (can be NULL) @@ -178,11 +177,11 @@ int yaca_key_export(const yaca_key_h key, * * @since_tizen 3.0 * - * @remarks This function is used to generate symmetric and private asymmetric keys. + * @remarks This function is used to generate symmetric and private asymmetric keys. * - * Supported key lengths: - * - RSA: length >= 256bits - * - DSA: length >= 512bits, multiple of 64 + * @remarks Supported key lengths: + * - RSA: length >= 256bits + * - DSA: length >= 512bits, multiple of 64 * * @param[in] key_type Type of the key to be generated * @param[in] key_bit_len Length of the key (in bits) to be generated @@ -244,7 +243,6 @@ int yaca_key_destroy(yaca_key_h key); /** * @defgroup Key-Derivation Advanced API for the key derivation. * - * TODO: extended description and examples. * * @{ */ diff --git a/api/yaca/yaca_seal.h b/api/yaca/yaca_seal.h index 784a494..d79fb8f 100644 --- a/api/yaca/yaca_seal.h +++ b/api/yaca/yaca_seal.h @@ -34,11 +34,10 @@ extern "C" { /** * @defgroup Advanced-Encryption-Asymmetric Advanced API for the asymmetric encryption. * - * TODO: extended description and examples. * - * @remarks 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. + * @remarks 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. * * @{ */ diff --git a/api/yaca/yaca_sign.h b/api/yaca/yaca_sign.h index 1b91fd0..2d9206f 100644 --- a/api/yaca/yaca_sign.h +++ b/api/yaca/yaca_sign.h @@ -34,8 +34,6 @@ extern "C" { /** * @defgroup Advanced-Integrity Advanced API for the integrity handling - HMAC, CMAC and digital signature. * - * TODO: extended description and examples. - * TODO: add documentation how to set padding etc * * @{ */ @@ -45,8 +43,8 @@ extern "C" { * * @since_tizen 3.0 * - * @remarks For verification use yaca_verify_initialize(), yaca_verify_update() and - * yaca_verify_finalize() functions with matching public key. + * @remarks For verification use yaca_verify_initialize(), yaca_verify_update() and + * yaca_verify_finalize() functions with matching public key. * * @param[out] ctx Newly created context (must be freed with yaca_context_destroy()) * @param[in] algo Digest algorithm that will be used @@ -80,8 +78,8 @@ int yaca_sign_initialize(yaca_context_h *ctx, * * @since_tizen 3.0 * - * @remarks For verification, calculate message HMAC and compare with received MAC using - * yaca_memcmp(). + * @remarks For verification, calculate message HMAC and compare with received MAC using + * yaca_memcmp(). * * @param[out] ctx Newly created context (must be freed with yaca_context_destroy()) * @param[in] algo Digest algorithm that will be used @@ -112,8 +110,8 @@ int yaca_sign_initialize_hmac(yaca_context_h *ctx, * * @since_tizen 3.0 * - * @remarks For verification, calculate message CMAC and compare with received MAC using - * yaca_memcmp(). + * @remarks For verification, calculate message CMAC and compare with received MAC using + * yaca_memcmp(). * * @param[out] ctx Newly created context (must be freed with yaca_context_destroy()) * @param[in] algo Encryption algorithm that will be used diff --git a/api/yaca/yaca_simple.h b/api/yaca/yaca_simple.h index b1854c6..5dd2b13 100644 --- a/api/yaca/yaca_simple.h +++ b/api/yaca/yaca_simple.h @@ -34,15 +34,13 @@ extern "C" { /** * @defgroup Simple-API Simple API. * - * @remarks This is simple API. - * Design constraints: - * - All operations are single-shot (no streaming possible) - * - Context is not used - * - For now only digest and symmetric ciphers are supported - * - GCM and CCM chaining is not supported - * - All outputs are allocated by the library - * - * TODO: extended description and examples. + * @remarks This is simple API. + * Design constraints: + * - All operations are single-shot (no streaming possible) + * - Context is not used + * - For now only digest and symmetric ciphers are supported + * - GCM and CCM chaining is not supported + * - All outputs are allocated by the library * * @{ */ @@ -221,8 +219,8 @@ int yaca_simple_verify_signature(yaca_digest_algorithm_e algo, * * @since_tizen 3.0 * - * @remarks For verification, calculate message HMAC and compare with received MAC using - * yaca_memcmp(). + * @remarks For verification, calculate message HMAC and compare with received MAC using + * yaca_memcmp(). * * @param[in] algo Digest algorithm that will be used * @param[in] key Key that will be used, supported key types: @@ -258,8 +256,8 @@ int yaca_simple_calculate_hmac(yaca_digest_algorithm_e algo, * * @since_tizen 3.0 * - * @remarks For verification, calculate message CMAC and compare with received MAC using - * yaca_memcmp(). + * @remarks For verification, calculate message CMAC and compare with received MAC using + * yaca_memcmp(). * * @param[in] algo Encryption algorithm that will be used * @param[in] key Key that will be used, supported key types: diff --git a/api/yaca/yaca_types.h b/api/yaca/yaca_types.h index 96d23c8..4b35953 100644 --- a/api/yaca/yaca_types.h +++ b/api/yaca/yaca_types.h @@ -31,7 +31,6 @@ extern "C" { /** * @defgroup Crypto-Types Yet Another Crypto API - types. * - * TODO: extended description. * * @{ */ @@ -167,7 +166,7 @@ typedef enum { * #YACA_BCM_GCM, * #YACA_BCM_CCM, * #YACA_BCM_CTR - * - see #yaca_block_cipher_mode_e for details on additional parameters (mandatory). + * - see #yaca_block_cipher_mode_e for details on additional properties (mandatory). */ YACA_ENCRYPT_AES = 0, @@ -181,7 +180,7 @@ typedef enum { * #YACA_BCM_CFB1, * #YACA_BCM_CFB8, * #YACA_BCM_ECB - * - see #yaca_block_cipher_mode_e for details on additional parameters (mandatory). + * - see #yaca_block_cipher_mode_e for details on additional properties (mandatory). */ YACA_ENCRYPT_UNSAFE_DES, @@ -193,7 +192,7 @@ typedef enum { * #YACA_BCM_OFB, * #YACA_BCM_CFB, * #YACA_BCM_ECB - * - see #yaca_block_cipher_mode_e for details on additional parameters (mandatory). + * - see #yaca_block_cipher_mode_e for details on additional properties (mandatory). * - Use double DES keys to perform corresponding 2-key 3DES encryption. */ @@ -209,7 +208,7 @@ typedef enum { * #YACA_BCM_CFB1, * #YACA_BCM_CFB8, * #YACA_BCM_ECB - * - see #yaca_block_cipher_mode_e for details on additional parameters (mandatory). + * - see #yaca_block_cipher_mode_e for details on additional properties (mandatory). * - Use triple DES keys to perform corresponding 3-key 3DES encryption. */ YACA_ENCRYPT_3DES_3TDEA, @@ -218,7 +217,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 parameter by default equals to 128. + * - Effective key bits property by default equals to 128. * - Supported block cipher modes: * #YACA_BCM_CBC, * #YACA_BCM_OFB, @@ -244,7 +243,7 @@ typedef enum { * #YACA_BCM_OFB, * #YACA_BCM_CFB, * #YACA_BCM_ECB - * - see #yaca_block_cipher_mode_e for details on additional parameters (mandatory). + * - see #yaca_block_cipher_mode_e for details on additional properties (mandatory). */ YACA_ENCRYPT_CAST5, } yaca_encrypt_algorithm_e; @@ -282,7 +281,7 @@ typedef enum { * GCM block cipher mode. * This is a variable IV length mode (recommended 96 bits IV). * - * Supported parameters: + * 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 @@ -332,7 +331,7 @@ typedef enum { * 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 * - * Supported parameters: + * 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 * Set after yaca_encrypt_initialize() and before yaca_encrypt_update() diff --git a/todo.txt b/todo.txt index 26e6208..e2ef626 100644 --- a/todo.txt +++ b/todo.txt @@ -7,3 +7,4 @@ Global: - 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. \ No newline at end of file -- 2.7.4 From 0d5462da065eb7699d00a80808c9c1e0ff77ac8e Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Mon, 13 Jun 2016 09:27:56 +0200 Subject: [PATCH 08/16] Silently export error translation function Change-Id: I4cc7e8b2219b8c30f8a2895c91e2a2e5338232d5 --- src/debug.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/debug.c b/src/debug.c index 2f277d0..02d80c6 100644 --- a/src/debug.c +++ b/src/debug.c @@ -41,7 +41,7 @@ API void yaca_debug_set_error_cb(yaca_error_cb fn) error_cb = fn; } -char *error_translate(yaca_error_e err) +API char *yaca_debug_translate_error(yaca_error_e err) { switch (err) { case YACA_ERROR_NONE: @@ -74,7 +74,7 @@ void error_dump(const char *file, int line, const char *function, int code) char buf[BUF_SIZE]; unsigned long err; size_t written; - const char *err_str = error_translate(code); + const char *err_str = yaca_debug_translate_error(code); written = snprintf(buf, BUF_SIZE, "%s:%d %s() API error: ", file, line, function); if (err_str != NULL) -- 2.7.4 From 48fc3c9d30d4dbcc7af6d54839c023accb14585d Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Thu, 9 Jun 2016 17:03:50 +0200 Subject: [PATCH 09/16] Merge encrypt/decrypt and seal/open common code. Change-Id: Ic9f1b7a527ce111f099459ee66eb4032d462c40e --- src/encrypt.c | 155 +++++++++++++++++----------------- src/internal.h | 38 ++++++++- src/seal.c | 259 ++++++++++++--------------------------------------------- 3 files changed, 168 insertions(+), 284 deletions(-) diff --git a/src/encrypt.c b/src/encrypt.c index a53a442..7a01f33 100644 --- a/src/encrypt.c +++ b/src/encrypt.c @@ -33,35 +33,22 @@ #include "internal.h" -enum encrypt_op_type { - OP_ENCRYPT = 0, - OP_DECRYPT = 1 -}; - -struct yaca_encrypt_ctx_s { - struct yaca_context_s ctx; - - EVP_CIPHER_CTX *cipher_ctx; - enum encrypt_op_type op_type; /* Operation context was created for */ - size_t tag_len; -}; - -static struct yaca_encrypt_ctx_s *get_encrypt_ctx(const yaca_context_h ctx) +struct yaca_encrypt_context_s *get_encrypt_context(const yaca_context_h ctx) { if (ctx == YACA_CONTEXT_NULL) return NULL; switch (ctx->type) { case YACA_CTX_ENCRYPT: - return (struct yaca_encrypt_ctx_s *)ctx; + return (struct yaca_encrypt_context_s *)ctx; default: return NULL; } } -static void destroy_encrypt_ctx(const yaca_context_h ctx) +void destroy_encrypt_context(const yaca_context_h ctx) { - struct yaca_encrypt_ctx_s *nc = get_encrypt_ctx(ctx); + struct yaca_encrypt_context_s *nc = get_encrypt_context(ctx); if (nc == NULL) return; @@ -70,9 +57,9 @@ static void destroy_encrypt_ctx(const yaca_context_h ctx) nc->cipher_ctx = NULL; } -static int get_encrypt_output_length(const yaca_context_h ctx, size_t input_len, size_t *output_len) +int get_encrypt_output_length(const yaca_context_h ctx, size_t input_len, size_t *output_len) { - struct yaca_encrypt_ctx_s *nc = get_encrypt_ctx(ctx); + struct yaca_encrypt_context_s *nc = get_encrypt_context(ctx); int block_size; if (nc == NULL) @@ -99,24 +86,42 @@ static int get_encrypt_output_length(const yaca_context_h ctx, size_t input_len, return YACA_ERROR_NONE; } -static int set_encrypt_param(yaca_context_h ctx, - yaca_property_e param, - const void *value, - size_t value_len) +int set_encrypt_property(yaca_context_h ctx, yaca_property_e property, + const void *value, size_t value_len) { - struct yaca_encrypt_ctx_s *c = get_encrypt_ctx(ctx); + struct yaca_encrypt_context_s *c = get_encrypt_context(ctx); int len; if (c == NULL || value == NULL) return YACA_ERROR_INVALID_PARAMETER; assert(c->cipher_ctx != NULL); - switch (param) { + switch (property) { case YACA_PROPERTY_GCM_AAD: case YACA_PROPERTY_CCM_AAD: - if (EVP_EncryptUpdate(c->cipher_ctx, NULL, &len, value, value_len) != 1) { - ERROR_DUMP(YACA_ERROR_INTERNAL); - return YACA_ERROR_INTERNAL; + if (c->op_type == OP_ENCRYPT) { + if (EVP_EncryptUpdate(c->cipher_ctx, NULL, &len, value, value_len) != 1) { + ERROR_DUMP(YACA_ERROR_INTERNAL); + return YACA_ERROR_INTERNAL; + } + } + if (c->op_type == OP_DECRYPT) { + if (EVP_DecryptUpdate(c->cipher_ctx, NULL, &len, value, value_len) != 1) { + ERROR_DUMP(YACA_ERROR_INTERNAL); + return YACA_ERROR_INTERNAL; + } + } + if (c->op_type == OP_SEAL) { + if (EVP_SealUpdate(c->cipher_ctx, NULL, &len, value, value_len) != 1) { + ERROR_DUMP(YACA_ERROR_INTERNAL); + return YACA_ERROR_INTERNAL; + } + } + if (c->op_type == OP_OPEN) { + if (EVP_OpenUpdate(c->cipher_ctx, NULL, &len, value, value_len) != 1) { + ERROR_DUMP(YACA_ERROR_INTERNAL); + return YACA_ERROR_INTERNAL; + } } break; case YACA_PROPERTY_GCM_TAG: @@ -152,21 +157,20 @@ static int set_encrypt_param(yaca_context_h ctx, default: return YACA_ERROR_INVALID_PARAMETER; } + return YACA_ERROR_NONE; } -static int get_encrypt_param(const yaca_context_h ctx, - yaca_property_e param, - void **value, - size_t *value_len) +int get_encrypt_property(const yaca_context_h ctx, yaca_property_e property, + void **value, size_t *value_len) { - struct yaca_encrypt_ctx_s *c = get_encrypt_ctx(ctx); + struct yaca_encrypt_context_s *c = get_encrypt_context(ctx); if (c == NULL || value == NULL || value_len == NULL) return YACA_ERROR_INVALID_PARAMETER; assert(c->cipher_ctx != NULL); - switch (param) { + switch (property) { case YACA_PROPERTY_GCM_TAG: if (c->tag_len == 0) return YACA_ERROR_INVALID_PARAMETER; @@ -195,6 +199,7 @@ static int get_encrypt_param(const yaca_context_h ctx, return YACA_ERROR_INVALID_PARAMETER; break; } + return YACA_ERROR_NONE; } @@ -305,16 +310,16 @@ int encrypt_get_algorithm(yaca_encrypt_algorithm_e algo, return YACA_ERROR_NONE; } -static int encrypt_init(yaca_context_h *ctx, - yaca_encrypt_algorithm_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) +static int encrypt_initialize(yaca_context_h *ctx, + yaca_encrypt_algorithm_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; + struct yaca_encrypt_context_s *nc; const EVP_CIPHER *cipher; size_t key_bits; unsigned char *iv_data = NULL; @@ -329,15 +334,15 @@ static int encrypt_init(yaca_context_h *ctx, if (lkey == NULL) return YACA_ERROR_INVALID_PARAMETER; - ret = yaca_zalloc(sizeof(struct yaca_encrypt_ctx_s), (void**)&nc); + ret = yaca_zalloc(sizeof(struct yaca_encrypt_context_s), (void**)&nc); if (ret != YACA_ERROR_NONE) return ret; nc->ctx.type = YACA_CTX_ENCRYPT; - nc->ctx.ctx_destroy = destroy_encrypt_ctx; + nc->ctx.ctx_destroy = destroy_encrypt_context; nc->ctx.get_output_length = get_encrypt_output_length; - nc->ctx.set_param = set_encrypt_param; - nc->ctx.get_param = get_encrypt_param; + nc->ctx.set_param = set_encrypt_property; + nc->ctx.get_param = get_encrypt_property; nc->op_type = op_type; nc->tag_len = 0; @@ -465,36 +470,36 @@ exit: return ret; } -static int encrypt_update(yaca_context_h ctx, - const unsigned char *input, - size_t input_len, - unsigned char *output, - size_t *output_len, - enum encrypt_op_type op_type) +int encrypt_update(yaca_context_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); + struct yaca_encrypt_context_s *c = get_encrypt_context(ctx); int ret; int loutput_len; if (c == NULL || input_len == 0 || output_len == NULL || op_type != c->op_type) return YACA_ERROR_INVALID_PARAMETER; - loutput_len = *output_len; - switch (op_type) { case OP_ENCRYPT: - ret = EVP_EncryptUpdate(c->cipher_ctx, output, &loutput_len, - input, input_len); + ret = EVP_EncryptUpdate(c->cipher_ctx, output, &loutput_len, input, input_len); + break; + case OP_SEAL: + ret = EVP_SealUpdate(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); + ret = EVP_DecryptUpdate(c->cipher_ctx, output, &loutput_len, input, input_len); + break; + case OP_OPEN: + ret = EVP_OpenUpdate(c->cipher_ctx, output, &loutput_len, input, input_len); break; default: return YACA_ERROR_INVALID_PARAMETER; } - if (ret != 1) { + if (ret != 1 || loutput_len < 0) { ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); return ret; @@ -504,21 +509,17 @@ static int encrypt_update(yaca_context_h ctx, return YACA_ERROR_NONE; } -static int encrypt_final(yaca_context_h ctx, - unsigned char *output, - size_t *output_len, - enum encrypt_op_type op_type) +int encrypt_finalize(yaca_context_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); + struct yaca_encrypt_context_s *c = get_encrypt_context(ctx); int ret; int loutput_len; - if (c == NULL || output == NULL || output_len == NULL || - op_type != c->op_type) + if (c == NULL || output == NULL || output_len == NULL || op_type != c->op_type) return YACA_ERROR_INVALID_PARAMETER; - loutput_len = *output_len; - switch (op_type) { case OP_ENCRYPT: ret = EVP_EncryptFinal(c->cipher_ctx, output, &loutput_len); @@ -526,11 +527,17 @@ static int encrypt_final(yaca_context_h ctx, case OP_DECRYPT: ret = EVP_DecryptFinal(c->cipher_ctx, output, &loutput_len); break; + case OP_SEAL: + ret = EVP_SealFinal(c->cipher_ctx, output, &loutput_len); + break; + case OP_OPEN: + ret = EVP_OpenFinal(c->cipher_ctx, output, &loutput_len); + break; default: return YACA_ERROR_INVALID_PARAMETER; } - if (ret != 1) { + if (ret != 1 || loutput_len < 0) { ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); return ret; @@ -568,7 +575,7 @@ API int yaca_encrypt_initialize(yaca_context_h *ctx, const yaca_key_h sym_key, const yaca_key_h iv) { - return encrypt_init(ctx, algo, bcm, sym_key, iv, OP_ENCRYPT); + return encrypt_initialize(ctx, algo, bcm, sym_key, iv, OP_ENCRYPT); } API int yaca_encrypt_update(yaca_context_h ctx, @@ -585,8 +592,7 @@ API int yaca_encrypt_finalize(yaca_context_h ctx, char *ciphertext, size_t *ciphertext_len) { - return encrypt_final(ctx, (unsigned char*)ciphertext, - ciphertext_len, OP_ENCRYPT); + return encrypt_finalize(ctx, (unsigned char*)ciphertext, ciphertext_len, OP_ENCRYPT); } API int yaca_decrypt_initialize(yaca_context_h *ctx, @@ -595,7 +601,7 @@ API int yaca_decrypt_initialize(yaca_context_h *ctx, const yaca_key_h sym_key, const yaca_key_h iv) { - return encrypt_init(ctx, algo, bcm, sym_key, iv, OP_DECRYPT); + return encrypt_initialize(ctx, algo, bcm, sym_key, iv, OP_DECRYPT); } API int yaca_decrypt_update(yaca_context_h ctx, @@ -612,6 +618,5 @@ API int yaca_decrypt_finalize(yaca_context_h ctx, char *plaintext, size_t *plaintext_len) { - return encrypt_final(ctx, (unsigned char*)plaintext, plaintext_len, - OP_DECRYPT); + return encrypt_finalize(ctx, (unsigned char*)plaintext, plaintext_len, OP_DECRYPT); } diff --git a/src/internal.h b/src/internal.h index 62aa8fd..5a6285e 100644 --- a/src/internal.h +++ b/src/internal.h @@ -38,8 +38,14 @@ enum yaca_ctx_type_e { YACA_CTX_INVALID = 0, YACA_CTX_DIGEST, YACA_CTX_SIGN, - YACA_CTX_ENCRYPT, - YACA_CTX_SEAL + YACA_CTX_ENCRYPT +}; + +enum encrypt_op_type { + OP_ENCRYPT = 0, + OP_DECRYPT = 1, + OP_SEAL = 2, + OP_OPEN = 3 }; /* Base structure for crypto contexts - to be inherited */ @@ -54,6 +60,13 @@ struct yaca_context_s { void **value, size_t *value_len); }; +struct yaca_encrypt_context_s { + struct yaca_context_s ctx; + + EVP_CIPHER_CTX *cipher_ctx; + enum encrypt_op_type op_type; /* Operation context was created for */ + size_t tag_len; +}; /* Base structure for crypto keys - to be inherited */ struct yaca_key_s { @@ -89,11 +102,32 @@ struct yaca_key_evp_s { int digest_get_algorithm(yaca_digest_algorithm_e algo, const EVP_MD **md); +struct yaca_encrypt_context_s *get_encrypt_context(const yaca_context_h ctx); + +void destroy_encrypt_context(const yaca_context_h ctx); + +int get_encrypt_output_length(const yaca_context_h ctx, size_t input_len, size_t *output_len); + +int set_encrypt_property(yaca_context_h ctx, yaca_property_e property, + const void *value, size_t value_len); + +int get_encrypt_property(const yaca_context_h ctx, yaca_property_e property, + void **value, size_t *value_len); + int encrypt_get_algorithm(yaca_encrypt_algorithm_e algo, yaca_block_cipher_mode_e bcm, size_t key_bits, const EVP_CIPHER **cipher); +int encrypt_update(yaca_context_h ctx, + const unsigned char *input, size_t input_len, + unsigned char *output, size_t *output_len, + enum encrypt_op_type op_type); + +int encrypt_finalize(yaca_context_h ctx, + unsigned char *output, size_t *output_len, + enum encrypt_op_type op_type); + struct yaca_key_simple_s *key_get_simple(const yaca_key_h key); struct yaca_key_evp_s *key_get_evp(const yaca_key_h key); diff --git a/src/seal.c b/src/seal.c index 50b977d..9f30bd8 100644 --- a/src/seal.c +++ b/src/seal.c @@ -33,81 +33,18 @@ #include "internal.h" -enum seal_op_type { - OP_SEAL = 0, - OP_OPEN = 1 -}; - -struct yaca_seal_ctx_s { - struct yaca_context_s ctx; - - EVP_CIPHER_CTX *cipher_ctx; - enum seal_op_type op_type; /* Operation context was created for */ -}; - -static struct yaca_seal_ctx_s *get_seal_ctx(const yaca_context_h ctx) -{ - if (ctx == YACA_CONTEXT_NULL) - return NULL; - - switch (ctx->type) { - case YACA_CTX_SEAL: - return (struct yaca_seal_ctx_s *)ctx; - default: - return NULL; - } -} - -static void destroy_seal_ctx(const yaca_context_h ctx) -{ - struct yaca_seal_ctx_s *nc = get_seal_ctx(ctx); - - if (nc == NULL) - return; - - EVP_CIPHER_CTX_free(nc->cipher_ctx); - nc->cipher_ctx = NULL; -} - -static int get_seal_output_length(const yaca_context_h ctx, size_t input_len, size_t *output_len) -{ - struct yaca_seal_ctx_s *nc = get_seal_ctx(ctx); - int block_size; - - if (nc == NULL) - return YACA_ERROR_INVALID_PARAMETER; - assert(nc->cipher_ctx); - - block_size = EVP_CIPHER_CTX_block_size(nc->cipher_ctx); - if (block_size <= 0) { - ERROR_DUMP(YACA_ERROR_INTERNAL); - return YACA_ERROR_INTERNAL; - } - - if (input_len > 0) { - if ((size_t)block_size > SIZE_MAX - input_len + 1) - return YACA_ERROR_INVALID_PARAMETER; - - *output_len = block_size + input_len - 1; - } else { - *output_len = block_size; - } - - return YACA_ERROR_NONE; -} - -static int seal_init(yaca_context_h *ctx, - const yaca_key_h pub_key, - yaca_encrypt_algorithm_e algo, - yaca_block_cipher_mode_e bcm, - size_t sym_key_bits, - yaca_key_h *sym_key, - yaca_key_h *iv) +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 sym_key_bit_len, + yaca_key_h *sym_key, + yaca_key_h *iv) { struct yaca_key_evp_s *lpub; struct yaca_key_simple_s *lkey = NULL; struct yaca_key_simple_s *liv = NULL; - struct yaca_seal_ctx_s *nc; + struct yaca_encrypt_context_s *nc; const EVP_CIPHER *cipher; int pub_key_length; unsigned char *key_data = NULL; @@ -124,14 +61,17 @@ static int seal_init(yaca_context_h *ctx, lpub = key_get_evp(pub_key); assert(lpub); - ret = yaca_zalloc(sizeof(struct yaca_seal_ctx_s), (void**)&nc); + ret = yaca_zalloc(sizeof(struct yaca_encrypt_context_s), (void**)&nc); if (ret != YACA_ERROR_NONE) return ret; - nc->ctx.type = YACA_CTX_SEAL; - nc->ctx.ctx_destroy = destroy_seal_ctx; - nc->ctx.get_output_length = get_seal_output_length; + nc->ctx.type = YACA_CTX_ENCRYPT; + nc->ctx.ctx_destroy = destroy_encrypt_context; + nc->ctx.get_output_length = get_encrypt_output_length; + nc->ctx.set_param = set_encrypt_property; + nc->ctx.get_param = get_encrypt_property; nc->op_type = OP_SEAL; + nc->tag_len = 0; nc->cipher_ctx = EVP_CIPHER_CTX_new(); if (nc->cipher_ctx == NULL) { @@ -153,7 +93,7 @@ static int seal_init(yaca_context_h *ctx, goto exit; key_data = (unsigned char*)lkey->d; - ret = encrypt_get_algorithm(algo, bcm, sym_key_bits, &cipher); + ret = encrypt_get_algorithm(algo, bcm, sym_key_bit_len, &cipher); if (ret != YACA_ERROR_NONE) goto exit; @@ -211,18 +151,35 @@ exit: return ret; } -static int open_init(yaca_context_h *ctx, - const yaca_key_h prv_key, - yaca_encrypt_algorithm_e algo, - yaca_block_cipher_mode_e bcm, - size_t sym_key_bits, - const yaca_key_h sym_key, - const yaca_key_h iv) +API int yaca_seal_update(yaca_context_h ctx, + const char *plaintext, + size_t plaintext_len, + char *ciphertext, + size_t *ciphertext_len) +{ + return encrypt_update(ctx, (const unsigned char*)plaintext, plaintext_len, + (unsigned char*)ciphertext, ciphertext_len, OP_SEAL); +} + +API int yaca_seal_finalize(yaca_context_h ctx, + char *ciphertext, + size_t *ciphertext_len) +{ + return encrypt_finalize(ctx, (unsigned char*)ciphertext, ciphertext_len, OP_SEAL); +} + +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 sym_key_bit_len, + const yaca_key_h sym_key, + const yaca_key_h iv) { const struct yaca_key_evp_s *lprv; const struct yaca_key_simple_s *lkey; const struct yaca_key_simple_s *liv; - struct yaca_seal_ctx_s *nc; + struct yaca_encrypt_context_s *nc; const EVP_CIPHER *cipher; unsigned char *iv_data = NULL; size_t iv_bits; @@ -241,16 +198,19 @@ static int open_init(yaca_context_h *ctx, if (lkey == NULL || lkey->key.type != YACA_KEY_TYPE_SYMMETRIC) return YACA_ERROR_INVALID_PARAMETER; - ret = yaca_zalloc(sizeof(struct yaca_seal_ctx_s), (void**)&nc); + ret = yaca_zalloc(sizeof(struct yaca_encrypt_context_s), (void**)&nc); if (ret != YACA_ERROR_NONE) return ret; - nc->ctx.type = YACA_CTX_SEAL; - nc->ctx.ctx_destroy = destroy_seal_ctx; - nc->ctx.get_output_length = get_seal_output_length; + nc->ctx.type = YACA_CTX_ENCRYPT; + nc->ctx.ctx_destroy = destroy_encrypt_context; + nc->ctx.get_output_length = get_encrypt_output_length; + nc->ctx.set_param = set_encrypt_property; + nc->ctx.get_param = get_encrypt_property; nc->op_type = OP_OPEN; + nc->tag_len = 0; - ret = encrypt_get_algorithm(algo, bcm, sym_key_bits, &cipher); + ret = encrypt_get_algorithm(algo, bcm, sym_key_bit_len, &cipher); if (ret != YACA_ERROR_NONE) goto exit; @@ -314,134 +274,19 @@ exit: return ret; } -static int seal_update(yaca_context_h ctx, - const unsigned char *input, - size_t input_len, - unsigned char *output, - size_t *output_len, - enum seal_op_type op_type) -{ - struct yaca_seal_ctx_s *c = get_seal_ctx(ctx); - int ret; - - if (c == NULL || input == NULL || input_len == 0 || - output == NULL || output_len == NULL || op_type != c->op_type) - return YACA_ERROR_INVALID_PARAMETER; - - switch (op_type) { - case OP_SEAL: - ret = EVP_SealUpdate(c->cipher_ctx, output, (int*)output_len, input, input_len); - break; - case OP_OPEN: - ret = EVP_OpenUpdate(c->cipher_ctx, output, (int*)output_len, input, input_len); - break; - default: - return YACA_ERROR_INVALID_PARAMETER; - } - - if (ret != 1) { - ret = YACA_ERROR_INTERNAL; - ERROR_DUMP(ret); - return ret; - } - - return YACA_ERROR_NONE; -} - -static int seal_final(yaca_context_h ctx, - unsigned char *output, - size_t *output_len, - enum seal_op_type op_type) -{ - struct yaca_seal_ctx_s *c = get_seal_ctx(ctx); - int ret; - - if (c == NULL || output == NULL || output_len == NULL || op_type != c->op_type) - return YACA_ERROR_INVALID_PARAMETER; - - switch (op_type) { - case OP_SEAL: - ret = EVP_SealFinal(c->cipher_ctx, output, (int*)output_len); - break; - case OP_OPEN: - ret = EVP_OpenFinal(c->cipher_ctx, output, (int*)output_len); - break; - default: - return YACA_ERROR_INVALID_PARAMETER; - } - - if (ret != 1) { - ret = YACA_ERROR_INTERNAL; - ERROR_DUMP(ret); - return ret; - } - - return YACA_ERROR_NONE; -} - -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 sym_key_bit_len, - yaca_key_h *sym_key, - yaca_key_h *iv) -{ - return seal_init(ctx, pub_key, algo, bcm, sym_key_bit_len, sym_key, iv); -} - -API int yaca_seal_update(yaca_context_h ctx, - const char *plaintext, - size_t plaintext_len, - char *ciphertext, - size_t *ciphertext_len) -{ - return seal_update(ctx, - (const unsigned char*)plaintext, - plaintext_len, - (unsigned char*)ciphertext, - ciphertext_len, - OP_SEAL); -} - -API int yaca_seal_finalize(yaca_context_h ctx, - char *ciphertext, - size_t *ciphertext_len) -{ - return seal_final(ctx, - (unsigned char*)ciphertext, - ciphertext_len, - OP_SEAL); -} - -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 sym_key_bit_len, - const yaca_key_h sym_key, - const yaca_key_h iv) -{ - return open_init(ctx, prv_key, algo, bcm, sym_key_bit_len, sym_key, iv); -} - API int yaca_open_update(yaca_context_h ctx, const char *ciphertext, size_t ciphertext_len, char *plaintext, size_t *plaintext_len) { - return seal_update(ctx, - (const unsigned char*)ciphertext, - ciphertext_len, - (unsigned char*)plaintext, - plaintext_len, - OP_OPEN); + return encrypt_update(ctx, (const unsigned char*)ciphertext, ciphertext_len, + (unsigned char*)plaintext, plaintext_len, OP_OPEN); } API int yaca_open_finalize(yaca_context_h ctx, char *plaintext, size_t *plaintext_len) { - return seal_final(ctx, (unsigned char*)plaintext, plaintext_len, OP_OPEN); + return encrypt_finalize(ctx, (unsigned char*)plaintext, plaintext_len, OP_OPEN); } -- 2.7.4 From 307ade12aedc5023f2fd083c3f861dace686673b Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Thu, 9 Jun 2016 17:07:37 +0200 Subject: [PATCH 10/16] Add more usage examples of seal/open. Change-Id: Icd89007c56fa6775c381874df4dd08fa1c5ba1e2 --- examples/seal.c | 366 +++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 338 insertions(+), 28 deletions(-) diff --git a/examples/seal.c b/examples/seal.c index 11e40fc..96e5888 100644 --- a/examples/seal.c +++ b/examples/seal.c @@ -32,25 +32,24 @@ #include "misc.h" #include "../src/debug.h" -void encrypt_seal(void) +void encrypt_seal(const yaca_encrypt_algorithm_e algo, + const yaca_block_cipher_mode_e bcm, + const size_t key_bits) { - const yaca_encrypt_algorithm_e algo = YACA_ENCRYPT_AES; - const yaca_block_cipher_mode_e bcm = YACA_BCM_CBC; - const size_t key_bits = YACA_KEY_LENGTH_256BIT; yaca_context_h ctx = YACA_CONTEXT_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 sym_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; + size_t enc_len; + size_t dec_len; size_t block_len; size_t output_len; - size_t out_size; + size_t out_len; size_t rem; printf("Plain data (16 of %zu bytes): %.16s\n", LOREM4096_SIZE, lorem4096); @@ -64,7 +63,7 @@ void encrypt_seal(void) /* Encrypt a.k.a. seal */ { - if (yaca_seal_initialize(&ctx, key_pub, algo, bcm, key_bits, &aes_key, &iv) != YACA_ERROR_NONE) + if (yaca_seal_initialize(&ctx, key_pub, algo, bcm, key_bits, &sym_key, &iv) != YACA_ERROR_NONE) goto exit; /* For the update */ @@ -76,22 +75,22 @@ void encrypt_seal(void) goto exit; /* Calculate max output: size of update + final chunks */ - enc_size = output_len + block_len; - if (yaca_malloc(enc_size, (void**)&enc) != YACA_ERROR_NONE) + enc_len = output_len + block_len; + if (yaca_malloc(enc_len, (void**)&enc) != YACA_ERROR_NONE) goto exit; /* Seal and finalize */ - out_size = enc_size; - if (yaca_seal_update(ctx, lorem4096, LOREM4096_SIZE, enc, &out_size) != YACA_ERROR_NONE) + out_len = enc_len; + if (yaca_seal_update(ctx, lorem4096, LOREM4096_SIZE, enc, &out_len) != YACA_ERROR_NONE) goto exit; - rem = enc_size - out_size; - if (yaca_seal_finalize(ctx, enc + out_size, &rem) != YACA_ERROR_NONE) + rem = enc_len - out_len; + if (yaca_seal_finalize(ctx, enc + out_len, &rem) != YACA_ERROR_NONE) goto exit; - enc_size = rem + out_size; + enc_len = rem + out_len; - dump_hex(enc, 16, "Encrypted data (16 of %zu bytes): ", enc_size); + dump_hex(enc, 16, "Encrypted data (16 of %zu bytes): ", enc_len); yaca_context_destroy(ctx); ctx = YACA_CONTEXT_NULL; @@ -99,7 +98,7 @@ void encrypt_seal(void) /* Decrypt a.k.a. open */ { - if (yaca_open_initialize(&ctx, key_priv, algo, bcm, key_bits, aes_key, iv) != YACA_ERROR_NONE) + if (yaca_open_initialize(&ctx, key_priv, algo, bcm, key_bits, sym_key, iv) != YACA_ERROR_NONE) goto exit; /* For the update */ @@ -111,29 +110,318 @@ void encrypt_seal(void) goto exit; /* Calculate max output: size of update + final chunks */ - dec_size = output_len + block_len; - if (yaca_malloc(dec_size, (void**)&dec) != YACA_ERROR_NONE) + dec_len = output_len + block_len; + if (yaca_malloc(dec_len, (void**)&dec) != YACA_ERROR_NONE) goto exit; /* Open and finalize */ - out_size = dec_size; - if (yaca_open_update(ctx, enc, enc_size, dec, &out_size) != YACA_ERROR_NONE) + out_len = dec_len; + if (yaca_open_update(ctx, enc, enc_len, dec, &out_len) != YACA_ERROR_NONE) goto exit; - rem = dec_size - out_size; - if (yaca_open_finalize(ctx, dec + out_size, &rem) != YACA_ERROR_NONE) + rem = dec_len - out_len; + if (yaca_open_finalize(ctx, dec + out_len, &rem) != YACA_ERROR_NONE) goto exit; - dec_size = rem + out_size; + dec_len = rem + out_len; - printf("Decrypted data (16 of %zu bytes): %.16s\n", dec_size, dec); + printf("Decrypted data (16 of %zu bytes): %.16s\n\n", dec_len, dec); } exit: yaca_free(dec); yaca_free(enc); yaca_context_destroy(ctx); - yaca_key_destroy(aes_key); + yaca_key_destroy(sym_key); + yaca_key_destroy(iv); + yaca_key_destroy(key_pub); + yaca_key_destroy(key_priv); +} + +void encrypt_seal_aes_gcm(void) +{ + yaca_encrypt_algorithm_e algo = YACA_ENCRYPT_AES; + yaca_block_cipher_mode_e bcm = YACA_BCM_GCM; + size_t key_bits = YACA_KEY_LENGTH_256BIT; + + yaca_context_h ctx = YACA_CONTEXT_NULL; + yaca_key_h key_pub = YACA_KEY_NULL; + yaca_key_h key_priv = YACA_KEY_NULL; + yaca_key_h sym_key = YACA_KEY_NULL; + yaca_key_h iv = YACA_KEY_NULL; + + char *enc = NULL; + char *dec = NULL; + size_t enc_len; + size_t dec_len; + + char *aad = NULL; + char *tag = NULL; + size_t aad_len = 16; + size_t tag_len = 13; + + size_t block_len; + size_t output_len; + size_t out_len; + size_t rem; + + printf("Plain data (16 of %zu bytes): %.16s\n", LOREM4096_SIZE, lorem4096); + + /* Generate key pair */ + if (yaca_key_generate(YACA_KEY_TYPE_RSA_PRIV, YACA_KEY_LENGTH_4096BIT, &key_priv) != YACA_ERROR_NONE) + return; + + if (yaca_key_extract_public(key_priv, &key_pub) != YACA_ERROR_NONE) + goto exit; + + if (yaca_zalloc(aad_len, (void**)&aad) != YACA_ERROR_NONE) + goto exit; + + if (yaca_randomize_bytes(aad, aad_len) != YACA_ERROR_NONE) + goto exit; + + if (yaca_zalloc(tag_len, (void**)&tag) != YACA_ERROR_NONE) + goto exit; + + /* Encryption */ + { + if (yaca_seal_initialize(&ctx, key_pub, algo, bcm, key_bits, &sym_key, &iv) != YACA_ERROR_NONE) + goto exit; + + /* Provide any AAD data */ + if (yaca_context_set_property(ctx, YACA_PROPERTY_GCM_AAD, aad, aad_len) != YACA_ERROR_NONE) + goto exit; + + /* For the update */ + if (yaca_context_get_output_length(ctx, LOREM4096_SIZE, &output_len) != YACA_ERROR_NONE) + goto exit; + + /* For the finalize */ + if (yaca_context_get_output_length(ctx, 0, &block_len) != YACA_ERROR_NONE) + goto exit; + + /* Calculate max output: size of update + final chunks */ + enc_len = output_len + block_len; + if (yaca_malloc(enc_len, (void**)&enc) != YACA_ERROR_NONE) + goto exit; + + out_len = enc_len; + if (yaca_seal_update(ctx, lorem4096, LOREM4096_SIZE, enc, &out_len) != YACA_ERROR_NONE) + goto exit; + + rem = enc_len - out_len; + if (yaca_seal_finalize(ctx, enc + out_len, &rem) != YACA_ERROR_NONE) + goto exit; + + enc_len = rem + out_len; + + /* Set the tag length and get the tag after final encryption */ + if (yaca_context_set_property(ctx, YACA_PROPERTY_GCM_TAG_LEN, + (void*)&tag_len, sizeof(tag_len)) != YACA_ERROR_NONE) + goto exit; + + if (yaca_context_get_property(ctx, YACA_PROPERTY_GCM_TAG, (void**)tag, &tag_len) != YACA_ERROR_NONE) + goto exit; + + dump_hex(enc, 16, "Encrypted data (16 of %zu bytes): ", enc_len); + + yaca_context_destroy(ctx); + ctx = YACA_CONTEXT_NULL; + } + + /* Decryption */ + { + if (yaca_open_initialize(&ctx, key_priv, algo, bcm, key_bits, sym_key, iv) != YACA_ERROR_NONE) + goto exit; + + /* Provide any AAD data */ + if (yaca_context_set_property(ctx, YACA_PROPERTY_GCM_AAD, aad, aad_len) != YACA_ERROR_NONE) + goto exit; + + /* For the update */ + if (yaca_context_get_output_length(ctx, LOREM4096_SIZE, &output_len) != YACA_ERROR_NONE) + goto exit; + + /* For the finalize */ + if (yaca_context_get_output_length(ctx, 0, &block_len) != YACA_ERROR_NONE) + goto exit; + + /* Calculate max output: size of update + final chunks */ + dec_len = output_len + block_len; + if (yaca_malloc(dec_len, (void**)&dec) != YACA_ERROR_NONE) + goto exit; + + out_len = dec_len; + if (yaca_open_update(ctx, enc, enc_len, dec, &out_len) != YACA_ERROR_NONE) + goto exit; + + rem = dec_len - out_len; + + /* Set expected tag value before final decryption */ + if (yaca_context_set_property(ctx, YACA_PROPERTY_GCM_TAG, tag, tag_len) != YACA_ERROR_NONE) + goto exit; + + if (yaca_open_finalize(ctx, dec + out_len, &rem) != YACA_ERROR_NONE) + goto exit; + + dec_len = rem + out_len; + + printf("Decrypted data (16 of %zu bytes): %.16s\n\n", dec_len, dec); + } + +exit: + yaca_free(dec); + yaca_free(enc); + yaca_context_destroy(ctx); + yaca_key_destroy(sym_key); + yaca_key_destroy(iv); + yaca_key_destroy(key_pub); + yaca_key_destroy(key_priv); +} + +void encrypt_seal_aes_ccm(void) +{ + yaca_encrypt_algorithm_e algo = YACA_ENCRYPT_AES; + yaca_block_cipher_mode_e bcm = YACA_BCM_CCM; + size_t key_bits = YACA_KEY_LENGTH_192BIT; + + yaca_context_h ctx = YACA_CONTEXT_NULL; + yaca_key_h key_pub = YACA_KEY_NULL; + yaca_key_h key_priv = YACA_KEY_NULL; + yaca_key_h sym_key = YACA_KEY_NULL; + yaca_key_h iv = YACA_KEY_NULL; + + char *enc = NULL; + char *dec = NULL; + size_t enc_len; + size_t dec_len; + + char *aad = NULL; + char *tag = NULL; + size_t aad_len = 16; + size_t tag_len = 12; + + size_t block_len; + size_t output_len; + size_t out_len; + size_t rem; + size_t len; + + printf("Plain data (16 of %zu bytes): %.16s\n", LOREM4096_SIZE, lorem4096); + + /* Generate key pair */ + if (yaca_key_generate(YACA_KEY_TYPE_RSA_PRIV, YACA_KEY_LENGTH_3072BIT, &key_priv) != YACA_ERROR_NONE) + return; + + if (yaca_key_extract_public(key_priv, &key_pub) != YACA_ERROR_NONE) + goto exit; + + if (yaca_zalloc(aad_len, (void**)&aad) != YACA_ERROR_NONE) + goto exit; + + if (yaca_randomize_bytes(aad, aad_len) != YACA_ERROR_NONE) + goto exit; + + if (yaca_zalloc(tag_len, (void**)&tag) != YACA_ERROR_NONE) + goto exit; + + /* Encryption */ + { + if (yaca_seal_initialize(&ctx, key_pub, algo, bcm, key_bits, &sym_key, &iv) != YACA_ERROR_NONE) + goto exit; + + /* Set tag length (optionally) */ + if (yaca_context_set_property(ctx, YACA_PROPERTY_CCM_TAG_LEN, + (void*)&tag_len, sizeof(tag_len)) != YACA_ERROR_NONE) + goto exit; + + /* The total plain text length must be passed (only needed if AAD is passed) */ + if (yaca_seal_update(ctx, NULL, LOREM4096_SIZE , NULL, &len) != YACA_ERROR_NONE) + goto exit; + + /* Provide any AAD data */ + if (yaca_context_set_property(ctx, YACA_PROPERTY_CCM_AAD, aad, aad_len) != YACA_ERROR_NONE) + goto exit; + + /* For the update */ + if (yaca_context_get_output_length(ctx, LOREM4096_SIZE, &output_len) != YACA_ERROR_NONE) + goto exit; + + /* For the finalize */ + if (yaca_context_get_output_length(ctx, 0, &block_len) != YACA_ERROR_NONE) + goto exit; + + /* Calculate max output: size of update + final chunks */ + enc_len = output_len + block_len; + if (yaca_malloc(enc_len, (void**)&enc) != YACA_ERROR_NONE) + goto exit; + + out_len = enc_len; + if (yaca_seal_update(ctx, lorem4096, LOREM4096_SIZE, enc, &out_len) != YACA_ERROR_NONE) + goto exit; + + rem = enc_len - out_len; + if (yaca_seal_finalize(ctx, enc + out_len, &rem) != YACA_ERROR_NONE) + goto exit; + + enc_len = rem + out_len; + + /* Get the tag after final encryption */ + if (yaca_context_get_property(ctx, YACA_PROPERTY_CCM_TAG, (void**)tag, &tag_len) != YACA_ERROR_NONE) + goto exit; + + dump_hex(enc, 16, "Encrypted data (16 of %zu bytes): ", enc_len); + + yaca_context_destroy(ctx); + ctx = YACA_CONTEXT_NULL; + } + + /* Decryption */ + { + if (yaca_open_initialize(&ctx, key_priv, algo, bcm, key_bits, sym_key, iv) != YACA_ERROR_NONE) + goto exit; + + /* Set expected tag value */ + if (yaca_context_set_property(ctx, YACA_PROPERTY_CCM_TAG, tag, tag_len) != YACA_ERROR_NONE) + goto exit; + + /* The total encrypted text length must be passed (only needed if AAD is passed) */ + if (yaca_open_update(ctx, NULL, enc_len , NULL, &len) != YACA_ERROR_NONE) + goto exit; + + /* Provide any AAD data */ + if (yaca_context_set_property(ctx, YACA_PROPERTY_CCM_AAD, aad, aad_len) != YACA_ERROR_NONE) + goto exit; + + /* For the update */ + if (yaca_context_get_output_length(ctx, LOREM4096_SIZE, &output_len) != YACA_ERROR_NONE) + goto exit; + + /* For the finalize */ + if (yaca_context_get_output_length(ctx, 0, &block_len) != YACA_ERROR_NONE) + goto exit; + + /* Calculate max output: size of update + final chunks */ + dec_len = output_len + block_len; + if (yaca_malloc(dec_len, (void**)&dec) != YACA_ERROR_NONE) + goto exit; + + out_len = dec_len; + /* The tag verify is performed when you call the final yaca_open_update(), + * there is no call to yaca_open_finalize() */ + if (yaca_open_update(ctx, enc, enc_len, dec, &out_len) != YACA_ERROR_NONE) + goto exit; + + dec_len = out_len; + + printf("Decrypted data (16 of %zu bytes): %.16s\n\n", dec_len, dec); + } + +exit: + yaca_free(dec); + yaca_free(enc); + yaca_context_destroy(ctx); + yaca_key_destroy(sym_key); yaca_key_destroy(iv); yaca_key_destroy(key_pub); yaca_key_destroy(key_priv); @@ -147,7 +435,29 @@ int main() if (ret != YACA_ERROR_NONE) return ret; - encrypt_seal(); + printf("AES CBC 256bit key seal/open\n"); + yaca_encrypt_algorithm_e algo = YACA_ENCRYPT_AES; + yaca_block_cipher_mode_e bcm = YACA_BCM_CBC; + size_t key_bits = YACA_KEY_LENGTH_256BIT; + encrypt_seal(algo, bcm, key_bits); + + printf("3DES 192bit key seal/open\n"); + algo = YACA_ENCRYPT_3DES_3TDEA; + bcm = YACA_BCM_CFB; + key_bits = YACA_KEY_LENGTH_192BIT; + encrypt_seal(algo, bcm, key_bits); + + printf("RC4 40bit key seal/open\n"); + algo = YACA_ENCRYPT_UNSAFE_RC4; + bcm = YACA_BCM_NONE; + key_bits = YACA_KEY_LENGTH_UNSAFE_40BIT; + encrypt_seal(algo, bcm, key_bits); + + printf("AES GCM 256bit key seal/open\n"); + encrypt_seal_aes_gcm(); + + printf("AES CCM 192bit key seal/open\n"); + encrypt_seal_aes_ccm(); yaca_cleanup(); return ret; -- 2.7.4 From fb56dee38ee9686a5f2704ddc7f83ee49a476637 Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Fri, 10 Jun 2016 14:58:52 +0200 Subject: [PATCH 11/16] ACR: Update documentation. Change-Id: I971dcdc742373385c11e9e908b561ac0caf8702f --- api/yaca/yaca_seal.h | 7 ++++++- api/yaca/yaca_types.h | 46 +++++++++++++++++++++++++--------------------- 2 files changed, 31 insertions(+), 22 deletions(-) diff --git a/api/yaca/yaca_seal.h b/api/yaca/yaca_seal.h index d79fb8f..2171130 100644 --- a/api/yaca/yaca_seal.h +++ b/api/yaca/yaca_seal.h @@ -43,7 +43,11 @@ extern "C" { */ /** - * @brief Initializes an asymmetric encryption context. + * @brief Initializes an asymmetric encryption context and generates symmetric key and IV. + * + * @remarks Generated symmetric key is encrypted with public key, + * so can be ONLY used with yaca_open_initialize(). It can be exported, + * but after import it can be ONLY used with yaca_open_initialize() as well. * * @since_tizen 3.0 * @@ -70,6 +74,7 @@ extern "C" { * @see #yaca_key_bit_length_e * @see yaca_seal_update() * @see yaca_seal_finalize() + * @see yaca_open_initialize() * @see yaca_key_destroy() * @see yaca_context_destroy() */ diff --git a/api/yaca/yaca_types.h b/api/yaca/yaca_types.h index 4b35953..60c82f9 100644 --- a/api/yaca/yaca_types.h +++ b/api/yaca/yaca_types.h @@ -285,20 +285,22 @@ typedef enum { * - #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 - * Set after yaca_encrypt_finalize() and before yaca_context_get_property(#YACA_PROPERTY_GCM_TAG) - * in encryption operation.\n\n + * Set after yaca_encrypt_finalize() / yaca_seal_finalize() and before + * yaca_context_get_property(#YACA_PROPERTY_GCM_TAG) + * in encryption / seal operation.\n\n * * - #YACA_PROPERTY_GCM_TAG = GCM tag\n - * Get after yaca_encrypt_finalize() in encryption operation.\n - * Set before yaca_decrypt_finalize() in decryption operation.\n\n + * Get after yaca_encrypt_finalize() / yaca_seal_finalize() in encryption / seal operation.\n + * Set before yaca_decrypt_finalize() / yaca_open_finalize() in decryption / open operation.\n\n * * - #YACA_PROPERTY_GCM_AAD = additional authentication data (optional)\n - * Set after yaca_encrypt_initialize() and before yaca_encrypt_update() - * in encryption operation.\n - * Set after yaca_decrypt_initialize() and before yaca_decrypt_update() - * in decryption operation.\n\n + * Set after yaca_encrypt_initialize() / yaca_seal_initialize() and before + * yaca_encrypt_update() / yaca_seal_update() in encryption / seal operation.\n + * Set after yaca_decrypt_initialize() / yaca_open_initialize() and before + * yaca_decrypt_update() / yaca_open_update() in decryption / open operation.\n\n * * @see examples/encrypt_aes_gcm_ccm.c + * @see examples/seal.c */ YACA_BCM_GCM, @@ -334,27 +336,29 @@ 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 - * Set after yaca_encrypt_initialize() and before yaca_encrypt_update() - * in encryption operation.\n\n + * Set after yaca_encrypt_initialize() / yaca_seal_initialize() and before + * yaca_encrypt_update() / yaca_seal_update() in encryption / seal operation.\n\n * * - #YACA_PROPERTY_CCM_TAG = CCM tag\n - * Get after yaca_encrypt_finalize() in encryption operation.\n - * Set after yaca_decrypt_initialize() and before yaca_decrypt_update() - * in decryption operation.\n\n + * Get after yaca_encrypt_finalize() / yaca_seal_finalize() in encryption / seal operation.\n + * Set after yaca_decrypt_initialize() / yaca_open_initialize() and before + * yaca_decrypt_update() / yaca_open_update() in decryption / open operation.\n\n * * - #YACA_PROPERTY_CCM_AAD = additional authentication data (optional)\n - * The total plaintext length must be passed to yaca_encrypt_update() + * The total plaintext length must be passed to yaca_encrypt_update() / yaca_seal_update() * if AAD is used.\n - * Set after yaca_encrypt_initialize() and before yaca_encrypt_update() - * in encryption operation.\n - * You can only call yaca_encrypt_update() once for AAD and once for the plaintext.\n\n + * Set after yaca_encrypt_initialize() / yaca_seal_initialize() and before + * yaca_encrypt_update() / yaca_seal_update() in encryption / seal operation.\n + * You can only call yaca_encrypt_update() / yaca_seal_update() once for AAD + * and once for the plaintext.\n\n * - * The total encrypted text length must be passed to yaca_decrypt_update() - * if AAD is used.\n - * Set after yaca_decrypt_initialize() and before yaca_decrypt_update() - * in decryption operation.\n\n + * The total encrypted text length must be passed to yaca_decrypt_update() / + * yaca_open_update() if AAD is used.\n + * Set after yaca_decrypt_initialize() / yaca_open_initialize() and before + * yaca_decrypt_update() / yaca_open_update() in decryption / open operation.\n\n * * @see examples/encrypt_aes_gcm_ccm.c + * @see examples/seal.c */ YACA_BCM_CCM -- 2.7.4 From ed9b04efd23c746423bf88982935f75e56a9fe72 Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Thu, 9 Jun 2016 10:16:03 +0200 Subject: [PATCH 12/16] ACR: Initialize and cleanup per thread. yaca_initialize() and yaca_cleanup() should be called once per each thread that uses yaca. Change-Id: I098b7562712193aa5e1eb9475b106255c664de62 --- api/yaca/yaca_crypto.h | 6 +- src/crypto.c | 166 +++++++++++++++++++++++++++++++------------------ 2 files changed, 108 insertions(+), 64 deletions(-) diff --git a/api/yaca/yaca_crypto.h b/api/yaca/yaca_crypto.h index e93d0f1..b9d9899 100644 --- a/api/yaca/yaca_crypto.h +++ b/api/yaca/yaca_crypto.h @@ -46,7 +46,8 @@ extern "C" { #define YACA_CONTEXT_NULL ((yaca_context_h) NULL) /** - * @brief Initializes the library. Must be called before any other crypto function. + * @brief Initializes the library. Must be called before any other crypto + * function. Should be called once in each thread that uses yaca. * * @since_tizen 3.0 * @@ -60,7 +61,8 @@ extern "C" { int yaca_initialize(void); /** - * @brief Closes the library. Must be called before exiting the application. + * @brief Cleans up the library. Must be called before exiting the thread that + * called yaca_initialize(). * * @since_tizen 3.0 * diff --git a/src/crypto.c b/src/crypto.c index fc48c9e..6acdc2a 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -37,6 +38,10 @@ static pthread_mutex_t *mutexes = NULL; +static __thread bool current_thread_initialized = false; +static size_t threads_cnt = 0; +static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER; + static void locking_callback(int mode, int type, UNUSED const char *file, UNUSED int line) { /* Ignore NULL mutexes and lock/unlock error codes as we can't do anything @@ -70,84 +75,121 @@ static void destroy_mutexes(int count) API int yaca_initialize(void) { - int ret; - if (mutexes != NULL) - return YACA_ERROR_INTERNAL; // TODO introduce new one? - - OPENSSL_init(); - - /* This should never fail on a /dev/random equipped system. If it does it - * means we might need to figure out another way of a truly random seed. - * https://wiki.openssl.org/index.php/Random_Numbers - * - * Another things to maybe consider for the future: - * - entropy on a mobile device (no mouse/keyboard) - * - fork safety: https://wiki.openssl.org/index.php/Random_fork-safety - * - hardware random generator (RdRand on new Intels, Samsung hardware?) - */ - if (RAND_status() != 1) { - ERROR_DUMP(YACA_ERROR_INTERNAL); + int ret = YACA_ERROR_NONE; + + /* no calling yaca_initalize() twice on the same thread */ + if (current_thread_initialized) return YACA_ERROR_INTERNAL; - } - OpenSSL_add_all_digests(); - OpenSSL_add_all_ciphers(); - - /* enable threads support */ - if (CRYPTO_num_locks() > 0) { - ret = yaca_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t), (void**)&mutexes); - if (ret != YACA_ERROR_NONE) - return ret; - - for (int i = 0; i < CRYPTO_num_locks(); i++) { - if (pthread_mutex_init(&mutexes[i], NULL) != 0) { - int ret = YACA_ERROR_NONE; - switch (errno) { - case ENOMEM: - ret = YACA_ERROR_OUT_OF_MEMORY; - break; - case EAGAIN: - case EPERM: - case EBUSY: - case EINVAL: - default: - ret = YACA_ERROR_INTERNAL; + pthread_mutex_lock(&init_mutex); + { + if (threads_cnt == 0) + { + assert(mutexes == NULL); + + OPENSSL_init(); + + /* This should never fail on a /dev/random equipped system. If it does it + * means we might need to figure out another way of a truly random seed. + * https://wiki.openssl.org/index.php/Random_Numbers + * + * Another things to maybe consider for the future: + * - entropy on a mobile device (no mouse/keyboard) + * - fork safety: https://wiki.openssl.org/index.php/Random_fork-safety + * - hardware random generator (RdRand on new Intels, Samsung hardware?) + */ + if (RAND_status() != 1) { + ERROR_DUMP(YACA_ERROR_INTERNAL); + ret = YACA_ERROR_INTERNAL; + goto exit; + } + + OpenSSL_add_all_digests(); + OpenSSL_add_all_ciphers(); + + /* enable threads support */ + if (CRYPTO_num_locks() > 0) { + ret = yaca_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t), + (void**)&mutexes); + + if (ret != YACA_ERROR_NONE) + goto exit; + + for (int i = 0; i < CRYPTO_num_locks(); i++) { + if (pthread_mutex_init(&mutexes[i], NULL) != 0) { + ret = YACA_ERROR_NONE; + switch (errno) { + case ENOMEM: + ret = YACA_ERROR_OUT_OF_MEMORY; + break; + case EAGAIN: + case EPERM: + case EBUSY: + case EINVAL: + default: + ret = YACA_ERROR_INTERNAL; + } + destroy_mutexes(i); + + goto exit; + } } - destroy_mutexes(i); - return ret; + CRYPTO_set_id_callback(thread_id_callback); + CRYPTO_set_locking_callback(locking_callback); } - } - CRYPTO_set_id_callback(thread_id_callback); - CRYPTO_set_locking_callback(locking_callback); + /* + * TODO: + * - We should also decide on Openssl config. + * - Here's a good tutorial for initalization and cleanup: + * https://wiki.openssl.org/index.php/Library_Initialization + * - We should also initialize the entropy for random number generator: + * https://wiki.openssl.org/index.php/Random_Numbers#Initialization + */ + } + threads_cnt++; + current_thread_initialized = true; } +exit: + pthread_mutex_unlock(&init_mutex); - /* - * TODO: - * - We should also decide on Openssl config. - * - Here's a good tutorial for initalization and cleanup: - * https://wiki.openssl.org/index.php/Library_Initialization - * - We should also initialize the entropy for random number generator: - * https://wiki.openssl.org/index.php/Random_Numbers#Initialization - */ - - return YACA_ERROR_NONE; + return ret; } API int yaca_cleanup(void) { - ERR_free_strings(); + /* calling cleanup twice on the same thread is a NOP */ + if (!current_thread_initialized) + return YACA_ERROR_NONE; + + /* per thread cleanup */ ERR_remove_thread_state(NULL); - EVP_cleanup(); - RAND_cleanup(); CRYPTO_cleanup_all_ex_data(); - /* threads support cleanup */ - CRYPTO_set_id_callback(NULL); - CRYPTO_set_locking_callback(NULL); + pthread_mutex_lock(&init_mutex); + { + /* last one turns off the light */ + if (threads_cnt == 1) { + ERR_free_strings(); + ERR_remove_thread_state(NULL); + EVP_cleanup(); + RAND_cleanup(); + CRYPTO_cleanup_all_ex_data(); + + /* threads support cleanup */ + CRYPTO_set_id_callback(NULL); + CRYPTO_set_locking_callback(NULL); + + destroy_mutexes(CRYPTO_num_locks()); + } + + assert(threads_cnt > 0); - destroy_mutexes(CRYPTO_num_locks()); + threads_cnt--; + current_thread_initialized = false; + } + pthread_mutex_unlock(&init_mutex); return YACA_ERROR_NONE; } -- 2.7.4 From 5cf03a65e98469da6b1ae7d75772aa7f6c71f2ce Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Mon, 13 Jun 2016 15:16:34 +0200 Subject: [PATCH 13/16] Update error translation function Use macro for error translation. Don't return NULL. Update usage in error_dump(). Change-Id: I4e6368732a89f5710c2354e704dd073512a6b2f1 --- src/debug.c | 42 ++++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/src/debug.c b/src/debug.c index 02d80c6..3778fc9 100644 --- a/src/debug.c +++ b/src/debug.c @@ -41,25 +41,20 @@ API void yaca_debug_set_error_cb(yaca_error_cb fn) error_cb = fn; } -API char *yaca_debug_translate_error(yaca_error_e err) +#define ERRORDESCRIBE(name) case name: return #name +API const char *yaca_debug_translate_error(yaca_error_e err) { - switch (err) { - case YACA_ERROR_NONE: - return "YACA_ERROR_NONE"; - case YACA_ERROR_INVALID_PARAMETER: - return "YACA_ERROR_INVALID_PARAMETER"; - case YACA_ERROR_OUT_OF_MEMORY: - return "YACA_ERROR_OUT_OF_MEMORY"; - case YACA_ERROR_INTERNAL: - return "YACA_ERROR_INTERNAL"; - case YACA_ERROR_DATA_MISMATCH: - return "YACA_ERROR_DATA_MISMATCH"; - case YACA_ERROR_INVALID_PASSWORD: - return "YACA_ERROR_INVALID_PASSWORD"; - default: - return NULL; - } + switch(err) { + ERRORDESCRIBE(YACA_ERROR_NONE); + ERRORDESCRIBE(YACA_ERROR_INVALID_PARAMETER); + ERRORDESCRIBE(YACA_ERROR_OUT_OF_MEMORY); + ERRORDESCRIBE(YACA_ERROR_INTERNAL); + ERRORDESCRIBE(YACA_ERROR_DATA_MISMATCH); + ERRORDESCRIBE(YACA_ERROR_INVALID_PASSWORD); + default: return "Error not defined"; + } } +#undef ERRORDESCRIBE void error_dump(const char *file, int line, const char *function, int code) { @@ -75,12 +70,15 @@ void error_dump(const char *file, int line, const char *function, int code) unsigned long err; size_t written; const char *err_str = yaca_debug_translate_error(code); + const char *sign = ""; + + if (code < 0) { + code *= -1; + sign = "-"; + } - written = snprintf(buf, BUF_SIZE, "%s:%d %s() API error: ", file, line, function); - if (err_str != NULL) - written += snprintf(buf + written, BUF_SIZE - written, "%s\n", err_str); - else - written += snprintf(buf + written, BUF_SIZE - written, "0x%X\n", code); + written = snprintf(buf, BUF_SIZE, "%s:%d %s() API error: %s0x%02X (%s)\n", file, + line, function, sign, code, err_str); while ((err = ERR_get_error()) != 0 && written < BUF_SIZE - 1) { if (!error_strings_loaded) { -- 2.7.4 From 6d708b68bad86163b9b1393b52bc6e3747adfe6c Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Mon, 13 Jun 2016 16:29:43 +0200 Subject: [PATCH 14/16] Make sure library errors are not treated as fatal Openssl defines a bit flag ERR_R_FATAL = 64 which may be used with common error reasons (ERR_R_...). However, it's possible that library specific error reasons (>99) have the bit set as well. ERR_FATAL_ERROR macro doesn't check it. Check added. Change-Id: I92b8b1011d0d22b84ec7e43f53bc60431cfe17fd --- src/debug.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/debug.c b/src/debug.c index 3778fc9..66ece0e 100644 --- a/src/debug.c +++ b/src/debug.c @@ -35,6 +35,7 @@ // TODO any better idea than to use __thread? static __thread yaca_error_cb error_cb = NULL; static bool error_strings_loaded = false; +static const int GENERIC_REASON_MAX = 99; API void yaca_debug_set_error_cb(yaca_error_cb fn) { @@ -133,8 +134,9 @@ int error_handle(const char *file, int line, const char *function) } /* fatal errors */ - if (ret == YACA_ERROR_NONE && ERR_FATAL_ERROR(err) > 0) { - switch (ERR_GET_REASON(err)) { + int reason = ERR_GET_REASON(err); + if (ret == YACA_ERROR_NONE && reason <= GENERIC_REASON_MAX && ERR_FATAL_ERROR(err) > 0) { + switch (reason) { case ERR_R_MALLOC_FAILURE: ret = YACA_ERROR_OUT_OF_MEMORY; break; -- 2.7.4 From fb6985a9cde6c0af3b33068ac79dc99125ecacab Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Wed, 15 Jun 2016 10:18:12 +0200 Subject: [PATCH 15/16] ACR: Describe yaca_key_bit_length_e values Change-Id: Id51e3f99f9ece8279c338896d66020687ec4fb65 --- api/yaca/yaca_types.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/api/yaca/yaca_types.h b/api/yaca/yaca_types.h index 60c82f9..2d5edc9 100644 --- a/api/yaca/yaca_types.h +++ b/api/yaca/yaca_types.h @@ -109,21 +109,37 @@ typedef enum { * @since_tizen 3.0 */ typedef enum { + /** 24 bits */ YACA_KEY_LENGTH_IV_UNSAFE_24BIT = 24, + /** 64 bits */ YACA_KEY_LENGTH_IV_64BIT = 64, + /** 128 bits */ YACA_KEY_LENGTH_IV_128BIT = 128, + /** 256 bits */ YACA_KEY_LENGTH_IV_256BIT = 256, + /** 8 bits */ YACA_KEY_LENGTH_UNSAFE_8BIT = 8, + /** 40 bits */ YACA_KEY_LENGTH_UNSAFE_40BIT = 40, + /** 64 bits */ YACA_KEY_LENGTH_UNSAFE_64BIT = 64, + /** 80 bits */ YACA_KEY_LENGTH_UNSAFE_80BIT = 80, + /** 128 bits */ YACA_KEY_LENGTH_UNSAFE_128BIT = 128, + /** 192 bits */ YACA_KEY_LENGTH_192BIT = 192, + /** 256 bits */ YACA_KEY_LENGTH_256BIT = 256, + /** 512 bits */ YACA_KEY_LENGTH_512BIT = 512, + /** 1024 bits */ YACA_KEY_LENGTH_1024BIT = 1024, + /** 2048 bits */ YACA_KEY_LENGTH_2048BIT = 2048, + /** 3072 bits */ YACA_KEY_LENGTH_3072BIT = 3072, + /** 4096 bits */ YACA_KEY_LENGTH_4096BIT = 4096 } yaca_key_bit_length_e; -- 2.7.4 From f2b88dbd1879cc6dde334a759d696178e5147532 Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Wed, 15 Jun 2016 17:32:31 +0200 Subject: [PATCH 16/16] Make sure output length argument is not NULL Change-Id: I2ed584063314213efba934b282f603ce49f69899 --- src/crypto.c | 2 +- src/digest.c | 2 ++ src/encrypt.c | 2 ++ src/sign.c | 2 ++ 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/crypto.c b/src/crypto.c index 6acdc2a..40f6a99 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -291,7 +291,7 @@ API int yaca_context_destroy(yaca_context_h ctx) API int yaca_context_get_output_length(const yaca_context_h ctx, size_t input_len, size_t *output_len) { - if (ctx == YACA_CONTEXT_NULL) + if (ctx == YACA_CONTEXT_NULL || output_len == NULL) return YACA_ERROR_INVALID_PARAMETER; return ctx->get_output_length(ctx, input_len, output_len); diff --git a/src/digest.c b/src/digest.c index 235a0a2..64b88f4 100644 --- a/src/digest.c +++ b/src/digest.c @@ -54,6 +54,8 @@ static int get_digest_output_length(const yaca_context_h ctx, UNUSED size_t input_len, size_t *output_len) { + assert(output_len != NULL); + struct yaca_digest_ctx_s *c = get_digest_ctx(ctx); if (c == NULL) diff --git a/src/encrypt.c b/src/encrypt.c index 7a01f33..5942e2e 100644 --- a/src/encrypt.c +++ b/src/encrypt.c @@ -59,6 +59,8 @@ void destroy_encrypt_context(const yaca_context_h ctx) int get_encrypt_output_length(const yaca_context_h ctx, size_t input_len, size_t *output_len) { + assert(output_len != NULL); + struct yaca_encrypt_context_s *nc = get_encrypt_context(ctx); int block_size; diff --git a/src/sign.c b/src/sign.c index 7be2005..98543e0 100644 --- a/src/sign.c +++ b/src/sign.c @@ -67,6 +67,8 @@ static int get_sign_output_length(const yaca_context_h ctx, UNUSED size_t input_len, size_t *output_len) { + assert(output_len != NULL); + struct yaca_sign_ctx_s *c = get_sign_ctx(ctx); if (c == NULL) -- 2.7.4