From 9ce0b9aa4c0d951859fbca69264d157e459a06a9 Mon Sep 17 00:00:00 2001 From: Mateusz Kulikowski Date: Wed, 6 Apr 2016 15:31:22 +0200 Subject: [PATCH 01/16] key: implement pbkdf2 - Fixup key_len - it is now size_t - Add maximum password length Change-Id: Ic5bc6de538f305020c52219793e2dc440de47eb3 Signed-off-by: Mateusz Kulikowski --- api/yaca/key.h | 2 +- src/key.c | 44 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/api/yaca/key.h b/api/yaca/key.h index 342d733..7198ff3 100644 --- a/api/yaca/key.h +++ b/api/yaca/key.h @@ -184,7 +184,7 @@ int yaca_key_derive_pbkdf2(const char *password, size_t salt_len, int iter, yaca_digest_algo_e algo, - yaca_key_len_e key_len, + size_t key_len, yaca_key_h *key); // TODO: specify diff --git a/src/key.c b/src/key.c index e230156..41070da 100644 --- a/src/key.c +++ b/src/key.c @@ -20,6 +20,9 @@ #include #include #include +#include + +#include #include #include @@ -390,8 +393,45 @@ API int yaca_key_derive_pbkdf2(const char *password, size_t salt_len, int iter, yaca_digest_algo_e algo, - yaca_key_len_e key_len, + size_t key_len, yaca_key_h *key) { - return YACA_ERROR_NOT_IMPLEMENTED; + const EVP_MD *md; + struct yaca_key_simple_s *nk; + int ret; + + if (password == NULL || salt == NULL || salt_len == 0 || + iter == 0 || key_len == 0 || key == NULL) + return YACA_ERROR_INVALID_ARGUMENT; + + ret = get_digest_algorithm(algo, &md); + if (ret < 0) + return ret; + + if (key_len % 8) /* Key length must be multiple of 8-bits */ + return YACA_ERROR_INVALID_ARGUMENT; + + if (key_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_len); + if (nk == NULL) + return YACA_ERROR_OUT_OF_MEMORY; + + nk->length = key_len; + nk->key.type = YACA_KEY_TYPE_SYMMETRIC; // TODO: how to handle other keys? + + ret = PKCS5_PBKDF2_HMAC(password, -1, (const unsigned char*)salt, + salt_len, iter, md, key_len / 8, + (unsigned char*)nk->d); + if (ret != 1) { + ret = YACA_ERROR_OPENSSL_FAILURE; // TODO: yaca_get_error_code_from_openssl(ret); + goto err; + } + + *key = (yaca_key_h)nk; + return 0; +err: + yaca_free(nk); + return ret; } -- 2.7.4 From 668268c553ad5cdc9bf98e4ec9898a48d86af3cd Mon Sep 17 00:00:00 2001 From: Mateusz Kulikowski Date: Wed, 6 Apr 2016 15:32:10 +0200 Subject: [PATCH 02/16] key: Check for key_len overflows Affected functions: - key_import - key_gen Change-Id: I1b2898b03d3bf950706c21671afe9d6a89311255 Signed-off-by: Mateusz Kulikowski --- src/key.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/key.c b/src/key.c index 41070da..426ec6d 100644 --- a/src/key.c +++ b/src/key.c @@ -155,7 +155,7 @@ API int yaca_key_import(yaca_key_h *key, struct yaca_key_simple_s *nk = NULL; yaca_key_h k; - if (sizeof(struct yaca_key_s) + data_len < data_len) + 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); @@ -230,6 +230,8 @@ API int yaca_key_gen(yaca_key_h *sym_key, if (key_type != YACA_KEY_TYPE_SYMMETRIC && key_type != YACA_KEY_TYPE_IV) return YACA_ERROR_NOT_IMPLEMENTED; + if (key_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_len); if (nk == NULL) -- 2.7.4 From a75b4108770d47157886ede13774eeab3a858d08 Mon Sep 17 00:00:00 2001 From: Mateusz Kulikowski Date: Wed, 6 Apr 2016 15:33:39 +0200 Subject: [PATCH 03/16] key: Cleanups - Clean import for symmetric keys - Clean generation of "simple/single" keys - Return proper error from yaca_key_gen (key not supported vs invalid type) Change-Id: Ia993ad1b1908dd9c5babc31b687e2e9b9bc07eba Signed-off-by: Mateusz Kulikowski --- src/key.c | 42 +++++++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/src/key.c b/src/key.c index 426ec6d..41000d2 100644 --- a/src/key.c +++ b/src/key.c @@ -153,7 +153,6 @@ API int yaca_key_import(yaca_key_h *key, if (key_type == YACA_KEY_TYPE_SYMMETRIC) { struct yaca_key_simple_s *nk = NULL; - yaca_key_h k; if (data_len > SIZE_MAX - sizeof(struct yaca_key_simple_s)) return YACA_ERROR_TOO_BIG_ARGUMENT; @@ -164,10 +163,9 @@ API int yaca_key_import(yaca_key_h *key, memcpy(nk->d, data, data_len); /* TODO: CRYPTO_/EVP_... */ nk->length = data_len * 8; + nk->key.type = key_type; - k = (yaca_key_h)nk; - k->type = key_type; - *key = k; + *key = (yaca_key_h)nk; return 0; } @@ -227,9 +225,29 @@ API int yaca_key_gen(yaca_key_h *sym_key, if (sym_key == NULL) return YACA_ERROR_INVALID_ARGUMENT; - if (key_type != YACA_KEY_TYPE_SYMMETRIC && - key_type != YACA_KEY_TYPE_IV) + switch(key_type) + { + case YACA_KEY_TYPE_SYMMETRIC: + case YACA_KEY_TYPE_IV: + break; + case YACA_KEY_TYPE_DES: + case YACA_KEY_TYPE_RSA_PUB: /**< RSA public key */ + case YACA_KEY_TYPE_RSA_PRIV: /**< RSA private key */ + case YACA_KEY_TYPE_DSA_PUB: /**< DSA public key */ + case YACA_KEY_TYPE_DSA_PRIV: /**< DSA private key */ + case YACA_KEY_TYPE_DH_PUB: /**< Diffie-Hellman public key */ + case YACA_KEY_TYPE_DH_PRIV: /**< Diffie-Hellman private key */ + case YACA_KEY_TYPE_ECC_PUB: /**< ECC public key */ + case YACA_KEY_TYPE_ECC_PRIV: /**< ECC private key */ + case YACA_KEY_TYPE_PAIR_RSA: /**< Pair of RSA keys */ + case YACA_KEY_TYPE_PAIR_DSA: /**< Pair of DSA keys */ + case YACA_KEY_TYPE_PAIR_DH: /**< Pair of Diffie-Hellman keys */ + case YACA_KEY_TYPE_PAIR_ECC: /**< Pair of ECC keys */ return YACA_ERROR_NOT_IMPLEMENTED; + default: + return YACA_ERROR_INVALID_ARGUMENT; + } + if (key_len > SIZE_MAX - sizeof(struct yaca_key_simple_s)) return YACA_ERROR_TOO_BIG_ARGUMENT; @@ -238,20 +256,18 @@ API int yaca_key_gen(yaca_key_h *sym_key, return YACA_ERROR_OUT_OF_MEMORY; nk->length = key_len; + nk->key.type = key_type; ret = yaca_rand_bytes(nk->d, key_len); if (ret != 0) - goto free; + goto err; *sym_key = (yaca_key_h)nk; - (*sym_key)->type = key_type; - - ret = 0; -free: - if (ret != 0) - yaca_free(nk); + return 0; +err: + yaca_free(nk); return ret; } -- 2.7.4 From 372c0a8ee63467eaaa0248342a9252672e10d0fe Mon Sep 17 00:00:00 2001 From: Mateusz Kulikowski Date: Fri, 8 Apr 2016 12:25:37 +0200 Subject: [PATCH 04/16] Convert all key lengths to bits - Rename API parameters to avoid confusion (key_len -> key_bits) - Rename internal key length to key_bits - Fix key length handling where it was done incorrectly Change-Id: If3dcf8ad87246a144019d3fc93c6251c3529d881 Signed-off-by: Mateusz Kulikowski --- api/yaca/crypto.h | 8 ++++---- api/yaca/key.h | 16 ++++++++-------- api/yaca/types.h | 2 +- src/crypto.c | 2 +- src/key.c | 42 ++++++++++++++++++++++-------------------- 5 files changed, 36 insertions(+), 34 deletions(-) diff --git a/api/yaca/crypto.h b/api/yaca/crypto.h index 526bda3..66d77e6 100644 --- a/api/yaca/crypto.h +++ b/api/yaca/crypto.h @@ -165,15 +165,15 @@ int yaca_get_output_length(const yaca_ctx_h ctx, size_t input_len); /** * @brief yaca_get_iv_length 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_len Key length (@see crypto_key_len_e). + * @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. */ int yaca_get_iv_length(yaca_enc_algo_e algo, yaca_block_cipher_mode_e bcm, - size_t key_len); + size_t key_bits); /**@}*/ diff --git a/api/yaca/key.h b/api/yaca/key.h index 7198ff3..b479867 100644 --- a/api/yaca/key.h +++ b/api/yaca/key.h @@ -48,7 +48,7 @@ extern "C" { * * @param[in] key Key which length we return. * - * @return negative on error (@see error.h) or key length. + * @return negative on error (@see error.h) or key length (in bits). */ int yaca_key_get_length(const yaca_key_h key); @@ -91,13 +91,13 @@ int yaca_key_export(const yaca_key_h key, * * @param[out] sym_key Newly generated key (must be freed with @see yaca_key_free). * @param[in] key_type Type of the key to be generated. - * @param[in] key_len Length of the key to be generated. + * @param[in] key_bits Length of the key (in bits) to be generated. * * @return 0 on success, negative on error (@see error.h). */ int yaca_key_gen(yaca_key_h *sym_key, yaca_key_type_e key_type, - size_t key_len); + size_t key_bits); /** * @brief yaca_key_gen_pair Generates a new key pair. @@ -105,18 +105,18 @@ int yaca_key_gen(yaca_key_h *sym_key, * @param[out] prv_key Newly generated private key (must be freed with @see yaca_key_free). * @param[out] pub_key Newly generated public key (must be freed with @see yaca_key_free). * @param[in] key_type Type of the key to be generated (must be YACA_KEY_TYPE_PAIR*). - * @param[in] key_len Length of the key to be generated. + * @param[in] key_bits Length of the key (in bits) to be generated. * * @return 0 on success, negative on error (@see error.h). */ int yaca_key_gen_pair(yaca_key_h *prv_key, yaca_key_h *pub_key, yaca_key_type_e key_type, - size_t key_len); + size_t key_bits); /** * @brief yaca_key_free Frees the key created by the library. - * Passing YACA_KEY_NULL is allowed. + * Passing YACA_KEY_NULL is allowed. * * @param key Key to be freed. * @@ -174,7 +174,7 @@ int yaca_key_derive_kea(const yaca_key_h prv_key, * @param[in] salt_len Length of the salt. * @param[in] iter Number of iterations. (TODO: add enum to proposed number of iterations, pick sane defaults). * @param[in] algo Digest algorithm that should be used in key generation. (TODO: sane defaults). - * @param[in] key_len Length of a key to be generated. + * @param[in] key_bits Length of a key (in bits) to be generated. * @param[out] key Newly generated key (must be freed with @see yaca_key_free). * * @return 0 on success, negative on error (@see error.h). @@ -184,7 +184,7 @@ int yaca_key_derive_pbkdf2(const char *password, size_t salt_len, int iter, yaca_digest_algo_e algo, - size_t key_len, + size_t key_bits, yaca_key_h *key); // TODO: specify diff --git a/api/yaca/types.h b/api/yaca/types.h index 020af4d..c4e52b8 100644 --- a/api/yaca/types.h +++ b/api/yaca/types.h @@ -105,7 +105,7 @@ typedef enum { YACA_KEY_2048BIT = 2048, YACA_KEY_3072BIT = 3072, YACA_KEY_4096BIT = 4096 -} yaca_key_len_e; +} yaca_key_bits_e; /** * @brief Message digest algorithms. CMAC is included to simplify API diff --git a/src/crypto.c b/src/crypto.c index 74c3f12..b77e9a2 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -108,7 +108,7 @@ API int yaca_get_output_length(const yaca_ctx_h ctx, size_t input_len) API int yaca_get_iv_length(yaca_enc_algo_e algo, yaca_block_cipher_mode_e bcm, - size_t key_len) + size_t key_bits) { return YACA_ERROR_NOT_IMPLEMENTED; } diff --git a/src/key.c b/src/key.c index 41000d2..b169bc3 100644 --- a/src/key.c +++ b/src/key.c @@ -44,7 +44,7 @@ struct yaca_key_simple_s { struct yaca_key_s key; - size_t length; + size_t bits; char d[0]; }; @@ -99,8 +99,8 @@ static struct yaca_key_evp_s *get_evp_key(const yaca_key_h key) static inline void simple_key_sanity_check(const struct yaca_key_simple_s *key) { - assert(key->length); - assert(key->length % 8 == 0); + assert(key->bits); + assert(key->bits % 8 == 0); } // TODO: do we need a sanity check sanity for Evp keys? @@ -128,7 +128,7 @@ API int yaca_key_get_length(const yaca_key_h key) if (simple_key != NULL) { simple_key_sanity_check(simple_key); - return simple_key->length; + return simple_key->bits; } if (evp_key != NULL) { @@ -162,7 +162,7 @@ API int yaca_key_import(yaca_key_h *key, return YACA_ERROR_OUT_OF_MEMORY; memcpy(nk->d, data, data_len); /* TODO: CRYPTO_/EVP_... */ - nk->length = data_len * 8; + nk->bits = data_len * 8; nk->key.type = key_type; *key = (yaca_key_h)nk; @@ -198,7 +198,7 @@ API int yaca_key_export(const yaca_key_h key, if (simple_key != NULL) { simple_key_sanity_check(simple_key); - byte_len = simple_key->length / 8; + byte_len = simple_key->bits / 8; *data = yaca_malloc(byte_len); memcpy(*data, simple_key->d, byte_len); *data_len = byte_len; @@ -217,10 +217,11 @@ API int yaca_key_export(const yaca_key_h key, API int yaca_key_gen(yaca_key_h *sym_key, yaca_key_type_e key_type, - size_t key_len) + size_t key_bits) { int ret; struct yaca_key_simple_s *nk = NULL; + size_t key_byte_len = key_bits / 8; if (sym_key == NULL) return YACA_ERROR_INVALID_ARGUMENT; @@ -248,17 +249,17 @@ API int yaca_key_gen(yaca_key_h *sym_key, return YACA_ERROR_INVALID_ARGUMENT; } - if (key_len > SIZE_MAX - sizeof(struct yaca_key_simple_s)) + 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_len); + nk = yaca_malloc(sizeof(struct yaca_key_simple_s) + key_byte_len); if (nk == NULL) return YACA_ERROR_OUT_OF_MEMORY; - nk->length = key_len; + nk->bits = key_bits; nk->key.type = key_type; - ret = yaca_rand_bytes(nk->d, key_len); + ret = yaca_rand_bytes(nk->d, key_byte_len); if (ret != 0) goto err; @@ -274,7 +275,7 @@ err: API int yaca_key_gen_pair(yaca_key_h *prv_key, yaca_key_h *pub_key, yaca_key_type_e key_type, - size_t key_len) + size_t key_bits) { int ret; struct yaca_key_evp_s *nk_prv = NULL; @@ -319,7 +320,7 @@ API int yaca_key_gen_pair(yaca_key_h *prv_key, goto free_bne; } - ret = RSA_generate_key_ex(rsa, key_len, bne, NULL); + ret = RSA_generate_key_ex(rsa, key_bits, bne, NULL); if (ret != 1) { ret = YACA_ERROR_OPENSSL_FAILURE; goto free_rsa; @@ -411,36 +412,37 @@ API int yaca_key_derive_pbkdf2(const char *password, size_t salt_len, int iter, yaca_digest_algo_e algo, - size_t key_len, + size_t key_bits, yaca_key_h *key) { const EVP_MD *md; struct yaca_key_simple_s *nk; + size_t key_byte_len = key_bits / 8; int ret; if (password == NULL || salt == NULL || salt_len == 0 || - iter == 0 || key_len == 0 || key == NULL) + iter == 0 || key_bits == 0 || key == NULL) return YACA_ERROR_INVALID_ARGUMENT; ret = get_digest_algorithm(algo, &md); if (ret < 0) return ret; - if (key_len % 8) /* Key length must be multiple of 8-bits */ + if (key_bits % 8) /* Key length must be multiple of 8-bits */ return YACA_ERROR_INVALID_ARGUMENT; - if (key_len > SIZE_MAX - sizeof(struct yaca_key_simple_s)) + 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_len); + nk = yaca_malloc(sizeof(struct yaca_key_simple_s) + key_byte_len); if (nk == NULL) return YACA_ERROR_OUT_OF_MEMORY; - nk->length = key_len; + nk->bits = key_bits; nk->key.type = YACA_KEY_TYPE_SYMMETRIC; // TODO: how to handle other keys? ret = PKCS5_PBKDF2_HMAC(password, -1, (const unsigned char*)salt, - salt_len, iter, md, key_len / 8, + salt_len, iter, md, key_byte_len, (unsigned char*)nk->d); if (ret != 1) { ret = YACA_ERROR_OPENSSL_FAILURE; // TODO: yaca_get_error_code_from_openssl(ret); -- 2.7.4 From c971d9b0bd5327c72e8f449832a7084e4b810445 Mon Sep 17 00:00:00 2001 From: Mateusz Kulikowski Date: Fri, 8 Apr 2016 12:48:07 +0200 Subject: [PATCH 05/16] Move key structures to internal API header, expose getters - Rename get_evp|simple_key to key_get_evp|simple and expose as internal API - Move key structures to internal API header Change-Id: I192d456b90043446e93b788fab5c9e5625dfd3f6 Signed-off-by: Mateusz Kulikowski --- src/internal.h | 33 ++++++++++++++++++++++ src/key.c | 86 +++++++++++++++++++--------------------------------------- 2 files changed, 61 insertions(+), 58 deletions(-) diff --git a/src/internal.h b/src/internal.h index 75d42c2..a1bc9a6 100644 --- a/src/internal.h +++ b/src/internal.h @@ -55,6 +55,39 @@ struct yaca_key_s int (*get_key_length)(const struct yaca_key_s *key); }; +/** + * Internal type for: + * - YACA_KEY_TYPE_SYMMETRIC + * - YACA_KEY_TYPE_DES + * - YACA_KEY_TYPE_IV + */ +struct yaca_key_simple_s +{ + struct yaca_key_s key; + + size_t bits; + char d[0]; +}; + +/** + * Internal type for: + * - YACA_KEY_TYPE_RSA_PUB + * - YACA_KEY_TYPE_RSA_PRIV + * - YACA_KEY_TYPE_DSA_PUB + * - YACA_KEY_TYPE_DSA_PRIV + * + * TODO: and possibly others (for every key that uses EVP_PKEY) + */ +struct yaca_key_evp_s +{ + struct yaca_key_s key; + + EVP_PKEY *evp; +}; + int get_digest_algorithm(yaca_digest_algo_e algo, const EVP_MD **md); +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); + #endif diff --git a/src/key.c b/src/key.c index b169bc3..9de4611 100644 --- a/src/key.c +++ b/src/key.c @@ -34,37 +34,31 @@ #include "internal.h" -/** - * Internal type for: - * - YACA_KEY_TYPE_SYMMETRIC - * - YACA_KEY_TYPE_DES - * - YACA_KEY_TYPE_IV - */ -struct yaca_key_simple_s +static inline void simple_key_sanity_check(const struct yaca_key_simple_s *key) { - struct yaca_key_s key; - - size_t bits; - char d[0]; -}; - -/** - * Internal type for: - * - YACA_KEY_TYPE_RSA_PUB - * - YACA_KEY_TYPE_RSA_PRIV - * - YACA_KEY_TYPE_DSA_PUB - * - YACA_KEY_TYPE_DSA_PRIV - * - * TODO: and possibly others (for every key that uses EVP_PKEY) - */ -struct yaca_key_evp_s + assert(key->bits); + assert(key->bits % 8 == 0); +} + +// TODO: do we need a sanity check sanity for Evp keys? +static inline void evp_key_sanity_check(const struct yaca_key_evp_s *key) +{ +} + +// TODO: do we need this variant? or the two above are enough? +static inline void key_sanity_check(const yaca_key_h key) { - struct yaca_key_s key; + const struct yaca_key_simple_s *simple_key = key_get_simple(key); + const struct yaca_key_evp_s *evp_key = key_get_evp(key); - EVP_PKEY *evp; -}; + if (simple_key != NULL) + simple_key_sanity_check(simple_key); -static struct yaca_key_simple_s *get_simple_key(const yaca_key_h key) + if (evp_key != NULL) + evp_key_sanity_check(evp_key); +} + +struct yaca_key_simple_s *key_get_simple(const yaca_key_h key) { if (key == YACA_KEY_NULL) return NULL; @@ -80,7 +74,7 @@ static struct yaca_key_simple_s *get_simple_key(const yaca_key_h key) } } -static struct yaca_key_evp_s *get_evp_key(const yaca_key_h key) +struct yaca_key_evp_s *key_get_evp(const yaca_key_h key) { if (key == YACA_KEY_NULL) return NULL; @@ -97,34 +91,10 @@ static struct yaca_key_evp_s *get_evp_key(const yaca_key_h key) } } -static inline void simple_key_sanity_check(const struct yaca_key_simple_s *key) -{ - assert(key->bits); - assert(key->bits % 8 == 0); -} - -// TODO: do we need a sanity check sanity for Evp keys? -static inline void evp_key_sanity_check(const struct yaca_key_evp_s *key) -{ -} - -// TODO: do we need this variant? or the two above are enough? -static inline void key_sanity_check(const yaca_key_h key) -{ - const struct yaca_key_simple_s *simple_key = get_simple_key(key); - const struct yaca_key_evp_s *evp_key = get_evp_key(key); - - if (simple_key != NULL) - simple_key_sanity_check(simple_key); - - if (evp_key != NULL) - evp_key_sanity_check(evp_key); -} - API int yaca_key_get_length(const yaca_key_h key) { - const struct yaca_key_simple_s *simple_key = get_simple_key(key); - const struct yaca_key_evp_s *evp_key = get_evp_key(key); + const struct yaca_key_simple_s *simple_key = key_get_simple(key); + const struct yaca_key_evp_s *evp_key = key_get_evp(key); if (simple_key != NULL) { simple_key_sanity_check(simple_key); @@ -186,8 +156,8 @@ API int yaca_key_export(const yaca_key_h key, size_t *data_len) { size_t byte_len; - struct yaca_key_simple_s *simple_key = get_simple_key(key); - struct yaca_key_evp_s *evp_key = get_evp_key(key); + struct yaca_key_simple_s *simple_key = key_get_simple(key); + struct yaca_key_evp_s *evp_key = key_get_evp(key); if (data == NULL || data_len == NULL) return YACA_ERROR_INVALID_ARGUMENT; @@ -379,8 +349,8 @@ free_prv: API void yaca_key_free(yaca_key_h key) { - struct yaca_key_simple_s *simple_key = get_simple_key(key); - struct yaca_key_evp_s *evp_key = get_evp_key(key); + struct yaca_key_simple_s *simple_key = key_get_simple(key); + struct yaca_key_evp_s *evp_key = key_get_evp(key); if (simple_key != NULL) yaca_free(simple_key); -- 2.7.4 From 6f48732023cc006e21c1680a19e3db263760d189 Mon Sep 17 00:00:00 2001 From: Mateusz Kulikowski Date: Fri, 8 Apr 2016 12:49:31 +0200 Subject: [PATCH 06/16] Rename get_digest_algorithm -> digest_get_algorithm Use common naming for internal API Change-Id: Ie6dce91fca60d099249e32938b9ebc5dd8a1a6d2 Signed-off-by: Mateusz Kulikowski --- src/digest.c | 4 ++-- src/internal.h | 2 +- src/key.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/digest.c b/src/digest.c index 8893e57..4cc0ceb 100644 --- a/src/digest.c +++ b/src/digest.c @@ -70,7 +70,7 @@ static void destroy_digest_context(yaca_ctx_h ctx) EVP_MD_CTX_destroy(c->mdctx); } -int get_digest_algorithm(yaca_digest_algo_e algo, const EVP_MD **md) +int digest_get_algorithm(yaca_digest_algo_e algo, const EVP_MD **md) { int ret = 0; @@ -129,7 +129,7 @@ API int yaca_digest_init(yaca_ctx_h *ctx, yaca_digest_algo_e algo) nc->ctx.ctx_destroy = destroy_digest_context; nc->ctx.get_output_length = get_digest_output_length; - ret = get_digest_algorithm(algo, &nc->md); + ret = digest_get_algorithm(algo, &nc->md); if (ret < 0) goto free; diff --git a/src/internal.h b/src/internal.h index a1bc9a6..6aefaa8 100644 --- a/src/internal.h +++ b/src/internal.h @@ -85,7 +85,7 @@ struct yaca_key_evp_s EVP_PKEY *evp; }; -int get_digest_algorithm(yaca_digest_algo_e algo, const EVP_MD **md); +int digest_get_algorithm(yaca_digest_algo_e algo, const EVP_MD **md); 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/key.c b/src/key.c index 9de4611..65245d0 100644 --- a/src/key.c +++ b/src/key.c @@ -394,7 +394,7 @@ API int yaca_key_derive_pbkdf2(const char *password, iter == 0 || key_bits == 0 || key == NULL) return YACA_ERROR_INVALID_ARGUMENT; - ret = get_digest_algorithm(algo, &md); + ret = digest_get_algorithm(algo, &md); if (ret < 0) return ret; -- 2.7.4 From 72833a0f34413ad54a44042e3f3f08a7e363c6f1 Mon Sep 17 00:00:00 2001 From: Mateusz Kulikowski Date: Mon, 11 Apr 2016 11:43:04 +0200 Subject: [PATCH 07/16] yaca_ctx_free: NULL context handling Ignore null contexts. Change-Id: I7ecac9603519d91d5708f4eed11af0a9f8a4ce17 Signed-off-by: Mateusz Kulikowski --- src/crypto.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/crypto.c b/src/crypto.c index b77e9a2..af73404 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -94,8 +94,10 @@ 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) { - ctx->ctx_destroy(ctx); - yaca_free(ctx); + if (ctx != YACA_CTX_NULL) { + ctx->ctx_destroy(ctx); + yaca_free(ctx); + } } API int yaca_get_output_length(const yaca_ctx_h ctx, size_t input_len) -- 2.7.4 From a8733e8a18c0b9261987108ee2c937f624e53546 Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Fri, 8 Apr 2016 16:26:48 +0200 Subject: [PATCH 08/16] Fix compilation with Clang. Some bugs in the code fixed, caught by Clang warnings/errors. Change-Id: If6b2b617222ea8d07d5d3af4202a4dae3b7ebebe Signed-off-by: Lukasz Pawelczyk --- examples/encrypt.c | 5 +++-- examples/encrypt_aes_gcm.c | 8 ++++---- examples/lorem.c | 2 +- examples/sign.c | 6 +++--- src/key.c | 2 ++ 5 files changed, 13 insertions(+), 10 deletions(-) diff --git a/examples/encrypt.c b/examples/encrypt.c index 26f21e8..8ca1bc1 100644 --- a/examples/encrypt.c +++ b/examples/encrypt.c @@ -100,7 +100,7 @@ void encrypt_advanced(void) if (ret) return; - ret = yaca_key_gen(&iv, YACA_KEY_IV_256BIT, YACA_KEY_TYPE_SYMMETRIC); + ret = yaca_key_gen(&iv, YACA_KEY_TYPE_SYMMETRIC, YACA_KEY_IV_256BIT); if (ret) goto ex_key; @@ -208,7 +208,8 @@ void encrypt_seal(void) /// Generate key pair ret = yaca_key_gen_pair(&key_priv, &key_pub, - YACA_KEY_2048BIT, YACA_KEY_TYPE_PAIR_RSA); + YACA_KEY_TYPE_PAIR_RSA, + YACA_KEY_2048BIT); if (ret) return; /// Encrypt a.k.a. seal diff --git a/examples/encrypt_aes_gcm.c b/examples/encrypt_aes_gcm.c index bd65c0d..3976170 100644 --- a/examples/encrypt_aes_gcm.c +++ b/examples/encrypt_aes_gcm.c @@ -36,7 +36,7 @@ void encrypt_decrypt_aes_gcm(void) { int ret; - yaca_ctx_h ctx; + yaca_ctx_h ctx = YACA_CTX_NULL; yaca_key_h key = YACA_KEY_NULL; yaca_key_h iv = YACA_KEY_NULL; @@ -55,17 +55,17 @@ void encrypt_decrypt_aes_gcm(void) /// Key generation - ret = yaca_key_gen(&key, YACA_KEY_256BIT, YACA_KEY_TYPE_SYMMETRIC); // key_type, key_len, *key ? looks imo much better + ret = yaca_key_gen(&key, YACA_KEY_TYPE_SYMMETRIC, YACA_KEY_256BIT); // key_type, key_len, *key ? looks imo much better if (ret < 0) goto clean; // use YACA_KEY_IV_128BIT & YACA_KEY_TYPE_IV or maybe YACA_KEY_128BIT & YACA_KEY_TYPE_SYMMETRIC ? - ret = yaca_key_gen(&iv, YACA_KEY_IV_128BIT, YACA_KEY_TYPE_IV); + ret = yaca_key_gen(&iv, YACA_KEY_TYPE_IV, YACA_KEY_IV_128BIT); if (ret < 0) goto clean; // use YACA_KEY_128BIT & YACA_KEY_TYPE_SYMMETRIC or maybe add YACA_KEY_AAD_128BIT & YACA_KEY_TYPE_AAD ? - ret = yaca_key_gen(&aad_key, YACA_KEY_UNSAFE_128BIT, YACA_KEY_TYPE_SYMMETRIC); + ret = yaca_key_gen(&aad_key, YACA_KEY_TYPE_SYMMETRIC, YACA_KEY_UNSAFE_128BIT); if (ret < 0) goto clean; diff --git a/examples/lorem.c b/examples/lorem.c index cfeaebb..ac6955f 100644 --- a/examples/lorem.c +++ b/examples/lorem.c @@ -18,7 +18,7 @@ /** * @file lorem.c - * @brief + * @brief Lorem Ipsum */ const char *lorem8 = "Lorem i"; diff --git a/examples/sign.c b/examples/sign.c index eb3fc28..dbec172 100644 --- a/examples/sign.c +++ b/examples/sign.c @@ -110,7 +110,7 @@ void sign_verify_rsa(void) // GENERATE - if (yaca_key_gen_pair(&prv, &pub, YACA_KEY_4096BIT, YACA_KEY_TYPE_PAIR_RSA)) + if (yaca_key_gen_pair(&prv, &pub, YACA_KEY_TYPE_PAIR_RSA, YACA_KEY_4096BIT)) return; @@ -160,7 +160,7 @@ void sign_verify_hmac(void) // GENERATE - if (yaca_key_gen(&key, YACA_KEY_256BIT, YACA_KEY_TYPE_SYMMETRIC)) + if (yaca_key_gen(&key, YACA_KEY_TYPE_SYMMETRIC, YACA_KEY_256BIT)) return; // SIGN @@ -197,7 +197,7 @@ void sign_verify_cmac(void) // GENERATE - if( yaca_key_gen(&key, YACA_KEY_256BIT, YACA_KEY_TYPE_SYMMETRIC)) + if( yaca_key_gen(&key, YACA_KEY_TYPE_SYMMETRIC, YACA_KEY_256BIT)) return; // SIGN diff --git a/src/key.c b/src/key.c index 65245d0..78dd5c8 100644 --- a/src/key.c +++ b/src/key.c @@ -46,6 +46,7 @@ static inline void evp_key_sanity_check(const struct yaca_key_evp_s *key) } // TODO: do we need this variant? or the two above are enough? +#if 0 static inline void key_sanity_check(const yaca_key_h key) { const struct yaca_key_simple_s *simple_key = key_get_simple(key); @@ -57,6 +58,7 @@ static inline void key_sanity_check(const yaca_key_h key) if (evp_key != NULL) evp_key_sanity_check(evp_key); } +#endif struct yaca_key_simple_s *key_get_simple(const yaca_key_h key) { -- 2.7.4 From a4216c9caa65f8d2466ef00e0eb0136ce28e3193 Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Mon, 11 Apr 2016 14:24:27 +0200 Subject: [PATCH 09/16] Enable extra compilation flags. Change-Id: I689300d8176eacdad75ddf19bb1b3f91510e872d --- CMakeLists.txt | 12 +++++++----- src/internal.h | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bffb0dd..a42b702 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,16 +58,18 @@ SET(CMAKE_C_FLAGS_RELEASE "-std=c11 -O2 -DNDEBUG") 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 -#ADD_DEFINITIONS("-pedantic") # Be pedantic -#ADD_DEFINITIONS("-pedantic-errors") # Make pedantic warnings into errors +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}") IF("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang") # Warn about documentation problems - SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wdocumentation") + ADD_DEFINITIONS("-Wdocumentation") # Enable all diagnostics - #SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Weverything") + #ADD_DEFINITIONS("-Weverything") ENDIF() ## Subdirectories ############################################################## diff --git a/src/internal.h b/src/internal.h index 6aefaa8..074951b 100644 --- a/src/internal.h +++ b/src/internal.h @@ -66,7 +66,7 @@ struct yaca_key_simple_s struct yaca_key_s key; size_t bits; - char d[0]; + char d[]; }; /** -- 2.7.4 From dd9801ab8d32af0132c1b1d8c0814b121091d1a4 Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Tue, 12 Apr 2016 13:30:02 +0200 Subject: [PATCH 10/16] Add YACA_ERROR_SIGNATURE_INVALID error code. Mentioned in the doxygen. Change-Id: Ieff9d6a8408c878b7ff9656f637382abab23f742 --- api/yaca/error.h | 3 ++- api/yaca/sign.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/api/yaca/error.h b/api/yaca/error.h index 9a192f4..e8d11ed 100644 --- a/api/yaca/error.h +++ b/api/yaca/error.h @@ -37,7 +37,8 @@ enum __yaca_error_code { YACA_ERROR_OPENSSL_FAILURE = -3, YACA_ERROR_NOT_SUPPORTED = -4, YACA_ERROR_TOO_BIG_ARGUMENT = -5, - YACA_ERROR_OUT_OF_MEMORY = -6 + YACA_ERROR_OUT_OF_MEMORY = -6, + YACA_ERROR_SIGNATURE_INVALID = -7 }; #ifdef __cplusplus diff --git a/api/yaca/sign.h b/api/yaca/sign.h index 0f0855e..217d15d 100644 --- a/api/yaca/sign.h +++ b/api/yaca/sign.h @@ -113,7 +113,7 @@ int yaca_verify_update(yaca_ctx_h ctx, * @param[in] mac_len Size of the MAC or the signature. * * @return 0 on success, negative on error (@see error.h). - * TODO: CRYTPO_ERROR_SIGNATURE_INVALID when verification fails. + * TODO: YACA_ERROR_SIGNATURE_INVALID when verification fails. */ int yaca_verify_final(yaca_ctx_h ctx, const char *mac, -- 2.7.4 From 4d688df05d74a6f2624902130faae9048f899208 Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Tue, 12 Apr 2016 13:30:44 +0200 Subject: [PATCH 11/16] Add todo.txt file for global TODOs. Change-Id: I79d942960fa25b44095b6ea150d5bd1f408c8343 --- todo.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 todo.txt diff --git a/todo.txt b/todo.txt new file mode 100644 index 0000000..4f24242 --- /dev/null +++ b/todo.txt @@ -0,0 +1,3 @@ +Global: +- Rethink and possibly add verification of output buffer lengths. + In other words check whether the user won't cause a buffer overflow. -- 2.7.4 From 0af4e6ef1b64389a57475fee28f0d1e39d9e805a Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Tue, 12 Apr 2016 13:33:19 +0200 Subject: [PATCH 12/16] Get rid of EVP_MD from digest struct, it's redudant. Change-Id: I52d84125d4b0f2ab1face439477efcc82ee0a0fe --- src/digest.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/digest.c b/src/digest.c index 4cc0ceb..bd3f62f 100644 --- a/src/digest.c +++ b/src/digest.c @@ -32,7 +32,6 @@ struct yaca_digest_ctx_s { struct yaca_ctx_s ctx; - const EVP_MD *md; EVP_MD_CTX *mdctx; }; @@ -57,7 +56,7 @@ static int get_digest_output_length(const yaca_ctx_h ctx, size_t input_len) if (c == NULL) return YACA_ERROR_INVALID_ARGUMENT; - return EVP_MD_size(c->md); + return EVP_MD_CTX_size(c->mdctx); } static void destroy_digest_context(yaca_ctx_h ctx) @@ -117,6 +116,7 @@ API int yaca_digest_init(yaca_ctx_h *ctx, yaca_digest_algo_e algo) { int ret; struct yaca_digest_ctx_s *nc = NULL; + const EVP_MD *md; if (ctx == NULL) return YACA_ERROR_INVALID_ARGUMENT; @@ -129,7 +129,7 @@ API int yaca_digest_init(yaca_ctx_h *ctx, yaca_digest_algo_e algo) nc->ctx.ctx_destroy = destroy_digest_context; nc->ctx.get_output_length = get_digest_output_length; - ret = digest_get_algorithm(algo, &nc->md); + ret = digest_get_algorithm(algo, &md); if (ret < 0) goto free; @@ -139,7 +139,7 @@ API int yaca_digest_init(yaca_ctx_h *ctx, yaca_digest_algo_e algo) goto free; } - ret = EVP_DigestInit(nc->mdctx, nc->md); + ret = EVP_DigestInit(nc->mdctx, md); if (ret != 1) { ret = YACA_ERROR_OPENSSL_FAILURE; goto ctx; -- 2.7.4 From 8eb62230e8f7849a09c81283f0fd56ce77d72046 Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Tue, 12 Apr 2016 13:34:04 +0200 Subject: [PATCH 13/16] Small cosmetic change in digest.c to line it up with the style of the rest of the code. Change-Id: Ib22750311254ffaaa0f241191f9a9fdeed1a00b7 --- src/digest.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/digest.c b/src/digest.c index bd3f62f..93a2535 100644 --- a/src/digest.c +++ b/src/digest.c @@ -147,15 +147,12 @@ API int yaca_digest_init(yaca_ctx_h *ctx, yaca_digest_algo_e algo) *ctx = (yaca_ctx_h)nc; - ret = 0; + return 0; ctx: - if (ret != 0) - EVP_MD_CTX_destroy(nc->mdctx); + EVP_MD_CTX_destroy(nc->mdctx); free: - if (ret != 0) - yaca_free(nc); - + yaca_free(nc); return ret; } -- 2.7.4 From d475db4315e73f0b5a6875c79f4087d92f5da895 Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Tue, 12 Apr 2016 13:34:44 +0200 Subject: [PATCH 14/16] Implement getting the bits of an evp type key. Change-Id: Ibbd62e146bcfc7ecaa999a694416db2488e14052 --- src/key.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/key.c b/src/key.c index 78dd5c8..6ba3c9e 100644 --- a/src/key.c +++ b/src/key.c @@ -104,8 +104,16 @@ API int yaca_key_get_length(const yaca_key_h key) } if (evp_key != NULL) { + int ret; + evp_key_sanity_check(evp_key); - return YACA_ERROR_NOT_IMPLEMENTED; + + // TODO: handle ECC keys when they're implemented + ret = EVP_PKEY_bits(evp_key->evp); + if (ret <= 0) + return YACA_ERROR_OPENSSL_FAILURE; + + return ret; } return YACA_ERROR_INVALID_ARGUMENT; -- 2.7.4 From dbffca578cb0f37f323ca093512b7de20bb104bf Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Tue, 12 Apr 2016 14:54:01 +0200 Subject: [PATCH 15/16] Remove unused function pointer, no need to do that for keys. Change-Id: I1b856243bc42a09783cadfe42b402f9c8dc144f0 --- src/internal.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/internal.h b/src/internal.h index 074951b..491ec2d 100644 --- a/src/internal.h +++ b/src/internal.h @@ -51,8 +51,6 @@ struct yaca_ctx_s struct yaca_key_s { yaca_key_type_e type; - - int (*get_key_length)(const struct yaca_key_s *key); }; /** -- 2.7.4 From 6f066fc11fb5daa91f5e31594dca5d2b9c9d54d8 Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Tue, 12 Apr 2016 13:42:30 +0200 Subject: [PATCH 16/16] Add SIGN context to context types. Change-Id: If61017092a29d5b50c6036b825492a7760e87cd6 --- src/internal.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/internal.h b/src/internal.h index 491ec2d..deeff97 100644 --- a/src/internal.h +++ b/src/internal.h @@ -34,7 +34,8 @@ enum yaca_ctx_type_e { YACA_CTX_INVALID = 0, - YACA_CTX_DIGEST + YACA_CTX_DIGEST, + YACA_CTX_SIGN }; /* Base structure for crypto contexts - to be inherited */ -- 2.7.4