From 5cfcdf2db3a35e35334d67d5d5091c2ac00c467a Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Wed, 20 Apr 2016 15:28:15 +0200 Subject: [PATCH 01/16] Split ECC key types into ECDSA and ECDH Change-Id: I58b90609886d529cc1b387c56dd544977e5b6803 --- api/yaca/types.h | 34 +++++++++++++++++++--------------- examples/key_exchange.c | 4 ++-- src/key.c | 27 +++++++++++++++------------ 3 files changed, 36 insertions(+), 29 deletions(-) diff --git a/api/yaca/types.h b/api/yaca/types.h index c4e52b8..19428df 100644 --- a/api/yaca/types.h +++ b/api/yaca/types.h @@ -60,26 +60,30 @@ typedef enum { * @brief Key types, IV is considered as key */ typedef enum { - YACA_KEY_TYPE_SYMMETRIC, /**< Generic symmetric cipher KEY */ - YACA_KEY_TYPE_DES, /**< DES* key - must be handled differently because of parity bits */ - YACA_KEY_TYPE_IV, /**< IV for symmetric algorithms */ + YACA_KEY_TYPE_SYMMETRIC, /**< Generic symmetric cipher KEY */ + YACA_KEY_TYPE_DES, /**< DES* key - must be handled differently because of parity bits */ + YACA_KEY_TYPE_IV, /**< Initialization Vector for symmetric algorithms */ - YACA_KEY_TYPE_RSA_PUB, /**< RSA public key */ - YACA_KEY_TYPE_RSA_PRIV, /**< RSA private key */ + YACA_KEY_TYPE_RSA_PUB, /**< RSA public key */ + YACA_KEY_TYPE_RSA_PRIV, /**< RSA private key */ - YACA_KEY_TYPE_DSA_PUB, /**< DSA public key */ - YACA_KEY_TYPE_DSA_PRIV, /**< DSA private key */ + YACA_KEY_TYPE_DSA_PUB, /**< Digital Signature Algorithm public key */ + YACA_KEY_TYPE_DSA_PRIV, /**< Digital Signature Algorithm private key */ - YACA_KEY_TYPE_DH_PUB, /**< Diffie-Hellman public key */ - YACA_KEY_TYPE_DH_PRIV, /**< Diffie-Hellman private key */ + YACA_KEY_TYPE_DH_PUB, /**< Diffie-Hellman public key */ + YACA_KEY_TYPE_DH_PRIV, /**< Diffie-Hellman private key */ - YACA_KEY_TYPE_ECC_PUB, /**< ECC public key */ - YACA_KEY_TYPE_ECC_PRIV, /**< ECC private key */ + YACA_KEY_TYPE_ECDSA_PUB, /**< Elliptic Curve Digital Signature Algorithm public key */ + YACA_KEY_TYPE_ECDSA_PRIV, /**< Elliptic Curve Digital Signature Algorithm private key */ - YACA_KEY_TYPE_PAIR_RSA, /**< Pair of RSA keys */ - YACA_KEY_TYPE_PAIR_DSA, /**< Pair of DSA keys */ - YACA_KEY_TYPE_PAIR_DH, /**< Pair of Diffie-Hellman keys */ - YACA_KEY_TYPE_PAIR_ECC /**< Pair of ECC keys */ + YACA_KEY_TYPE_ECDH_PUB, /**< Elliptic Curve Diffie-Hellman public key */ + YACA_KEY_TYPE_ECDH_PRIV, /**< Elliptic Curve Diffie-Hellman private key */ + + YACA_KEY_TYPE_PAIR_RSA, /**< Pair of RSA keys */ + YACA_KEY_TYPE_PAIR_DSA, /**< Pair of DSA keys */ + YACA_KEY_TYPE_PAIR_DH, /**< Pair of DH keys */ + YACA_KEY_TYPE_PAIR_ECDSA, /**< Pair of ECDSA keys */ + YACA_KEY_TYPE_PAIR_ECDH /**< Pair of ECDH keys */ } yaca_key_type_e; /** diff --git a/examples/key_exchange.c b/examples/key_exchange.c index 2377c20..82db88a 100644 --- a/examples/key_exchange.c +++ b/examples/key_exchange.c @@ -100,7 +100,7 @@ void key_exchange_ecdh(void) long size; // generate private, public key - ret = yaca_key_gen_pair(&private_key, &public_key, YACA_KEY_TYPE_PAIR_ECC, YACA_KEY_CURVE_P256); + ret = yaca_key_gen_pair(&private_key, &public_key, YACA_KEY_TYPE_PAIR_ECDH, YACA_KEY_CURVE_P256); if (ret < 0) goto clean; @@ -122,7 +122,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_ECC_PUB, buffer, size); + ret = yaca_key_import(&peer_key, YACA_KEY_FORMAT_RAW, YACA_KEY_TYPE_ECDH_PUB, buffer, size); if (ret < 0) goto clean; diff --git a/src/key.c b/src/key.c index f5aa42c..3fbd596 100644 --- a/src/key.c +++ b/src/key.c @@ -212,18 +212,21 @@ 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: /**< 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 */ + 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; -- 2.7.4 From 5e2949b23829e35ab7d24e7d5589cb4663ae6835 Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Tue, 12 Apr 2016 13:42:52 +0200 Subject: [PATCH 02/16] Sign/verify initial implementation. Examples to follow. Change-Id: I31205fdbb897011b2cf5cbff02acbae396e95205 --- api/yaca/error.h | 2 +- src/sign.c | 353 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 346 insertions(+), 9 deletions(-) diff --git a/api/yaca/error.h b/api/yaca/error.h index e8d11ed..1e5ee16 100644 --- a/api/yaca/error.h +++ b/api/yaca/error.h @@ -33,7 +33,7 @@ extern "C" { enum __yaca_error_code { YACA_ERROR_INVALID_ARGUMENT = -1, - YACA_ERROR_NOT_IMPLEMENTED= -2, + YACA_ERROR_NOT_IMPLEMENTED = -2, YACA_ERROR_OPENSSL_FAILURE = -3, YACA_ERROR_NOT_SUPPORTED = -4, YACA_ERROR_TOO_BIG_ARGUMENT = -5, diff --git a/src/sign.c b/src/sign.c index 2f37c0f..aee4c8c 100644 --- a/src/sign.c +++ b/src/sign.c @@ -18,52 +18,389 @@ #include -#include -#include +#include #include #include #include "internal.h" +/* Operation type saved in context to recognize what + * type of operation is performed and how to perform it. +*/ +enum sign_op_type { + OP_SIGN = 0, + OP_VERIFY_SYMMETRIC = 1, + OP_VERIFY_ASYMMETRIC = 2 +}; + +struct yaca_sign_ctx_s +{ + struct yaca_ctx_s ctx; + + EVP_MD_CTX *mdctx; + enum sign_op_type op_type; +}; + +static struct yaca_sign_ctx_s *get_sign_ctx(const yaca_ctx_h ctx) +{ + if (ctx == YACA_CTX_NULL) + return NULL; + + switch (ctx->type) + { + case YACA_CTX_SIGN: + return (struct yaca_sign_ctx_s *)ctx; + default: + return NULL; + } +} + +static int get_sign_output_length(const yaca_ctx_h ctx, size_t input_len) +{ + struct yaca_sign_ctx_s *c = get_sign_ctx(ctx); + + if (c == NULL || c->mdctx == NULL || c->mdctx->pctx == NULL) + return YACA_ERROR_INVALID_ARGUMENT; + + EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(c->mdctx->pctx); + if (pkey == NULL) + return YACA_ERROR_INVALID_ARGUMENT; + + size_t len = EVP_PKEY_size(pkey); + if (len <= 0) + return YACA_ERROR_INVALID_ARGUMENT; + + return len; +} + +static void destroy_sign_context(yaca_ctx_h ctx) +{ + struct yaca_sign_ctx_s *c = get_sign_ctx(ctx); + + if (c == NULL) + return; + + EVP_MD_CTX_destroy(c->mdctx); + c->mdctx = NULL; +} + +static int create_sign_pkey(const yaca_key_h key, EVP_PKEY **pkey) +{ + 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 (pkey == NULL) + return YACA_ERROR_INVALID_ARGUMENT; + + if (simple_key != NULL) + { + *pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, + NULL, + (unsigned char *)simple_key->d, + simple_key->bits / 8); + if (*pkey == NULL) + return YACA_ERROR_OPENSSL_FAILURE; + + return 0; + } + + if (evp_key != NULL) + { + *pkey = evp_key->evp; + /* Add a reference so we can free it afterwards anyway */ + CRYPTO_add(&(*pkey)->references, 1, CRYPTO_LOCK_EVP_PKEY); + + return 0; + } + + return YACA_ERROR_INVALID_ARGUMENT; +} + +/* TODO: error checking? + * should DES and IV keys be rejected by us or silently let them work? + */ API int yaca_sign_init(yaca_ctx_h *ctx, yaca_digest_algo_e algo, const yaca_key_h key) { - return YACA_ERROR_NOT_IMPLEMENTED; + struct yaca_sign_ctx_s *nc = NULL; + EVP_PKEY *pkey; + const EVP_MD *md; + int ret; + + if (ctx == NULL) + return YACA_ERROR_INVALID_ARGUMENT; + + ret = create_sign_pkey(key, &pkey); + if (ret != 0) + return ret; + + // TODO: use zalloc when available + nc = yaca_malloc(sizeof(struct yaca_sign_ctx_s)); + if (nc == NULL) { + ret = YACA_ERROR_OUT_OF_MEMORY; + goto free_key; + } + + nc->ctx.type = YACA_CTX_SIGN; + nc->ctx.ctx_destroy = destroy_sign_context; + nc->ctx.get_output_length = get_sign_output_length; + + switch (key->type) + { + case YACA_KEY_TYPE_SYMMETRIC: + case YACA_KEY_TYPE_RSA_PRIV: + nc->op_type = OP_SIGN; + break; + case YACA_KEY_TYPE_DSA_PRIV: + case YACA_KEY_TYPE_ECDSA_PRIV: + ret = YACA_ERROR_NOT_IMPLEMENTED; + goto free_ctx; + default: + ret = YACA_ERROR_INVALID_ARGUMENT; + goto free_ctx; + } + + ret = digest_get_algorithm(algo, &md); + if (ret != 0) + goto free_ctx; + + nc->mdctx = EVP_MD_CTX_create(); + if (nc->mdctx == NULL) { + ret = YACA_ERROR_OPENSSL_FAILURE; + goto free_ctx; + } + + ret = EVP_DigestSignInit(nc->mdctx, NULL, md, NULL, pkey); + if (ret == -2) { + ret = YACA_ERROR_NOT_SUPPORTED; + goto ctx; + } + if (ret != 1) { + ret = YACA_ERROR_OPENSSL_FAILURE; + goto ctx; + } + + *ctx = (yaca_ctx_h)nc; + + ret = 0; + +ctx: + if (ret != 0) + EVP_MD_CTX_destroy(nc->mdctx); +free_ctx: + if (ret != 0) + yaca_free(nc); +free_key: + EVP_PKEY_free(pkey); + + return ret; } API int yaca_sign_update(yaca_ctx_h ctx, const char *data, size_t data_len) { - return YACA_ERROR_NOT_IMPLEMENTED; + struct yaca_sign_ctx_s *c = get_sign_ctx(ctx); + int ret; + + if (c == NULL || c->op_type != OP_SIGN || + data == NULL || data_len == 0) + return YACA_ERROR_INVALID_ARGUMENT; + + ret = EVP_DigestSignUpdate(c->mdctx, data, data_len); + if (ret == -2) + return YACA_ERROR_NOT_SUPPORTED; + if (ret != 1) + return YACA_ERROR_OPENSSL_FAILURE; + + return 0; } API int yaca_sign_final(yaca_ctx_h ctx, char *mac, size_t *mac_len) { - return YACA_ERROR_NOT_IMPLEMENTED; + struct yaca_sign_ctx_s *c = get_sign_ctx(ctx); + int ret; + + if (c == NULL || c->op_type != OP_SIGN || + mac == NULL || mac_len == NULL || *mac_len == 0) + return YACA_ERROR_INVALID_ARGUMENT; + + ret = EVP_DigestSignFinal(c->mdctx, (unsigned char *)mac, mac_len); + if (ret == -2) + return YACA_ERROR_NOT_SUPPORTED; + if (ret != 1) + return YACA_ERROR_OPENSSL_FAILURE; + + return 0; } API int yaca_verify_init(yaca_ctx_h *ctx, yaca_digest_algo_e algo, const yaca_key_h key) { - return YACA_ERROR_NOT_IMPLEMENTED; + struct yaca_sign_ctx_s *nc = NULL; + EVP_PKEY *pkey; + const EVP_MD *md; + int ret; + + if (ctx == NULL) + return YACA_ERROR_INVALID_ARGUMENT; + + ret = create_sign_pkey(key, &pkey); + if (ret != 0) + return ret; + + // TODO: use zalloc when available + nc = yaca_malloc(sizeof(struct yaca_sign_ctx_s)); + if (nc == NULL) { + ret = YACA_ERROR_OUT_OF_MEMORY; + goto free_key; + } + + nc->ctx.type = YACA_CTX_SIGN; + nc->ctx.ctx_destroy = destroy_sign_context; + nc->ctx.get_output_length = NULL; + + switch (key->type) + { + case YACA_KEY_TYPE_SYMMETRIC: + nc->op_type = OP_VERIFY_SYMMETRIC; + break; + case YACA_KEY_TYPE_RSA_PUB: + nc->op_type = OP_VERIFY_ASYMMETRIC; + break; + case YACA_KEY_TYPE_DSA_PUB: + case YACA_KEY_TYPE_ECDSA_PUB: + ret = YACA_ERROR_NOT_IMPLEMENTED; + goto free_ctx; + default: + ret = YACA_ERROR_INVALID_ARGUMENT; + goto free_ctx; + } + + ret = digest_get_algorithm(algo, &md); + if (ret < 0) + goto free_ctx; + + nc->mdctx = EVP_MD_CTX_create(); + if (nc->mdctx == NULL) { + ret = YACA_ERROR_OPENSSL_FAILURE; + goto free_ctx; + } + + switch (nc->op_type) + { + case OP_VERIFY_SYMMETRIC: + ret = EVP_DigestSignInit(nc->mdctx, NULL, md, NULL, pkey); + break; + case OP_VERIFY_ASYMMETRIC: + ret = EVP_DigestVerifyInit(nc->mdctx, NULL, md, NULL, pkey); + break; + default: + ret = YACA_ERROR_INVALID_ARGUMENT; + goto ctx; + } + + if (ret == -2) { + ret = YACA_ERROR_NOT_SUPPORTED; + goto ctx; + } + if (ret != 1) { + ret = YACA_ERROR_OPENSSL_FAILURE; + goto ctx; + } + + *ctx = (yaca_ctx_h)nc; + + ret = 0; + +ctx: + if (ret != 0) + EVP_MD_CTX_destroy(nc->mdctx); +free_ctx: + if (ret != 0) + yaca_free(nc); +free_key: + EVP_PKEY_free(pkey); + + return ret; } API int yaca_verify_update(yaca_ctx_h ctx, const char *data, size_t data_len) { - return YACA_ERROR_NOT_IMPLEMENTED; + struct yaca_sign_ctx_s *c = get_sign_ctx(ctx); + int ret; + + if (c == NULL || data == NULL || data_len == 0) + return YACA_ERROR_INVALID_ARGUMENT; + + switch (c->op_type) + { + case OP_VERIFY_SYMMETRIC: + ret = EVP_DigestSignUpdate(c->mdctx, data, data_len); + break; + case OP_VERIFY_ASYMMETRIC: + ret = EVP_DigestVerifyUpdate(c->mdctx, data, data_len); + break; + default: + return YACA_ERROR_INVALID_ARGUMENT; + } + + if (ret == -2) + return YACA_ERROR_NOT_SUPPORTED; + if (ret != 1) + return YACA_ERROR_OPENSSL_FAILURE; + + return 0; } API int yaca_verify_final(yaca_ctx_h ctx, const char *mac, size_t mac_len) { - return YACA_ERROR_NOT_IMPLEMENTED; + struct yaca_sign_ctx_s *c = get_sign_ctx(ctx); + char mac_cmp[mac_len]; + size_t mac_cmp_len = mac_len; + int ret; + + if (c == NULL || mac == NULL || mac_len == 0) + return YACA_ERROR_INVALID_ARGUMENT; + + switch (c->op_type) + { + case OP_VERIFY_SYMMETRIC: + ret = EVP_DigestSignFinal(c->mdctx, + (unsigned char *)mac_cmp, + &mac_cmp_len); + if (ret == -2) + return YACA_ERROR_NOT_SUPPORTED; + if (ret != 1) + return YACA_ERROR_OPENSSL_FAILURE; + + if (mac_len != mac_cmp_len || + CRYPTO_memcmp(mac, mac_cmp, mac_len) != 0) + return YACA_ERROR_SIGNATURE_INVALID; + + return 0; + case OP_VERIFY_ASYMMETRIC: + ret = EVP_DigestVerifyFinal(c->mdctx, + (unsigned char *)mac, + mac_len); + if (ret == 0) + return YACA_ERROR_SIGNATURE_INVALID; + if (ret == -2) + return YACA_ERROR_NOT_SUPPORTED; + if (ret != 1) + return YACA_ERROR_OPENSSL_FAILURE; + + return 0; + default: + return YACA_ERROR_INVALID_ARGUMENT; + } } -- 2.7.4 From 6832d413b26b5596a7722e5ab33e2d20dfd30cf3 Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Thu, 14 Apr 2016 16:56:31 +0200 Subject: [PATCH 03/16] Examples reviewed and simplified after RSA/HMAC sign implementation. Change-Id: I4b771695346d77ff0a133a6907e701de6fcfe856 --- examples/sign.c | 179 +++++++++++++++++++++++++------------------------------- 1 file changed, 80 insertions(+), 99 deletions(-) diff --git a/examples/sign.c b/examples/sign.c index dbec172..f8f7bec 100644 --- a/examples/sign.c +++ b/examples/sign.c @@ -25,76 +25,11 @@ #include #include #include -#include "misc.h" - -size_t IDX = 0; -size_t MAX_IDX = 2345; -const size_t SIZE = 666; - -void reset() -{ - IDX = 0; -} - -size_t read_data(char* buffer, size_t size) -{ - size_t i = 0; - - for(; i < size && IDX < MAX_IDX; i++, IDX++) - buffer[i] = IDX%0xff; - - return i; -} - -int sign(yaca_ctx_h ctx, char** signature, size_t* signature_len) -{ - char buffer[SIZE]; - - reset(); - for (;;) { - size_t read = read_data(buffer, SIZE); - if (read == 0) - break; - - if (yaca_sign_update(ctx, buffer, read)) - return -1; - } - - // TODO: is it a size in bytes or length in characters? - *signature_len = yaca_get_digest_length(ctx); - *signature = (char*)yaca_malloc(*signature_len); - - // TODO: yaca_get_digest_length() returns int but yaca_sign_final accepts size_t. Use common type. - if (yaca_sign_final(ctx, *signature, signature_len)) - return -1; - - dump_hex(*signature, *signature_len, "Message signature: "); - return 0; -} - -int verify(yaca_ctx_h ctx, const char* signature, size_t signature_len) -{ - char buffer[SIZE]; - - reset(); - for (;;) { - size_t read = read_data(buffer, SIZE); - if (read == 0) - break; - - if (yaca_verify_update(ctx, buffer, read)) - return -1; - } - - // TODO: use int or size_t for output sizes - if (yaca_verify_final(ctx, signature, (size_t)signature_len)) - return -1; - - printf("Verification succeeded\n"); +#include "lorem.h" +#include "misc.h" - return 0; -} +#define PADDING_IMPLEMENTED 0 // Signature creation and verification using advanced API void sign_verify_rsa(void) @@ -105,43 +40,59 @@ void sign_verify_rsa(void) yaca_ctx_h ctx = YACA_CTX_NULL; yaca_key_h prv = YACA_KEY_NULL; yaca_key_h pub = YACA_KEY_NULL; +#if PADDING_IMPLEMENTED yaca_padding_e padding = YACA_PADDING_PKCS1; - +#endif // GENERATE - - if (yaca_key_gen_pair(&prv, &pub, YACA_KEY_TYPE_PAIR_RSA, YACA_KEY_4096BIT)) + if (yaca_key_gen_pair(&prv, &pub, YACA_KEY_TYPE_PAIR_RSA, YACA_KEY_4096BIT) != 0) return; - // SIGN - - if (yaca_sign_init(&ctx, YACA_DIGEST_SHA512, prv)) + if (yaca_sign_init(&ctx, YACA_DIGEST_SHA512, prv) != 0) goto finish; +#if PADDING_IMPLEMENTED // TODO: yaca_ctx_set_param should take void* not char* - if (yaca_ctx_set_param(ctx, YACA_PARAM_PADDING, (char*)(&padding), sizeof(padding))) + if (yaca_ctx_set_param(ctx, YACA_PARAM_PADDING, (char*)(&padding), sizeof(padding)) != 0) + goto finish; +#endif + + if (yaca_sign_update(ctx, lorem4096, LOREM4096_SIZE) != 0) + goto finish; + + if ((signature_len = yaca_get_sign_length(ctx)) <= 0) goto finish; - if (sign(ctx, &signature, &signature_len)) + if ((signature = yaca_malloc(signature_len)) == NULL) goto finish; - // TODO: is this necessary or will next ctx init handle it? + if (yaca_sign_final(ctx, signature, &signature_len) != 0) + goto finish; + + dump_hex(signature, signature_len, "RSA Signature of lorem4096:"); + + // CLEANUP yaca_ctx_free(ctx); ctx = YACA_CTX_NULL; - // VERIFY - - if (yaca_verify_init(&ctx, YACA_DIGEST_SHA512, pub)) + if (yaca_verify_init(&ctx, YACA_DIGEST_SHA512, pub) != 0) goto finish; - if (yaca_ctx_set_param(ctx, YACA_PARAM_PADDING, (char*)(&padding), sizeof(padding))) +#if PADDING_IMPLEMENTED + if (yaca_ctx_set_param(ctx, YACA_PARAM_PADDING, (char*)(&padding), sizeof(padding)) != 0) goto finish; +#endif - if (verify(ctx, signature, signature_len)) + if (yaca_verify_update(ctx, lorem4096, LOREM4096_SIZE) != 0) goto finish; + if (yaca_verify_final(ctx, signature, signature_len) != 0) + printf("RSA verification failed\n"); + else + printf("RSA verification succesful\n"); + finish: yaca_free(signature); yaca_key_free(prv); @@ -157,29 +108,44 @@ void sign_verify_hmac(void) yaca_ctx_h ctx = YACA_CTX_NULL; yaca_key_h key = YACA_KEY_NULL; - // GENERATE - - if (yaca_key_gen(&key, YACA_KEY_TYPE_SYMMETRIC, YACA_KEY_256BIT)) + if (yaca_key_gen(&key, YACA_KEY_TYPE_SYMMETRIC, YACA_KEY_256BIT) != 0) return; // SIGN + if (yaca_sign_init(&ctx, YACA_DIGEST_SHA512, key) != 0) + goto finish; - if (yaca_sign_init(&ctx, YACA_DIGEST_SHA512, key)) + if (yaca_sign_update(ctx, lorem4096, LOREM4096_SIZE) != 0) goto finish; - if (sign(ctx, &signature, &signature_len)) + if ((signature_len = yaca_get_sign_length(ctx)) <= 0) goto finish; + if ((signature = yaca_malloc(signature_len)) == NULL) + goto finish; - // VERIFY + if (yaca_sign_final(ctx, signature, &signature_len) != 0) + goto finish; + + dump_hex(signature, signature_len, "HMAC Signature of lorem4096:"); + + // CLEANUP + yaca_ctx_free(ctx); + ctx = YACA_CTX_NULL; - if (yaca_verify_init(&ctx, YACA_DIGEST_SHA512, key)) + // VERIFY + if (yaca_verify_init(&ctx, YACA_DIGEST_SHA512, key) != 0) goto finish; - if (verify(ctx, signature, signature_len)) + if (yaca_verify_update(ctx, lorem4096, LOREM4096_SIZE) != 0) goto finish; + if (yaca_verify_final(ctx, signature, signature_len) != 0) + printf("HMAC verification failed\n"); + else + printf("HMAC verification succesful\n"); + finish: yaca_free(signature); yaca_key_free(key); @@ -194,36 +160,51 @@ void sign_verify_cmac(void) yaca_ctx_h ctx = YACA_CTX_NULL; yaca_key_h key = YACA_KEY_NULL; - // GENERATE - - if( yaca_key_gen(&key, YACA_KEY_TYPE_SYMMETRIC, YACA_KEY_256BIT)) + if (yaca_key_gen(&key, YACA_KEY_TYPE_SYMMETRIC, YACA_KEY_256BIT)) return; // SIGN // TODO: CMAC must extract the key length to select the proper evp (EVP_aes_XXX_cbc()) it should be documented - if( yaca_sign_init(&ctx, YACA_DIGEST_CMAC, key)) + if (yaca_sign_init(&ctx, YACA_DIGEST_CMAC, key) != 0) goto finish; - if( sign(ctx, &signature, &signature_len)) + if (yaca_sign_update(ctx, lorem4096, LOREM4096_SIZE)) goto finish; + if ((signature_len = yaca_get_sign_length(ctx)) <= 0) + goto finish; - // VERIFY + if ((signature = yaca_malloc(signature_len)) == NULL) + goto finish; - if( yaca_verify_init(&ctx, YACA_DIGEST_CMAC, key)) + if (yaca_sign_final(ctx, signature, &signature_len)) goto finish; - if( verify(ctx, signature, signature_len)) + dump_hex(signature, signature_len, "CMAC Signature of lorem4096:"); + + // CLEANUP + yaca_ctx_free(ctx); + ctx = YACA_CTX_NULL; + + // VERIFY + if (yaca_verify_init(&ctx, YACA_DIGEST_CMAC, key) != 0) goto finish; + if (yaca_verify_update(ctx, lorem4096, LOREM4096_SIZE) != 0) + goto finish; + + if (yaca_verify_final(ctx, signature, signature_len) != 0) + printf("CMAC verification failed\n"); + else + printf("CMAC verification succesful\n"); + finish: yaca_free(signature); yaca_key_free(key); yaca_ctx_free(ctx); } - int main() { int ret = yaca_init(); -- 2.7.4 From 9efcc3699a73004520fc01d10d3460d8a43394bf Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Thu, 21 Apr 2016 11:45:31 +0200 Subject: [PATCH 04/16] Bugfix: yaca_encrypt_final used in decryption Change-Id: I26f60bc9adfd8e55390a1522c6d36197cccc46b5 --- examples/encrypt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/encrypt.c b/examples/encrypt.c index eb8f3ce..303bcd7 100644 --- a/examples/encrypt.c +++ b/examples/encrypt.c @@ -207,7 +207,7 @@ void encrypt_advanced(void) goto ex_in; rem = dec_size - out_size; - ret = yaca_encrypt_final(ctx, dec + out_size, &rem); + ret = yaca_decrypt_final(ctx, dec + out_size, &rem); if (ret < 0) goto ex_in; -- 2.7.4 From d3ada7279a4bfd452f1eae81a40bf7c5ea549976 Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Thu, 21 Apr 2016 13:15:53 +0200 Subject: [PATCH 05/16] Add helper functions for openssl error handling Change-Id: Ibc20d9e37bc2d90a92646e1115d9a1b63f5342e6 --- api/yaca/error.h | 18 ++++++++++++ src/crypto.c | 3 ++ src/error.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/internal.h | 3 ++ 4 files changed, 110 insertions(+) create mode 100644 src/error.c diff --git a/api/yaca/error.h b/api/yaca/error.h index 1e5ee16..5012c34 100644 --- a/api/yaca/error.h +++ b/api/yaca/error.h @@ -41,6 +41,24 @@ enum __yaca_error_code { YACA_ERROR_SIGNATURE_INVALID = -7 }; +// TODO disable debug function in release? + +/** + * @brief Debug callback type. + */ +typedef void (*yaca_debug_func)(const char*); + +/** + * @brief yaca_error_set_debug_func Sets a current thread debug callback that will be called each + * time an internal error occurs. A NULL terminated string with + * location and description of the error will be passed as an + * argument. + * + * @param[in] fn Function to set as internal error callback. + */ +void yaca_error_set_debug_func(yaca_debug_func fn); + + #ifdef __cplusplus } /* extern */ #endif diff --git a/src/crypto.c b/src/crypto.c index 2ffb10c..4cc313f 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -46,6 +47,8 @@ API int yaca_init(void) API void yaca_exit(void) { + ERR_free_strings(); + ERR_remove_thread_state(NULL); EVP_cleanup(); CRYPTO_cleanup_all_ex_data(); } diff --git a/src/error.c b/src/error.c new file mode 100644 index 0000000..140d1b4 --- /dev/null +++ b/src/error.c @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +/* + * @file error.c + * @author Krzysztof Jackiewicz (k.jackiewicz@samsung.com) + */ + +#include +#include +#include + +#include + +#include +#include "internal.h" + +// TODO any better idea than to use __thread? +static __thread yaca_debug_func debug_fn = NULL; +static bool error_strings_loaded = false; + +API void yaca_error_set_debug_func(yaca_debug_func fn) +{ + debug_fn = fn; +} + +// TODO use peeking function to intercept common errors +//unsigned long ERR_peek_error(); + +void error_dump(const char *file, int line, const char *function, int code) +{ + if (debug_fn == NULL) + return; + + static const size_t BUF_SIZE = 512; + static const char ELLIPSIS[] = "...\n"; + static const size_t ELLIPSIS_SIZE = sizeof(ELLIPSIS) / sizeof(ELLIPSIS[0]); + char buf[BUF_SIZE]; + unsigned long err; + size_t written; + + written = snprintf(buf, BUF_SIZE, "%s:%d %s() API error: %d\n", file, line, function, code); + + while ((err = ERR_get_error()) != 0 && written < BUF_SIZE - 1) { + if (!error_strings_loaded) { + /* + * Both these functions are thread-safe as long as static locks are + * installed according to doc so calling them twice won't break + * anything and I don't want to use synchronization mechanisms + * here. + */ + ERR_load_crypto_strings(); + ERR_clear_error(); + error_strings_loaded = true; + } + + ERR_error_string_n(err, buf + written, BUF_SIZE - written); + written = strlen(buf); /* I trust you, openssl */ + if (written < BUF_SIZE - 1) { + buf[written] = '\n'; + written++; + } + } + + if (written >= BUF_SIZE - 1) { + strncpy(buf + BUF_SIZE - ELLIPSIS_SIZE, ELLIPSIS, ELLIPSIS_SIZE); + written = BUF_SIZE - 1; + ERR_clear_error(); + } + buf[written] = '\0'; + + (*debug_fn)(buf); +} + diff --git a/src/internal.h b/src/internal.h index 25f0edc..2b5dc9f 100644 --- a/src/internal.h +++ b/src/internal.h @@ -94,4 +94,7 @@ 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); +void error_dump(const char *file, int line, const char *function, int code); +#define ERROR_DUMP(code) error_dump(__FILE__, __LINE__, __FUNCTION__, (code)) + #endif -- 2.7.4 From a943253129d8c399bd7f78dc506cebe01468abed Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Thu, 21 Apr 2016 12:51:54 +0200 Subject: [PATCH 06/16] Dump openssl errors after each failure Change-Id: Ie665574073d00e29a451fcd799488efa35023bbb --- src/crypto.c | 10 +++++-- src/digest.c | 20 ++++++++++---- src/encrypt.c | 38 +++++++++++++++++-------- src/key.c | 20 +++++++++++--- src/sign.c | 89 ++++++++++++++++++++++++++++++++++++++++------------------- 5 files changed, 125 insertions(+), 52 deletions(-) diff --git a/src/crypto.c b/src/crypto.c index 4cc313f..bfcb358 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -84,12 +84,16 @@ 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 YACA_ERROR_NOT_SUPPORTED; if (ret == 1) return 0; - return YACA_ERROR_OPENSSL_FAILURE; + if (ret == -1) + ret = YACA_ERROR_NOT_SUPPORTED; + else + ret = YACA_ERROR_OPENSSL_FAILURE; + + ERROR_DUMP(ret); + return ret; } API int yaca_ctx_set_param(yaca_ctx_h ctx, yaca_ex_param_e param, diff --git a/src/digest.c b/src/digest.c index 2a5f01d..e23f7b5 100644 --- a/src/digest.c +++ b/src/digest.c @@ -107,8 +107,10 @@ int digest_get_algorithm(yaca_digest_algo_e algo, const EVP_MD **md) break; } - if (ret == 0 && *md == NULL) + if (ret == 0 && *md == NULL) { ret = YACA_ERROR_OPENSSL_FAILURE; + ERROR_DUMP(ret); + } return ret; } @@ -137,12 +139,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; + ERROR_DUMP(ret); goto free; } ret = EVP_DigestInit(nc->mdctx, md); if (ret != 1) { ret = YACA_ERROR_OPENSSL_FAILURE; + ERROR_DUMP(ret); goto ctx; } @@ -166,8 +170,11 @@ API int yaca_digest_update(yaca_ctx_h ctx, const char *data, size_t data_len) return YACA_ERROR_INVALID_ARGUMENT; ret = EVP_DigestUpdate(c->mdctx, data, data_len); - if (ret != 1) - return YACA_ERROR_OPENSSL_FAILURE; + if (ret != 1) { + ret = YACA_ERROR_OPENSSL_FAILURE; + ERROR_DUMP(ret); + return ret; + } return 0; } @@ -185,8 +192,11 @@ API int yaca_digest_final(yaca_ctx_h ctx, char *digest, size_t *digest_len) return YACA_ERROR_INVALID_ARGUMENT; ret = EVP_DigestFinal_ex(c->mdctx, (unsigned char*)digest, &len); - if (ret != 1) - return YACA_ERROR_OPENSSL_FAILURE; + if (ret != 1) { + ret = YACA_ERROR_OPENSSL_FAILURE; + ERROR_DUMP(ret); + return ret; + } *digest_len = len; diff --git a/src/encrypt.c b/src/encrypt.c index 5aeecf7..a18a05c 100644 --- a/src/encrypt.c +++ b/src/encrypt.c @@ -77,8 +77,10 @@ static int get_encrypt_output_length(const yaca_ctx_h ctx, size_t input_len) return YACA_ERROR_INVALID_ARGUMENT; block_size = EVP_CIPHER_CTX_block_size(nc->cipher_ctx); - if (block_size == 0) - return YACA_ERROR_OPENSSL_FAILURE; // TODO: extract openssl error here + if (block_size == 0) { + ERROR_DUMP(YACA_ERROR_OPENSSL_FAILURE); + return YACA_ERROR_OPENSSL_FAILURE; + } if (input_len > 0) return block_size + input_len - 1; @@ -155,8 +157,11 @@ int get_encrypt_algorithm(yaca_enc_algo_e algo, return YACA_ERROR_INVALID_ARGUMENT; lcipher = EVP_get_cipherbyname(cipher_name); - if (lcipher == NULL) - return YACA_ERROR_OPENSSL_FAILURE; // TODO: yaca_get_error_code_from_openssl(ret); + if (lcipher == NULL) { + ret = YACA_ERROR_OPENSSL_FAILURE; + ERROR_DUMP(ret); + return ret; + } *cipher = lcipher; return 0; @@ -204,8 +209,11 @@ static int encrypt_init(yaca_ctx_h *ctx, goto err_free; ret = EVP_CIPHER_iv_length(cipher); - if (ret < 0) + if (ret < 0) { + ret = YACA_ERROR_OPENSSL_FAILURE; + ERROR_DUMP(ret); goto err_free; + } iv_bits = ret * 8; if (iv_bits == 0 && iv != NULL) { /* 0 -> cipher doesn't use iv, but it was provided */ @@ -227,7 +235,8 @@ 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; // TODO: yaca_get_error_code_from_openssl(ret); + ret = YACA_ERROR_OPENSSL_FAILURE; + ERROR_DUMP(ret); goto err_free; } @@ -248,7 +257,8 @@ static int encrypt_init(yaca_ctx_h *ctx, } if (ret != 1) { - ret = YACA_ERROR_OPENSSL_FAILURE; // TODO: yaca_get_error_code_from_openssl(ret); + ret = YACA_ERROR_OPENSSL_FAILURE; + ERROR_DUMP(ret); goto err_ctx; } @@ -292,8 +302,11 @@ static int encrypt_update(yaca_ctx_h ctx, return YACA_ERROR_INVALID_ARGUMENT; } - if (ret != 1) - return YACA_ERROR_OPENSSL_FAILURE; // TODO: yaca_get_error_code_from_openssl(ret); + if (ret != 1) { + ret = YACA_ERROR_OPENSSL_FAILURE; + ERROR_DUMP(ret); + return ret; + } *output_len = loutput_len; return 0; @@ -325,8 +338,11 @@ static int encrypt_final(yaca_ctx_h ctx, return YACA_ERROR_INVALID_ARGUMENT; } - if (ret != 1) - return YACA_ERROR_OPENSSL_FAILURE; // TODO: yaca_get_error_code_from_openssl(ret); + if (ret != 1) { + ret = YACA_ERROR_OPENSSL_FAILURE; + ERROR_DUMP(ret); + return ret; + } *output_len = loutput_len; return 0; diff --git a/src/key.c b/src/key.c index 3fbd596..2debe7d 100644 --- a/src/key.c +++ b/src/key.c @@ -110,8 +110,11 @@ API int yaca_key_get_length(const yaca_key_h key) // TODO: handle ECC keys when they're implemented ret = EVP_PKEY_bits(evp_key->evp); - if (ret <= 0) - return YACA_ERROR_OPENSSL_FAILURE; + if (ret <= 0) { + ret = YACA_ERROR_OPENSSL_FAILURE; + ERROR_DUMP(ret); + return ret; + } return ret; } @@ -288,48 +291,56 @@ API int yaca_key_gen_pair(yaca_key_h *prv_key, bne = BN_new(); if (bne == NULL) { ret = YACA_ERROR_OUT_OF_MEMORY; + ERROR_DUMP(ret); goto free_pub; } ret = BN_set_word(bne, RSA_F4); if (ret != 1) { ret = YACA_ERROR_OPENSSL_FAILURE; + ERROR_DUMP(ret); goto free_bne; } rsa = RSA_new(); if (rsa == NULL) { - ret = YACA_ERROR_OPENSSL_FAILURE; + ret = YACA_ERROR_OUT_OF_MEMORY; + ERROR_DUMP(ret); goto free_bne; } ret = RSA_generate_key_ex(rsa, key_bits, bne, NULL); if (ret != 1) { ret = YACA_ERROR_OPENSSL_FAILURE; + ERROR_DUMP(ret); goto free_rsa; } nk_prv->evp = EVP_PKEY_new(); if (nk_prv->evp == NULL) { ret = YACA_ERROR_OUT_OF_MEMORY; + ERROR_DUMP(ret); goto free_rsa; } nk_pub->evp = EVP_PKEY_new(); if (nk_prv->evp == NULL) { ret = YACA_ERROR_OUT_OF_MEMORY; + ERROR_DUMP(ret); goto free_evp_prv; } ret = EVP_PKEY_assign_RSA(nk_prv->evp, RSAPrivateKey_dup(rsa)); if (ret != 1) { ret = YACA_ERROR_OPENSSL_FAILURE; + 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; + ERROR_DUMP(ret); goto free_evp_pub; } @@ -428,7 +439,8 @@ 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; // TODO: yaca_get_error_code_from_openssl(ret); + ret = YACA_ERROR_OPENSSL_FAILURE; + ERROR_DUMP(ret); goto err; } diff --git a/src/sign.c b/src/sign.c index aee4c8c..a77b403 100644 --- a/src/sign.c +++ b/src/sign.c @@ -64,12 +64,16 @@ static int get_sign_output_length(const yaca_ctx_h ctx, size_t input_len) return YACA_ERROR_INVALID_ARGUMENT; EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(c->mdctx->pctx); - if (pkey == NULL) + if (pkey == NULL) { + ERROR_DUMP(YACA_ERROR_INVALID_ARGUMENT); return YACA_ERROR_INVALID_ARGUMENT; + } size_t len = EVP_PKEY_size(pkey); - if (len <= 0) + if (len <= 0) { + ERROR_DUMP(YACA_ERROR_INVALID_ARGUMENT); return YACA_ERROR_INVALID_ARGUMENT; + } return len; } @@ -99,8 +103,10 @@ static int create_sign_pkey(const yaca_key_h key, EVP_PKEY **pkey) NULL, (unsigned char *)simple_key->d, simple_key->bits / 8); - if (*pkey == NULL) + if (*pkey == NULL) { + ERROR_DUMP(YACA_ERROR_OPENSSL_FAILURE); return YACA_ERROR_OPENSSL_FAILURE; + } return 0; } @@ -169,16 +175,19 @@ API int yaca_sign_init(yaca_ctx_h *ctx, nc->mdctx = EVP_MD_CTX_create(); if (nc->mdctx == NULL) { ret = YACA_ERROR_OPENSSL_FAILURE; + ERROR_DUMP(ret); goto free_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_OPENSSL_FAILURE; + ERROR_DUMP(ret); goto ctx; } @@ -210,12 +219,16 @@ 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) - return YACA_ERROR_NOT_SUPPORTED; - if (ret != 1) - return YACA_ERROR_OPENSSL_FAILURE; + ret = YACA_ERROR_NOT_SUPPORTED; + else + ret = YACA_ERROR_OPENSSL_FAILURE; - return 0; + ERROR_DUMP(ret); + return ret; } API int yaca_sign_final(yaca_ctx_h ctx, @@ -230,12 +243,16 @@ 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) - return YACA_ERROR_NOT_SUPPORTED; - if (ret != 1) - return YACA_ERROR_OPENSSL_FAILURE; + ret = YACA_ERROR_NOT_SUPPORTED; + else + ret = YACA_ERROR_OPENSSL_FAILURE; - return 0; + ERROR_DUMP(ret); + return ret; } API int yaca_verify_init(yaca_ctx_h *ctx, @@ -289,6 +306,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; + ERROR_DUMP(ret); goto free_ctx; } @@ -307,10 +325,12 @@ API int yaca_verify_init(yaca_ctx_h *ctx, if (ret == -2) { ret = YACA_ERROR_NOT_SUPPORTED; + ERROR_DUMP(ret); goto ctx; } if (ret != 1) { ret = YACA_ERROR_OPENSSL_FAILURE; + ERROR_DUMP(ret); goto ctx; } @@ -352,12 +372,16 @@ API int yaca_verify_update(yaca_ctx_h ctx, return YACA_ERROR_INVALID_ARGUMENT; } + if (ret == 1) + return 0; + if (ret == -2) - return YACA_ERROR_NOT_SUPPORTED; - if (ret != 1) - return YACA_ERROR_OPENSSL_FAILURE; + ret = YACA_ERROR_NOT_SUPPORTED; + else + ret = YACA_ERROR_OPENSSL_FAILURE; - return 0; + ERROR_DUMP(ret); + return ret; } API int yaca_verify_final(yaca_ctx_h ctx, @@ -378,28 +402,35 @@ API int yaca_verify_final(yaca_ctx_h ctx, ret = EVP_DigestSignFinal(c->mdctx, (unsigned char *)mac_cmp, &mac_cmp_len); - if (ret == -2) - return YACA_ERROR_NOT_SUPPORTED; - if (ret != 1) - return YACA_ERROR_OPENSSL_FAILURE; + 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 (mac_len != mac_cmp_len || - CRYPTO_memcmp(mac, mac_cmp, mac_len) != 0) - return YACA_ERROR_SIGNATURE_INVALID; + if (ret == -2) + ret = YACA_ERROR_NOT_SUPPORTED; + else + ret = YACA_ERROR_OPENSSL_FAILURE; - return 0; + ERROR_DUMP(ret); + return ret; case OP_VERIFY_ASYMMETRIC: ret = EVP_DigestVerifyFinal(c->mdctx, (unsigned char *)mac, mac_len); + if (ret == 1) + return 0; + if (ret == 0) - return YACA_ERROR_SIGNATURE_INVALID; - if (ret == -2) - return YACA_ERROR_NOT_SUPPORTED; - if (ret != 1) - return YACA_ERROR_OPENSSL_FAILURE; + ret = YACA_ERROR_SIGNATURE_INVALID; + else if (ret == -2) + ret = YACA_ERROR_NOT_SUPPORTED; + else + ret = YACA_ERROR_OPENSSL_FAILURE; - return 0; + ERROR_DUMP(ret); + return ret; default: return YACA_ERROR_INVALID_ARGUMENT; } -- 2.7.4 From 858010f791ffa33efb9fdeca8bfac73e02ee8468 Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Thu, 21 Apr 2016 13:06:40 +0200 Subject: [PATCH 07/16] Set debug function in examples Change-Id: Ia4e65acbad056d988b7ceffa3f9190f40b35270a --- examples/digest.c | 3 +++ examples/encrypt.c | 3 +++ examples/encrypt_aes_gcm.c | 3 +++ examples/key_exchange.c | 4 ++++ examples/misc.c | 5 +++++ examples/misc.h | 2 ++ examples/seal.c | 3 +++ examples/sign.c | 3 +++ examples/test.c | 3 +++ 9 files changed, 29 insertions(+) diff --git a/examples/digest.c b/examples/digest.c index 70978a6..9ee0b41 100644 --- a/examples/digest.c +++ b/examples/digest.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "lorem.h" #include "misc.h" @@ -80,6 +81,8 @@ exit_ctx: int main() { + yaca_error_set_debug_func(debug_func); + int ret = yaca_init(); if (ret < 0) return ret; diff --git a/examples/encrypt.c b/examples/encrypt.c index 303bcd7..8615abe 100644 --- a/examples/encrypt.c +++ b/examples/encrypt.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "lorem.h" #include "misc.h" @@ -230,6 +231,8 @@ ex_key: int main() { + yaca_error_set_debug_func(debug_func); + int ret = yaca_init(); if (ret < 0) return ret; diff --git a/examples/encrypt_aes_gcm.c b/examples/encrypt_aes_gcm.c index 3976170..9b2c6f8 100644 --- a/examples/encrypt_aes_gcm.c +++ b/examples/encrypt_aes_gcm.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "lorem.h" #include "misc.h" @@ -178,6 +179,8 @@ clean: int main() { + yaca_error_set_debug_func(debug_func); + int ret = yaca_init(); if (ret < 0) return ret; diff --git a/examples/key_exchange.c b/examples/key_exchange.c index 82db88a..2b0b61c 100644 --- a/examples/key_exchange.c +++ b/examples/key_exchange.c @@ -26,6 +26,8 @@ #include #include #include +#include +#include "misc.h" void key_exchange_dh(void) { @@ -143,6 +145,8 @@ clean: int main() { + yaca_error_set_debug_func(debug_func); + int ret = yaca_init(); if (ret < 0) return ret; diff --git a/examples/misc.c b/examples/misc.c index 8672fd9..bd951e9 100644 --- a/examples/misc.c +++ b/examples/misc.c @@ -14,3 +14,8 @@ void dump_hex(const char *buf, size_t dump_size, const char *fmt, ...) putchar('\n'); BIO_dump_fp(stdout, buf, dump_size); } + +void debug_func(const char* buf) +{ + puts(buf); +} diff --git a/examples/misc.h b/examples/misc.h index dc73467..a4436f5 100644 --- a/examples/misc.h +++ b/examples/misc.h @@ -35,4 +35,6 @@ void dump_hex(const char *buf, size_t dump_size, const char *fmt, ...); +void debug_func(const char* buf); + #endif /* MISC_H */ diff --git a/examples/seal.c b/examples/seal.c index e2377a1..985f5dc 100644 --- a/examples/seal.c +++ b/examples/seal.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "lorem.h" #include "misc.h" @@ -151,6 +152,8 @@ ex_pk: int main() { + yaca_error_set_debug_func(debug_func); + int ret = yaca_init(); if (ret < 0) return ret; diff --git a/examples/sign.c b/examples/sign.c index f8f7bec..58b921f 100644 --- a/examples/sign.c +++ b/examples/sign.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "lorem.h" #include "misc.h" @@ -207,6 +208,8 @@ finish: int main() { + yaca_error_set_debug_func(debug_func); + int ret = yaca_init(); if (ret < 0) return ret; diff --git a/examples/test.c b/examples/test.c index e6d9048..22f9632 100644 --- a/examples/test.c +++ b/examples/test.c @@ -20,12 +20,15 @@ #include #include #include +#include #include "misc.h" /** Simple test for development of library (before API is ready) */ int main(int argc, char* argv[]) { + yaca_error_set_debug_func(debug_func); + yaca_key_h key; char *k; size_t kl; -- 2.7.4 From f4d1ac95ac8b5e891e07f16586738b77849231f7 Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Tue, 12 Apr 2016 15:48:14 +0200 Subject: [PATCH 08/16] Change spaces to tab in CMakeLists Change-Id: I721359eaade46100c96d6a9fd9ed3e24293868d6 --- CMakeLists.txt | 28 ++++++++++++++-------------- examples/CMakeLists.txt | 44 +++++++++++++++++++------------------------- src/CMakeLists.txt | 7 +++---- 3 files changed, 36 insertions(+), 43 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0c2f401..78db916 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,16 +33,16 @@ INCLUDE(GNUInstallDirs) ## Color output if it's possible: IF (( "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" AND NOT (CMAKE_C_COMPILER_VERSION VERSION_LESS 4.9)) - OR ("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" )) + OR ("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" )) - IF (YACA_BUILD_FORCE_COMPILER_COLORS) - SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fdiagnostics-color=always") - ENDIF() + IF (YACA_BUILD_FORCE_COMPILER_COLORS) + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fdiagnostics-color=always") + ENDIF() ENDIF() ## Compiler flags, depending on the build type ################################# IF(NOT CMAKE_BUILD_TYPE) - SET(CMAKE_BUILD_TYPE "DEBUG") + SET(CMAKE_BUILD_TYPE "DEBUG") ENDIF(NOT CMAKE_BUILD_TYPE) ## Print build information ##################################################### @@ -66,10 +66,10 @@ 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 - ADD_DEFINITIONS("-Wdocumentation") - # Enable all diagnostics - #ADD_DEFINITIONS("-Weverything") + # Warn about documentation problems + ADD_DEFINITIONS("-Wdocumentation") + # Enable all diagnostics + #ADD_DEFINITIONS("-Weverything") ENDIF() ## Subdirectories ############################################################## @@ -79,23 +79,23 @@ 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}") + SET(LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") ENDIF(NOT DEFINED LIB_INSTALL_DIR) IF(NOT DEFINED INCLUDE_INSTALL_DIR) - SET(INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}") + SET(INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}") ENDIF(NOT DEFINED INCLUDE_INSTALL_DIR) IF(NOT DEFINED BIN_INSTALL_DIR) - SET(BIN_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}") + SET(BIN_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}") ENDIF(NOT DEFINED BIN_INSTALL_DIR) IF(NOT DEFINED SHARE_INSTALL_PREFIX) - SET(SHARE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}/share") + SET(SHARE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}/share") ENDIF(NOT DEFINED SHARE_INSTALL_PREFIX) IF(NOT DEFINED EXAMPLES_DIR) - SET(EXAMPLES_DIR "${SHARE_INSTALL_PREFIX}/${PROJECT_NAME}/examples") + SET(EXAMPLES_DIR "${SHARE_INSTALL_PREFIX}/${PROJECT_NAME}/examples") ENDIF(NOT DEFINED EXAMPLES_DIR) ADD_SUBDIRECTORY(${SRC_FOLDER}) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index cda1c9c..9048331 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,7 +1,7 @@ # # Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved # -# Contact: +# 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. @@ -18,35 +18,29 @@ # # @file CMakeLists.txt # @author Krzysztof Jackiewicz (k.jackiewicz@samsung.com) -# @version 1.0 -# @brief # INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/api) -SET(COMMON_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/lorem.c - ${CMAKE_CURRENT_SOURCE_DIR}/misc.c - ) +SET(COMMON_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/lorem.c + ${CMAKE_CURRENT_SOURCE_DIR}/misc.c) FUNCTION(BUILD_EXAMPLE EXAMPLE_NAME SOURCE_FILE) - ADD_EXECUTABLE(${EXAMPLE_NAME} - ${CMAKE_CURRENT_SOURCE_DIR}/${SOURCE_FILE} - ${COMMON_SOURCES} - ) - TARGET_LINK_LIBRARIES(${EXAMPLE_NAME} ${PROJECT_NAME}) - INSTALL(TARGETS ${EXAMPLE_NAME} - DESTINATION ${BIN_INSTALL_DIR} - PERMISSIONS OWNER_READ - OWNER_WRITE - OWNER_EXECUTE - GROUP_READ - GROUP_EXECUTE - WORLD_READ - WORLD_EXECUTE - ) - INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${SOURCE_FILE} - DESTINATION ${EXAMPLES_DIR}) + ADD_EXECUTABLE(${EXAMPLE_NAME} + ${CMAKE_CURRENT_SOURCE_DIR}/${SOURCE_FILE} + ${COMMON_SOURCES}) + TARGET_LINK_LIBRARIES(${EXAMPLE_NAME} ${PROJECT_NAME}) + INSTALL(TARGETS ${EXAMPLE_NAME} + DESTINATION ${BIN_INSTALL_DIR} + PERMISSIONS OWNER_READ + OWNER_WRITE + OWNER_EXECUTE + GROUP_READ + GROUP_EXECUTE + WORLD_READ + WORLD_EXECUTE) + INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${SOURCE_FILE} + DESTINATION ${EXAMPLES_DIR}) ENDFUNCTION(BUILD_EXAMPLE) BUILD_EXAMPLE("yaca-example-digest" digest.c) @@ -58,4 +52,4 @@ BUILD_EXAMPLE("yaca-example-key-exchange" key_exchange.c) BUILD_EXAMPLE("yaca-example-test" test.c) INSTALL(FILES ${COMMON_SOURCES} - DESTINATION ${EXAMPLES_DIR}) + DESTINATION ${EXAMPLES_DIR}) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4f6cc74..9d8369b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -41,9 +41,8 @@ ADD_DEFINITIONS(-fvisibility=hidden) ## Setup target ################################################################ ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS} ${HEADERS}) SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES - SOVERSION ${_LIB_SOVERSION_} - VERSION ${_LIB_VERSION_} -) + SOVERSION ${_LIB_SOVERSION_} + VERSION ${_LIB_VERSION_}) ## Link libraries ############################################################## PKG_CHECK_MODULES(YACA_DEPS REQUIRED openssl) @@ -64,4 +63,4 @@ INSTALL(TARGETS ${PROJECT_NAME} COMPONENT RuntimeLibraries) INSTALL(FILES ${HEADERS} - DESTINATION ${INCLUDE_INSTALL_DIR}/yaca) + DESTINATION ${INCLUDE_INSTALL_DIR}/yaca) -- 2.7.4 From 59b774dcfe65ac398e56813bc4af774fcbbdc716 Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Thu, 21 Apr 2016 16:06:38 +0200 Subject: [PATCH 09/16] yaca_open_init() needs key length to generate EVP_CIPHER Change-Id: I5d12ca2ac41c54a6a73844033c9ab6a0118b954f --- api/yaca/seal.h | 14 ++++++++------ examples/seal.c | 2 +- src/seal.c | 1 + 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/api/yaca/seal.h b/api/yaca/seal.h index a080247..3467291 100644 --- a/api/yaca/seal.h +++ b/api/yaca/seal.h @@ -97,12 +97,13 @@ int yaca_seal_final(yaca_ctx_h ctx, /** * @brief yaca_open_init Initializes an asymmetric decryption context. * - * @param[out] ctx Newly created context. Must be freed by @see yaca_ctx_free. - * @param[in] prv_key Private key, part of the pair that was used for the encryption. - * @param[in] algo Symmetric algorithm that was used for the encryption. - * @param[in] bcm Block chaining mode for the symmetric algorithm. - * @param[in] sym_key Symmetric key, encrypted with the public key, that was used to encrypt the data. - * @param[in] iv Initialization vector that was used for the encryption. + * @param[out] ctx Newly created context. Must be freed by @see yaca_ctx_free. + * @param[in] prv_key Private key, part of the pair that was used for the encryption. + * @param[in] algo Symmetric algorithm that was used for the encryption. + * @param[in] bcm Block chaining mode for the symmetric algorithm. + * @param[in] sym_key_bits Symmetric key length (in bits) that was used for the encryption. + * @param[in] sym_key Symmetric key, encrypted with the public key, that was used to encrypt the data. + * @param[in] iv Initialization vector that was used for the encryption. * * @return 0 on success, negative on error (@see error.h). */ @@ -110,6 +111,7 @@ int yaca_open_init(yaca_ctx_h *ctx, const yaca_key_h prv_key, yaca_enc_algo_e algo, yaca_block_cipher_mode_e bcm, + yaca_key_bits_e sym_key_bits, const yaca_key_h sym_key, const yaca_key_h iv); diff --git a/examples/seal.c b/examples/seal.c index 985f5dc..c913b48 100644 --- a/examples/seal.c +++ b/examples/seal.c @@ -100,7 +100,7 @@ void encrypt_seal(void) size_t rem; ret = yaca_open_init(&ctx, key_priv, - YACA_ENC_AES, YACA_BCM_CBC, + YACA_ENC_AES, YACA_BCM_CBC, YACA_KEY_192BIT, aes_key, iv); if (ret < 0) { yaca_free(enc); diff --git a/src/seal.c b/src/seal.c index 7b9308a..cc4b1c9 100644 --- a/src/seal.c +++ b/src/seal.c @@ -61,6 +61,7 @@ API int yaca_open_init(yaca_ctx_h *ctx, const yaca_key_h prv_key, yaca_enc_algo_e algo, yaca_block_cipher_mode_e bcm, + yaca_key_bits_e sym_key_bits, const yaca_key_h sym_key, const yaca_key_h iv) { -- 2.7.4 From 15368c9cbb29f4d3472956b34505655c023d90c1 Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Thu, 21 Apr 2016 13:09:18 +0200 Subject: [PATCH 10/16] Seal/Open implementation. Change-Id: I8c89eb8117158440fb6bd5ab8a6875ca29755093 --- api/yaca/key.h | 4 +- src/encrypt.c | 14 +- src/internal.h | 6 + src/key.c | 2 +- src/seal.c | 404 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- 5 files changed, 390 insertions(+), 40 deletions(-) diff --git a/api/yaca/key.h b/api/yaca/key.h index b479867..114b02c 100644 --- a/api/yaca/key.h +++ b/api/yaca/key.h @@ -44,13 +44,13 @@ extern "C" { // TODO: We need a way to import keys encrypted with hw (or other) keys. New function like yaca_key_load or sth?? /** - * @brief yaca_key_get_length Get key's length. + * @brief yaca_key_get_bits Get key's length (in bits). * * @param[in] key Key which length we return. * * @return negative on error (@see error.h) or key length (in bits). */ -int yaca_key_get_length(const yaca_key_h key); +int yaca_key_get_bits(const yaca_key_h key); /** * @brief yaca_key_import Imports a key from the arbitrary format. diff --git a/src/encrypt.c b/src/encrypt.c index a18a05c..3fee076 100644 --- a/src/encrypt.c +++ b/src/encrypt.c @@ -134,9 +134,9 @@ static const char *bcm_to_str(yaca_block_cipher_mode_e bcm) } } -int get_encrypt_algorithm(yaca_enc_algo_e algo, +int encrypt_get_algorithm(yaca_enc_algo_e algo, yaca_block_cipher_mode_e bcm, - unsigned key_bits, + size_t key_bits, const EVP_CIPHER **cipher) { char cipher_name[32]; @@ -149,7 +149,7 @@ int get_encrypt_algorithm(yaca_enc_algo_e algo, cipher == NULL) return YACA_ERROR_INVALID_ARGUMENT; - ret = snprintf(cipher_name, sizeof(cipher_name), "%s-%d-%s", algo_name, + ret = snprintf(cipher_name, sizeof(cipher_name), "%s-%zu-%s", algo_name, key_bits, bcm_name); if (ret < 0) return YACA_ERROR_INVALID_ARGUMENT; @@ -199,12 +199,12 @@ static int encrypt_init(yaca_ctx_h *ctx, nc->op_type = op_type; // TODO: handling of algorithms with variable key length - ret = yaca_key_get_length(sym_key); + ret = yaca_key_get_bits(sym_key); if (ret < 0) goto err_free; key_bits = ret; - ret = get_encrypt_algorithm(algo, bcm, key_bits, &cipher); + ret = encrypt_get_algorithm(algo, bcm, key_bits, &cipher); if (ret != 0) goto err_free; @@ -228,7 +228,7 @@ static int encrypt_init(yaca_ctx_h *ctx, } // TODO: handling of algorithms with variable IV length - if (iv_bits != yaca_key_get_length(iv)) { /* IV length doesn't match cipher */ + if (iv_bits != yaca_key_get_bits(iv)) { /* IV length doesn't match cipher */ ret = YACA_ERROR_INVALID_ARGUMENT; goto err_free; } @@ -355,7 +355,7 @@ API int yaca_get_iv_bits(yaca_enc_algo_e algo, const EVP_CIPHER *cipher; int ret; - ret = get_encrypt_algorithm(algo, bcm, key_bits, &cipher); + ret = encrypt_get_algorithm(algo, bcm, key_bits, &cipher); if (ret < 0) return ret; diff --git a/src/internal.h b/src/internal.h index 2b5dc9f..5bff4f1 100644 --- a/src/internal.h +++ b/src/internal.h @@ -37,6 +37,7 @@ enum yaca_ctx_type_e YACA_CTX_DIGEST, YACA_CTX_SIGN, YACA_CTX_ENCRYPT, + YACA_CTX_SEAL }; /* Base structure for crypto contexts - to be inherited */ @@ -91,6 +92,11 @@ struct yaca_key_evp_s int digest_get_algorithm(yaca_digest_algo_e algo, const EVP_MD **md); +int encrypt_get_algorithm(yaca_enc_algo_e algo, + yaca_block_cipher_mode_e bcm, + size_t key_bits, + const EVP_CIPHER **cipher); + 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 2debe7d..4365e3c 100644 --- a/src/key.c +++ b/src/key.c @@ -93,7 +93,7 @@ struct yaca_key_evp_s *key_get_evp(const yaca_key_h key) } } -API int yaca_key_get_length(const yaca_key_h key) +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); diff --git a/src/seal.c b/src/seal.c index cc4b1c9..c39b8be 100644 --- a/src/seal.c +++ b/src/seal.c @@ -30,56 +30,400 @@ #include "internal.h" +enum seal_op_type { + OP_SEAL = 0, + OP_OPEN = 1 +}; + +struct yaca_seal_ctx_s +{ + struct yaca_ctx_s ctx; + + EVP_CIPHER_CTX *cipher_ctx; + enum seal_op_type op_type; /* Operation context was created for */ +}; + +static struct yaca_seal_ctx_s *get_seal_ctx(const yaca_ctx_h ctx) +{ + if (ctx == YACA_CTX_NULL) + return NULL; + + switch (ctx->type) + { + case YACA_CTX_SEAL: + return (struct yaca_seal_ctx_s *)ctx; + default: + return NULL; + } +} + +static void destroy_seal_ctx(const yaca_ctx_h ctx) +{ + struct yaca_seal_ctx_s *nc = get_seal_ctx(ctx); + + if (nc == NULL) + return; + + EVP_CIPHER_CTX_free(nc->cipher_ctx); + nc->cipher_ctx = NULL; +} + +static int get_seal_output_length(const yaca_ctx_h ctx, size_t input_len) +{ + struct yaca_seal_ctx_s *nc = get_seal_ctx(ctx); + int block_size; + + if (nc == NULL) + return YACA_ERROR_INVALID_ARGUMENT; + assert(nc->cipher_ctx); + + 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; + } + + if (input_len > 0) + return block_size + input_len - 1; + return block_size; +} + +static int seal_init(yaca_ctx_h *ctx, + const yaca_key_h pub_key, + yaca_enc_algo_e algo, + yaca_block_cipher_mode_e bcm, + yaca_key_bits_e sym_key_bits, + yaca_key_h *sym_key, + yaca_key_h *iv) +{ + struct yaca_key_evp_s *lpub; + struct yaca_key_simple_s *lkey; + struct yaca_key_simple_s *liv; + struct yaca_seal_ctx_s *nc; + const EVP_CIPHER *cipher; + int pub_key_length; + int iv_length; + int ret; + + if (ctx == NULL || pub_key == YACA_KEY_NULL) + return YACA_ERROR_INVALID_ARGUMENT; + + if (pub_key->type != YACA_KEY_TYPE_RSA_PUB) + return YACA_ERROR_INVALID_ARGUMENT; + lpub = key_get_evp(pub_key); + assert(lpub); + + nc = yaca_zalloc(sizeof(struct yaca_seal_ctx_s)); + if (nc == NULL) + return YACA_ERROR_OUT_OF_MEMORY; + + nc->ctx.type = YACA_CTX_SEAL; + nc->ctx.ctx_destroy = destroy_seal_ctx; + nc->ctx.get_output_length = get_seal_output_length; + nc->op_type = OP_SEAL; + + nc->cipher_ctx = EVP_CIPHER_CTX_new(); + if (nc->cipher_ctx == NULL) { + ret = YACA_ERROR_OPENSSL_FAILURE; + ERROR_DUMP(ret); + goto err_free; + } + + ret = EVP_PKEY_size(lpub->evp); + if (ret <= 0) { + ret = YACA_ERROR_OPENSSL_FAILURE; + ERROR_DUMP(ret); + goto err_ctx; + } + + pub_key_length = ret; + lkey = yaca_zalloc(sizeof(struct yaca_key_simple_s) + pub_key_length); + if (lkey == NULL) { + ret = YACA_ERROR_OUT_OF_MEMORY; + goto err_ctx; + } + + ret = encrypt_get_algorithm(algo, bcm, sym_key_bits, &cipher); + if (ret != 0) + goto err_key; + + ret = EVP_CIPHER_iv_length(cipher); + if (ret < 0) { + ret = YACA_ERROR_OPENSSL_FAILURE; + ERROR_DUMP(ret); + goto err_key; + } + + iv_length = ret; + liv = yaca_zalloc(sizeof(struct yaca_key_simple_s) + iv_length); + if (liv == NULL) { + ret = YACA_ERROR_OUT_OF_MEMORY; + goto err_key; + } + + unsigned char *key_data = (unsigned char*)lkey->d; + int key_data_length; + + ret = EVP_SealInit(nc->cipher_ctx, + cipher, + &key_data, + &key_data_length, + (unsigned char*)liv->d, + &lpub->evp, + 1); + + if (ret != 1) { + ret = YACA_ERROR_OPENSSL_FAILURE; + ERROR_DUMP(ret); + goto err_iv; + } + + lkey->bits = key_data_length * 8; + lkey->key.type = YACA_KEY_TYPE_SYMMETRIC; + *sym_key = (yaca_key_h)lkey; + + liv->bits = iv_length * 8; + liv->key.type = YACA_KEY_TYPE_IV; + *iv = (yaca_key_h)liv; + + *ctx = (yaca_ctx_h)nc; + + return 0; + +err_iv: + yaca_free(liv); +err_key: + yaca_free(lkey); +err_ctx: + EVP_CIPHER_CTX_free(nc->cipher_ctx); +err_free: + yaca_free(nc); + return ret; +} + +static int open_init(yaca_ctx_h *ctx, + const yaca_key_h prv_key, + yaca_enc_algo_e algo, + yaca_block_cipher_mode_e bcm, + yaca_key_bits_e sym_key_bits, + const yaca_key_h sym_key, + const yaca_key_h iv) +{ + const struct yaca_key_evp_s *lprv; + const struct yaca_key_simple_s *lkey; + const struct yaca_key_simple_s *liv; + struct yaca_seal_ctx_s *nc; + const EVP_CIPHER *cipher; + int iv_bits; + int ret; + + if (ctx == NULL || prv_key == YACA_KEY_NULL || sym_key == YACA_KEY_NULL) + return YACA_ERROR_INVALID_ARGUMENT; + + if (prv_key->type != YACA_KEY_TYPE_RSA_PRIV) + return YACA_ERROR_INVALID_ARGUMENT; + lprv = key_get_evp(prv_key); + assert(lprv); + + lkey = key_get_simple(sym_key); + if (lkey == NULL || lkey->key.type != YACA_KEY_TYPE_SYMMETRIC) + return YACA_ERROR_INVALID_ARGUMENT; + + nc = yaca_zalloc(sizeof(struct yaca_seal_ctx_s)); + if (nc == NULL) + return YACA_ERROR_OUT_OF_MEMORY; + + nc->ctx.type = YACA_CTX_SEAL; + nc->ctx.ctx_destroy = destroy_seal_ctx; + nc->ctx.get_output_length = get_seal_output_length; + nc->op_type = OP_OPEN; + + ret = encrypt_get_algorithm(algo, bcm, sym_key_bits, &cipher); + if (ret != 0) + goto err_free; + + ret = EVP_CIPHER_iv_length(cipher); + if (ret < 0) { + ret = YACA_ERROR_OPENSSL_FAILURE; + ERROR_DUMP(ret); + goto err_free; + } + + iv_bits = ret * 8; + if (iv_bits == 0 && iv != NULL) { /* 0 -> cipher doesn't use iv, but it was provided */ + ret = YACA_ERROR_INVALID_ARGUMENT; + goto err_free; + } + + liv = key_get_simple(iv); + /* cipher requires iv, but none was provided, or provided wrong iv */ + if (iv_bits != 0 && (liv == NULL || liv->key.type != YACA_KEY_TYPE_IV)) { + ret = YACA_ERROR_INVALID_ARGUMENT; + goto err_free; + } + + // TODO: handling of algorithms with variable IV length + if (iv_bits != yaca_key_get_bits(iv)) { /* IV length doesn't match cipher */ + ret = YACA_ERROR_INVALID_ARGUMENT; + goto err_free; + } + + nc->cipher_ctx = EVP_CIPHER_CTX_new(); + if (nc->cipher_ctx == NULL) { + ret = YACA_ERROR_OPENSSL_FAILURE; + ERROR_DUMP(ret); + goto err_free; + } + + ret = EVP_OpenInit(nc->cipher_ctx, cipher, + (unsigned char*)lkey->d, + EVP_PKEY_size(lprv->evp), + (unsigned char*)liv->d, + lprv->evp); + if (ret != 1) { + ret = YACA_ERROR_OPENSSL_FAILURE; + ERROR_DUMP(ret); + goto err_ctx; + } + + *ctx = (yaca_ctx_h)nc; + return 0; + +err_ctx: + EVP_CIPHER_CTX_free(nc->cipher_ctx); +err_free: + yaca_free(nc); + return ret; +} + +static int seal_update(yaca_ctx_h ctx, + const unsigned char *input, + size_t input_len, + unsigned char *output, + size_t *output_len, + enum seal_op_type op_type) +{ + struct yaca_seal_ctx_s *c = get_seal_ctx(ctx); + int ret; + + if (c == NULL || input == NULL || input_len == 0 || + output == NULL || output_len == NULL || op_type != c->op_type) + return YACA_ERROR_INVALID_ARGUMENT; + + switch (op_type) { + case OP_SEAL: + ret = EVP_SealUpdate(c->cipher_ctx, output, (int*)output_len, input, input_len); + break; + case OP_OPEN: + ret = EVP_OpenUpdate(c->cipher_ctx, output, (int*)output_len, input, input_len); + break; + default: + return YACA_ERROR_INVALID_ARGUMENT; + } + + if (ret != 1) { + ret = YACA_ERROR_OPENSSL_FAILURE; + ERROR_DUMP(ret); + return ret; + } + + return 0; +} + +static int seal_final(yaca_ctx_h ctx, + unsigned char *output, + size_t *output_len, + enum seal_op_type op_type) +{ + struct yaca_seal_ctx_s *c = get_seal_ctx(ctx); + int ret; + + if (c == NULL || output == NULL || output_len == NULL || op_type != c->op_type) + return YACA_ERROR_INVALID_ARGUMENT; + + switch (op_type) { + case OP_SEAL: + ret = EVP_SealFinal(c->cipher_ctx, output, (int*)output_len); + break; + case OP_OPEN: + ret = EVP_OpenFinal(c->cipher_ctx, output, (int*)output_len); + break; + default: + return YACA_ERROR_INVALID_ARGUMENT; + } + + if (ret != 1) { + ret = YACA_ERROR_OPENSSL_FAILURE; + ERROR_DUMP(ret); + return ret; + } + + return 0; +} + API int yaca_seal_init(yaca_ctx_h *ctx, - const yaca_key_h pub_key, - yaca_enc_algo_e algo, - yaca_block_cipher_mode_e bcm, - yaca_key_bits_e sym_key_bits, - yaca_key_h *sym_key, - yaca_key_h *iv) + const yaca_key_h pub_key, + yaca_enc_algo_e algo, + yaca_block_cipher_mode_e bcm, + yaca_key_bits_e sym_key_bits, + yaca_key_h *sym_key, + yaca_key_h *iv) { - return YACA_ERROR_NOT_IMPLEMENTED; + return seal_init(ctx, pub_key, algo, bcm, sym_key_bits, sym_key, iv); } API int yaca_seal_update(yaca_ctx_h ctx, - const char *plain, - size_t plain_len, - char *cipher, - size_t *cipher_len) + const char *plain, + size_t plain_len, + char *cipher, + size_t *cipher_len) { - return YACA_ERROR_NOT_IMPLEMENTED; + return seal_update(ctx, + (const unsigned char*)plain, + plain_len, + (unsigned char*)cipher, + cipher_len, + OP_SEAL); } API int yaca_seal_final(yaca_ctx_h ctx, - char *cipher, - size_t *cipher_len) + char *cipher, + size_t *cipher_len) { - return YACA_ERROR_NOT_IMPLEMENTED; + return seal_final(ctx, + (unsigned char*)cipher, + cipher_len, + OP_SEAL); } API int yaca_open_init(yaca_ctx_h *ctx, - const yaca_key_h prv_key, - yaca_enc_algo_e algo, - yaca_block_cipher_mode_e bcm, - yaca_key_bits_e sym_key_bits, - const yaca_key_h sym_key, - const yaca_key_h iv) + const yaca_key_h prv_key, + yaca_enc_algo_e algo, + yaca_block_cipher_mode_e bcm, + yaca_key_bits_e sym_key_bits, + const yaca_key_h sym_key, + const yaca_key_h iv) { - return YACA_ERROR_NOT_IMPLEMENTED; + return open_init(ctx, prv_key, algo, bcm, sym_key_bits, sym_key, iv); } API int yaca_open_update(yaca_ctx_h ctx, - const char *cipher, - size_t cipher_len, - char *plain, - size_t *plain_len) + const char *cipher, + size_t cipher_len, + char *plain, + size_t *plain_len) { - return YACA_ERROR_NOT_IMPLEMENTED; + return seal_update(ctx, + (const unsigned char*)cipher, + cipher_len, + (unsigned char*)plain, + plain_len, + OP_OPEN); } API int yaca_open_final(yaca_ctx_h ctx, - char *plain, - size_t *plain_len) + char *plain, + size_t *plain_len) { - return YACA_ERROR_NOT_IMPLEMENTED; + return seal_final(ctx, (unsigned char*)plain, plain_len, OP_OPEN); } -- 2.7.4 From 67a9f817aec8be46f57c1c69333fc8f7d25a7814 Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Thu, 21 Apr 2016 13:06:31 +0200 Subject: [PATCH 11/16] Review and simplify Seal/Open example. Change-Id: I3d41c8de8edf79237027162f654af65952a5d9d3 --- examples/seal.c | 95 +++++++++++++++++++++++---------------------------------- 1 file changed, 39 insertions(+), 56 deletions(-) diff --git a/examples/seal.c b/examples/seal.c index c913b48..a631c91 100644 --- a/examples/seal.c +++ b/examples/seal.c @@ -32,7 +32,9 @@ void encrypt_seal(void) { - int ret; + const yaca_enc_algo_e algo = YACA_ENC_AES; + const yaca_block_cipher_mode_e bcm = YACA_BCM_CBC; + const size_t key_bits = YACA_KEY_256BIT; yaca_ctx_h ctx = YACA_CTX_NULL; yaca_key_h key_pub = YACA_KEY_NULL; yaca_key_h key_priv = YACA_KEY_NULL; @@ -44,98 +46,78 @@ void encrypt_seal(void) size_t enc_size; size_t dec_size; - printf("Plain data (16 of %zu bytes): %.16s\n", (size_t)4096, lorem1024); + size_t block_len; + size_t output_len; + size_t out_size; + size_t rem; - /// Generate key pair - ret = yaca_key_gen_pair(&key_priv, &key_pub, - YACA_KEY_TYPE_PAIR_RSA, - YACA_KEY_2048BIT); - if (ret) return; + printf("Plain data (16 of %zu bytes): %.16s\n", LOREM4096_SIZE, lorem4096); - /// Encrypt a.k.a. seal - { - size_t out_size; - size_t rem; + /* Generate key pair */ + if (yaca_key_gen_pair(&key_priv, &key_pub, YACA_KEY_TYPE_PAIR_RSA, YACA_KEY_4096BIT) != 0) + return; - ret = yaca_seal_init(&ctx, key_pub, - YACA_ENC_AES, YACA_BCM_CBC, YACA_KEY_192BIT, - &aes_key, &iv); - if (ret < 0) + /* Encrypt a.k.a. seal */ + { + if (yaca_seal_init(&ctx, key_pub, algo, bcm, key_bits, &aes_key, &iv) != 0) goto ex_pk; - ret = yaca_seal_update(ctx, lorem4096, 4096, NULL, &enc_size); - if (ret < 0) + if ((block_len = yaca_get_block_length(ctx)) <= 0) goto ex_ak; - ret = yaca_get_block_length(ctx); - if (ret < 0) + if ((output_len = yaca_get_output_length(ctx, LOREM4096_SIZE)) <= 0) goto ex_ak; - enc_size = enc_size + ret; - enc = yaca_malloc(enc_size); - if (enc == NULL) + /* Calculate max output: size of update + final chunks */ + enc_size = output_len + block_len; + if ((enc = yaca_malloc(enc_size)) == NULL) goto ex_ak; - // Seal and finalize + /* Seal and finalize */ out_size = enc_size; - ret = yaca_seal_update(ctx, lorem4096, 4096, enc, &out_size); - if (ret < 0) + if (yaca_seal_update(ctx, lorem4096, LOREM4096_SIZE, enc, &out_size) != 0) goto ex_of; rem = enc_size - out_size; - ret = yaca_seal_final(ctx, enc + out_size, &rem); - if (ret < 0) + if (yaca_seal_final(ctx, enc + out_size, &rem) != 0) goto ex_of; enc_size = rem + out_size; dump_hex(enc, 16, "Encrypted data (16 of %zu bytes): ", enc_size); - yaca_ctx_free(ctx); // TODO: perhaps it should not return value + yaca_ctx_free(ctx); + ctx = YACA_CTX_NULL; } - /// Decrypt a.k.a. open + /* Decrypt a.k.a. open */ { - size_t out_size; - size_t rem; - - ret = yaca_open_init(&ctx, key_priv, - YACA_ENC_AES, YACA_BCM_CBC, YACA_KEY_192BIT, - aes_key, iv); - if (ret < 0) { - yaca_free(enc); - goto ex_ak; - } + if (yaca_open_init(&ctx, key_priv, algo, bcm, key_bits, aes_key, iv) != 0) + goto ex_of; - ret = yaca_open_update(ctx, enc, enc_size, NULL, &dec_size); - if (ret < 0) + if ((block_len = yaca_get_block_length(ctx)) <= 0) goto ex_of; - ret = yaca_get_block_length(ctx); - if (ret < 0) + if ((output_len = yaca_get_output_length(ctx, LOREM4096_SIZE)) <= 0) goto ex_of; - dec_size = dec_size + ret; - dec = yaca_malloc(dec_size); - if (dec == NULL) + /* Calculate max output: size of update + final chunks */ + dec_size = output_len + block_len; + if ((dec = yaca_malloc(dec_size)) == NULL) goto ex_of; - // Seal and finalize - out_size = enc_size; - ret = yaca_open_update(ctx, enc, enc_size, dec, &out_size); - if (ret < 0) + /* Open and finalize */ + out_size = dec_size; + if (yaca_open_update(ctx, enc, enc_size, dec, &out_size) != 0) goto ex_in; rem = dec_size - out_size; - ret = yaca_open_final(ctx, dec + out_size, &rem); - if (ret < 0) + if (yaca_open_final(ctx, dec + out_size, &rem) != 0) goto ex_in; dec_size = rem + out_size; - printf("Decrypted data (16 of %zu bytes): %.16s\n", (size_t)dec_size, dec); - - yaca_ctx_free(ctx); // TODO: perhaps it should not return value + printf("Decrypted data (16 of %zu bytes): %.16s\n", dec_size, dec); } ex_in: @@ -143,6 +125,7 @@ ex_in: ex_of: yaca_free(enc); ex_ak: + yaca_ctx_free(ctx); yaca_key_free(aes_key); yaca_key_free(iv); ex_pk: @@ -160,6 +143,6 @@ int main() encrypt_seal(); - yaca_exit(); // TODO: what about handing of return value from exit?? + yaca_exit(); return ret; } -- 2.7.4 From 76c758b272e5837520af1837c1fa49f68ff5f5fe Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Thu, 28 Apr 2016 13:07:47 +0200 Subject: [PATCH 12/16] Cleanup API documentation. Change-Id: I4e4e1ce027d9672adb1bf92eebfc8e8696f90cb5 --- api/yaca/crypto.h | 39 ++++++++----- api/yaca/digest.h | 16 +++-- api/yaca/encrypt.h | 86 +++++++++++++++------------ api/yaca/error.h | 27 +++++---- api/yaca/key.h | 94 ++++++++++++++++-------------- api/yaca/seal.h | 86 +++++++++++++++------------ api/yaca/sign.h | 56 ++++++++++-------- api/yaca/simple.h | 74 +++++++++++++----------- api/yaca/types.h | 167 ++++++++++++++++++++++++++++++++++++----------------- doc/doxygen.cfg | 4 +- 10 files changed, 386 insertions(+), 263 deletions(-) diff --git a/api/yaca/crypto.h b/api/yaca/crypto.h index b3d16db..52c7a32 100644 --- a/api/yaca/crypto.h +++ b/api/yaca/crypto.h @@ -32,7 +32,7 @@ extern "C" { #endif /** - * @defgroup Non-Crypto Non crypto related functions. + * @defgroup Non-Crypto Yet Another Crypto API - non crypto related functions. * * TODO: extended description and examples. * @@ -47,13 +47,15 @@ extern "C" { /** * @brief yaca_init Initializes the library. Must be called before any other crypto function. * - * @return 0 on success, negative on error (@see error.h). + * @return 0 on success, negative on error. + * @see yaca_exit() */ int yaca_init(void); /** * @brief yaca_exit Closes the library. Must be called before exiting the application. * + * @see yaca_init() */ void yaca_exit(void); @@ -63,6 +65,7 @@ void yaca_exit(void); * @param[in] size Size of the allocation (bytes). * * @return NULL on failure, pointer to allocated memory otherwise. + * @see yaca_zalloc(), yaca_realloc(), yaca_free() */ // TODO: this should be a macro to CRYPTO_* void *yaca_malloc(size_t size); @@ -73,6 +76,7 @@ void *yaca_malloc(size_t size); * @param[in] size Size of the allocation (bytes). * * @return NULL on failure, pointer to allocated and zeroed memory otherwise. + * @see yaca_malloc(), yaca_realloc(), yaca_free() */ // TODO: this should be a macro to CRYPTO_* void *yaca_zalloc(size_t size); @@ -84,15 +88,17 @@ void *yaca_zalloc(size_t size); * @param[in] size Size of the new allocation (bytes). * * @return NULL on failure, pointer to allocated memory otherwise. + * @see yaca_malloc(), yaca_zalloc(), yaca_free() */ // TODO: this should be a macro to CRYPTO_* void *yaca_realloc(void *addr, size_t size); /** - * @brief yaca_free Frees the memory allocated by @see yaca_malloc - * or one of the cryptographics operations. + * @brief yaca_free Frees the memory allocated by yaca_malloc(), yaca_zalloc(), + * yaca_realloc() or one of the cryptographic operations. * * @param[in] ptr Pointer to the memory to be freed. + * @see yaca_malloc(), yaca_zalloc(), yaca_realloc() * */ // TODO: this should be a macro to CRYPTO_* @@ -104,7 +110,7 @@ void yaca_free(void *ptr); * @param[in,out] data Pointer to the memory to be randomized. * @param[in] data_len Length of the memory to be randomized. * - * @return 0 on success, negative on error (@see error.h). + * @return 0 on success, negative on error. */ int yaca_rand_bytes(char *data, size_t data_len); @@ -117,10 +123,13 @@ int yaca_rand_bytes(char *data, size_t data_len); * @param[in] value Parameter value. * @param[in] value_len Length of the parameter value. * - * @return 0 on success, negative on error (@see error.h). + * @return 0 on success, negative on error. + * @see #yaca_ex_param_e, yaca_ctx_get_param() */ -int yaca_ctx_set_param(yaca_ctx_h ctx, yaca_ex_param_e param, - const void *value, size_t value_len); +int yaca_ctx_set_param(yaca_ctx_h ctx, + yaca_ex_param_e param, + const void *value, + size_t value_len); /** * @brief yaca_ctx_get_param Returns the extended context parameters. @@ -128,13 +137,16 @@ int yaca_ctx_set_param(yaca_ctx_h ctx, yaca_ex_param_e param, * * @param[in] ctx Previously initialized crypto context. * @param[in] param Parameter to be read. - * @param[out] value Copy of the parameter value (must be freed with @see yaca_free). + * @param[out] value Copy of the parameter value (must be freed with yaca_free()). * @param[out] value_len Length of the parameter value will be returned here. * - * @return 0 on success, negative on error (@see error.h). + * @return 0 on success, negative on error. + * @see #yaca_ex_param_e, yaca_ctx_set_param() */ -int yaca_ctx_get_param(const yaca_ctx_h ctx, yaca_ex_param_e param, - void **value, size_t *value_len); +int yaca_ctx_get_param(const yaca_ctx_h ctx, + yaca_ex_param_e param, + void **value, + size_t *value_len); /** * @brief yaca_ctx_free Destroys the crypto context. Must be called @@ -142,6 +154,7 @@ int yaca_ctx_get_param(const yaca_ctx_h ctx, yaca_ex_param_e param, * Passing YACA_CTX_NULL is allowed. * * @param[in,out] ctx Crypto context. + * @see #yaca_ctx_h * */ void yaca_ctx_free(yaca_ctx_h ctx); @@ -153,7 +166,7 @@ void yaca_ctx_free(yaca_ctx_h ctx); * @param[in] ctx Previously initialized crypto context. * @param[in] input_len Length of the input data to be processed. * - * @return negative on error (@see error.h) or length of output. + * @return negative on error or length of output. */ // TODO: this function should probably return the value by param of // size_t type and leave the return int value only to report errors diff --git a/api/yaca/digest.h b/api/yaca/digest.h index 1e8edf3..dc49b92 100644 --- a/api/yaca/digest.h +++ b/api/yaca/digest.h @@ -42,21 +42,23 @@ extern "C" { /** * @brief yaca_digest_init Initializes a digest context. * - * @param[out] ctx Newly created context (must be freed with @see yaca_ctx_free). + * @param[out] ctx Newly created context (must be freed with yaca_ctx_free()). * @param[in] algo Digest algorithm that will be used. * - * @return 0 on success, negative on error (@see error.h). + * @return 0 on success, negative on error. + * @see #yaca_digest_algo_e, yaca_digest_update(), yaca_digest_final() */ int yaca_digest_init(yaca_ctx_h *ctx, yaca_digest_algo_e algo); /** * @brief yaca_digest_update Feeds the data into the message digest algorithm. * - * @param[in,out] ctx Context created by @see yaca_digest_init. + * @param[in,out] ctx Context created by yaca_digest_init(). * @param[in] data Data from which the digest is to be calculated. * @param[in] data_len Length of the data. * - * @return 0 on success, negative on error (@see error.h). + * @return 0 on success, negative on error. + * @see yaca_digest_init(), yaca_digest_final() */ int yaca_digest_update(yaca_ctx_h ctx, const char *data, size_t data_len); @@ -64,10 +66,12 @@ int yaca_digest_update(yaca_ctx_h ctx, const char *data, size_t data_len); * @brief yaca_digest_final Calculates the final digest. * * @param[in,out] ctx A valid digest context. - * @param[out] digest Buffer for the message digest (must be allocated by client, @see yaca_get_digest_length). + * @param[out] digest Buffer for the message digest (must be allocated by client, + * see yaca_get_digest_length()). * @param[out] digest_len Length of the digest, actual number of bytes written will be returned here. * - * @return 0 on success, negative on error (@see error.h). + * @return 0 on success, negative on error. + * @see yaca_digest_init(), yaca_digest_update() */ int yaca_digest_final(yaca_ctx_h ctx, char *digest, size_t *digest_len); diff --git a/api/yaca/encrypt.h b/api/yaca/encrypt.h index 8c52fc9..b62541d 100644 --- a/api/yaca/encrypt.h +++ b/api/yaca/encrypt.h @@ -44,109 +44,119 @@ extern "C" { /** * @brief yaca_encrypt_init Initializes an encryption context. * - * @param[out] ctx Newly created context (must be freed with @see yaca_ctx_free). + * @param[out] ctx Newly created context (must be freed with yaca_ctx_free()). * @param[in] algo Encryption algorithm that will be used. * @param[in] bcm Chaining mode that will be used. * @param[in] sym_key Symmetric key that will be used. * @param[in] iv Initialization vector that will be used. * - * @return 0 on success, negative on error (@see error.h). + * @return 0 on success, negative on error. + * @see #yaca_enc_algo_e, #yaca_block_cipher_mode_e, yaca_encrypt_update(), yaca_encrypt_final() */ int yaca_encrypt_init(yaca_ctx_h *ctx, - yaca_enc_algo_e algo, - yaca_block_cipher_mode_e bcm, - const yaca_key_h sym_key, - const yaca_key_h iv); + yaca_enc_algo_e algo, + yaca_block_cipher_mode_e bcm, + const yaca_key_h sym_key, + const yaca_key_h iv); /** * @brief yaca_encrypt_update Encrypts chunk of the data. * - * @param[in,out] ctx Context created by @see yaca_encrypt_init. + * @param[in,out] ctx Context created by yaca_encrypt_init(). * @param[in] plain Plain text to be encrypted. * @param[in] plain_len Length of the plain text. - * @param[out] cipher Buffer for the encrypted data (must be allocated by client, @see yaca_get_output_length). + * @param[out] cipher Buffer for the encrypted data (must be allocated by client, see + * yaca_get_output_length()). * @param[out] cipher_len Length of the encrypted data, actual number of bytes written will be returned here. * - * @return 0 on success, negative on error (@see error.h). + * @return 0 on success, negative on error. + * @see yaca_encrypt_init(), yaca_encrypt_final() */ int yaca_encrypt_update(yaca_ctx_h ctx, - const char *plain, - size_t plain_len, - char *cipher, - size_t *cipher_len); + const char *plain, + size_t plain_len, + char *cipher, + size_t *cipher_len); /** * @brief yaca_encrypt_final Encrypts the final chunk of the data. * * @param[in,out] ctx A valid encrypt context. - * @param[out] cipher Final piece of the encrypted data (must be allocated by client, @see yaca_get_block_length). + * @param[out] cipher Final piece of the encrypted data (must be allocated by client, see + * yaca_get_block_length()). * @param[out] cipher_len Length of the final piece, actual number of bytes written will be returned here. * - * @return 0 on success, negative on error (@see error.h). + * @return 0 on success, negative on error. + * @see yaca_encrypt_init(), yaca_encrypt_update() */ int yaca_encrypt_final(yaca_ctx_h ctx, - char *cipher, - size_t *cipher_len); + char *cipher, + size_t *cipher_len); /** * @brief yaca_decrypt_init Initializes an decryption context. * - * @param[out] ctx Newly created context (must be freed with @see yaca_ctx_free). + * @param[out] ctx Newly created context (must be freed with yaca_ctx_free()). * @param[in] algo Encryption algorithm that was used to encrypt the data. * @param[in] bcm Chaining mode that was used to encrypt the data. * @param[in] sym_key Symmetric key that was used to encrypt the data. * @param[in] iv Initialization vector that was used to encrypt the data. * - * @return 0 on success, negative on error (@see error.h). + * @return 0 on success, negative on error. + * @see #yaca_enc_algo_e, #yaca_block_cipher_mode_e, yaca_decrypt_update(), yaca_decrypt_final() */ int yaca_decrypt_init(yaca_ctx_h *ctx, - yaca_enc_algo_e algo, - yaca_block_cipher_mode_e bcm, - const yaca_key_h sym_key, - const yaca_key_h iv); + yaca_enc_algo_e algo, + yaca_block_cipher_mode_e bcm, + const yaca_key_h sym_key, + const yaca_key_h iv); /** * @brief yaca_decrypt_update Decrypts chunk of the data. * - * @param[in,out] ctx Context created by @see yaca_decrypt_init. + * @param[in,out] ctx Context created by yaca_decrypt_init(). * @param[in] cipher Cipher text to be decrypted. * @param[in] cipher_len Length of the cipher text. - * @param[out] plain Buffer for the decrypted data (must be allocated by client, @see yaca_get_output_length). + * @param[out] plain Buffer for the decrypted data (must be allocated by client, see + * yaca_get_output_length()). * @param[out] plain_len Length of the decrypted data, actual number of bytes written will be returned here. * - * @return 0 on success, negative on error (@see error.h). + * @return 0 on success, negative on error. + * @see yaca_decrypt_init(), yaca_decrypt_final() */ int yaca_decrypt_update(yaca_ctx_h ctx, - const char *cipher, - size_t cipher_len, - char *plain, - size_t *plain_len); + const char *cipher, + size_t cipher_len, + char *plain, + size_t *plain_len); /** * @brief yaca_decrypt_final Decrypts the final chunk of the data. * * @param[in,out] ctx A valid decrypt context. - * @param[out] plain Final piece of the decrypted data (must be allocated by client, @see yaca_get_block_length). + * @param[out] plain Final piece of the decrypted data (must be allocated by client, see + * yaca_get_block_length()). * @param[out] plain_len Length of the final piece, actual number of bytes written will be returned here. * - * @return 0 on success, negative on error (@see error.h). + * @return 0 on success, negative on error. + * @see yaca_decrypt_init(), yaca_decrypt_update() */ int yaca_decrypt_final(yaca_ctx_h ctx, - char *plain, - size_t *plain_len); + char *plain, + size_t *plain_len); /** * @brief yaca_get_iv_bits Returns the recomended/default length of the IV for a given encryption configuration. * * @param[in] algo Encryption algorithm. * @param[in] bcm Chain mode. - * @param[in] key_bits Key length in bits (@see crypto_key_len_e). + * @param[in] key_bits Key length in bits. * - * @return negative on error (@see error.h) or the IV length in bits. + * @return negative on error or the IV length in bits. */ int yaca_get_iv_bits(yaca_enc_algo_e algo, - yaca_block_cipher_mode_e bcm, - size_t key_bits); + yaca_block_cipher_mode_e bcm, + size_t key_bits); /**@}*/ diff --git a/api/yaca/error.h b/api/yaca/error.h index 5012c34..d82c3fc 100644 --- a/api/yaca/error.h +++ b/api/yaca/error.h @@ -24,21 +24,27 @@ #ifndef ERROR_H #define ERROR_H -/* - TODO: Error enums should be placed here - */ #ifdef __cplusplus extern "C" { #endif +/** + * @defgroup Error Yet another Crypto API - error enums and debug functions. + * + * @{ + */ + +/** + * @brief Error enums + */ enum __yaca_error_code { - YACA_ERROR_INVALID_ARGUMENT = -1, - YACA_ERROR_NOT_IMPLEMENTED = -2, - YACA_ERROR_OPENSSL_FAILURE = -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_INVALID_ARGUMENT = -1, + YACA_ERROR_NOT_IMPLEMENTED = -2, + YACA_ERROR_OPENSSL_FAILURE = -3, + YACA_ERROR_NOT_SUPPORTED = -4, + YACA_ERROR_TOO_BIG_ARGUMENT = -5, + YACA_ERROR_OUT_OF_MEMORY = -6, + YACA_ERROR_SIGNATURE_INVALID = -7 }; // TODO disable debug function in release? @@ -58,6 +64,7 @@ typedef void (*yaca_debug_func)(const char*); */ void yaca_error_set_debug_func(yaca_debug_func fn); +/**@}*/ #ifdef __cplusplus } /* extern */ diff --git a/api/yaca/key.h b/api/yaca/key.h index 114b02c..c9c924c 100644 --- a/api/yaca/key.h +++ b/api/yaca/key.h @@ -32,7 +32,7 @@ extern "C" { #endif /** - * @defgroup Key Key and IV handling functions + * @defgroup Key Advanced API for the key and IV handling. * * TODO: extended description and examples. * @@ -48,77 +48,81 @@ extern "C" { * * @param[in] key Key which length we return. * - * @return negative on error (@see error.h) or key length (in bits). + * @return negative on error or key length (in bits). */ 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 @see yaca_key_free). + * @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. * - * @return 0 on success, negative on error (@see error.h). + * @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_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); /** * @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 @see yaca_free). + * @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 error.h). + * @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, - char **data, - size_t *data_len); - -// TODO: still a matter of ordering, should the key in key_gen functions be first or last? + yaca_key_fmt_e key_fmt, + char **data, + size_t *data_len); /** * @brief yaca_key_gen Generates a secure symmetric key (or an initialization vector). * - * @param[out] sym_key Newly generated key (must be freed with @see yaca_key_free). + * @param[out] sym_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 error.h). + * @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, - yaca_key_type_e key_type, - size_t key_bits); + yaca_key_type_e key_type, + size_t key_bits); /** * @brief yaca_key_gen_pair Generates a new key pair. * - * @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[out] prv_key Newly generated private key (must be freed with yaca_key_free()). + * @param[out] pub_key Newly generated public key (must be freed with yaca_key_free()). * @param[in] key_type Type of the key to be generated (must be YACA_KEY_TYPE_PAIR*). * @param[in] key_bits Length of the key (in bits) to be generated. * - * @return 0 on success, negative on error (@see error.h). + * @return 0 on success, negative on error. + * @see #yaca_key_type_e, #yaca_key_bits_e, yaca_key_gen(), yaca_key_free() */ 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); /** * @brief yaca_key_free Frees the key created by the library. * Passing YACA_KEY_NULL is allowed. * * @param key Key to be freed. + * @see yaca_key_import(), yaca_key_export(), yaca_key_gen(), yaca_key_gen_pair() * */ void yaca_key_free(yaca_key_h key); @@ -126,7 +130,7 @@ void yaca_key_free(yaca_key_h key); /**@}*/ /** - * @defgroup Key-Derivation Key derivation functions + * @defgroup Key-Derivation Advanced API for the key derivation. * * TODO: rethink separate group. * TODO: extended description and examples. @@ -139,13 +143,14 @@ void yaca_key_free(yaca_key_h key); * * @param[in] prv_key Our private key. * @param[in] pub_key Peer public key. - * @param[out] sym_key Shared secret, that can be used as a symmetric key (must be freed with @see yaca_key_free). + * @param[out] sym_key Shared secret, that can be used as a symmetric key + * (must be freed with yaca_key_free()). * - * @return 0 on success, negative on error (@see error.h). + * @return 0 on success, negative on error. */ 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); /** * @brief yaca_key_derive_kea Derives a key using KEA key exchange protocol. @@ -156,15 +161,16 @@ int yaca_key_derive_dh(const yaca_key_h prv_key, * DH public component sent to peer to verify our identity. * @param[in] pub_key_auth Peers' public key used for signature verification * of pub_key from peer (peer authentication). - * @param[out] sym_key Shared secret, that can be used as a symmetric key (must be freed with @see yaca_key_free). + * @param[out] sym_key Shared secret, that can be used as a symmetric key + * (must be freed with yaca_key_free()). * - * @return 0 on success, negative on error (@see error.h). + * @return 0 on success, negative on error. */ 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); /** * @brief yaca_key_derive_pbkdf2 Derives a key from user password (PKCS #5 a.k.a. pbkdf2 algorithm). @@ -175,17 +181,17 @@ int yaca_key_derive_kea(const yaca_key_h prv_key, * @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_bits Length of a key (in bits) to be generated. - * @param[out] key Newly generated key (must be freed with @see yaca_key_free). + * @param[out] key Newly generated key (must be freed with yaca_key_free()). * - * @return 0 on success, negative on error (@see error.h). + * @return 0 on success, negative on error. */ 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); // TODO: specify //int yaca_key_wrap(yaca_key_h key, ??); diff --git a/api/yaca/seal.h b/api/yaca/seal.h index 3467291..a6897be 100644 --- a/api/yaca/seal.h +++ b/api/yaca/seal.h @@ -46,7 +46,7 @@ extern "C" { /** * @brief yaca_seal_init Initializes an asymmetric encryption context. * - * @param[out] ctx Newly created context (must be freed with @see yaca_ctx_free). + * @param[out] ctx Newly created context (must be freed with yaca_ctx_free()). * @param[in] pub_key Public key of the peer that will receive the encrypted data. * @param[in] algo Symmetric algorithm that will be used. * @param[in] bcm Block chaining mode for the symmetric algorithm. @@ -54,50 +54,55 @@ extern "C" { * @param[out] sym_key Generated symmetric key that will be used. It is encrypted with peer's public key. * @param[out] iv Generated initialization vector that will be used. * - * @return 0 on success, negative on error (@see error.h). + * @return 0 on success, negative on error. + * @see #yaca_enc_algo_e, #yaca_block_cipher_mode_e, yaca_seal_update(), yaca_seal_final() */ int yaca_seal_init(yaca_ctx_h *ctx, - const yaca_key_h pub_key, - yaca_enc_algo_e algo, - yaca_block_cipher_mode_e bcm, - yaca_key_bits_e sym_key_bits, - yaca_key_h *sym_key, - yaca_key_h *iv); + const yaca_key_h pub_key, + yaca_enc_algo_e algo, + yaca_block_cipher_mode_e bcm, + yaca_key_bits_e sym_key_bits, + yaca_key_h *sym_key, + yaca_key_h *iv); /** * @brief yaca_seal_update Encrypts piece of the data. * - * @param[in,out] ctx Context created by @see yaca_seal_init. + * @param[in,out] ctx Context created by yaca_seal_init(). * @param[in] plain Plain text to be encrypted. * @param[in] plain_len Length of the plain text. - * @param[out] cipher Buffer for the encrypted data (must be allocated by client, @see yaca_get_output_length). + * @param[out] cipher Buffer for the encrypted data (must be allocated by client, see + * yaca_get_output_length()). * @param[out] cipher_len Length of the encrypted data, actual number of bytes written will be returned here. * - * @return 0 on success, negative on error (@see error.h). + * @return 0 on success, negative on error. + * @see yaca_seal_init(), yaca_seal_final() */ int yaca_seal_update(yaca_ctx_h ctx, - const char *plain, - size_t plain_len, - char *cipher, - size_t *cipher_len); + const char *plain, + size_t plain_len, + char *cipher, + size_t *cipher_len); /** * @brief yaca_seal_final Encrypts the final piece of the data. * * @param[in,out] ctx A valid seal context. - * @param[out] cipher Final piece of the encrypted data (must be allocated by client, @see yaca_get_block_length). + * @param[out] cipher Final piece of the encrypted data (must be allocated by client, see + * yaca_get_block_length()). * @param[out] cipher_len Length of the final piece, actual number of bytes written will be returned here. * - * @return 0 on success, negative on error (@see error.h). + * @return 0 on success, negative on error. + * @see yaca_seal_init(), yaca_seal_update() */ int yaca_seal_final(yaca_ctx_h ctx, - char *cipher, - size_t *cipher_len); + char *cipher, + size_t *cipher_len); /** * @brief yaca_open_init Initializes an asymmetric decryption context. * - * @param[out] ctx Newly created context. Must be freed by @see yaca_ctx_free. + * @param[out] ctx Newly created context. Must be freed by yaca_ctx_free(). * @param[in] prv_key Private key, part of the pair that was used for the encryption. * @param[in] algo Symmetric algorithm that was used for the encryption. * @param[in] bcm Block chaining mode for the symmetric algorithm. @@ -105,45 +110,50 @@ int yaca_seal_final(yaca_ctx_h ctx, * @param[in] sym_key Symmetric key, encrypted with the public key, that was used to encrypt the data. * @param[in] iv Initialization vector that was used for the encryption. * - * @return 0 on success, negative on error (@see error.h). + * @return 0 on success, negative on error. + * @see #yaca_enc_algo_e, #yaca_block_cipher_mode_e, yaca_open_update(), yaca_open_final() */ int yaca_open_init(yaca_ctx_h *ctx, - const yaca_key_h prv_key, - yaca_enc_algo_e algo, - yaca_block_cipher_mode_e bcm, - yaca_key_bits_e sym_key_bits, - const yaca_key_h sym_key, - const yaca_key_h iv); + const yaca_key_h prv_key, + yaca_enc_algo_e algo, + yaca_block_cipher_mode_e bcm, + yaca_key_bits_e sym_key_bits, + const yaca_key_h sym_key, + const yaca_key_h iv); /** * @brief yaca_open_update Decrypts piece of the data. * - * @param[in,out] ctx Context created by @see yaca_open_init. + * @param[in,out] ctx Context created by yaca_open_init(). * @param[in] cipher Cipher text to be decrypted. * @param[in] cipher_len Length of the cipher text. - * @param[out] plain Buffer for the decrypted data (must be allocated by client, @see yaca_get_output_length). + * @param[out] plain Buffer for the decrypted data (must be allocated by client, see + * yaca_get_output_length()). * @param[out] plain_len Length of the decrypted data, actual number of bytes written will be returned here. * - * @return 0 on success, negative on error (@see error.h). + * @return 0 on success, negative on error. + * @see yaca_open_init(), yaca_open_final() */ int yaca_open_update(yaca_ctx_h ctx, - const char *cipher, - size_t cipher_len, - char *plain, - size_t *plain_len); + const char *cipher, + size_t cipher_len, + char *plain, + size_t *plain_len); /** * @brief yaca_open_final Decrypts last chunk of sealed message. * * @param[in,out] ctx A valid open context. - * @param[out] plain Final piece of the decrypted data (must be allocated by client, @see yaca_get_block_length). + * @param[out] plain Final piece of the decrypted data (must be allocated by client, see + * yaca_get_block_length()). * @param[out] plain_len Length of the final piece, actual number of bytes written will be returned here. * - * @return 0 on success, negative on error (@see error.h). + * @return 0 on success, negative on error. + * @see yaca_open_init(), yaca_open_update() */ int yaca_open_final(yaca_ctx_h ctx, - char *plain, - size_t *plain_len); + char *plain, + size_t *plain_len); /**@}*/ diff --git a/api/yaca/sign.h b/api/yaca/sign.h index 217d15d..91c47d1 100644 --- a/api/yaca/sign.h +++ b/api/yaca/sign.h @@ -43,81 +43,87 @@ extern "C" { /** * @brief yaca_sign_init Initializes a signature context. * - * @param[out] ctx Newly created context (must be freed with @see yaca_ctx_free). + * @param[out] ctx Newly created context (must be freed with yaca_ctx_free()). * @param[in] algo Digest algorithm that will be used. * @param[in] key Private or symmetric key that will be used (algorithm is deduced based on key type). * - * @return 0 on success, negative on error (@see error.h). + * @return 0 on success, negative on error. + * @see #yaca_digest_algo_e, yaca_sign_update(), yaca_sign_final() */ int yaca_sign_init(yaca_ctx_h *ctx, - yaca_digest_algo_e algo, - const yaca_key_h key); + yaca_digest_algo_e algo, + const yaca_key_h key); /** * @brief yaca_sign_update Feeds the data into the digital signature algorithm. * - * @param[in,out] ctx Context created by @see yaca_sign_init. + * @param[in,out] ctx Context created by yaca_sign_init(). * @param[in] data Data to be signed. * @param[in] data_len Length of the data. * - * @return 0 on success, negative on error (@see error.h). + * @return 0 on success, negative on error. + * @see yaca_sign_init(), yaca_sign_final() */ int yaca_sign_update(yaca_ctx_h ctx, - const char *data, - size_t data_len); + const char *data, + size_t data_len); /** * @brief yaca_sign_final Calculates the final signature. * * @param[in,out] ctx A valid sign context. - * @param[out] mac Buffer for the MAC or the signature (must be allocated by client, @see yaca_get_sign_length). + * @param[out] mac Buffer for the MAC or the signature (must be allocated by client, see + * yaca_get_sign_length()). * @param[out] mac_len Length of the MAC or the signature, actual number of bytes written will be returned here. * - * @return 0 on success, negative on error (@see error.h). + * @return 0 on success, negative on error. + * @see yaca_sign_init(), yaca_sign_update() */ int yaca_sign_final(yaca_ctx_h ctx, - char *mac, - size_t *mac_len); + char *mac, + size_t *mac_len); /** * @brief yaca_verify_init Initializes a signature verification context. * - * @param[out] ctx Newly created context (must be freed with @see yaca_ctx_free). + * @param[out] ctx Newly created context (must be freed with yaca_ctx_free()). * @param[in] algo Digest algorithm that will be used. * @param[in] key Private or symmetric key that will be used (algorithm is deduced based on key type). * - * @return 0 on success, negative on error (@see error.h). + * @return 0 on success, negative on error. + * @see #yaca_digest_algo_e, yaca_verify_update(), yaca_verify_final() */ int yaca_verify_init(yaca_ctx_h *ctx, - yaca_digest_algo_e algo, - const yaca_key_h key); + yaca_digest_algo_e algo, + const yaca_key_h key); /** * @brief yaca_verify_update Feeds the data into the digital signature verification algorithm. * - * @param[in,out] ctx Context created by @see yaca_verify_init. + * @param[in,out] ctx Context created by yaca_verify_init(). * @param[in] data Data to be verified. * @param[in] data_len Length of the data. * - * @return 0 on success, negative on error (@see error.h). + * @return 0 on success, negative on error. + * @see yaca_verify_init(), yaca_verify_final() */ int yaca_verify_update(yaca_ctx_h ctx, - const char *data, - size_t data_len); + const char *data, + size_t data_len); /** * @brief yaca_verify_final Performs the verification. * * @param[in,out] ctx A valid verify context. - * @param[in] mac Input MAC or signature (returned by @see yaca_sign_final). + * @param[in] mac Input MAC or signature (returned by yaca_sign_final()). * @param[in] mac_len Size of the MAC or the signature. * - * @return 0 on success, negative on error (@see error.h). - * TODO: YACA_ERROR_SIGNATURE_INVALID when verification fails. + * @return 0 on success, negative on error. + * @see yaca_verify_init(), yaca_verify_update() */ int yaca_verify_final(yaca_ctx_h ctx, - const char *mac, - size_t mac_len); + const char *mac, + size_t mac_len); /**@}*/ diff --git a/api/yaca/simple.h b/api/yaca/simple.h index 8a7dc25..3075aac 100644 --- a/api/yaca/simple.h +++ b/api/yaca/simple.h @@ -50,65 +50,71 @@ extern "C" { /** * @brief yaca_digest_calc Calculate a digest of a buffer. * - * @param[in] algo Digest algorithm (select @see YACA_DIGEST_SHA256 if unsure). + * @param[in] algo Digest algorithm (select #YACA_DIGEST_SHA256 if unsure). * @param[in] data Data from which the digest is to be calculated. * @param[in] data_len Length of the data. - * @param[out] digest Message digest, will be allocated by the library (should be freed with @see yaca_free). + * @param[out] digest Message digest, will be allocated by the library + * (should be freed with yaca_free()). * @param[out] digest_len Length of message digest (depends on algorithm). * - * @return 0 on success, negative on error (@see error.h). + * @return 0 on success, negative on error. + * @see #yaca_digest_algo_e */ int yaca_digest_calc(yaca_digest_algo_e algo, - const char *data, - size_t data_len, - char **digest, - size_t *digest_len); + const char *data, + size_t data_len, + char **digest, + size_t *digest_len); /** * @brief yaca_encrypt Encrypt data using a symmetric cipher. * - * @param[in] algo Encryption algorithm (select @see YACA_ENC_AES if unsure). - * @param[in] bcm Chaining mode (select @see YACA_BCM_CBC if unsure). - * @param[in] sym_key Symmetric encryption key (@see key.h for key generation functions). + * @param[in] algo Encryption algorithm (select #YACA_ENC_AES if unsure). + * @param[in] bcm Chaining mode (select #YACA_BCM_CBC if unsure). + * @param[in] sym_key Symmetric encryption key (see key.h for key generation functions). * @param[in] iv Initialization vector. * @param[in] plain Plain text to be encrypted. * @param[in] plain_len Length of the plain text. - * @param[out] cipher Encrypted data, will be allocated by the library (should be freed with @see yaca_free). + * @param[out] cipher Encrypted data, will be allocated by the library + * (should be freed with yaca_free()). * @param[out] cipher_len Length of the encrypted data (may be larger than decrypted). * - * @return 0 on success, negative on error (@see error.h). + * @return 0 on success, negative on error. + * @see #yaca_enc_algo_e, #yaca_block_cipher_mode_e, yaca_decrypt() */ int yaca_encrypt(yaca_enc_algo_e algo, - yaca_block_cipher_mode_e bcm, - const yaca_key_h sym_key, - const yaca_key_h iv, - const char *plain, - size_t plain_len, - char **cipher, - size_t *cipher_len); + yaca_block_cipher_mode_e bcm, + const yaca_key_h sym_key, + const yaca_key_h iv, + const char *plain, + size_t plain_len, + char **cipher, + size_t *cipher_len); /** * @brief yaca_decrypt Decrypta data using a symmetric cipher. * - * @param[in] algo Decryption algorithm that was used to encrypt the data. - * @param[in] bcm Chaining mode that was used to encrypt the data. - * @param[in] sym_key Symmetric encryption key that was used to encrypt the data. - * @param[in] iv Initialization vector that was used to encrypt the data. - * @param[in] cipher Cipher text to be decrypted. - * @param[in] cipher_len Length of cipher text. - * @param[out] plain Decrypted data, will be allocated by the library (should be freed with @see yaca_free). + * @param[in] algo Decryption algorithm that was used to encrypt the data. + * @param[in] bcm Chaining mode that was used to encrypt the data. + * @param[in] sym_key Symmetric encryption key that was used to encrypt the data. + * @param[in] iv Initialization vector that was used to encrypt the data. + * @param[in] cipher Cipher text to be decrypted. + * @param[in] cipher_len Length of cipher text. + * @param[out] plain Decrypted data, will be allocated by the library + * (should be freed with yaca_free()). * @param[out] plain_len Length of the decrypted data. * - * @return 0 on success, negative on error (@see error.h). + * @return 0 on success, negative on error. + * @see #yaca_enc_algo_e, #yaca_block_cipher_mode_e, yaca_encrypt() */ int yaca_decrypt(yaca_enc_algo_e algo, - yaca_block_cipher_mode_e bcm, - const yaca_key_h sym_key, - const yaca_key_h iv, - const char *cipher, - size_t cipher_len, - char **plain, - size_t * plain_len); + yaca_block_cipher_mode_e bcm, + const yaca_key_h sym_key, + const yaca_key_h iv, + const char *cipher, + size_t cipher_len, + char **plain, + size_t * plain_len); // TODO: sign/verify diff --git a/api/yaca/types.h b/api/yaca/types.h index 19428df..80750bf 100644 --- a/api/yaca/types.h +++ b/api/yaca/types.h @@ -29,7 +29,7 @@ extern "C" { #endif /** - * @defgroup Crypto-Types Enumerations for CryptoAPI + * @defgroup Crypto-Types Yet Another Crypto API - types. * * TODO: extended description. * @@ -128,63 +128,124 @@ typedef enum { * @brief Symmetric encryption algorithms */ typedef enum { - YACA_ENC_AES = 0, /**< AES encryption. - - see #yaca_block_cipher_mode_e for details on additional parameters (mandatory) - Supported key lengths: @c 128, @c 192 and @c 256 */ - - YACA_ENC_UNSAFE_DES, /**< DES encryption. - - see #yaca_block_cipher_mode_e for details on additional parameters (mandatory) - Supported key lengths: @c 56 */ - - YACA_ENC_UNSAFE_3DES_2TDEA, /**< 3DES 2-key encryption. - - see #yaca_block_cipher_mode_e for details on additional parameters (mandatory) - Use double DES keys to perform corresponding 2-key 3DES encryption. Supported key lengths: @c 112 */ - - YACA_ENC_3DES_3TDEA, /**< 3DES 3-key encryption. - - see #yaca_block_cipher_mode_e for details on additional parameters (mandatory) - Use triple DES keys to perform corresponding 3-key 3DES encryption. Supported key lengths: @c 168 */ - - YACA_ENC_UNSAFE_RC2, /**< RC2 encryption. - - see #yaca_block_cipher_mode_e for details on additional parameters (mandatory) - The key length is extracted from the key buffer. Supported key lengths: 8-1024 bits in steps of 8 bits. */ - - YACA_ENC_UNSAFE_RC4, /**< RC4 encryption. - The key length is extracted from the key buffer. Supported key lengths: 40–2048 bits in steps of 8 bits */ - - YACA_ENC_CAST5, /**< CAST5 encryption. - - see #yaca_block_cipher_mode_e for details on additional parameters (mandatory) - The key length is extracted from the key buffer. Supported key lengths: 40-128 bits in steps of 8 bits */ - - YACA_ENC_UNSAFE_SKIPJACK /**< SKIPJACK algorithm - - see #yaca_block_cipher_mode_e for details on additional parameters (mandatory) - Supported key length: 80 bits */ + /** + * AES encryption. + * - see #yaca_block_cipher_mode_e for details on additional parameters (mandatory). + * - Supported key lengths: @c 128, @c 192 and @c 256. + */ + YACA_ENC_AES = 0, + + /** + * DES encryption. + * - see #yaca_block_cipher_mode_e for details on additional parameters (mandatory). + * - Supported key lengths: @c 56. + */ + YACA_ENC_UNSAFE_DES, + + /** + * 3DES 2-key encryption. + * - see #yaca_block_cipher_mode_e for details on additional parameters (mandatory). + * - Use double DES keys to perform corresponding 2-key 3DES encryption. + * - Supported key lengths: @c 112. + */ + YACA_ENC_UNSAFE_3DES_2TDEA, + + /** + * 3DES 3-key encryption. + * - see #yaca_block_cipher_mode_e for details on additional parameters (mandatory). + * - Use triple DES keys to perform corresponding 3-key 3DES encryption. + * - Supported key lengths: @c 168. + */ + YACA_ENC_3DES_3TDEA, + + /** + * RC2 encryption. + * - The key length is extracted from the key buffer. + * - Supported key lengths: 8-1024 bits in steps of 8 bits. + */ + YACA_ENC_UNSAFE_RC2, + + /** + * RC4 encryption. + * - The key length is extracted from the key buffer. + * - Supported key lengths: 40–2048 bits in steps of 8 bits. + */ + YACA_ENC_UNSAFE_RC4, + + /** + * CAST5 encryption. + * - see #yaca_block_cipher_mode_e for details on additional parameters (mandatory). + * - The key length is extracted from the key buffer. + * - Supported key lengths: 40-128 bits in steps of 8 bits. + */ + YACA_ENC_CAST5, + + /** + * SKIPJACK algorithm. + * - Supported key length: 80 bits. + */ + YACA_ENC_UNSAFE_SKIPJACK } yaca_enc_algo_e; /** * @brief Chaining modes for block ciphers */ typedef enum { - YACA_BCM_ECB, /**< ECB block cipher mode. Encrypts 64 bit at a time. No IV is used. */ - - YACA_BCM_CTR, /**< CTR block cipher mode. 16-byte initialization vector is mandatory. - Supported parameters: - - YACA_PARAM_CTR_CNT = length of counter block in bits - (optional, only 128b is supported at the moment) */ - - YACA_BCM_CBC, /**< CBC block cipher mode. 16-byte initialization vector is mandatory. */ - - YACA_BCM_GCM, /**< GCM block cipher mode. IV is needed. - Supported parameters: - - YACA_PARAM_TAG = GCM tag - - YACA_PARAM_AAD = additional authentication data(optional) */ - - YACA_BCM_CFB, /**< CFB block cipher mode. 16-byte initialization vector is mandatory. */ - - YACA_BCM_OFB, /**< OFB block cipher mode. 16-byte initialization vector is mandatory. */ - - YACA_BCM_OCB, /**< Offest Codebook Mode (AES) */ - - YACA_BCM_CCM /**< CBC-MAC Mode (AES) */ + /** + * ECB block cipher mode. + * Encrypts 64 bit at a time. No IV is used. + */ + YACA_BCM_ECB, + + /** + * CTR block cipher mode. + * 16-byte initialization vector is mandatory. + * Supported parameters: + * - #YACA_PARAM_CTR_CNT = length of counter block in bits + * (optional, only 128b is supported at the moment) + */ + YACA_BCM_CTR, + + /** + * CBC block cipher mode. + * 16-byte initialization vector is mandatory. + */ + YACA_BCM_CBC, + + /** + * GCM block cipher mode, IV is needed. + * Supported parameters: + * - #YACA_PARAM_GCM_TAG = GCM tag + * - #YACA_PARAM_GCM_TAG_LEN = GCM tag length + * - #YACA_PARAM_GCM_AAD = additional authentication data(optional) + */ + YACA_BCM_GCM, + + /** + * CFB block cipher mode. + * 16-byte initialization vector is mandatory. + */ + YACA_BCM_CFB, + + /** + * OFB block cipher mode. + * 16-byte initialization vector is mandatory. + */ + YACA_BCM_OFB, + + /** + * Offest Codebook Mode (AES) + */ + YACA_BCM_OCB, + + /** + * CBC-MAC Mode (AES). + * Supported parameters: + * - #YACA_PARAM_CCM_TAG = CCM tag + * - #YACA_PARAM_CCM_TAG_LEN = CCM tag length + * - #YACA_PARAM_CCM_AAD = additional authentication data(optional) + */ + YACA_BCM_CCM } yaca_block_cipher_mode_e; @@ -207,7 +268,7 @@ typedef enum { } yaca_ex_param_e; /** - * @brief Paddings supported by CryptoAPI + * @brief Paddings supported by Yet Another Crypto API */ typedef enum { YACA_PADDING_NONE = 0, /**< total number of data MUST multiple of block size, Default */ diff --git a/doc/doxygen.cfg b/doc/doxygen.cfg index b6a7957..87e9f10 100644 --- a/doc/doxygen.cfg +++ b/doc/doxygen.cfg @@ -551,7 +551,7 @@ INLINE_INFO = YES # name. If set to NO, the members will appear in declaration order. # The default value is: YES. -SORT_MEMBER_DOCS = YES +SORT_MEMBER_DOCS = NO # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief # descriptions of file, namespace and class members alphabetically by member @@ -578,7 +578,7 @@ SORT_MEMBERS_CTORS_1ST = NO # appear in their defined order. # The default value is: NO. -SORT_GROUP_NAMES = NO +SORT_GROUP_NAMES = YES # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by # fully-qualified names, including namespaces. If set to NO, the class list will -- 2.7.4 From 82526fc1f310cc359f2bcfbc8a95b137a23171bd Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Thu, 28 Apr 2016 14:01:30 +0200 Subject: [PATCH 13/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 14/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 15/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 16/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