From 82526fc1f310cc359f2bcfbc8a95b137a23171bd Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Thu, 28 Apr 2016 14:01:30 +0200 Subject: [PATCH 01/16] Replace YACA_ERROR_OPENSSL_FAILURE with YACA_ERROR_INTERNAL Change-Id: Ibb6ffca3dc778479556ba7412b46b3f9c542c424 --- api/yaca/error.h | 2 +- src/crypto.c | 2 +- src/digest.c | 10 +++++----- src/encrypt.c | 16 ++++++++-------- src/key.c | 12 ++++++------ src/seal.c | 22 +++++++++++----------- src/sign.c | 22 +++++++++++----------- 7 files changed, 43 insertions(+), 43 deletions(-) diff --git a/api/yaca/error.h b/api/yaca/error.h index d82c3fc..eaca621 100644 --- a/api/yaca/error.h +++ b/api/yaca/error.h @@ -40,7 +40,7 @@ extern "C" { enum __yaca_error_code { YACA_ERROR_INVALID_ARGUMENT = -1, YACA_ERROR_NOT_IMPLEMENTED = -2, - YACA_ERROR_OPENSSL_FAILURE = -3, + YACA_ERROR_INTERNAL = -3, YACA_ERROR_NOT_SUPPORTED = -4, YACA_ERROR_TOO_BIG_ARGUMENT = -5, YACA_ERROR_OUT_OF_MEMORY = -6, diff --git a/src/crypto.c b/src/crypto.c index bfcb358..734dba5 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -90,7 +90,7 @@ API int yaca_rand_bytes(char *data, size_t data_len) if (ret == -1) ret = YACA_ERROR_NOT_SUPPORTED; else - ret = YACA_ERROR_OPENSSL_FAILURE; + ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); return ret; diff --git a/src/digest.c b/src/digest.c index e23f7b5..b9f4ce4 100644 --- a/src/digest.c +++ b/src/digest.c @@ -108,7 +108,7 @@ int digest_get_algorithm(yaca_digest_algo_e algo, const EVP_MD **md) } if (ret == 0 && *md == NULL) { - ret = YACA_ERROR_OPENSSL_FAILURE; + ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); } @@ -138,14 +138,14 @@ API int yaca_digest_init(yaca_ctx_h *ctx, yaca_digest_algo_e algo) nc->mdctx = EVP_MD_CTX_create(); if (nc->mdctx == NULL) { - ret = YACA_ERROR_OPENSSL_FAILURE; + ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); goto free; } ret = EVP_DigestInit(nc->mdctx, md); if (ret != 1) { - ret = YACA_ERROR_OPENSSL_FAILURE; + ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); goto ctx; } @@ -171,7 +171,7 @@ API int yaca_digest_update(yaca_ctx_h ctx, const char *data, size_t data_len) ret = EVP_DigestUpdate(c->mdctx, data, data_len); if (ret != 1) { - ret = YACA_ERROR_OPENSSL_FAILURE; + ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); return ret; } @@ -193,7 +193,7 @@ API int yaca_digest_final(yaca_ctx_h ctx, char *digest, size_t *digest_len) ret = EVP_DigestFinal_ex(c->mdctx, (unsigned char*)digest, &len); if (ret != 1) { - ret = YACA_ERROR_OPENSSL_FAILURE; + ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); return ret; } diff --git a/src/encrypt.c b/src/encrypt.c index 3fee076..40aa2ee 100644 --- a/src/encrypt.c +++ b/src/encrypt.c @@ -78,8 +78,8 @@ static int get_encrypt_output_length(const yaca_ctx_h ctx, size_t input_len) block_size = EVP_CIPHER_CTX_block_size(nc->cipher_ctx); if (block_size == 0) { - ERROR_DUMP(YACA_ERROR_OPENSSL_FAILURE); - return YACA_ERROR_OPENSSL_FAILURE; + ERROR_DUMP(YACA_ERROR_INTERNAL); + return YACA_ERROR_INTERNAL; } if (input_len > 0) @@ -158,7 +158,7 @@ int encrypt_get_algorithm(yaca_enc_algo_e algo, lcipher = EVP_get_cipherbyname(cipher_name); if (lcipher == NULL) { - ret = YACA_ERROR_OPENSSL_FAILURE; + ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); return ret; } @@ -210,7 +210,7 @@ static int encrypt_init(yaca_ctx_h *ctx, ret = EVP_CIPHER_iv_length(cipher); if (ret < 0) { - ret = YACA_ERROR_OPENSSL_FAILURE; + ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); goto err_free; } @@ -235,7 +235,7 @@ static int encrypt_init(yaca_ctx_h *ctx, nc->cipher_ctx = EVP_CIPHER_CTX_new(); if (nc->cipher_ctx == NULL) { - ret = YACA_ERROR_OPENSSL_FAILURE; + ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); goto err_free; } @@ -257,7 +257,7 @@ static int encrypt_init(yaca_ctx_h *ctx, } if (ret != 1) { - ret = YACA_ERROR_OPENSSL_FAILURE; + ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); goto err_ctx; } @@ -303,7 +303,7 @@ static int encrypt_update(yaca_ctx_h ctx, } if (ret != 1) { - ret = YACA_ERROR_OPENSSL_FAILURE; + ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); return ret; } @@ -339,7 +339,7 @@ static int encrypt_final(yaca_ctx_h ctx, } if (ret != 1) { - ret = YACA_ERROR_OPENSSL_FAILURE; + ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); return ret; } diff --git a/src/key.c b/src/key.c index 4365e3c..477fb18 100644 --- a/src/key.c +++ b/src/key.c @@ -111,7 +111,7 @@ API int yaca_key_get_bits(const yaca_key_h key) // TODO: handle ECC keys when they're implemented ret = EVP_PKEY_bits(evp_key->evp); if (ret <= 0) { - ret = YACA_ERROR_OPENSSL_FAILURE; + ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); return ret; } @@ -297,7 +297,7 @@ API int yaca_key_gen_pair(yaca_key_h *prv_key, ret = BN_set_word(bne, RSA_F4); if (ret != 1) { - ret = YACA_ERROR_OPENSSL_FAILURE; + ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); goto free_bne; } @@ -311,7 +311,7 @@ API int yaca_key_gen_pair(yaca_key_h *prv_key, ret = RSA_generate_key_ex(rsa, key_bits, bne, NULL); if (ret != 1) { - ret = YACA_ERROR_OPENSSL_FAILURE; + ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); goto free_rsa; } @@ -332,14 +332,14 @@ API int yaca_key_gen_pair(yaca_key_h *prv_key, ret = EVP_PKEY_assign_RSA(nk_prv->evp, RSAPrivateKey_dup(rsa)); if (ret != 1) { - ret = YACA_ERROR_OPENSSL_FAILURE; + ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); goto free_evp_pub; } ret = EVP_PKEY_assign_RSA(nk_pub->evp, RSAPublicKey_dup(rsa)); if (ret != 1) { - ret = YACA_ERROR_OPENSSL_FAILURE; + ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); goto free_evp_pub; } @@ -439,7 +439,7 @@ API int yaca_key_derive_pbkdf2(const char *password, salt_len, iter, md, key_byte_len, (unsigned char*)nk->d); if (ret != 1) { - ret = YACA_ERROR_OPENSSL_FAILURE; + ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); goto err; } diff --git a/src/seal.c b/src/seal.c index c39b8be..a5fb2ae 100644 --- a/src/seal.c +++ b/src/seal.c @@ -79,8 +79,8 @@ static int get_seal_output_length(const yaca_ctx_h ctx, size_t input_len) block_size = EVP_CIPHER_CTX_block_size(nc->cipher_ctx); if (block_size <= 0) { - ERROR_DUMP(YACA_ERROR_OPENSSL_FAILURE); - return YACA_ERROR_OPENSSL_FAILURE; + ERROR_DUMP(YACA_ERROR_INTERNAL); + return YACA_ERROR_INTERNAL; } if (input_len > 0) @@ -124,14 +124,14 @@ static int seal_init(yaca_ctx_h *ctx, nc->cipher_ctx = EVP_CIPHER_CTX_new(); if (nc->cipher_ctx == NULL) { - ret = YACA_ERROR_OPENSSL_FAILURE; + ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); goto err_free; } ret = EVP_PKEY_size(lpub->evp); if (ret <= 0) { - ret = YACA_ERROR_OPENSSL_FAILURE; + ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); goto err_ctx; } @@ -149,7 +149,7 @@ static int seal_init(yaca_ctx_h *ctx, ret = EVP_CIPHER_iv_length(cipher); if (ret < 0) { - ret = YACA_ERROR_OPENSSL_FAILURE; + ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); goto err_key; } @@ -173,7 +173,7 @@ static int seal_init(yaca_ctx_h *ctx, 1); if (ret != 1) { - ret = YACA_ERROR_OPENSSL_FAILURE; + ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); goto err_iv; } @@ -244,7 +244,7 @@ static int open_init(yaca_ctx_h *ctx, ret = EVP_CIPHER_iv_length(cipher); if (ret < 0) { - ret = YACA_ERROR_OPENSSL_FAILURE; + ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); goto err_free; } @@ -270,7 +270,7 @@ static int open_init(yaca_ctx_h *ctx, nc->cipher_ctx = EVP_CIPHER_CTX_new(); if (nc->cipher_ctx == NULL) { - ret = YACA_ERROR_OPENSSL_FAILURE; + ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); goto err_free; } @@ -281,7 +281,7 @@ static int open_init(yaca_ctx_h *ctx, (unsigned char*)liv->d, lprv->evp); if (ret != 1) { - ret = YACA_ERROR_OPENSSL_FAILURE; + ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); goto err_ctx; } @@ -322,7 +322,7 @@ static int seal_update(yaca_ctx_h ctx, } if (ret != 1) { - ret = YACA_ERROR_OPENSSL_FAILURE; + ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); return ret; } @@ -353,7 +353,7 @@ static int seal_final(yaca_ctx_h ctx, } if (ret != 1) { - ret = YACA_ERROR_OPENSSL_FAILURE; + ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); return ret; } diff --git a/src/sign.c b/src/sign.c index a77b403..0c789bc 100644 --- a/src/sign.c +++ b/src/sign.c @@ -104,8 +104,8 @@ static int create_sign_pkey(const yaca_key_h key, EVP_PKEY **pkey) (unsigned char *)simple_key->d, simple_key->bits / 8); if (*pkey == NULL) { - ERROR_DUMP(YACA_ERROR_OPENSSL_FAILURE); - return YACA_ERROR_OPENSSL_FAILURE; + ERROR_DUMP(YACA_ERROR_INTERNAL); + return YACA_ERROR_INTERNAL; } return 0; @@ -174,7 +174,7 @@ API int yaca_sign_init(yaca_ctx_h *ctx, nc->mdctx = EVP_MD_CTX_create(); if (nc->mdctx == NULL) { - ret = YACA_ERROR_OPENSSL_FAILURE; + ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); goto free_ctx; } @@ -186,7 +186,7 @@ API int yaca_sign_init(yaca_ctx_h *ctx, goto ctx; } if (ret != 1) { - ret = YACA_ERROR_OPENSSL_FAILURE; + ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); goto ctx; } @@ -225,7 +225,7 @@ API int yaca_sign_update(yaca_ctx_h ctx, if (ret == -2) ret = YACA_ERROR_NOT_SUPPORTED; else - ret = YACA_ERROR_OPENSSL_FAILURE; + ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); return ret; @@ -249,7 +249,7 @@ API int yaca_sign_final(yaca_ctx_h ctx, if (ret == -2) ret = YACA_ERROR_NOT_SUPPORTED; else - ret = YACA_ERROR_OPENSSL_FAILURE; + ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); return ret; @@ -305,7 +305,7 @@ API int yaca_verify_init(yaca_ctx_h *ctx, nc->mdctx = EVP_MD_CTX_create(); if (nc->mdctx == NULL) { - ret = YACA_ERROR_OPENSSL_FAILURE; + ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); goto free_ctx; } @@ -329,7 +329,7 @@ API int yaca_verify_init(yaca_ctx_h *ctx, goto ctx; } if (ret != 1) { - ret = YACA_ERROR_OPENSSL_FAILURE; + ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); goto ctx; } @@ -378,7 +378,7 @@ API int yaca_verify_update(yaca_ctx_h ctx, if (ret == -2) ret = YACA_ERROR_NOT_SUPPORTED; else - ret = YACA_ERROR_OPENSSL_FAILURE; + ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); return ret; @@ -411,7 +411,7 @@ API int yaca_verify_final(yaca_ctx_h ctx, if (ret == -2) ret = YACA_ERROR_NOT_SUPPORTED; else - ret = YACA_ERROR_OPENSSL_FAILURE; + ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); return ret; @@ -427,7 +427,7 @@ API int yaca_verify_final(yaca_ctx_h ctx, else if (ret == -2) ret = YACA_ERROR_NOT_SUPPORTED; else - ret = YACA_ERROR_OPENSSL_FAILURE; + ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); return ret; -- 2.7.4 From e78e0eda6122a683bffdebe9070fc1d17a27356e Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Mon, 25 Apr 2016 15:31:22 +0200 Subject: [PATCH 02/16] Switch to smart-tabs in key.c and key.h Change-Id: I8d6186819fe1edb3cea5a58124e06e4b1fbbbac9 --- src/key.c | 52 ++++++++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/src/key.c b/src/key.c index 477fb18..6f47834 100644 --- a/src/key.c +++ b/src/key.c @@ -123,10 +123,10 @@ API int yaca_key_get_bits(const yaca_key_h key) } API int yaca_key_import(yaca_key_h *key, - yaca_key_fmt_e key_fmt, - yaca_key_type_e key_type, - const char *data, - size_t data_len) + yaca_key_fmt_e key_fmt, + yaca_key_type_e key_type, + const char *data, + size_t data_len) { if (key == NULL || data == NULL || data_len == 0) return YACA_ERROR_INVALID_ARGUMENT; @@ -164,9 +164,9 @@ API int yaca_key_import(yaca_key_h *key, } API int yaca_key_export(const yaca_key_h key, - yaca_key_fmt_e key_fmt, - char **data, - size_t *data_len) + yaca_key_fmt_e key_fmt, + char **data, + size_t *data_len) { size_t byte_len; struct yaca_key_simple_s *simple_key = key_get_simple(key); @@ -199,8 +199,8 @@ 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_bits) + yaca_key_type_e key_type, + size_t key_bits) { int ret; struct yaca_key_simple_s *nk = NULL; @@ -259,9 +259,9 @@ 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_bits) + yaca_key_h *pub_key, + yaca_key_type_e key_type, + size_t key_bits) { int ret; struct yaca_key_evp_s *nk_prv = NULL; @@ -386,28 +386,28 @@ API void yaca_key_free(yaca_key_h key) } API int yaca_key_derive_dh(const yaca_key_h prv_key, - const yaca_key_h pub_key, - yaca_key_h *sym_key) + const yaca_key_h pub_key, + yaca_key_h *sym_key) { return YACA_ERROR_NOT_IMPLEMENTED; } API int yaca_key_derive_kea(const yaca_key_h prv_key, - const yaca_key_h pub_key, - const yaca_key_h prv_key_auth, - const yaca_key_h pub_key_auth, - yaca_key_h *sym_key) + const yaca_key_h pub_key, + const yaca_key_h prv_key_auth, + const yaca_key_h pub_key_auth, + yaca_key_h *sym_key) { return YACA_ERROR_NOT_IMPLEMENTED; } API int yaca_key_derive_pbkdf2(const char *password, - const char *salt, - size_t salt_len, - int iter, - yaca_digest_algo_e algo, - size_t key_bits, - yaca_key_h *key) + const char *salt, + size_t salt_len, + int iter, + yaca_digest_algo_e algo, + size_t key_bits, + yaca_key_h *key) { const EVP_MD *md; struct yaca_key_simple_s *nk; @@ -436,8 +436,8 @@ API int yaca_key_derive_pbkdf2(const char *password, 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_byte_len, - (unsigned char*)nk->d); + salt_len, iter, md, key_byte_len, + (unsigned char*)nk->d); if (ret != 1) { ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); -- 2.7.4 From e14076c63ee6c0954c7e0036e9ff1f41f2ce827b Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Wed, 20 Apr 2016 15:19:50 +0200 Subject: [PATCH 03/16] Rename key_fmt to key_file_fmt type and introduce a real key_fmt enum. key_file_fmt is a format of the file (PEM, DER, RAW, BASE64). Newly added key_fmt is a format of a key within file format (PKCS#X, etc). E.g. we can have PKCS#1 encoded as PEM or DER and PKCS#8 encoded again as PEM or DER. Those two format types are independent of each other. Change-Id: I38b9106c619a5b45c09be48d95f9278f43b79dd4 --- api/yaca/key.h | 24 ++++++++++++------------ api/yaca/types.h | 16 ++++++++++++---- examples/encrypt_aes_gcm.c | 2 +- examples/key_exchange.c | 4 ++-- examples/test.c | 2 +- src/key.c | 8 ++++---- todo.txt | 2 ++ 7 files changed, 34 insertions(+), 24 deletions(-) diff --git a/api/yaca/key.h b/api/yaca/key.h index c9c924c..dd1dbe8 100644 --- a/api/yaca/key.h +++ b/api/yaca/key.h @@ -55,17 +55,17 @@ int yaca_key_get_bits(const yaca_key_h key); /** * @brief yaca_key_import Imports a key from the arbitrary format. * - * @param[out] key Returned key (must be freed with yaca_key_free()). - * @param[in] key_fmt Format of the key. - * @param[in] key_type Type of the key. - * @param[in] data Blob containing the key. - * @param[in] data_len Size of the blob. + * @param[out] key Returned key (must be freed with yaca_key_free()). + * @param[in] key_file_fmt Format of the key file. + * @param[in] key_type Type of the key. + * @param[in] data Blob containing the key. + * @param[in] data_len Size of the blob. * * @return 0 on success, negative on error. * @see #yaca_key_fmt_e, #yaca_key_type_e, yaca_key_export(), yaca_key_free() */ int yaca_key_import(yaca_key_h *key, - yaca_key_fmt_e key_fmt, + yaca_key_file_fmt_e key_file_fmt, yaca_key_type_e key_type, const char *data, size_t data_len); @@ -73,17 +73,17 @@ int yaca_key_import(yaca_key_h *key, /** * @brief yaca_key_export Exports a key to arbitrary format. Export may fail if key is HW-based. * - * @param[in] key Key to be exported. - * @param[in] key_fmt Format of the key. - * @param[out] data Data, allocated by the library, containing exported key - * (must be freed with yaca_free()). - * @param[out] data_len Size of the output data. + * @param[in] key Key to be exported. + * @param[in] key_file_fmt Format of the key. + * @param[out] data Data, allocated by the library, containing exported key + * (must be freed with yaca_free()). + * @param[out] data_len Size of the output data. * * @return 0 on success, negative on error. * @see #yaca_key_fmt_e, yaca_key_import(), yaca_key_free() */ int yaca_key_export(const yaca_key_h key, - yaca_key_fmt_e key_fmt, + yaca_key_file_fmt_e key_file_fmt, char **data, size_t *data_len); diff --git a/api/yaca/types.h b/api/yaca/types.h index 80750bf..5478a46 100644 --- a/api/yaca/types.h +++ b/api/yaca/types.h @@ -50,13 +50,21 @@ typedef struct yaca_key_s *yaca_key_h; * @brief Key formats */ typedef enum { - YACA_KEY_FORMAT_RAW, /**< key is in clear format */ - YACA_KEY_FORMAT_BASE64, /**< key is encoded in ASCII-base64 */ - YACA_KEY_FORMAT_PEM, /**< key is in PEM file format */ - YACA_KEY_FORMAT_DER /**< key is in DER file format */ + YACA_KEY_FORMAT_DEFAULT, /**< key is either PKCS#1 for RSA or SSLeay for DSA, also use this option for symmetric */ + YACA_KEY_FORMAT_PKCS8 /**< key is in PKCS#8, can only be used for asymmetric private keys */ } yaca_key_fmt_e; /** + * @brief Key file formats + */ +typedef enum { + YACA_KEY_FILE_FORMAT_RAW, /**< key file is in raw binary format, used for symmetric keys */ + YACA_KEY_FILE_FORMAT_BASE64, /**< key file is encoded in ASCII-base64, used for symmetric keys */ + YACA_KEY_FILE_FORMAT_PEM, /**< key file is in PEM file format, used for asymmetric keys */ + YACA_KEY_FILE_FORMAT_DER /**< key file is in DER file format, used for asymmetric keys */ +} yaca_key_file_fmt_e; + +/** * @brief Key types, IV is considered as key */ typedef enum { diff --git a/examples/encrypt_aes_gcm.c b/examples/encrypt_aes_gcm.c index 9b2c6f8..17c51ff 100644 --- a/examples/encrypt_aes_gcm.c +++ b/examples/encrypt_aes_gcm.c @@ -71,7 +71,7 @@ void encrypt_decrypt_aes_gcm(void) goto clean; // generate and export aad? - ret = yaca_key_export(aad_key, YACA_KEY_FORMAT_RAW, &aad, &aad_len); + ret = yaca_key_export(aad_key, YACA_KEY_FILE_FORMAT_RAW, &aad, &aad_len); if (ret < 0) goto clean; diff --git a/examples/key_exchange.c b/examples/key_exchange.c index 2b0b61c..edbcd5d 100644 --- a/examples/key_exchange.c +++ b/examples/key_exchange.c @@ -68,7 +68,7 @@ void key_exchange_dh(void) goto clean; ret = yaca_key_import(&peer_key, - YACA_KEY_FORMAT_RAW, YACA_KEY_TYPE_DH_PUB, + YACA_KEY_FILE_FORMAT_RAW, YACA_KEY_TYPE_DH_PUB, buffer, size); if (ret < 0) goto clean; @@ -124,7 +124,7 @@ void key_exchange_ecdh(void) if (1 != fread(buffer, size, 1, fp)) goto clean; - ret = yaca_key_import(&peer_key, YACA_KEY_FORMAT_RAW, YACA_KEY_TYPE_ECDH_PUB, buffer, size); + ret = yaca_key_import(&peer_key, YACA_KEY_FILE_FORMAT_RAW, YACA_KEY_TYPE_ECDH_PUB, buffer, size); if (ret < 0) goto clean; diff --git a/examples/test.c b/examples/test.c index 22f9632..a26148a 100644 --- a/examples/test.c +++ b/examples/test.c @@ -45,7 +45,7 @@ int main(int argc, char* argv[]) printf("done (%d)\n", ret); printf("Exporting key using CryptoAPI.. "); - ret = yaca_key_export(key, YACA_KEY_FORMAT_RAW, &k, &kl); + ret = yaca_key_export(key, YACA_KEY_FILE_FORMAT_RAW, &k, &kl); if (ret < 0) return ret; printf("done (%d)\n", ret); diff --git a/src/key.c b/src/key.c index 6f47834..eacaccd 100644 --- a/src/key.c +++ b/src/key.c @@ -123,7 +123,7 @@ API int yaca_key_get_bits(const yaca_key_h key) } API int yaca_key_import(yaca_key_h *key, - yaca_key_fmt_e key_fmt, + yaca_key_file_fmt_e key_file_fmt, yaca_key_type_e key_type, const char *data, size_t data_len) @@ -131,7 +131,7 @@ API int yaca_key_import(yaca_key_h *key, if (key == NULL || data == NULL || data_len == 0) return YACA_ERROR_INVALID_ARGUMENT; - if (key_fmt != YACA_KEY_FORMAT_RAW) + if (key_file_fmt != YACA_KEY_FILE_FORMAT_RAW) return YACA_ERROR_NOT_IMPLEMENTED; if (key_type == YACA_KEY_TYPE_SYMMETRIC) { @@ -164,7 +164,7 @@ API int yaca_key_import(yaca_key_h *key, } API int yaca_key_export(const yaca_key_h key, - yaca_key_fmt_e key_fmt, + yaca_key_file_fmt_e key_file_fmt, char **data, size_t *data_len) { @@ -175,7 +175,7 @@ API int yaca_key_export(const yaca_key_h key, if (data == NULL || data_len == NULL) return YACA_ERROR_INVALID_ARGUMENT; - if (key_fmt != YACA_KEY_FORMAT_RAW) + if (key_file_fmt != YACA_KEY_FILE_FORMAT_RAW) return YACA_ERROR_NOT_IMPLEMENTED; if (simple_key != NULL) { diff --git a/todo.txt b/todo.txt index 4f24242..b2e5846 100644 --- a/todo.txt +++ b/todo.txt @@ -1,3 +1,5 @@ Global: - Rethink and possibly add verification of output buffer lengths. In other words check whether the user won't cause a buffer overflow. +- Importing/exporting encrypted (passphrased) RSA keys +- What about importing RSA priv and generating PUB from it? -- 2.7.4 From aaaec9752659528bde03a642ad1d43b9c2ae3945 Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Thu, 5 May 2016 12:39:23 +0200 Subject: [PATCH 04/16] Add info about yaca tests. Remove unnecessary test dir. Change-Id: Icb519091c09c426993c50f5fac8ef6d9c1c8c874 --- CMakeLists.txt | 2 -- readme.txt | 6 ++++++ test/.keep | 0 3 files changed, 6 insertions(+), 2 deletions(-) delete mode 100644 test/.keep diff --git a/CMakeLists.txt b/CMakeLists.txt index 78db916..aa4f6ac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -76,7 +76,6 @@ ENDIF() SET(API_FOLDER ${PROJECT_SOURCE_DIR}/api) SET(EXAMPLES_FOLDER ${PROJECT_SOURCE_DIR}/examples) SET(SRC_FOLDER ${PROJECT_SOURCE_DIR}/src) -SET(TEST_FOLDER ${PROJECT_SOURCE_DIR}/test) IF(NOT DEFINED LIB_INSTALL_DIR) SET(LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") @@ -99,5 +98,4 @@ IF(NOT DEFINED EXAMPLES_DIR) ENDIF(NOT DEFINED EXAMPLES_DIR) ADD_SUBDIRECTORY(${SRC_FOLDER}) -#ADD_SUBDIRECTORY(${TEST_FOLDER}) ADD_SUBDIRECTORY(${EXAMPLES_FOLDER}) diff --git a/readme.txt b/readme.txt index c970a3b..b0fe7f2 100644 --- a/readme.txt +++ b/readme.txt @@ -38,3 +38,9 @@ API: Examples: - It is possible to compile-check examples with "make" command + +Tests: + All tests are developed at security-tests repository from tizen.org, branch yaca. + git clone ssh://[USER_ID]@review.tizen.org:29418/platform/core/test/security-tests -b yaca + Build all tests with command: cmake -DBUILD_ALL_TESTS=OFF -DBUILD_YACA=ON; make + Run all tests with command: yaca-test diff --git a/test/.keep b/test/.keep deleted file mode 100644 index e69de29..0000000 -- 2.7.4 From 04e0b98b70502efc859928d0704627bb7f59e768 Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Wed, 20 Apr 2016 16:35:44 +0200 Subject: [PATCH 05/16] API changes around key_import and key_export key_import will autodetect key_format and key_file_format. Only the expected key_type is required. key_export needs to have key_format and key_file_format explicitly given (obviously). It will get the key_type from the key. Change-Id: I6a8e04c886f6acd95dc124918606fbad992108c2 --- api/yaca/key.h | 45 +++++++++++++++++++++++++++++++++++---------- examples/encrypt_aes_gcm.c | 2 +- examples/key_exchange.c | 5 ++--- examples/test.c | 2 +- src/key.c | 8 ++++---- 5 files changed, 43 insertions(+), 19 deletions(-) diff --git a/api/yaca/key.h b/api/yaca/key.h index dd1dbe8..3a829d5 100644 --- a/api/yaca/key.h +++ b/api/yaca/key.h @@ -53,19 +53,29 @@ extern "C" { int yaca_key_get_bits(const yaca_key_h key); /** - * @brief yaca_key_import Imports a key from the arbitrary format. + * @brief yaca_key_import Imports a key. * - * @param[out] key Returned key (must be freed with yaca_key_free()). - * @param[in] key_file_fmt Format of the key file. - * @param[in] key_type Type of the key. - * @param[in] data Blob containing the key. - * @param[in] data_len Size of the blob. + * This function imports a key trying to match it to the key_type specified. + * It should autodetect both, key format and file format. + * + * 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. + * + * 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. + * + * @param[out] key Returned key (must be freed with yaca_key_free()). + * @param[in] key_type Type of the key. + * @param[in] data Blob containing the key. + * @param[in] data_len Size of the blob. * * @return 0 on success, negative on error. - * @see #yaca_key_fmt_e, #yaca_key_type_e, yaca_key_export(), yaca_key_free() + * @see #yaca_key_type_e, yaca_key_export(), yaca_key_free() */ int yaca_key_import(yaca_key_h *key, - yaca_key_file_fmt_e key_file_fmt, yaca_key_type_e key_type, const char *data, size_t data_len); @@ -73,16 +83,31 @@ int yaca_key_import(yaca_key_h *key, /** * @brief yaca_key_export Exports a key to arbitrary format. Export may fail if key is HW-based. * + * This function exports the key to an arbitrary key format and key file format. + * + * For key formats two values are allowed: + * - #YACA_KEY_FORMAT_DEFAULT: this is the only option possible in case of symmetric keys (or IV), + * for asymmetric keys it will choose PKCS#1 for RSA and SSLeay for DSA. + * - #YACA_KEY_FORMAT_PKCS8: this will only work for private asymmetric keys. + * + * The following file formats are supported: + * - #YACA_KEY_FILE_FORMAT_RAW: used only for symmetric, raw binary format + * - #YACA_KEY_FILE_FORMAT_BASE64: used only for symmetric, BASE64 encoded binary form + * - #YACA_KEY_FILE_FORMAT_PEM: used only for asymmetric, PEM file format + * - #YACA_KEY_FILE_FORMAT_DER: used only for asymmetric, DER file format + * * @param[in] key Key to be exported. - * @param[in] key_file_fmt Format of the key. + * @param[in] key_fmt Format of the key. + * @param[in] key_file_fmt Format of the key file. * @param[out] data Data, allocated by the library, containing exported key * (must be freed with yaca_free()). * @param[out] data_len Size of the output data. * * @return 0 on success, negative on error. - * @see #yaca_key_fmt_e, yaca_key_import(), yaca_key_free() + * @see #yaca_key_fmt_e, #yaca_key_file_fmt_e, yaca_key_import(), yaca_key_free() */ int yaca_key_export(const yaca_key_h key, + yaca_key_fmt_e key_fmt, yaca_key_file_fmt_e key_file_fmt, char **data, size_t *data_len); diff --git a/examples/encrypt_aes_gcm.c b/examples/encrypt_aes_gcm.c index 17c51ff..9bc60fe 100644 --- a/examples/encrypt_aes_gcm.c +++ b/examples/encrypt_aes_gcm.c @@ -71,7 +71,7 @@ void encrypt_decrypt_aes_gcm(void) goto clean; // generate and export aad? - ret = yaca_key_export(aad_key, YACA_KEY_FILE_FORMAT_RAW, &aad, &aad_len); + ret = yaca_key_export(aad_key, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_RAW, &aad, &aad_len); if (ret < 0) goto clean; diff --git a/examples/key_exchange.c b/examples/key_exchange.c index edbcd5d..9192679 100644 --- a/examples/key_exchange.c +++ b/examples/key_exchange.c @@ -67,8 +67,7 @@ void key_exchange_dh(void) if (1 != fread(buffer, size, 1, fp)) goto clean; - ret = yaca_key_import(&peer_key, - YACA_KEY_FILE_FORMAT_RAW, YACA_KEY_TYPE_DH_PUB, + ret = yaca_key_import(&peer_key, YACA_KEY_TYPE_DH_PUB, buffer, size); if (ret < 0) goto clean; @@ -124,7 +123,7 @@ void key_exchange_ecdh(void) if (1 != fread(buffer, size, 1, fp)) goto clean; - ret = yaca_key_import(&peer_key, YACA_KEY_FILE_FORMAT_RAW, YACA_KEY_TYPE_ECDH_PUB, buffer, size); + ret = yaca_key_import(&peer_key, YACA_KEY_TYPE_ECDH_PUB, buffer, size); if (ret < 0) goto clean; diff --git a/examples/test.c b/examples/test.c index a26148a..6f1bdf4 100644 --- a/examples/test.c +++ b/examples/test.c @@ -45,7 +45,7 @@ int main(int argc, char* argv[]) printf("done (%d)\n", ret); printf("Exporting key using CryptoAPI.. "); - ret = yaca_key_export(key, YACA_KEY_FILE_FORMAT_RAW, &k, &kl); + ret = yaca_key_export(key, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_RAW, &k, &kl); if (ret < 0) return ret; printf("done (%d)\n", ret); diff --git a/src/key.c b/src/key.c index eacaccd..1aba0d3 100644 --- a/src/key.c +++ b/src/key.c @@ -123,7 +123,6 @@ API int yaca_key_get_bits(const yaca_key_h key) } API int yaca_key_import(yaca_key_h *key, - yaca_key_file_fmt_e key_file_fmt, yaca_key_type_e key_type, const char *data, size_t data_len) @@ -131,9 +130,6 @@ API int yaca_key_import(yaca_key_h *key, if (key == NULL || data == NULL || data_len == 0) return YACA_ERROR_INVALID_ARGUMENT; - if (key_file_fmt != YACA_KEY_FILE_FORMAT_RAW) - return YACA_ERROR_NOT_IMPLEMENTED; - if (key_type == YACA_KEY_TYPE_SYMMETRIC) { struct yaca_key_simple_s *nk = NULL; @@ -164,6 +160,7 @@ API int yaca_key_import(yaca_key_h *key, } API int yaca_key_export(const yaca_key_h key, + yaca_key_fmt_e key_fmt, yaca_key_file_fmt_e key_file_fmt, char **data, size_t *data_len) @@ -175,6 +172,9 @@ API int yaca_key_export(const yaca_key_h key, if (data == NULL || data_len == NULL) return YACA_ERROR_INVALID_ARGUMENT; + if (key_fmt != YACA_KEY_FORMAT_DEFAULT) + return YACA_ERROR_NOT_IMPLEMENTED; + if (key_file_fmt != YACA_KEY_FILE_FORMAT_RAW) return YACA_ERROR_NOT_IMPLEMENTED; -- 2.7.4 From 782ce7f8fe5088539326dd9d92df30b9f6b03ded Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Thu, 28 Apr 2016 13:39:06 +0200 Subject: [PATCH 06/16] Small fixes in key.c Check for key length (non zero and dividable by 8). Asymmetric keys in the current state are INVALID_ARGUMENT. Change-Id: Ic7dd64fa86a485f11e52b83b2b82f710c4d55c80 --- src/key.c | 27 ++++++--------------------- 1 file changed, 6 insertions(+), 21 deletions(-) diff --git a/src/key.c b/src/key.c index 1aba0d3..4006f5f 100644 --- a/src/key.c +++ b/src/key.c @@ -36,7 +36,7 @@ static inline void simple_key_sanity_check(const struct yaca_key_simple_s *key) { - assert(key->bits); + assert(key->bits != 0); assert(key->bits % 8 == 0); } @@ -206,7 +206,7 @@ API int yaca_key_gen(yaca_key_h *sym_key, struct yaca_key_simple_s *nk = NULL; size_t key_byte_len = key_bits / 8; - if (sym_key == NULL) + if (sym_key == NULL || key_bits % 8 != 0) return YACA_ERROR_INVALID_ARGUMENT; switch(key_type) @@ -215,21 +215,6 @@ API int yaca_key_gen(yaca_key_h *sym_key, 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: /* DH public key */ - case YACA_KEY_TYPE_DH_PRIV: /* DH private key */ - case YACA_KEY_TYPE_ECDSA_PUB: /* ECDSA public key */ - case YACA_KEY_TYPE_ECDSA_PRIV: /* ECDSA private key */ - case YACA_KEY_TYPE_ECDH_PUB: /* ECDH public key */ - case YACA_KEY_TYPE_ECDH_PRIV: /* ECDH 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 DH keys */ - case YACA_KEY_TYPE_PAIR_ECDSA: /* Pair of ECDSA keys */ - case YACA_KEY_TYPE_PAIR_ECDH: /* Pair of ECDH keys */ return YACA_ERROR_NOT_IMPLEMENTED; default: return YACA_ERROR_INVALID_ARGUMENT; @@ -418,16 +403,16 @@ API int yaca_key_derive_pbkdf2(const char *password, iter == 0 || key_bits == 0 || key == NULL) return YACA_ERROR_INVALID_ARGUMENT; - ret = digest_get_algorithm(algo, &md); - if (ret < 0) - return ret; - if (key_bits % 8) /* Key length must be multiple of 8-bits */ return YACA_ERROR_INVALID_ARGUMENT; if (key_byte_len > SIZE_MAX - sizeof(struct yaca_key_simple_s)) return YACA_ERROR_TOO_BIG_ARGUMENT; + ret = digest_get_algorithm(algo, &md); + if (ret < 0) + return ret; + nk = yaca_zalloc(sizeof(struct yaca_key_simple_s) + key_byte_len); if (nk == NULL) return YACA_ERROR_OUT_OF_MEMORY; -- 2.7.4 From f3cea1e67d96b68b600f4869009cf076a88fde7c Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Thu, 28 Apr 2016 13:55:04 +0200 Subject: [PATCH 07/16] Some TODOs added for things noticed Change-Id: I8683a77c3e50dea327cb5c10973d1fe310765470 --- api/yaca/types.h | 1 + 1 file changed, 1 insertion(+) diff --git a/api/yaca/types.h b/api/yaca/types.h index 5478a46..c467121 100644 --- a/api/yaca/types.h +++ b/api/yaca/types.h @@ -84,6 +84,7 @@ typedef enum { YACA_KEY_TYPE_ECDSA_PUB, /**< Elliptic Curve Digital Signature Algorithm public key */ YACA_KEY_TYPE_ECDSA_PRIV, /**< Elliptic Curve Digital Signature Algorithm private key */ + // TODO: ECDH might not exist as a separate key type, remove? YACA_KEY_TYPE_ECDH_PUB, /**< Elliptic Curve Diffie-Hellman public key */ YACA_KEY_TYPE_ECDH_PRIV, /**< Elliptic Curve Diffie-Hellman private key */ -- 2.7.4 From f64a279a8f0470812194f0a2515192c81d81bab8 Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Mon, 25 Apr 2016 18:33:26 +0200 Subject: [PATCH 08/16] yaca_key_export() implementation for YACA_KEY_FORMAT_DEFAULT Change-Id: I946b1f862dd7f75d93372cea00deb6487ae35fb7 --- src/key.c | 248 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 231 insertions(+), 17 deletions(-) diff --git a/src/key.c b/src/key.c index 4006f5f..8373a4c 100644 --- a/src/key.c +++ b/src/key.c @@ -31,6 +31,8 @@ #include #include +#include +#include #include "internal.h" @@ -60,6 +62,219 @@ static inline void key_sanity_check(const yaca_key_h key) } #endif +int export_simple_raw(struct yaca_key_simple_s *simple_key, + char **data, + size_t *data_len) +{ + assert(simple_key != NULL); + assert(data != NULL); + assert(data_len != NULL); + + size_t key_len = simple_key->bits / 8; + + *data = yaca_malloc(key_len); + if (*data == NULL) { + ERROR_DUMP(YACA_ERROR_OUT_OF_MEMORY); + return YACA_ERROR_OUT_OF_MEMORY; + } + + memcpy(*data, simple_key->d, key_len); + *data_len = key_len; + + return 0; +} + +int export_simple_base64(struct yaca_key_simple_s *simple_key, + char **data, + size_t *data_len) +{ + assert(simple_key != NULL); + assert(data != NULL); + assert(data_len != NULL); + + int ret; + size_t key_len = simple_key->bits / 8; + BIO *b64; + BIO *mem; + char *bio_data; + long bio_data_len; + + b64 = BIO_new(BIO_f_base64()); + if (b64 == NULL) { + ret = YACA_ERROR_INTERNAL; + ERROR_DUMP(ret); + return ret; + } + + mem = BIO_new(BIO_s_mem()); + if (mem == NULL) { + ret = YACA_ERROR_INTERNAL; + ERROR_DUMP(ret); + goto free_bio; + } + + BIO_push(b64, mem); + + ret = BIO_write(b64, simple_key->d, key_len); + if (ret <= 0 || (unsigned)ret != key_len) { + ret = YACA_ERROR_INTERNAL; + ERROR_DUMP(ret); + goto free_bio; + } + + ret = BIO_flush(b64); + if (ret <= 0) { + ret = YACA_ERROR_INTERNAL; + ERROR_DUMP(ret); + goto free_bio; + } + + bio_data_len = BIO_get_mem_data(mem, &bio_data); + if (bio_data_len <= 0) { + ret = YACA_ERROR_INTERNAL; + ERROR_DUMP(ret); + goto free_bio; + } + + *data = yaca_malloc(bio_data_len); + if (*data == NULL) { + ret = YACA_ERROR_OUT_OF_MEMORY; + ERROR_DUMP(ret); + goto free_bio; + } + + memcpy(*data, bio_data, bio_data_len); + *data_len = bio_data_len; + ret = 0; + +free_bio: + BIO_free_all(b64); + + return ret; +} + +int export_evp(struct yaca_key_evp_s *evp_key, + yaca_key_file_fmt_e key_file_fmt, + char **data, + size_t *data_len) +{ + assert(evp_key != NULL); + assert(data != NULL); + assert(data_len != NULL); + + int ret = 0; + BIO *mem; + char *bio_data; + long bio_data_len; + + mem = BIO_new(BIO_s_mem()); + if (mem == NULL) { + ret = YACA_ERROR_INTERNAL; + ERROR_DUMP(ret); + return ret; + } + + switch (key_file_fmt) { + + case YACA_KEY_FILE_FORMAT_PEM: + switch (evp_key->key.type) { + + case YACA_KEY_TYPE_RSA_PRIV: + case YACA_KEY_TYPE_DSA_PRIV: + ret = PEM_write_bio_PrivateKey(mem, evp_key->evp, NULL, NULL, 0, NULL, NULL); + break; + + case YACA_KEY_TYPE_RSA_PUB: + case YACA_KEY_TYPE_DSA_PUB: + ret = PEM_write_bio_PUBKEY(mem, evp_key->evp); + break; + + case YACA_KEY_TYPE_DH_PRIV: + case YACA_KEY_TYPE_DH_PUB: + case YACA_KEY_TYPE_ECDSA_PRIV: + case YACA_KEY_TYPE_ECDSA_PUB: + case YACA_KEY_TYPE_ECDH_PRIV: + case YACA_KEY_TYPE_ECDH_PUB: + ret = YACA_ERROR_NOT_IMPLEMENTED; + goto free_bio; + + default: + ret = YACA_ERROR_INVALID_ARGUMENT; + goto free_bio; + } + + break; + + case YACA_KEY_FILE_FORMAT_DER: + switch (evp_key->key.type) { + + case YACA_KEY_TYPE_RSA_PRIV: + case YACA_KEY_TYPE_DSA_PRIV: + ret = i2d_PrivateKey_bio(mem, evp_key->evp); + break; + + case YACA_KEY_TYPE_RSA_PUB: + case YACA_KEY_TYPE_DSA_PUB: + ret = i2d_PUBKEY_bio(mem, evp_key->evp); + break; + + case YACA_KEY_TYPE_DH_PRIV: + case YACA_KEY_TYPE_DH_PUB: + case YACA_KEY_TYPE_ECDSA_PRIV: + case YACA_KEY_TYPE_ECDSA_PUB: + case YACA_KEY_TYPE_ECDH_PRIV: + case YACA_KEY_TYPE_ECDH_PUB: + ret = YACA_ERROR_NOT_IMPLEMENTED; + goto free_bio; + + default: + ret = YACA_ERROR_INVALID_ARGUMENT; + goto free_bio; + } + + break; + + default: + ret = YACA_ERROR_INVALID_ARGUMENT; + goto free_bio; + } + + if (ret <= 0) { + ret = YACA_ERROR_INTERNAL; + ERROR_DUMP(ret); + goto free_bio; + } + + ret = BIO_flush(mem); + if (ret <= 0) { + ret = YACA_ERROR_INTERNAL; + ERROR_DUMP(ret); + goto free_bio; + } + + bio_data_len = BIO_get_mem_data(mem, &bio_data); + if (bio_data_len <= 0) { + ret = YACA_ERROR_INTERNAL; + ERROR_DUMP(ret); + goto free_bio; + } + + *data = yaca_malloc(bio_data_len); + if (*data == NULL) { + ret = YACA_ERROR_OUT_OF_MEMORY; + ERROR_DUMP(ret); + goto free_bio; + } + + memcpy(*data, bio_data, bio_data_len); + *data_len = bio_data_len; + ret = 0; + +free_bio: + BIO_free_all(mem); + return ret; +} + struct yaca_key_simple_s *key_get_simple(const yaca_key_h key) { if (key == YACA_KEY_NULL) @@ -165,35 +380,34 @@ API int yaca_key_export(const yaca_key_h key, char **data, size_t *data_len) { - size_t byte_len; 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; - if (key_fmt != YACA_KEY_FORMAT_DEFAULT) - return YACA_ERROR_NOT_IMPLEMENTED; - - if (key_file_fmt != YACA_KEY_FILE_FORMAT_RAW) - return YACA_ERROR_NOT_IMPLEMENTED; - - if (simple_key != NULL) { + if (simple_key != NULL) simple_key_sanity_check(simple_key); - byte_len = simple_key->bits / 8; - *data = yaca_malloc(byte_len); - memcpy(*data, simple_key->d, byte_len); - *data_len = byte_len; + if (evp_key != NULL) + evp_key_sanity_check(evp_key); + + if (key_fmt == YACA_KEY_FORMAT_DEFAULT && + key_file_fmt == YACA_KEY_FILE_FORMAT_RAW && + simple_key != NULL) + return export_simple_raw(simple_key, data, data_len); - return 0; - } + if (key_fmt == YACA_KEY_FORMAT_DEFAULT && + key_file_fmt == YACA_KEY_FILE_FORMAT_BASE64 && + simple_key != NULL) + return export_simple_base64(simple_key, data, data_len); - if (evp_key != NULL) { - evp_key_sanity_check(evp_key); + if (key_fmt == YACA_KEY_FORMAT_DEFAULT && + evp_key != NULL) + return export_evp(evp_key, key_file_fmt, data, data_len); + if (key_fmt == YACA_KEY_FORMAT_PKCS8) return YACA_ERROR_NOT_IMPLEMENTED; - } return YACA_ERROR_INVALID_ARGUMENT; } -- 2.7.4 From d978aca4ccfbfe374bcd55784fbfad730a88fdb4 Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Thu, 28 Apr 2016 18:30:29 +0200 Subject: [PATCH 09/16] yaca_key_import() basic implementation (symmetrical and RSA) Change-Id: I8a90a06326fabbbd8b013452c1d0797635451464 --- src/key.c | 316 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 291 insertions(+), 25 deletions(-) diff --git a/src/key.c b/src/key.c index 8373a4c..d6d95c4 100644 --- a/src/key.c +++ b/src/key.c @@ -21,6 +21,7 @@ #include #include #include +#include #include @@ -62,6 +63,277 @@ static inline void key_sanity_check(const yaca_key_h key) } #endif +int base64_decode_length(const char *data, size_t data_len, size_t *len) +{ + assert(data != NULL); + assert(data_len != 0); + assert(len != NULL); + + size_t padded = 0; + size_t tmp_len = data_len; + + if (data_len % 4 != 0) + return YACA_ERROR_INVALID_ARGUMENT; + + if (data[tmp_len - 1] == '=') { + padded = 1; + if (data[tmp_len - 2] == '=') + padded = 2; + } + + *len = data_len / 4 * 3 - padded; + return 0; +} + +#define TMP_BUF_LEN 512 + +int base64_decode(const char *data, size_t data_len, BIO **output) +{ + assert(data != NULL); + assert(data_len != 0); + assert(output != NULL); + + int ret; + BIO *b64 = NULL; + BIO *src = NULL; + BIO *dst = NULL; + char tmpbuf[TMP_BUF_LEN]; + size_t b64_len; + char *out; + long out_len; + + /* This is because of BIO_new_mem_buf() having its length param typed int */ + if (data_len > INT_MAX) + return YACA_ERROR_TOO_BIG_ARGUMENT; + + /* First phase of correctness checking, calculate expected output length */ + ret = base64_decode_length(data, data_len, &b64_len); + if (ret != 0) + return ret; + + b64 = BIO_new(BIO_f_base64()); + if (b64 == NULL) { + ret = YACA_ERROR_INTERNAL; + ERROR_DUMP(ret); + return ret; + } + + src = BIO_new_mem_buf(data, data_len); + if (src == NULL) { + ret = YACA_ERROR_INTERNAL; + ERROR_DUMP(ret); + goto free_bio; + } + + BIO_push(b64, src); + + dst = BIO_new(BIO_s_mem()); + if (dst == NULL) { + ret = YACA_ERROR_INTERNAL; + ERROR_DUMP(ret); + goto free_bio; + } + + BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); + + /* Try to decode */ + for(;;) { + ret = BIO_read(b64, tmpbuf, TMP_BUF_LEN); + if (ret < 0) { + ret = YACA_ERROR_INTERNAL; + ERROR_DUMP(ret); + goto free_bio; + } + + if (ret == 0) + break; + + if (BIO_write(dst, tmpbuf, ret) != ret) { + ret = YACA_ERROR_INTERNAL; + ERROR_DUMP(ret); + goto free_bio; + } + } + + BIO_flush(dst); + + /* Check wether the length of the decoded data is what we expected */ + out_len = BIO_get_mem_data(dst, &out); + if (out_len < 0) { + ret = YACA_ERROR_INTERNAL; + ERROR_DUMP(ret); + goto free_bio; + } + if ((size_t)out_len != b64_len) { + ret = YACA_ERROR_INVALID_ARGUMENT; + goto free_bio; + } + + *output = dst; + dst = NULL; + ret = 0; + +free_bio: + BIO_free_all(b64); + BIO_free_all(dst); + + return ret; +} + +int import_simple(yaca_key_h *key, + yaca_key_type_e key_type, + const char *data, + size_t data_len) +{ + assert(key != NULL); + assert(data != NULL); + assert(data_len != 0); + + int ret; + BIO *decoded = NULL; + const char *key_data; + size_t key_data_len; + struct yaca_key_simple_s *nk = NULL; + + ret = base64_decode(data, data_len, &decoded); + if (ret == 0) { + /* Conversion successfull, get the BASE64 */ + long len = BIO_get_mem_data(decoded, &key_data); + if (len <= 0 || key_data == NULL) { + ret = YACA_ERROR_INTERNAL; + ERROR_DUMP(ret); + return ret; + } + key_data_len = len; + } else if (ret == YACA_ERROR_INVALID_ARGUMENT) { + /* This was not BASE64 or it was corrupted, treat as RAW */ + key_data_len = data_len; + key_data = data; + } else { + /* Some other, possibly unrecoverable error, give up */ + return ret; + } + + if (key_data_len > SIZE_MAX - sizeof(struct yaca_key_simple_s)) { + ret = YACA_ERROR_TOO_BIG_ARGUMENT; + goto out; + } + + nk = yaca_zalloc(sizeof(struct yaca_key_simple_s) + key_data_len); + if (nk == NULL) { + ret = YACA_ERROR_OUT_OF_MEMORY; + goto out; + } + + memcpy(nk->d, key_data, key_data_len); + nk->bits = key_data_len * 8; + nk->key.type = key_type; + + *key = (yaca_key_h)nk; + ret = 0; + +out: + BIO_free_all(decoded); + return ret; +} + +int import_evp(yaca_key_h *key, + yaca_key_type_e key_type, + const char *data, + size_t data_len) +{ + assert(key != NULL); + assert(data != NULL); + assert(data_len != 0); + + BIO *src = NULL; + EVP_PKEY *pkey = NULL; + bool private; + yaca_key_type_e type; + struct yaca_key_evp_s *nk = NULL; + + /* Neither PEM nor DER will ever be shorter then 4 bytes (12 seems + * to be minimum for DER, much more for PEM). This is just to make + * sure we have at least 4 bytes for strncmp() below. + */ + if (data_len < 4) + return YACA_ERROR_INVALID_ARGUMENT; + + /* This is because of BIO_new_mem_buf() having its length param typed int */ + if (data_len > INT_MAX) + return YACA_ERROR_TOO_BIG_ARGUMENT; + + src = BIO_new_mem_buf(data, data_len); + if (src == NULL) { + ERROR_DUMP(YACA_ERROR_INTERNAL); + return YACA_ERROR_INTERNAL; + } + + /* Possible PEM */ + if (strncmp("----", data, 4) == 0) { + if (pkey == NULL) { + BIO_reset(src); + pkey = PEM_read_bio_PrivateKey(src, NULL, NULL, NULL); + private = true; + } + + if (pkey == NULL) { + BIO_reset(src); + pkey = PEM_read_bio_PUBKEY(src, NULL, NULL, NULL); + private = false; + } + } + /* Possible DER */ + else { + if (pkey == NULL) { + BIO_reset(src); + pkey = d2i_PrivateKey_bio(src, NULL); + private = true; + } + + if (pkey == NULL) { + BIO_reset(src); + pkey = d2i_PUBKEY_bio(src, NULL); + private = false; + } + } + + BIO_free(src); + + if (pkey == NULL) + return YACA_ERROR_INVALID_ARGUMENT; + + switch (EVP_PKEY_type(pkey->type)) { + case EVP_PKEY_RSA: + type = private ? YACA_KEY_TYPE_RSA_PRIV : YACA_KEY_TYPE_RSA_PUB; + break; + + case EVP_PKEY_DSA: + type = private ? YACA_KEY_TYPE_DSA_PRIV : YACA_KEY_TYPE_DSA_PUB; + break; + + case EVP_PKEY_EC: + type = private ? YACA_KEY_TYPE_ECDSA_PRIV : YACA_KEY_TYPE_ECDSA_PUB; + break; + + default: + return YACA_ERROR_INVALID_ARGUMENT; + } + + if (type != key_type) + return YACA_ERROR_INVALID_ARGUMENT; + + nk = yaca_zalloc(sizeof(struct yaca_key_evp_s)); + if (nk == NULL) + return YACA_ERROR_OUT_OF_MEMORY; + + nk->evp = pkey; + *key = (yaca_key_h)nk; + (*key)->type = type; + + return 0; +} + int export_simple_raw(struct yaca_key_simple_s *simple_key, char **data, size_t *data_len) @@ -114,6 +386,7 @@ int export_simple_base64(struct yaca_key_simple_s *simple_key, } BIO_push(b64, mem); + BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); ret = BIO_write(b64, simple_key->d, key_len); if (ret <= 0 || (unsigned)ret != key_len) { @@ -345,32 +618,25 @@ API int yaca_key_import(yaca_key_h *key, if (key == NULL || data == NULL || data_len == 0) return YACA_ERROR_INVALID_ARGUMENT; - if (key_type == YACA_KEY_TYPE_SYMMETRIC) { - struct yaca_key_simple_s *nk = NULL; - - if (data_len > SIZE_MAX - sizeof(struct yaca_key_simple_s)) - return YACA_ERROR_TOO_BIG_ARGUMENT; - - nk = yaca_zalloc(sizeof(struct yaca_key_simple_s) + data_len); - if (nk == NULL) - return YACA_ERROR_OUT_OF_MEMORY; - - memcpy(nk->d, data, data_len); /* TODO: CRYPTO_/EVP_... */ - nk->bits = data_len * 8; - nk->key.type = key_type; - - *key = (yaca_key_h)nk; - return 0; - } - - if (key_type == YACA_KEY_TYPE_DES) { - // TODO: ... - return YACA_ERROR_NOT_IMPLEMENTED; - } - - /* if (...) */ { - // TODO: all the other key types + switch (key_type) { + case YACA_KEY_TYPE_SYMMETRIC: + case YACA_KEY_TYPE_IV: + return import_simple(key, key_type, data, data_len); + case YACA_KEY_TYPE_RSA_PUB: + case YACA_KEY_TYPE_RSA_PRIV: + return import_evp(key, key_type, data, data_len); + case YACA_KEY_TYPE_DES: + case YACA_KEY_TYPE_DSA_PUB: + case YACA_KEY_TYPE_DSA_PRIV: + case YACA_KEY_TYPE_DH_PUB: + case YACA_KEY_TYPE_DH_PRIV: + case YACA_KEY_TYPE_ECDSA_PUB: + case YACA_KEY_TYPE_ECDSA_PRIV: + case YACA_KEY_TYPE_ECDH_PUB: + case YACA_KEY_TYPE_ECDH_PRIV: return YACA_ERROR_NOT_IMPLEMENTED; + default: + return YACA_ERROR_INVALID_ARGUMENT; } } -- 2.7.4 From 477f87afb5ee0d5f3f74a42ae2c15872108b8bb5 Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Tue, 26 Apr 2016 15:04:30 +0200 Subject: [PATCH 10/16] key_import/key_export example Change-Id: Ia638fdc60c88684163dc6afe3aa3e83d65684950 --- examples/CMakeLists.txt | 1 + examples/key_import_export.c | 231 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 232 insertions(+) create mode 100644 examples/key_import_export.c diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 9048331..fe238d2 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -50,6 +50,7 @@ BUILD_EXAMPLE("yaca-example-encrypt-gcm" encrypt_aes_gcm.c) BUILD_EXAMPLE("yaca-example-sign" sign.c) BUILD_EXAMPLE("yaca-example-key-exchange" key_exchange.c) BUILD_EXAMPLE("yaca-example-test" test.c) +BUILD_EXAMPLE("yaca-example-key-impexp" key_import_export.c) INSTALL(FILES ${COMMON_SOURCES} DESTINATION ${EXAMPLES_DIR}) diff --git a/examples/key_import_export.c b/examples/key_import_export.c new file mode 100644 index 0000000..fba4664 --- /dev/null +++ b/examples/key_import_export.c @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Krzysztof Jackiewicz + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +/** + * @file key_import_export.c + * @brief + */ + +#include + +#include "misc.h" + +#include +#include +#include +#include +#include + +void key_import_export_sym(yaca_key_h sym) +{ + int ret; + + char *raw = NULL; + size_t raw_len; + char *b64= NULL; + size_t b64_len; + + yaca_key_h raw_imported = YACA_KEY_NULL; + yaca_key_h b64_imported = YACA_KEY_NULL; + + + ret = yaca_key_export(sym, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_BASE64, &b64, &b64_len); + if (ret != 0) + return; + ret = yaca_key_import(&b64_imported, YACA_KEY_TYPE_SYMMETRIC, b64, b64_len); + if (ret != 0) + goto free; + + printf("\n\t***** BASE64 exported key: *****\n%*s\n", (int)b64_len, b64); + yaca_free(b64); + b64 = NULL; + + ret = yaca_key_export(b64_imported, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_BASE64, &b64, &b64_len); + if (ret != 0) + goto free; + + printf("\t***** BASE64 imported key: *****\n%*s\n", (int)b64_len, b64); + + + ret = yaca_key_export(sym, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_RAW, &raw, &raw_len); + if (ret != 0) + goto free; + ret = yaca_key_import(&raw_imported, YACA_KEY_TYPE_SYMMETRIC, raw, raw_len); + if (ret != 0) + goto free; + + dump_hex(raw, raw_len, "\n\t***** RAW exported key: *****"); + yaca_free(raw); + raw = NULL; + + ret = yaca_key_export(raw_imported, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_RAW, &raw, &raw_len); + if (ret != 0) + goto free; + + dump_hex(raw, raw_len, "\t***** RAW imported key: *****"); + +free: + yaca_key_free(raw_imported); + yaca_key_free(b64_imported); + yaca_free(raw); + yaca_free(b64); +} + +void key_import_export_rsa(yaca_key_h priv, yaca_key_h pub) +{ + int ret; + + char *pem_prv = NULL; + size_t pem_prv_len; + char *der_prv = NULL; + size_t der_prv_len; + + char *pem_pub = NULL; + size_t pem_pub_len; + char *der_pub = NULL; + size_t der_pub_len; + + yaca_key_h pem_prv_imported = YACA_KEY_NULL; + yaca_key_h der_prv_imported = YACA_KEY_NULL; + yaca_key_h pem_pub_imported = YACA_KEY_NULL; + yaca_key_h der_pub_imported = YACA_KEY_NULL; + + + /* PEM private */ + + ret = yaca_key_export(priv, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_PEM, &pem_prv, &pem_prv_len); + if (ret != 0) + return; + ret = yaca_key_import(&pem_prv_imported, YACA_KEY_TYPE_RSA_PRIV, pem_prv, pem_prv_len); + if (ret != 0) + goto free; + + printf("\n\t***** PEM exported private key: *****\n%*s", (int)pem_prv_len, pem_prv); + yaca_free(pem_prv); + pem_prv = NULL; + + ret = yaca_key_export(pem_prv_imported, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_PEM, &pem_prv, &pem_prv_len); + if (ret != 0) + goto free; + + printf("\t***** PEM imported private key: *****\n%*s", (int)pem_prv_len, pem_prv); + + + /* DER private */ + + ret = yaca_key_export(priv, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_DER, &der_prv, &der_prv_len); + if (ret != 0) + goto free; + ret = yaca_key_import(&der_prv_imported, YACA_KEY_TYPE_RSA_PRIV, der_prv, der_prv_len); + if (ret != 0) + goto free; + + dump_hex(der_prv, der_prv_len, "\n\t***** DER exported private key: *****"); + yaca_free(der_prv); + der_prv = NULL; + + ret = yaca_key_export(der_prv_imported, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_DER, &der_prv, &der_prv_len); + if (ret != 0) + goto free; + + dump_hex(der_prv, der_prv_len, "\t***** DER imported private key: *****"); + + + /* PEM public */ + + ret = yaca_key_export(pub, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_PEM, &pem_pub, &pem_pub_len); + if (ret != 0) + goto free; + ret = yaca_key_import(&pem_pub_imported, YACA_KEY_TYPE_RSA_PUB, pem_pub, pem_pub_len); + if (ret != 0) + goto free; + + printf("\n\t***** PEM exported public key: *****\n%*s", (int)pem_pub_len, pem_pub); + yaca_free(pem_pub); + pem_pub = NULL; + + ret = yaca_key_export(pem_pub_imported, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_PEM, &pem_pub, &pem_pub_len); + if (ret != 0) + goto free; + + printf("\t***** PEM imported public key: *****\n%*s", (int)pem_pub_len, pem_pub); + + + /* DER public */ + + ret = yaca_key_export(pub, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_DER, &der_pub, &der_pub_len); + if (ret != 0) + goto free; + ret = yaca_key_import(&der_pub_imported, YACA_KEY_TYPE_RSA_PUB, der_pub, der_pub_len); + if (ret != 0) + goto free; + + dump_hex(der_pub, der_pub_len, "\n\t***** DER exported public key: *****"); + yaca_free(der_pub); + der_pub = NULL; + + ret = yaca_key_export(der_pub_imported, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_DER, &der_pub, &der_pub_len); + if (ret != 0) + goto free; + + dump_hex(der_pub, der_pub_len, "\t***** DER imported public key: *****"); + +free: + yaca_key_free(der_pub_imported); + yaca_key_free(pem_pub_imported); + yaca_key_free(der_prv_imported); + yaca_key_free(pem_prv_imported); + yaca_free(der_pub); + yaca_free(pem_pub); + yaca_free(der_prv); + yaca_free(pem_prv); +} + +int main() +{ + yaca_key_h sym; + yaca_key_h rsa_priv; + yaca_key_h rsa_pub; + int ret; + + ret = yaca_init(); + if (ret != 0) + return ret; + + yaca_error_set_debug_func(debug_func); + + ret = yaca_key_gen(&sym, YACA_KEY_TYPE_SYMMETRIC, YACA_KEY_1024BIT); + if (ret != 0) + goto exit; + + ret = yaca_key_gen_pair(&rsa_priv, &rsa_pub, YACA_KEY_TYPE_PAIR_RSA, YACA_KEY_1024BIT); + if (ret != 0) + goto free_sym; + + key_import_export_sym(sym); + key_import_export_rsa(rsa_priv, rsa_pub); + + yaca_key_free(rsa_priv); + yaca_key_free(rsa_pub); +free_sym: + yaca_key_free(sym); +exit: + yaca_exit(); + + return ret; +} -- 2.7.4 From 3b7c99c08bd52ae2d1dcfa3b2d1c53ec3b782268 Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Thu, 5 May 2016 11:45:46 +0200 Subject: [PATCH 11/16] Make yaca GCC 5 compatibile GCC 5 issues a warning for __FUNCTION__. Use __func__ instead. Change-Id: I3d37621c8384e4f229140bfc3af8c92f81058ff5 --- src/internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/internal.h b/src/internal.h index 5bff4f1..119728f 100644 --- a/src/internal.h +++ b/src/internal.h @@ -101,6 +101,6 @@ 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); void error_dump(const char *file, int line, const char *function, int code); -#define ERROR_DUMP(code) error_dump(__FILE__, __LINE__, __FUNCTION__, (code)) +#define ERROR_DUMP(code) error_dump(__FILE__, __LINE__, __func__, (code)) #endif -- 2.7.4 From 4d45f43effc56dc4d826400ebdd042fb2796297a Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Fri, 6 May 2016 15:14:22 +0200 Subject: [PATCH 12/16] Remove YACA_ERROR_NOT_SUPPORTED Change-Id: I3f6b9cf907fc4fb4e0dd6dd84452f1448e223e65 --- api/yaca/error.h | 7 +++--- src/crypto.c | 23 ++++++------------- src/sign.c | 68 ++++++++++++++++++-------------------------------------- 3 files changed, 32 insertions(+), 66 deletions(-) diff --git a/api/yaca/error.h b/api/yaca/error.h index eaca621..944d8a3 100644 --- a/api/yaca/error.h +++ b/api/yaca/error.h @@ -41,10 +41,9 @@ enum __yaca_error_code { YACA_ERROR_INVALID_ARGUMENT = -1, YACA_ERROR_NOT_IMPLEMENTED = -2, YACA_ERROR_INTERNAL = -3, - YACA_ERROR_NOT_SUPPORTED = -4, - YACA_ERROR_TOO_BIG_ARGUMENT = -5, - YACA_ERROR_OUT_OF_MEMORY = -6, - YACA_ERROR_SIGNATURE_INVALID = -7 + YACA_ERROR_TOO_BIG_ARGUMENT = -4, + YACA_ERROR_OUT_OF_MEMORY = -5, + YACA_ERROR_SIGNATURE_INVALID = -6 }; // TODO disable debug function in release? diff --git a/src/crypto.c b/src/crypto.c index 734dba5..650bdcf 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -84,39 +84,30 @@ API int yaca_rand_bytes(char *data, size_t data_len) return YACA_ERROR_INVALID_ARGUMENT; ret = RAND_bytes((unsigned char *)data, data_len); - if (ret == 1) - return 0; - - if (ret == -1) - ret = YACA_ERROR_NOT_SUPPORTED; - else + if (ret != 1) { ret = YACA_ERROR_INTERNAL; + ERROR_DUMP(ret); + return ret; + } - ERROR_DUMP(ret); - return ret; + return 0; } API int yaca_ctx_set_param(yaca_ctx_h ctx, yaca_ex_param_e param, const void *value, size_t value_len) { - if (ctx == YACA_CTX_NULL) + if (ctx == YACA_CTX_NULL || ctx->set_param == NULL) return YACA_ERROR_INVALID_ARGUMENT; - if (ctx->set_param == NULL) - return YACA_ERROR_NOT_SUPPORTED; - return ctx->set_param(ctx, param, value, value_len); } API int yaca_ctx_get_param(const yaca_ctx_h ctx, yaca_ex_param_e param, void **value, size_t *value_len) { - if (ctx == YACA_CTX_NULL) + if (ctx == YACA_CTX_NULL || ctx->get_param == NULL) return YACA_ERROR_INVALID_ARGUMENT; - if (ctx->get_param == NULL) - return YACA_ERROR_NOT_SUPPORTED; - return ctx->get_param(ctx, param, value, value_len); } diff --git a/src/sign.c b/src/sign.c index 0c789bc..24fe7ac 100644 --- a/src/sign.c +++ b/src/sign.c @@ -180,11 +180,6 @@ API int yaca_sign_init(yaca_ctx_h *ctx, } ret = EVP_DigestSignInit(nc->mdctx, NULL, md, NULL, pkey); - if (ret == -2) { - ret = YACA_ERROR_NOT_SUPPORTED; - ERROR_DUMP(ret); - goto ctx; - } if (ret != 1) { ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); @@ -219,16 +214,13 @@ API int yaca_sign_update(yaca_ctx_h ctx, return YACA_ERROR_INVALID_ARGUMENT; ret = EVP_DigestSignUpdate(c->mdctx, data, data_len); - if (ret == 1) - return 0; - - if (ret == -2) - ret = YACA_ERROR_NOT_SUPPORTED; - else + if (ret != 1) { ret = YACA_ERROR_INTERNAL; + ERROR_DUMP(ret); + return ret; + } - ERROR_DUMP(ret); - return ret; + return 0; } API int yaca_sign_final(yaca_ctx_h ctx, @@ -243,16 +235,13 @@ API int yaca_sign_final(yaca_ctx_h ctx, return YACA_ERROR_INVALID_ARGUMENT; ret = EVP_DigestSignFinal(c->mdctx, (unsigned char *)mac, mac_len); - if(ret == 1) - return 0; - - if (ret == -2) - ret = YACA_ERROR_NOT_SUPPORTED; - else + if(ret != 1) { ret = YACA_ERROR_INTERNAL; + ERROR_DUMP(ret); + return ret; + } - ERROR_DUMP(ret); - return ret; + return 0; } API int yaca_verify_init(yaca_ctx_h *ctx, @@ -323,11 +312,6 @@ API int yaca_verify_init(yaca_ctx_h *ctx, goto ctx; } - if (ret == -2) { - ret = YACA_ERROR_NOT_SUPPORTED; - ERROR_DUMP(ret); - goto ctx; - } if (ret != 1) { ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); @@ -372,16 +356,13 @@ API int yaca_verify_update(yaca_ctx_h ctx, return YACA_ERROR_INVALID_ARGUMENT; } - if (ret == 1) - return 0; - - if (ret == -2) - ret = YACA_ERROR_NOT_SUPPORTED; - else + if (ret != 1) { ret = YACA_ERROR_INTERNAL; + ERROR_DUMP(ret); + return ret; + } - ERROR_DUMP(ret); - return ret; + return 0; } API int yaca_verify_final(yaca_ctx_h ctx, @@ -402,19 +383,16 @@ API int yaca_verify_final(yaca_ctx_h ctx, ret = EVP_DigestSignFinal(c->mdctx, (unsigned char *)mac_cmp, &mac_cmp_len); - if (ret == 1) { - if (mac_len != mac_cmp_len || CRYPTO_memcmp(mac, mac_cmp, mac_len) != 0) - return YACA_ERROR_SIGNATURE_INVALID; - return 0; + if (ret != 1) { + ret = YACA_ERROR_INTERNAL; + ERROR_DUMP(ret); + return ret; } - if (ret == -2) - ret = YACA_ERROR_NOT_SUPPORTED; - else - ret = YACA_ERROR_INTERNAL; + if (mac_len != mac_cmp_len || CRYPTO_memcmp(mac, mac_cmp, mac_len) != 0) + return YACA_ERROR_SIGNATURE_INVALID; - ERROR_DUMP(ret); - return ret; + return 0; case OP_VERIFY_ASYMMETRIC: ret = EVP_DigestVerifyFinal(c->mdctx, (unsigned char *)mac, @@ -424,8 +402,6 @@ API int yaca_verify_final(yaca_ctx_h ctx, if (ret == 0) ret = YACA_ERROR_SIGNATURE_INVALID; - else if (ret == -2) - ret = YACA_ERROR_NOT_SUPPORTED; else ret = YACA_ERROR_INTERNAL; -- 2.7.4 From 6d0a0767ece8013d89d38431fd56c6a88072f00d Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Mon, 9 May 2016 15:55:29 +0200 Subject: [PATCH 13/16] write_file()/read_file() functions added They are not used now, but they are very helpful for debugging and they will be used in future examples. Change-Id: Ia3cee5a67013543096cef45b04b649ce5faaf9e8 --- examples/misc.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ examples/misc.h | 4 +++ 2 files changed, 88 insertions(+) diff --git a/examples/misc.c b/examples/misc.c index bd951e9..b3a8fdc 100644 --- a/examples/misc.c +++ b/examples/misc.c @@ -1,5 +1,8 @@ #include #include +#include + +#include #include #include "misc.h" @@ -19,3 +22,84 @@ void debug_func(const char* buf) { puts(buf); } + +int write_file(const char *path, char *data, size_t data_len) +{ + size_t written = 0; + FILE *f; + + f = fopen(path, "w"); + if (f == NULL) + return -1; + + while (written != data_len) { + int ret = fwrite(data + written, 1, data_len - written, f); + + if (ferror(f) != 0) { + fclose(f); + return -1; + } + + written += ret; + } + + fclose(f); + return 0; +} + +#define BUF_SIZE 512 + +int read_file(const char *path, char **data, size_t *data_len) +{ + int ret; + char tmp[BUF_SIZE]; + char *buf = NULL; + size_t buf_len; + FILE *f; + + f = fopen(path, "r"); + if (f == NULL) + return -1; + + for(;;) { + size_t read = fread(tmp, 1, BUF_SIZE, f); + + if (read > 0) { + if (buf == NULL) { + buf = yaca_malloc(read); + if (buf == NULL) { + ret = -1; + break; + } + buf_len = 0; + } else { + char *new_buf = yaca_realloc(buf, buf_len + read); + if (new_buf == NULL) { + ret = -1; + break; + } + buf = new_buf; + } + + memcpy(buf + buf_len, tmp, read); + buf_len += read; + } + + if (ferror(f) != 0) { + ret = -1; + break; + } + + if (feof(f)) { + *data = buf; + *data_len = buf_len; + buf = NULL; + ret = 0; + break; + } + } + + fclose(f); + free(buf); + return ret; +} diff --git a/examples/misc.h b/examples/misc.h index a4436f5..7d89758 100644 --- a/examples/misc.h +++ b/examples/misc.h @@ -37,4 +37,8 @@ void dump_hex(const char *buf, void debug_func(const char* buf); +int write_file(const char *path, char *data, size_t data_len); + +int read_file(const char *path, char **data, size_t *data_len); + #endif /* MISC_H */ -- 2.7.4 From 32bc85cef8ae6e6dd60bcc742d252210008fc188 Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Wed, 11 May 2016 12:19:41 +0200 Subject: [PATCH 14/16] Incorporate sanity checks into key_get_* functions Change-Id: I2d13b621b202c6c5800b745fe5b9f48d5a88aac8 --- src/key.c | 57 +++++++++++++++++++-------------------------------------- 1 file changed, 19 insertions(+), 38 deletions(-) diff --git a/src/key.c b/src/key.c index d6d95c4..a8fb8ff 100644 --- a/src/key.c +++ b/src/key.c @@ -37,31 +37,6 @@ #include "internal.h" -static inline void simple_key_sanity_check(const struct yaca_key_simple_s *key) -{ - assert(key->bits != 0); - 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? -#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); - const struct yaca_key_evp_s *evp_key = key_get_evp(key); - - if (simple_key != NULL) - simple_key_sanity_check(simple_key); - - if (evp_key != NULL) - evp_key_sanity_check(evp_key); -} -#endif int base64_decode_length(const char *data, size_t data_len, size_t *len) { @@ -550,6 +525,8 @@ free_bio: struct yaca_key_simple_s *key_get_simple(const yaca_key_h key) { + struct yaca_key_simple_s *k; + if (key == YACA_KEY_NULL) return NULL; @@ -558,7 +535,14 @@ struct yaca_key_simple_s *key_get_simple(const yaca_key_h key) case YACA_KEY_TYPE_SYMMETRIC: case YACA_KEY_TYPE_DES: case YACA_KEY_TYPE_IV: - return (struct yaca_key_simple_s *)key; + k = (struct yaca_key_simple_s *)key; + + /* sanity check */ + assert(k->bits != 0); + assert(k->bits % 8 == 0); + assert(k->d != NULL); + + return k; default: return NULL; } @@ -566,6 +550,8 @@ 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) { + struct yaca_key_evp_s *k; + if (key == YACA_KEY_NULL) return NULL; @@ -575,7 +561,12 @@ struct yaca_key_evp_s *key_get_evp(const yaca_key_h key) case YACA_KEY_TYPE_RSA_PRIV: case YACA_KEY_TYPE_DSA_PUB: case YACA_KEY_TYPE_DSA_PRIV: - return (struct yaca_key_evp_s *)key; + k = (struct yaca_key_evp_s *)key; + + /* sanity check */ + assert(k->evp != NULL); + + return k; default: return NULL; } @@ -586,16 +577,12 @@ API int yaca_key_get_bits(const yaca_key_h 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); + if (simple_key != NULL) return simple_key->bits; - } if (evp_key != NULL) { int ret; - evp_key_sanity_check(evp_key); - // TODO: handle ECC keys when they're implemented ret = EVP_PKEY_bits(evp_key->evp); if (ret <= 0) { @@ -652,12 +639,6 @@ API int yaca_key_export(const yaca_key_h key, if (data == NULL || data_len == NULL) return YACA_ERROR_INVALID_ARGUMENT; - if (simple_key != NULL) - simple_key_sanity_check(simple_key); - - if (evp_key != NULL) - evp_key_sanity_check(evp_key); - if (key_fmt == YACA_KEY_FORMAT_DEFAULT && key_file_fmt == YACA_KEY_FILE_FORMAT_RAW && simple_key != NULL) -- 2.7.4 From 2758c7949bf6208e94e180565fabde70d795eb01 Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Mon, 2 May 2016 13:50:46 +0200 Subject: [PATCH 15/16] yaca_key_extract_public() public function The idea is to remove yaca_key_gen_pair() and always generate using yaca_key_gen(). The latter will always generate private keys for asymmetric types. Public key will be extracted (if needed) using the function implemented here. This approach has an advantage that we can extract public keys for private keys imported from external sources. Previously this was impossible. Change-Id: I081c81eb37ed3267518aac21a9bf36063ef0e901 --- api/yaca/key.h | 11 ++++++++++ src/key.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/api/yaca/key.h b/api/yaca/key.h index 3a829d5..c7e3727 100644 --- a/api/yaca/key.h +++ b/api/yaca/key.h @@ -127,6 +127,17 @@ int yaca_key_gen(yaca_key_h *sym_key, size_t key_bits); /** + * @brief yaca_key_extract_public Extracts public key from a private one. + * + * @param[in] prv_key Private key to extract the public one from. + * @param[out] pub_key Extracted public key (must be freed with yaca_key_free()). + * + * @return 0 on success, negative on error. + * @see yaca_key_gen(), yaca_key_import(), yaca_key_free() + */ +int yaca_key_extract_public(const yaca_key_h prv_key, yaca_key_h *pub_key); + +/** * @brief yaca_key_gen_pair Generates a new key pair. * * @param[out] prv_key Newly generated private key (must be freed with yaca_key_free()). diff --git a/src/key.c b/src/key.c index a8fb8ff..5c0d43c 100644 --- a/src/key.c +++ b/src/key.c @@ -704,6 +704,73 @@ err: return ret; } +API int yaca_key_extract_public(const yaca_key_h prv_key, yaca_key_h *pub_key) +{ + int ret; + struct yaca_key_evp_s *evp_key = key_get_evp(prv_key); + struct yaca_key_evp_s *nk = NULL; + RSA *rsa_pub = NULL; + + if (prv_key == YACA_KEY_NULL || evp_key == NULL || pub_key == NULL) + return YACA_ERROR_INVALID_ARGUMENT; + + nk = yaca_zalloc(sizeof(struct yaca_key_evp_s)); + if (nk == NULL) + return YACA_ERROR_OUT_OF_MEMORY; + + nk->evp = EVP_PKEY_new(); + if (nk->evp == NULL) { + ret = YACA_ERROR_OUT_OF_MEMORY; + ERROR_DUMP(ret); + goto free_key; + } + + switch(prv_key->type) + { + case YACA_KEY_TYPE_RSA_PRIV: + assert(EVP_PKEY_type(evp_key->evp->type) == EVP_PKEY_RSA); + + rsa_pub = RSAPublicKey_dup(EVP_PKEY_get0(evp_key->evp)); + if (rsa_pub == NULL) { + ret = YACA_ERROR_INTERNAL; + ERROR_DUMP(ret); + goto free_evp; + } + + ret = EVP_PKEY_assign_RSA(nk->evp, rsa_pub); + if (ret != 1) { + ret = YACA_ERROR_INTERNAL; + ERROR_DUMP(ret); + goto free_rsa; + } + + *pub_key = (yaca_key_h)nk; + (*pub_key)->type = YACA_KEY_TYPE_RSA_PUB; + + return 0; + + case YACA_KEY_TYPE_DSA_PRIV: + case YACA_KEY_TYPE_ECDSA_PRIV: + ret = YACA_ERROR_NOT_IMPLEMENTED; + goto free_evp; + + default: + ret = YACA_ERROR_INVALID_ARGUMENT; + goto free_evp; + } + + return YACA_ERROR_INVALID_ARGUMENT; + +free_rsa: + RSA_free(rsa_pub); +free_evp: + EVP_PKEY_free(nk->evp); +free_key: + yaca_free(nk); + + return ret; +} + API int yaca_key_gen_pair(yaca_key_h *prv_key, yaca_key_h *pub_key, yaca_key_type_e key_type, -- 2.7.4 From 44822be1342157167807fa3602de469071411095 Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Mon, 2 May 2016 17:48:47 +0200 Subject: [PATCH 16/16] Make it possible to generate private keys with yaca_key_gen() Change-Id: I7d4928ab27dad85cd52f3cff60ff9a9e61ae261f --- api/yaca/key.h | 8 ++-- src/key.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 115 insertions(+), 29 deletions(-) diff --git a/api/yaca/key.h b/api/yaca/key.h index c7e3727..e1126a6 100644 --- a/api/yaca/key.h +++ b/api/yaca/key.h @@ -113,16 +113,18 @@ int yaca_key_export(const yaca_key_h key, size_t *data_len); /** - * @brief yaca_key_gen Generates a secure symmetric key (or an initialization vector). + * @brief yaca_key_gen Generates a secure key (or an initialization vector). * - * @param[out] sym_key Newly generated key (must be freed with yaca_key_free()). + * This function is used to generate symmetric and private asymmetric keys. + * + * @param[out] key Newly generated key (must be freed with yaca_key_free()). * @param[in] key_type Type 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 #yaca_key_type_e, #yaca_key_bits_e, yaca_key_gen_pair(), yaca_key_free() */ -int yaca_key_gen(yaca_key_h *sym_key, +int yaca_key_gen(yaca_key_h *key, yaca_key_type_e key_type, size_t key_bits); diff --git a/src/key.c b/src/key.c index 5c0d43c..2ba3fe9 100644 --- a/src/key.c +++ b/src/key.c @@ -523,6 +523,88 @@ free_bio: return ret; } +int gen_simple(struct yaca_key_simple_s **out, size_t key_bits) +{ + assert(out != NULL); + + int ret; + struct yaca_key_simple_s *nk; + size_t key_byte_len = key_bits / 8; + + if (key_byte_len > SIZE_MAX - sizeof(struct yaca_key_simple_s)) + return YACA_ERROR_TOO_BIG_ARGUMENT; + + nk = yaca_zalloc(sizeof(struct yaca_key_simple_s) + key_byte_len); + if (nk == NULL) + return YACA_ERROR_OUT_OF_MEMORY; + + nk->bits = key_bits; + + ret = yaca_rand_bytes(nk->d, key_byte_len); + if (ret != 0) + return ret; + + *out = nk; + return 0; +} + +int gen_evp_rsa(struct yaca_key_evp_s **out, size_t key_bits) +{ + assert(out != NULL); + assert(key_bits > 0); + assert(key_bits % 8 == 0); + + int ret; + struct yaca_key_evp_s *nk; + EVP_PKEY_CTX *ctx; + EVP_PKEY *pkey = NULL; + + nk = yaca_zalloc(sizeof(struct yaca_key_evp_s)); + if (nk == NULL) + return YACA_ERROR_OUT_OF_MEMORY; + + ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL); + if (ctx == NULL) { + ret = YACA_ERROR_INTERNAL; + ERROR_DUMP(ret); + goto free_nk; + } + + ret = EVP_PKEY_keygen_init(ctx); + if (ret != 1) { + ret = YACA_ERROR_INTERNAL; + ERROR_DUMP(ret); + goto free_ctx; + } + + ret = EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, key_bits); + if (ret != 1) { + ret = YACA_ERROR_INTERNAL; + ERROR_DUMP(ret); + goto free_ctx; + } + + ret = EVP_PKEY_keygen(ctx, &pkey); + if (ret != 1) { + ret = YACA_ERROR_INTERNAL; + ERROR_DUMP(ret); + goto free_ctx; + } + + nk->evp = pkey; + + *out = nk; + nk = NULL; + ret = 0; + +free_ctx: + EVP_PKEY_CTX_free(ctx); +free_nk: + yaca_free(nk); + + return ret; +} + struct yaca_key_simple_s *key_get_simple(const yaca_key_h key) { struct yaca_key_simple_s *k; @@ -659,49 +741,51 @@ API int yaca_key_export(const yaca_key_h key, return YACA_ERROR_INVALID_ARGUMENT; } -API int yaca_key_gen(yaca_key_h *sym_key, +// TODO: this NEEDS random number generator initialized +// there is some other TODO elsewhere about it +API int yaca_key_gen(yaca_key_h *key, yaca_key_type_e key_type, size_t key_bits) { int ret; - struct yaca_key_simple_s *nk = NULL; - size_t key_byte_len = key_bits / 8; + struct yaca_key_simple_s *nk_simple = NULL; + struct yaca_key_evp_s *nk_evp = NULL; - if (sym_key == NULL || key_bits % 8 != 0) + if (key == NULL || key_bits == 0 || key_bits % 8 != 0) return YACA_ERROR_INVALID_ARGUMENT; switch(key_type) { case YACA_KEY_TYPE_SYMMETRIC: case YACA_KEY_TYPE_IV: - break; - case YACA_KEY_TYPE_DES: - return YACA_ERROR_NOT_IMPLEMENTED; - default: - return YACA_ERROR_INVALID_ARGUMENT; - } - - if (key_byte_len > SIZE_MAX - sizeof(struct yaca_key_simple_s)) - return YACA_ERROR_TOO_BIG_ARGUMENT; + ret = gen_simple(&nk_simple, key_bits); + if (ret != 0) + return ret; - nk = yaca_zalloc(sizeof(struct yaca_key_simple_s) + key_byte_len); - if (nk == NULL) - return YACA_ERROR_OUT_OF_MEMORY; + nk_simple->key.type = key_type; - nk->bits = key_bits; - nk->key.type = key_type; + *key = (yaca_key_h)nk_simple; + return 0; - ret = yaca_rand_bytes(nk->d, key_byte_len); - if (ret != 0) - goto err; + case YACA_KEY_TYPE_RSA_PRIV: + ret = gen_evp_rsa(&nk_evp, key_bits); + if (ret != 0) + return ret; - *sym_key = (yaca_key_h)nk; + nk_evp->key.type = key_type; - return 0; + *key = (yaca_key_h)nk_evp; + return 0; -err: - yaca_free(nk); - return ret; + case YACA_KEY_TYPE_DES: + case YACA_KEY_TYPE_DSA_PRIV: + case YACA_KEY_TYPE_DH_PRIV: + case YACA_KEY_TYPE_ECDSA_PRIV: + case YACA_KEY_TYPE_ECDH_PRIV: + return YACA_ERROR_NOT_IMPLEMENTED; + default: + return YACA_ERROR_INVALID_ARGUMENT; + } } API int yaca_key_extract_public(const yaca_key_h prv_key, yaca_key_h *pub_key) -- 2.7.4