From b1e172ef62a67a70fee37985459facd98775f90d Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Tue, 17 May 2016 15:07:18 +0200 Subject: [PATCH 01/16] Fix assert vs error codes usage in get_sign_output_length() Change-Id: Ieca2200d6f844590ed16b0dc314e56a4572c5dfa --- src/sign.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/sign.c b/src/sign.c index 7dd2a73..3ad2279 100644 --- a/src/sign.c +++ b/src/sign.c @@ -60,9 +60,14 @@ static int get_sign_output_length(const yaca_ctx_h ctx, size_t input_len, size_t { struct yaca_sign_ctx_s *c = get_sign_ctx(ctx); - if (c == NULL || c->mdctx == NULL || c->mdctx->pctx == NULL) + if (c == NULL) return YACA_ERROR_INVALID_ARGUMENT; + assert(c->mdctx != NULL); + + if (c->mdctx->pctx == NULL) + return YACA_ERROR_INTERNAL; + EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(c->mdctx->pctx); if (pkey == NULL) { ERROR_DUMP(YACA_ERROR_INVALID_ARGUMENT); -- 2.7.4 From ad0caccd86a7b35a81729a2ce1348fa597d00086 Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Tue, 17 May 2016 14:19:11 +0200 Subject: [PATCH 02/16] Lower the key bit_len in sign/verify example It takes too long to run the example with 4k key for our purposes. Change-Id: I331782d9cf90f621cf2b009ad4751a952157341f --- examples/sign.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/sign.c b/examples/sign.c index dab16bd..4874131 100644 --- a/examples/sign.c +++ b/examples/sign.c @@ -46,7 +46,7 @@ void sign_verify_asym(yaca_key_type_e type, const char *algo) #endif // GENERATE - if (yaca_key_gen(&prv, type, YACA_KEY_4096BIT) != 0) + if (yaca_key_gen(&prv, type, YACA_KEY_1024BIT) != 0) return; if (yaca_key_extract_public(prv, &pub) != 0) -- 2.7.4 From e800af8e1aee2336baa8b654c239f8a12df74cd5 Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Fri, 13 May 2016 19:16:25 +0200 Subject: [PATCH 03/16] get/set_ctx_param for sign/verify (RSA padding only) Change-Id: I9ce5bde7a43bae619546c9cc5b3e54c4388ca755 --- api/yaca/types.h | 11 +++-- examples/sign.c | 11 +---- src/sign.c | 129 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 135 insertions(+), 16 deletions(-) diff --git a/api/yaca/types.h b/api/yaca/types.h index 7ce9ec9..72d45f4 100644 --- a/api/yaca/types.h +++ b/api/yaca/types.h @@ -310,12 +310,11 @@ typedef enum { */ typedef enum { YACA_PADDING_NONE = 0, /**< total number of data MUST multiple of block size, Default */ - YACA_PADDING_ZEROS, /**< pad with zeros */ - YACA_PADDING_ISO10126, /**< ISO 10126 */ - YACA_PADDING_ANSIX923, /**< ANSI X.923 padding*/ - YACA_PADDING_ANSIX931, /**< ANSI X.931 padding*/ - YACA_PADDING_PKCS1, /**< RSA signature creation */ - YACA_PADDING_PKCS7 /**< Byte padding for symetric algos (RFC 5652), (PKCS5 padding is the same) */ + YACA_PADDING_X931, /**< RSA X9.31 padding*/ + YACA_PADDING_PKCS1, /**< RSA signature/verify operations */ + YACA_PADDING_PKCS1_PSS, /**< RSA signature/verify operations */ + YACA_PADDING_SSLV23, /**< RSA SSLv23 */ + YACA_PADDING_PKCS1_OAEP /**< RSA encrypt/decrypt operations */ } yaca_padding_e; /**@}*/ diff --git a/examples/sign.c b/examples/sign.c index 4874131..faf0131 100644 --- a/examples/sign.c +++ b/examples/sign.c @@ -30,8 +30,6 @@ #include "lorem.h" #include "misc.h" -#define PADDING_IMPLEMENTED 0 - // Signature creation and verification using advanced API void sign_verify_asym(yaca_key_type_e type, const char *algo) { @@ -41,9 +39,7 @@ void sign_verify_asym(yaca_key_type_e type, const char *algo) 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 + yaca_padding_e padding = YACA_PADDING_PKCS1_PSS; // GENERATE if (yaca_key_gen(&prv, type, YACA_KEY_1024BIT) != 0) @@ -56,11 +52,8 @@ void sign_verify_asym(yaca_key_type_e type, const char *algo) 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)) != 0) goto finish; -#endif if (yaca_sign_update(ctx, lorem4096, LOREM4096_SIZE) != 0) goto finish; @@ -84,10 +77,8 @@ void sign_verify_asym(yaca_key_type_e type, const char *algo) if (yaca_verify_init(&ctx, YACA_DIGEST_SHA512, pub) != 0) goto finish; -#if PADDING_IMPLEMENTED if (yaca_ctx_set_param(ctx, YACA_PARAM_PADDING, (char*)(&padding), sizeof(padding)) != 0) goto finish; -#endif if (yaca_verify_update(ctx, lorem4096, LOREM4096_SIZE) != 0) goto finish; diff --git a/src/sign.c b/src/sign.c index 3ad2279..9573c4c 100644 --- a/src/sign.c +++ b/src/sign.c @@ -17,8 +17,10 @@ */ #include +#include #include +#include #include #include @@ -95,6 +97,129 @@ static void destroy_sign_context(yaca_ctx_h ctx) c->mdctx = NULL; } +int set_sign_param(yaca_ctx_h ctx, yaca_ex_param_e param, const void *value, size_t value_len) +{ + int ret; + struct yaca_sign_ctx_s *c = get_sign_ctx(ctx); + yaca_padding_e padding; + int pad; + EVP_PKEY *pkey; + + if (c == NULL || value == NULL) + return YACA_ERROR_INVALID_ARGUMENT; + + assert(c->mdctx != NULL); + + if (c->mdctx->pctx == NULL) + return YACA_ERROR_INTERNAL; + + /* this function only supports padding */ + if (param != YACA_PARAM_PADDING || value_len != sizeof(yaca_padding_e)) + return YACA_ERROR_INVALID_ARGUMENT; + + padding = *(yaca_padding_e *)(value); + + // TODO: investigate whether it's possible to set + // RSA_NO_PADDING or RSA_SSLV23_PADDING in some cases + switch (padding) { + case YACA_PADDING_X931: + pad = RSA_X931_PADDING; + break; + case YACA_PADDING_PKCS1: + pad = RSA_PKCS1_PADDING; + break; + case YACA_PADDING_PKCS1_PSS: + pad = RSA_PKCS1_PSS_PADDING; + break; + default: + return YACA_ERROR_INVALID_ARGUMENT; + } + + pkey = EVP_PKEY_CTX_get0_pkey(c->mdctx->pctx); + if (pkey == NULL) { + ret = YACA_ERROR_INTERNAL; + ERROR_DUMP(ret); + return ret; + } + + /* padding only works for RSA */ + if (pkey->type != EVP_PKEY_RSA) + return YACA_ERROR_INVALID_ARGUMENT; + + ret = EVP_PKEY_CTX_set_rsa_padding(c->mdctx->pctx, pad); + if (ret <= 0) { + ret = YACA_ERROR_INTERNAL; + ERROR_DUMP(ret); + return ret; + } + + return 0; +} + +int get_sign_param(const yaca_ctx_h ctx, yaca_ex_param_e param, void **value, size_t *value_len) +{ + int ret; + struct yaca_sign_ctx_s *c = get_sign_ctx(ctx); + EVP_PKEY *pkey; + int pad; + yaca_padding_e padding; + + if (c == NULL || value == NULL || value_len == NULL) + return YACA_ERROR_INVALID_ARGUMENT; + + assert(c->mdctx != NULL); + + if (c->mdctx->pctx == NULL) + return YACA_ERROR_INTERNAL; + + /* this function only supports padding */ + if (param != YACA_PARAM_PADDING) + return YACA_ERROR_INVALID_ARGUMENT; + + pkey = EVP_PKEY_CTX_get0_pkey(c->mdctx->pctx); + if (pkey == NULL) { + ret = YACA_ERROR_INTERNAL; + ERROR_DUMP(ret); + return ret; + } + + /* padding only works for RSA */ + if (pkey->type != EVP_PKEY_RSA) + return YACA_ERROR_INVALID_ARGUMENT; + + ret = EVP_PKEY_CTX_get_rsa_padding(c->mdctx->pctx, &pad); + if (ret <= 0) { + ret = YACA_ERROR_INTERNAL; + ERROR_DUMP(ret); + return ret; + } + + switch(pad) { + case RSA_X931_PADDING: + padding = YACA_PADDING_X931; + break; + case RSA_PKCS1_PADDING: + padding = YACA_PADDING_PKCS1; + break; + case RSA_PKCS1_PSS_PADDING: + padding = YACA_PADDING_PKCS1_PSS; + break; + default: + ret = YACA_ERROR_INTERNAL; + ERROR_DUMP(YACA_ERROR_INTERNAL); + return ret; + } + + *value = yaca_malloc(sizeof(yaca_padding_e)); + if (*value == NULL) + return YACA_ERROR_OUT_OF_MEMORY; + + memcpy(*value, &padding, sizeof(yaca_padding_e)); + *value_len = sizeof(yaca_padding_e); + + return 0; +} + 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); @@ -157,6 +282,8 @@ API int yaca_sign_init(yaca_ctx_h *ctx, nc->ctx.type = YACA_CTX_SIGN; nc->ctx.ctx_destroy = destroy_sign_context; nc->ctx.get_output_length = get_sign_output_length; + nc->ctx.set_param = set_sign_param; + nc->ctx.get_param = get_sign_param; switch (key->type) { @@ -274,6 +401,8 @@ API int yaca_verify_init(yaca_ctx_h *ctx, nc->ctx.type = YACA_CTX_SIGN; nc->ctx.ctx_destroy = destroy_sign_context; nc->ctx.get_output_length = NULL; + nc->ctx.set_param = set_sign_param; + nc->ctx.get_param = get_sign_param; switch (key->type) { -- 2.7.4 From 306a32c4cd94b3b9a11abba5c5728bbf2a2ec3c7 Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Wed, 18 May 2016 09:30:36 +0200 Subject: [PATCH 04/16] FIX: SIZE_MAX undeclared. Change-Id: I282d74613fc8f1617575597ae3a26ee4eef385f0 --- src/encrypt.c | 1 + src/seal.c | 1 + 2 files changed, 2 insertions(+) diff --git a/src/encrypt.c b/src/encrypt.c index 758fd2b..4b549f7 100644 --- a/src/encrypt.c +++ b/src/encrypt.c @@ -18,6 +18,7 @@ #include #include +#include #include #include diff --git a/src/seal.c b/src/seal.c index 586aac1..47fe00f 100644 --- a/src/seal.c +++ b/src/seal.c @@ -18,6 +18,7 @@ #include #include +#include #include #include -- 2.7.4 From 84bda780215f0af81b3bb9ee6a9ef8fd5a6414b7 Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Wed, 18 May 2016 10:28:59 +0200 Subject: [PATCH 05/16] Fix API for yaca_get_iv_bits(). Return the value by size_t param instead of signed int return. The return value is used only for error codes from now on. Change-Id: I90afedcffeb37ab315b4f4681323f3d64b7bc9ec --- api/yaca/encrypt.h | 15 ++++++++++----- examples/encrypt.c | 10 ++++------ src/encrypt.c | 14 +++++++++++--- 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/api/yaca/encrypt.h b/api/yaca/encrypt.h index 7806e16..7e81d9b 100644 --- a/api/yaca/encrypt.h +++ b/api/yaca/encrypt.h @@ -148,15 +148,20 @@ int yaca_decrypt_final(yaca_ctx_h ctx, /** * @brief 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. + * If returned iv_bits equals 0 that means that for this + * specific algorithm and its parameters IV is not used. * - * @return negative on error or the IV length in bits. + * @param[in] algo Encryption algorithm. + * @param[in] bcm Chain mode. + * @param[in] key_bits Key length in bits. + * @param[out] iv_bits Recommended IV length in bits. + * + * @return 0 on success, negative on error. */ int yaca_get_iv_bits(yaca_enc_algo_e algo, yaca_block_cipher_mode_e bcm, - size_t key_bits); + size_t key_bits, + size_t *iv_bits); /**@}*/ diff --git a/examples/encrypt.c b/examples/encrypt.c index c253586..3e95c86 100644 --- a/examples/encrypt.c +++ b/examples/encrypt.c @@ -44,7 +44,7 @@ void encrypt_simple(void) char *dec_data = NULL; size_t enc_len; size_t dec_len; - int iv_bits; + size_t iv_bits; printf("Simple Encrypt\nPlain data (16 of %zu bytes): %.16s\n", LOREM1024_SIZE, lorem1024); @@ -54,8 +54,7 @@ void encrypt_simple(void) if (ret) return; - iv_bits = yaca_get_iv_bits(algo, bcm, key_bits); - if (iv_bits < 0) + if (yaca_get_iv_bits(algo, bcm, key_bits, &iv_bits) != 0) return; if (iv_bits > 0) { @@ -101,7 +100,7 @@ void encrypt_advanced(void) char *dec = NULL; size_t enc_size; size_t dec_size; - int iv_bits; + size_t iv_bits; printf("Advanced Encrypt\nPlain data (16 of %zu bytes): %.16s\n", LOREM4096_SIZE, lorem4096); @@ -113,8 +112,7 @@ void encrypt_advanced(void) if (ret) return; - iv_bits = yaca_get_iv_bits(algo, bcm, key_bits); - if (iv_bits < 0) + if (yaca_get_iv_bits(algo, bcm, key_bits, &iv_bits) != 0) goto ex_key; if (iv_bits > 0) { diff --git a/src/encrypt.c b/src/encrypt.c index 4b549f7..c41b77a 100644 --- a/src/encrypt.c +++ b/src/encrypt.c @@ -414,8 +414,9 @@ static int encrypt_final(yaca_ctx_h ctx, } API 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, + size_t *iv_bits) { const EVP_CIPHER *cipher; int ret; @@ -424,7 +425,14 @@ API int yaca_get_iv_bits(yaca_enc_algo_e algo, if (ret < 0) return ret; - return EVP_CIPHER_iv_length(cipher) * 8; + ret = EVP_CIPHER_iv_length(cipher); + if (ret < 0) { + ERROR_DUMP(YACA_ERROR_INTERNAL); + return YACA_ERROR_INTERNAL; + } + + *iv_bits = ret * 8; + return 0; } API int yaca_encrypt_init(yaca_ctx_h *ctx, -- 2.7.4 From f2f040bd6fa704704190f1e0f423d2c85e06aa43 Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Tue, 17 May 2016 18:48:31 +0200 Subject: [PATCH 06/16] yaca_key import/export API change - passwords Change-Id: Ifcc7c3eca1323cb4418190867bedf1a197b08f73 --- api/yaca/error.h | 3 ++- api/yaca/key.h | 17 ++++++++++++++++- examples/encrypt_aes_gcm.c | 2 +- examples/key_exchange.c | 4 ++-- examples/key_import_export.c | 40 ++++++++++++++++++++-------------------- examples/test.c | 2 +- src/key.c | 2 ++ 7 files changed, 44 insertions(+), 26 deletions(-) diff --git a/api/yaca/error.h b/api/yaca/error.h index 55656bd..acdc2cb 100644 --- a/api/yaca/error.h +++ b/api/yaca/error.h @@ -43,7 +43,8 @@ enum __yaca_error_code { YACA_ERROR_INTERNAL = -3, YACA_ERROR_TOO_BIG_ARGUMENT = -4, YACA_ERROR_OUT_OF_MEMORY = -5, - YACA_ERROR_SIGNATURE_INVALID = -6 + YACA_ERROR_SIGNATURE_INVALID = -6, + YACA_ERROR_PASSWORD_INVALID = -7, }; // TODO disable debug function in release? diff --git a/api/yaca/key.h b/api/yaca/key.h index ce69f21..d6a34d2 100644 --- a/api/yaca/key.h +++ b/api/yaca/key.h @@ -67,16 +67,23 @@ int yaca_key_get_bits(const yaca_key_h key); * format. Additionally it is possible to import public RSA key from * X509 certificate. * + * If the key is encrypted the algorithm will be autodetected and password + * used. If it's not known if the key is encrypted one should pass NULL as + * password and check for the YACA_ERROR_PASSWORD_INVALID return code. + * * @param[out] key Returned key (must be freed with yaca_key_free()). * @param[in] key_type Type of the key. + * @param[in] password null terminated password for the key (can be NULL). * @param[in] data Blob containing the key. * @param[in] data_len Size of the blob. * - * @return 0 on success, negative on error. + * @return 0 on success, YACA_ERROR_PASSWORD_INVALID if wrong password given, + * negative on error. * @see #yaca_key_type_e, yaca_key_export(), yaca_key_free() */ int yaca_key_import(yaca_key_h *key, yaca_key_type_e key_type, + const char *password, const char *data, size_t data_len); @@ -96,9 +103,16 @@ int yaca_key_import(yaca_key_h *key, * - #YACA_KEY_FILE_FORMAT_PEM: used only for asymmetric, PEM file format * - #YACA_KEY_FILE_FORMAT_DER: used only for asymmetric, DER file format * + * If no password is provided the exported key will be unencrypted. Only private + * RSA/DSA exported as PEM can be encrypted. + * + * TODO: document the default encryption algorithm (AES256 for FORMAT_DEFAULT, + * unknown yet for the FORMAT_PKCS8) + * * @param[in] key Key to be exported. * @param[in] key_fmt Format of the key. * @param[in] key_file_fmt Format of the key file. + * @param[in] password Password used for the encryption (can be NULL). * @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. @@ -109,6 +123,7 @@ int yaca_key_import(yaca_key_h *key, int yaca_key_export(const yaca_key_h key, yaca_key_fmt_e key_fmt, yaca_key_file_fmt_e key_file_fmt, + const char *password, char **data, size_t *data_len); diff --git a/examples/encrypt_aes_gcm.c b/examples/encrypt_aes_gcm.c index 9fc1234..86da336 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_DEFAULT, YACA_KEY_FILE_FORMAT_RAW, &aad, &aad_len); + ret = yaca_key_export(aad_key, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_RAW, NULL, &aad, &aad_len); if (ret < 0) goto clean; diff --git a/examples/key_exchange.c b/examples/key_exchange.c index b3e4f05..9464732 100644 --- a/examples/key_exchange.c +++ b/examples/key_exchange.c @@ -69,7 +69,7 @@ void key_exchange_dh(void) if (1 != fread(buffer, size, 1, fp)) goto clean; - ret = yaca_key_import(&peer_key, YACA_KEY_TYPE_DH_PUB, + ret = yaca_key_import(&peer_key, YACA_KEY_TYPE_DH_PUB, NULL, buffer, size); if (ret < 0) goto clean; @@ -129,7 +129,7 @@ void key_exchange_ecdh(void) if (1 != fread(buffer, size, 1, fp)) goto clean; - ret = yaca_key_import(&peer_key, YACA_KEY_TYPE_ECDH_PUB, buffer, size); + ret = yaca_key_import(&peer_key, YACA_KEY_TYPE_ECDH_PUB, NULL, buffer, size); if (ret < 0) goto clean; diff --git a/examples/key_import_export.c b/examples/key_import_export.c index 1c4db07..9d005c2 100644 --- a/examples/key_import_export.c +++ b/examples/key_import_export.c @@ -46,10 +46,10 @@ int key_import_export_sym(yaca_key_h sym) /* BASE64 */ - ret = yaca_key_export(sym, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_BASE64, &b64, &b64_len); + ret = yaca_key_export(sym, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_BASE64, NULL, &b64, &b64_len); if (ret != 0) return ret; - ret = yaca_key_import(&b64_imported, YACA_KEY_TYPE_SYMMETRIC, b64, b64_len); + ret = yaca_key_import(&b64_imported, YACA_KEY_TYPE_SYMMETRIC, NULL, b64, b64_len); if (ret != 0) goto free; @@ -57,7 +57,7 @@ int key_import_export_sym(yaca_key_h sym) yaca_free(b64); b64 = NULL; - ret = yaca_key_export(b64_imported, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_BASE64, &b64, &b64_len); + ret = yaca_key_export(b64_imported, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_BASE64, NULL, &b64, &b64_len); if (ret != 0) goto free; @@ -66,10 +66,10 @@ int key_import_export_sym(yaca_key_h sym) /* RAW */ - ret = yaca_key_export(sym, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_RAW, &raw, &raw_len); + ret = yaca_key_export(sym, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_RAW, NULL, &raw, &raw_len); if (ret != 0) goto free; - ret = yaca_key_import(&raw_imported, YACA_KEY_TYPE_SYMMETRIC, raw, raw_len); + ret = yaca_key_import(&raw_imported, YACA_KEY_TYPE_SYMMETRIC, NULL, raw, raw_len); if (ret != 0) goto free; @@ -77,7 +77,7 @@ int key_import_export_sym(yaca_key_h sym) yaca_free(raw); raw = NULL; - ret = yaca_key_export(raw_imported, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_RAW, &raw, &raw_len); + ret = yaca_key_export(raw_imported, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_RAW, NULL, &raw, &raw_len); if (ret != 0) goto free; @@ -118,10 +118,10 @@ int key_import_export_asym(yaca_key_h priv, yaca_key_h pub, /* PEM private */ - ret = yaca_key_export(priv, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_PEM, &pem_prv, &pem_prv_len); + ret = yaca_key_export(priv, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_PEM, NULL, &pem_prv, &pem_prv_len); if (ret != 0) return ret; - ret = yaca_key_import(&pem_prv_imported, priv_type, pem_prv, pem_prv_len); + ret = yaca_key_import(&pem_prv_imported, priv_type, NULL, pem_prv, pem_prv_len); if (ret != 0) goto free; @@ -129,7 +129,7 @@ int key_import_export_asym(yaca_key_h priv, yaca_key_h pub, yaca_free(pem_prv); pem_prv = NULL; - ret = yaca_key_export(pem_prv_imported, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_PEM, &pem_prv, &pem_prv_len); + ret = yaca_key_export(pem_prv_imported, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_PEM, NULL, &pem_prv, &pem_prv_len); if (ret != 0) goto free; @@ -138,10 +138,10 @@ int key_import_export_asym(yaca_key_h priv, yaca_key_h pub, /* DER private */ - ret = yaca_key_export(priv, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_DER, &der_prv, &der_prv_len); + ret = yaca_key_export(priv, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_DER, NULL, &der_prv, &der_prv_len); if (ret != 0) goto free; - ret = yaca_key_import(&der_prv_imported, priv_type, der_prv, der_prv_len); + ret = yaca_key_import(&der_prv_imported, priv_type, NULL, der_prv, der_prv_len); if (ret != 0) goto free; @@ -149,7 +149,7 @@ int key_import_export_asym(yaca_key_h priv, yaca_key_h pub, yaca_free(der_prv); der_prv = NULL; - ret = yaca_key_export(der_prv_imported, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_DER, &der_prv, &der_prv_len); + ret = yaca_key_export(der_prv_imported, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_DER, NULL, &der_prv, &der_prv_len); if (ret != 0) goto free; @@ -158,10 +158,10 @@ int key_import_export_asym(yaca_key_h priv, yaca_key_h pub, /* PEM public */ - ret = yaca_key_export(pub, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_PEM, &pem_pub, &pem_pub_len); + ret = yaca_key_export(pub, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_PEM, NULL, &pem_pub, &pem_pub_len); if (ret != 0) goto free; - ret = yaca_key_import(&pem_pub_imported, pub_type, pem_pub, pem_pub_len); + ret = yaca_key_import(&pem_pub_imported, pub_type, NULL, pem_pub, pem_pub_len); if (ret != 0) goto free; @@ -169,7 +169,7 @@ int key_import_export_asym(yaca_key_h priv, yaca_key_h pub, yaca_free(pem_pub); pem_pub = NULL; - ret = yaca_key_export(pem_pub_imported, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_PEM, &pem_pub, &pem_pub_len); + ret = yaca_key_export(pem_pub_imported, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_PEM, NULL, &pem_pub, &pem_pub_len); if (ret != 0) goto free; @@ -178,10 +178,10 @@ int key_import_export_asym(yaca_key_h priv, yaca_key_h pub, /* DER public */ - ret = yaca_key_export(pub, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_DER, &der_pub, &der_pub_len); + ret = yaca_key_export(pub, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_DER, NULL, &der_pub, &der_pub_len); if (ret != 0) goto free; - ret = yaca_key_import(&der_pub_imported, pub_type, der_pub, der_pub_len); + ret = yaca_key_import(&der_pub_imported, pub_type, NULL, der_pub, der_pub_len); if (ret != 0) goto free; @@ -189,7 +189,7 @@ int key_import_export_asym(yaca_key_h priv, yaca_key_h pub, yaca_free(der_pub); der_pub = NULL; - ret = yaca_key_export(der_pub_imported, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_DER, &der_pub, &der_pub_len); + ret = yaca_key_export(der_pub_imported, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_DER, NULL, &der_pub, &der_pub_len); if (ret != 0) goto free; @@ -225,14 +225,14 @@ int key_import_x509(void) return ret; } - ret = yaca_key_import(&rsa_pub_from_cert, YACA_KEY_TYPE_RSA_PUB, pub, pub_len); + ret = yaca_key_import(&rsa_pub_from_cert, YACA_KEY_TYPE_RSA_PUB, NULL, pub, pub_len); if (ret != 0) goto free; yaca_free(pub); pub = NULL; - ret = yaca_key_export(rsa_pub_from_cert, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_PEM, &pub, &pub_len); + ret = yaca_key_export(rsa_pub_from_cert, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_PEM, NULL, &pub, &pub_len); if (ret != 0) goto free; diff --git a/examples/test.c b/examples/test.c index 6f1bdf4..4e6f7f0 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_DEFAULT, YACA_KEY_FILE_FORMAT_RAW, &k, &kl); + ret = yaca_key_export(key, YACA_KEY_FORMAT_DEFAULT, YACA_KEY_FILE_FORMAT_RAW, NULL, &k, &kl); if (ret < 0) return ret; printf("done (%d)\n", ret); diff --git a/src/key.c b/src/key.c index bb6bc32..c906d5a 100644 --- a/src/key.c +++ b/src/key.c @@ -850,6 +850,7 @@ API int yaca_key_get_bits(const yaca_key_h key) API int yaca_key_import(yaca_key_h *key, yaca_key_type_e key_type, + const char *password, const char *data, size_t data_len) { @@ -881,6 +882,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, + const char *password, char **data, size_t *data_len) { -- 2.7.4 From d528b491ced211becaf512a59ad2fdc7d7cf80d7 Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Wed, 18 May 2016 15:41:11 +0200 Subject: [PATCH 07/16] API changes around key getters. yaca_key_get_bits() - return bits by size_t typed output param yaca_key_get_type() - new getter to get the type of the key Change-Id: I255f3bf3056a50602c1c2bd0a25c177ecf88ee07 --- api/yaca/key.h | 17 ++++++++++++++--- src/encrypt.c | 17 +++++++++++------ src/key.c | 25 +++++++++++++++++++++---- src/seal.c | 10 ++++++++-- 4 files changed, 54 insertions(+), 15 deletions(-) diff --git a/api/yaca/key.h b/api/yaca/key.h index d6a34d2..c58bc60 100644 --- a/api/yaca/key.h +++ b/api/yaca/key.h @@ -44,13 +44,24 @@ 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 Get key's type. + * + * @param[in] key Key which type we return. + * @param[out] key_type Key type. + * + * @return 0 on success, negative on error. + */ +int yaca_key_get_type(const yaca_key_h key, yaca_key_type_e *key_type); + +/** * @brief Get key's length (in bits). * - * @param[in] key Key which length we return. + * @param[in] key Key which length we return. + * @param[out] key_bits Key length in bits. * - * @return negative on error or key length (in bits). + * @return 0 on success, negative on error. */ -int yaca_key_get_bits(const yaca_key_h key); +int yaca_key_get_bits(const yaca_key_h key, size_t *key_bits); /** * @brief Imports a key. diff --git a/src/encrypt.c b/src/encrypt.c index c41b77a..a4516c3 100644 --- a/src/encrypt.c +++ b/src/encrypt.c @@ -216,9 +216,10 @@ static int encrypt_init(yaca_ctx_h *ctx, const struct yaca_key_simple_s *liv; struct yaca_encrypt_ctx_s *nc; const EVP_CIPHER *cipher; - int key_bits; + size_t key_bits; unsigned char *iv_data = NULL; - int iv_bits; + size_t iv_bits; + size_t iv_bits_check; int ret; if (ctx == NULL || sym_key == YACA_KEY_NULL) @@ -237,10 +238,9 @@ static int encrypt_init(yaca_ctx_h *ctx, nc->ctx.get_output_length = get_encrypt_output_length; nc->op_type = op_type; - ret = yaca_key_get_bits(sym_key); - if (ret < 0) + ret = yaca_key_get_bits(sym_key, &key_bits); + if (ret != 0) goto err_free; - key_bits = ret; ret = encrypt_get_algorithm(algo, bcm, key_bits, &cipher); if (ret != 0) @@ -265,7 +265,12 @@ static int encrypt_init(yaca_ctx_h *ctx, ret = YACA_ERROR_INVALID_ARGUMENT; goto err_free; } - if (iv_bits != yaca_key_get_bits(iv)) { /* IV length doesn't match cipher */ + ret = yaca_key_get_bits(iv, &iv_bits_check); + if (ret != 0) { + ret = YACA_ERROR_INVALID_ARGUMENT; + goto err_free; + } + if (iv_bits != iv_bits_check) { /* IV length doesn't match cipher */ ret = YACA_ERROR_INVALID_ARGUMENT; goto err_free; } diff --git a/src/key.c b/src/key.c index c906d5a..2730c09 100644 --- a/src/key.c +++ b/src/key.c @@ -823,13 +823,29 @@ struct yaca_key_evp_s *key_get_evp(const yaca_key_h key) } } -API int yaca_key_get_bits(const yaca_key_h key) +API int yaca_key_get_type(const yaca_key_h key, yaca_key_type_e *key_type) +{ + const struct yaca_key_s *lkey = (const struct yaca_key_s *)key; + + if (lkey == NULL || key_type == NULL) + return YACA_ERROR_INVALID_ARGUMENT; + + *key_type = lkey->type; + return 0; +} + +API int yaca_key_get_bits(const yaca_key_h key, size_t *key_bits) { const struct yaca_key_simple_s *simple_key = key_get_simple(key); const struct yaca_key_evp_s *evp_key = key_get_evp(key); - if (simple_key != NULL) - return simple_key->bits; + if (key_bits == NULL) + return YACA_ERROR_INVALID_ARGUMENT; + + if (simple_key != NULL) { + *key_bits = simple_key->bits; + return 0; + } if (evp_key != NULL) { int ret; @@ -842,7 +858,8 @@ API int yaca_key_get_bits(const yaca_key_h key) return ret; } - return ret; + *key_bits = ret; + return 0; } return YACA_ERROR_INVALID_ARGUMENT; diff --git a/src/seal.c b/src/seal.c index 47fe00f..bbaa2ca 100644 --- a/src/seal.c +++ b/src/seal.c @@ -222,7 +222,8 @@ static int open_init(yaca_ctx_h *ctx, const struct yaca_key_simple_s *liv; struct yaca_seal_ctx_s *nc; const EVP_CIPHER *cipher; - int iv_bits; + size_t iv_bits; + size_t iv_bits_check; int ret; if (ctx == NULL || prv_key == YACA_KEY_NULL || sym_key == YACA_KEY_NULL) @@ -271,7 +272,12 @@ static int open_init(yaca_ctx_h *ctx, } // TODO: handling of algorithms with variable IV length - if (iv_bits != yaca_key_get_bits(iv)) { /* IV length doesn't match cipher */ + ret = yaca_key_get_bits(iv, &iv_bits_check); + if (ret != 0) { + ret = YACA_ERROR_INVALID_ARGUMENT; + goto err_free; + } + if (iv_bits != iv_bits_check) { /* IV length doesn't match cipher */ ret = YACA_ERROR_INVALID_ARGUMENT; goto err_free; } -- 2.7.4 From 89ae7be7c0fb58432c1ff5f7b0c4c6251ca0cd3d Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Wed, 18 May 2016 17:13:07 +0200 Subject: [PATCH 08/16] API update: add YACA_ERROR_NONE enum value Change-Id: I88b5786a375a7c5c0bda47266ea332a09fb73ae5 --- api/yaca/error.h | 1 + 1 file changed, 1 insertion(+) diff --git a/api/yaca/error.h b/api/yaca/error.h index acdc2cb..64de6f7 100644 --- a/api/yaca/error.h +++ b/api/yaca/error.h @@ -38,6 +38,7 @@ extern "C" { * @brief Error enums */ enum __yaca_error_code { + YACA_ERROR_NONE = 0, YACA_ERROR_INVALID_ARGUMENT = -1, YACA_ERROR_NOT_IMPLEMENTED = -2, YACA_ERROR_INTERNAL = -3, -- 2.7.4 From d3a8562d6c516dd966f543a413659dd64e1a194a Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Mon, 9 May 2016 16:25:03 +0200 Subject: [PATCH 09/16] Rework symmetric encrypt/decrypt example. Change-Id: If8427b9a1374169f28541bc2435ffb0ce4e20cd4 --- examples/encrypt.c | 197 ++++++++++++++++++++++++++--------------------------- 1 file changed, 97 insertions(+), 100 deletions(-) diff --git a/examples/encrypt.c b/examples/encrypt.c index 3e95c86..fe686ce 100644 --- a/examples/encrypt.c +++ b/examples/encrypt.c @@ -24,187 +24,148 @@ #include #include -#include #include +#include #include #include #include "lorem.h" #include "misc.h" -// Symmetric encryption using simple API -void encrypt_simple(void) +void encrypt_simple(const yaca_enc_algo_e algo, + const yaca_block_cipher_mode_e bcm, + const size_t key_bits) { - const yaca_enc_algo_e algo = YACA_ENC_AES; - const yaca_block_cipher_mode_e bcm = YACA_BCM_CBC; - const size_t key_bits = YACA_KEY_256BIT; - int ret; yaca_key_h key = YACA_KEY_NULL; yaca_key_h iv = YACA_KEY_NULL; - char *enc_data = NULL; - char *dec_data = NULL; - size_t enc_len; - size_t dec_len; + + char *enc = NULL; + char *dec = NULL; + size_t enc_size; + size_t dec_size; size_t iv_bits; - printf("Simple Encrypt\nPlain data (16 of %zu bytes): %.16s\n", - LOREM1024_SIZE, lorem1024); + printf("Plain data (16 of %zu bytes): %.16s\n", LOREM4096_SIZE, lorem4096); - ret = yaca_key_derive_pbkdf2("foo bar", "123456789", 10, 1000, - YACA_DIGEST_SHA256, key_bits, &key); - if (ret) + /* Key generation */ + if (yaca_key_derive_pbkdf2("foo bar", "123456789", 10, 1000, + YACA_DIGEST_SHA256, key_bits, &key) != 0) return; if (yaca_get_iv_bits(algo, bcm, key_bits, &iv_bits) != 0) - return; + goto exit; - if (iv_bits > 0) { - ret = yaca_key_gen(&iv, YACA_KEY_TYPE_IV, iv_bits); - if (ret) - goto exit; - } + if (iv_bits > 0 && yaca_key_gen(&iv, YACA_KEY_TYPE_IV, iv_bits) != 0) + goto exit; - ret = yaca_encrypt(algo, bcm, key, iv, lorem1024, LOREM1024_SIZE, - &enc_data, &enc_len); - if (ret) + if (yaca_encrypt(algo, bcm, key, iv, lorem4096, LOREM4096_SIZE, &enc, &enc_size) != 0) goto exit; - dump_hex(enc_data, 16, "Encrypted data (16 of %zu bytes): ", enc_len); + dump_hex(enc, 16, "Encrypted data (16 of %zu bytes): ", enc_size); - ret = yaca_decrypt(algo, bcm, key, iv, enc_data, enc_len, &dec_data, - &dec_len); - if (ret < 0) + if (yaca_decrypt(algo, bcm, key, iv, enc, enc_size, &dec, &dec_size) != 0) goto exit; - printf("Decrypted data (16 of %zu bytes): %.16s\n", dec_len, dec_data); + printf("Decrypted data (16 of %zu bytes): %.16s\n\n", dec_size, dec); + exit: - if (enc_data) - yaca_free(enc_data); - if (dec_data) - yaca_free(dec_data); - if (iv != YACA_KEY_NULL) - yaca_key_free(iv); + + yaca_free(enc); + yaca_free(dec); + yaca_key_free(iv); yaca_key_free(key); } -// Symmetric encryption using advanced API -void encrypt_advanced(void) +void encrypt_advanced(const yaca_enc_algo_e algo, + const yaca_block_cipher_mode_e bcm, + const yaca_key_type_e key_type, + const size_t key_bits) { - const yaca_enc_algo_e algo = YACA_ENC_AES; - const yaca_block_cipher_mode_e bcm = YACA_BCM_CBC; - const size_t key_bits = YACA_KEY_256BIT; - int ret; - yaca_ctx_h ctx; + yaca_ctx_h ctx = YACA_CTX_NULL; yaca_key_h key = YACA_KEY_NULL; yaca_key_h iv = YACA_KEY_NULL; + size_t iv_bits; + char *enc = NULL; char *dec = NULL; size_t enc_size; size_t dec_size; - size_t iv_bits; - printf("Advanced Encrypt\nPlain data (16 of %zu bytes): %.16s\n", - LOREM4096_SIZE, lorem4096); + size_t block_len; + size_t output_len; + size_t out_size; + size_t rem; - /// Key generation + printf("Plain data (16 of %zu bytes): %.16s\n", LOREM4096_SIZE, lorem4096); - ret = yaca_key_derive_pbkdf2("foo bar", "123456789", 10, 1000, - YACA_DIGEST_SHA256, key_bits, &key); - if (ret) + /* Key generation */ + if (yaca_key_gen(&key, key_type, key_bits) != 0) return; if (yaca_get_iv_bits(algo, bcm, key_bits, &iv_bits) != 0) goto ex_key; - if (iv_bits > 0) { - ret = yaca_key_gen(&iv, YACA_KEY_TYPE_IV, iv_bits); - if (ret) - goto ex_key; - } + if (iv_bits > 0 && yaca_key_gen(&iv, YACA_KEY_TYPE_IV, iv_bits) != 0) + goto ex_key; - /// Encryption + /* Encryption */ { - size_t block_len; - size_t output_len; - size_t out_size; - size_t rem; - - ret = yaca_encrypt_init(&ctx, algo, bcm, key, iv); - if (ret) + if (yaca_encrypt_init(&ctx, algo, bcm, key, iv) != 0) goto ex_iv; - ret = yaca_get_block_length(ctx, &block_len); - if (ret != 0) + if (yaca_get_block_length(ctx, &block_len) != 0) goto ex_ctx; - ret = yaca_get_output_length(ctx, LOREM4096_SIZE, &output_len); - if (ret != 0) + if (yaca_get_output_length(ctx, LOREM4096_SIZE, &output_len) != 0) goto ex_ctx; /* Calculate max output: size of update + final chunks */ enc_size = output_len + block_len; - enc = yaca_malloc(enc_size); - if (enc == NULL) + if ((enc = yaca_malloc(enc_size)) == NULL) goto ex_ctx; out_size = enc_size; - ret = yaca_encrypt_update(ctx, lorem4096, LOREM4096_SIZE, enc, - &out_size); - if (ret < 0) + if (yaca_encrypt_update(ctx, lorem4096, LOREM4096_SIZE, enc, &out_size) != 0) goto ex_of; rem = enc_size - out_size; - ret = yaca_encrypt_final(ctx, enc + out_size, &rem); - if (ret < 0) + if (yaca_encrypt_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); + dump_hex(enc, 16, "Encrypted data (16 of %zu bytes): ", enc_size); yaca_ctx_free(ctx); + ctx = YACA_CTX_NULL; } - /// Decryption + /* Decryption */ { - size_t block_len; - size_t output_len; - size_t out_size; - size_t rem; - - ret = yaca_decrypt_init(&ctx, algo, bcm, key, iv); - if (ret < 0) { - ctx = YACA_CTX_NULL; + if (yaca_decrypt_init(&ctx, algo, bcm, key, iv) != 0) goto ex_of; - } - ret = yaca_get_block_length(ctx, &block_len); - if (ret != 0) + if (yaca_get_block_length(ctx, &block_len) != 0) goto ex_of; - ret = yaca_get_output_length(ctx, LOREM4096_SIZE, &output_len); - if (ret != 0) - goto ex_ctx; + if (yaca_get_output_length(ctx, LOREM4096_SIZE, &output_len) != 0) + goto ex_of; /* Calculate max output: size of update + final chunks */ dec_size = output_len + block_len; - dec = yaca_malloc(dec_size); - if (dec == NULL) + if ((dec = yaca_malloc(dec_size)) == NULL) goto ex_of; out_size = dec_size; - ret = yaca_decrypt_update(ctx, enc, enc_size, dec, &out_size); - if (ret < 0) + if (yaca_decrypt_update(ctx, enc, enc_size, dec, &out_size) != 0) goto ex_in; rem = dec_size - out_size; - ret = yaca_decrypt_final(ctx, dec + out_size, &rem); - if (ret < 0) + if (yaca_decrypt_final(ctx, dec + out_size, &rem) != 0) goto ex_in; dec_size = rem + out_size; - printf("Decrypted data (16 of %zu bytes): %.16s\n", dec_size, dec); + printf("Decrypted data (16 of %zu bytes): %.16s\n\n", dec_size, dec); } ex_in: @@ -227,10 +188,46 @@ int main() if (ret < 0) return ret; - encrypt_simple(); + yaca_enc_algo_e algo = YACA_ENC_AES; + yaca_block_cipher_mode_e bcm = YACA_BCM_ECB; + yaca_key_type_e key_type = YACA_KEY_TYPE_SYMMETRIC; + size_t key_bits = YACA_KEY_256BIT; + + encrypt_simple(algo, bcm, key_bits); + encrypt_advanced(algo, bcm, key_type,key_bits); - encrypt_advanced(); + algo = YACA_ENC_3DES_3TDEA; + bcm = YACA_BCM_OFB; + key_type = YACA_KEY_TYPE_DES; + key_bits = YACA_KEY_192BIT; + + encrypt_advanced(algo, bcm, key_type,key_bits); + + algo = YACA_ENC_CAST5; + bcm = YACA_BCM_CFB; + key_type = YACA_KEY_TYPE_SYMMETRIC; + key_bits = YACA_KEY_UNSAFE_40BIT; + + encrypt_simple(algo, bcm, key_bits); + encrypt_advanced(algo, bcm, key_type,key_bits); + + algo = YACA_ENC_UNSAFE_RC2; + bcm = YACA_BCM_CBC; + key_type = YACA_KEY_TYPE_SYMMETRIC; + key_bits = YACA_KEY_UNSAFE_8BIT; + + encrypt_simple(algo, bcm, key_bits); + encrypt_advanced(algo, bcm, key_type,key_bits); + + algo = YACA_ENC_UNSAFE_RC4; + bcm = YACA_BCM_NONE; + key_type = YACA_KEY_TYPE_SYMMETRIC; + key_bits = YACA_KEY_2048BIT; + + encrypt_simple(algo, bcm, key_bits); + encrypt_advanced(algo, bcm, key_type,key_bits); yaca_exit(); + return ret; } -- 2.7.4 From 805dc74af5c322ca0199cf67bc30b7fae7f3c070 Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Thu, 12 May 2016 16:46:09 +0200 Subject: [PATCH 10/16] Update AES description. Change-Id: I4172389ae79b2c1028f3035d051f69db0a90804a --- api/yaca/types.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/api/yaca/types.h b/api/yaca/types.h index 72d45f4..282d007 100644 --- a/api/yaca/types.h +++ b/api/yaca/types.h @@ -133,8 +133,17 @@ typedef enum { typedef enum { /** * AES encryption. - * - see #yaca_block_cipher_mode_e for details on additional parameters (mandatory). * - Supported key lengths: @c 128, @c 192 and @c 256. + * - Supported block cipher modes: + * #YACA_BCM_CBC, + * #YACA_BCM_OFB, + * #YACA_BCM_CFB, + * #YACA_BCM_ECB, + * #YACA_BCM_GCM, + * #YACA_BCM_CCM, + * #YACA_BCM_CTR, + * #YACA_BCM_OCB + * - see #yaca_block_cipher_mode_e for details on additional parameters (mandatory). */ YACA_ENC_AES = 0, -- 2.7.4 From 0c1494615b5825062ded2f289fef36577eeb59be Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Thu, 12 May 2016 17:24:26 +0200 Subject: [PATCH 11/16] Add CFB1 and CFB8 chaining modes. Change-Id: Ia464613fd38ec14f3d32905966eefe7ead430444 --- api/yaca/types.h | 20 +++++++++++++++++++- src/encrypt.c | 4 ++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/api/yaca/types.h b/api/yaca/types.h index 282d007..d025a15 100644 --- a/api/yaca/types.h +++ b/api/yaca/types.h @@ -138,6 +138,8 @@ typedef enum { * #YACA_BCM_CBC, * #YACA_BCM_OFB, * #YACA_BCM_CFB, + * #YACA_BCM_CFB1, + * #YACA_BCM_CFB8, * #YACA_BCM_ECB, * #YACA_BCM_GCM, * #YACA_BCM_CCM, @@ -154,6 +156,8 @@ typedef enum { * #YACA_BCM_CBC, * #YACA_BCM_OFB, * #YACA_BCM_CFB, + * #YACA_BCM_CFB1, + * #YACA_BCM_CFB8, * #YACA_BCM_ECB * - see #yaca_block_cipher_mode_e for details on additional parameters (mandatory). */ @@ -180,6 +184,8 @@ typedef enum { * #YACA_BCM_CBC, * #YACA_BCM_OFB, * #YACA_BCM_CFB, + * #YACA_BCM_CFB1, + * #YACA_BCM_CFB8, * #YACA_BCM_ECB * - see #yaca_block_cipher_mode_e for details on additional parameters (mandatory). * - Use triple DES keys to perform corresponding 3-key 3DES encryption. @@ -268,12 +274,24 @@ typedef enum { YACA_BCM_GCM, /** - * CFB block cipher mode. + * Default CFB block cipher mode. * 16-byte initialization vector is mandatory. */ YACA_BCM_CFB, /** + * 1 bit CFB block cipher mode. + * 16-byte initialization vector is mandatory. + */ + YACA_BCM_CFB1, + + /** + * 8 bits CFB block cipher mode. + * 16-byte initialization vector is mandatory. + */ + YACA_BCM_CFB8, + + /** * OFB block cipher mode. * 16-byte initialization vector is mandatory. */ diff --git a/src/encrypt.c b/src/encrypt.c index a4516c3..784ac35 100644 --- a/src/encrypt.c +++ b/src/encrypt.c @@ -135,6 +135,10 @@ static const char *bcm_to_str(yaca_block_cipher_mode_e bcm) return "gcm"; case YACA_BCM_CFB: return "cfb"; + case YACA_BCM_CFB1: + return "cfb1"; + case YACA_BCM_CFB8: + return "cfb8"; case YACA_BCM_OFB: return "ofb"; case YACA_BCM_OCB: -- 2.7.4 From bac18777652e6585c78392b02970a07644c68f30 Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Tue, 17 May 2016 10:59:43 +0200 Subject: [PATCH 12/16] Remove OCB block cipher mode. Change-Id: I676b80d4491ad70b6bbc0ef4ade80a3df8ca649b --- api/yaca/types.h | 6 ------ src/encrypt.c | 2 -- todo.txt | 1 + 3 files changed, 1 insertion(+), 8 deletions(-) diff --git a/api/yaca/types.h b/api/yaca/types.h index d025a15..1b5c1cc 100644 --- a/api/yaca/types.h +++ b/api/yaca/types.h @@ -144,7 +144,6 @@ typedef enum { * #YACA_BCM_GCM, * #YACA_BCM_CCM, * #YACA_BCM_CTR, - * #YACA_BCM_OCB * - see #yaca_block_cipher_mode_e for details on additional parameters (mandatory). */ YACA_ENC_AES = 0, @@ -298,11 +297,6 @@ typedef enum { YACA_BCM_OFB, /** - * Offest Codebook Mode (AES) - */ - YACA_BCM_OCB, - - /** * CBC-MAC Mode (AES). * Supported parameters: * - #YACA_PARAM_CCM_TAG = CCM tag diff --git a/src/encrypt.c b/src/encrypt.c index 784ac35..86572e2 100644 --- a/src/encrypt.c +++ b/src/encrypt.c @@ -141,8 +141,6 @@ static const char *bcm_to_str(yaca_block_cipher_mode_e bcm) return "cfb8"; case YACA_BCM_OFB: return "ofb"; - case YACA_BCM_OCB: - return "ocb"; case YACA_BCM_CCM: return "ccm"; default: diff --git a/todo.txt b/todo.txt index a13943d..3ed8333 100644 --- a/todo.txt +++ b/todo.txt @@ -2,3 +2,4 @@ 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 +- Support for OCB mode was added in OpenSSL 1.1.0 -- 2.7.4 From eec19e94a1135030f38ba708ab7e765f1ca3ec0c Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Tue, 17 May 2016 11:11:18 +0200 Subject: [PATCH 13/16] Remove CTR bits param. Only default 128b is supported by openssl at the moment. Change-Id: Id5f70b196940172e567e7e357269babeae714a29 --- api/yaca/types.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/api/yaca/types.h b/api/yaca/types.h index 1b5c1cc..3284ede 100644 --- a/api/yaca/types.h +++ b/api/yaca/types.h @@ -251,9 +251,6 @@ typedef enum { /** * 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, @@ -315,7 +312,6 @@ typedef enum { YACA_PARAM_PADDING, /**< Padding */ YACA_PARAM_RC2_EFFECTIVE_KEY_BITS, /**< RC2 effective key bits, 1-1024, 1 bit resolution */ - YACA_PARAM_CTR_CNT, /**< CTR Counter bits */ YACA_PARAM_GCM_AAD, /**< GCM Additional Authentication Data */ YACA_PARAM_GCM_TAG, /**< GCM Tag bits */ -- 2.7.4 From 95524d72c14a4a337e7826fbe17b8646ce8dfb0e Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Fri, 13 May 2016 15:15:36 +0200 Subject: [PATCH 14/16] Hide debug function Debug function is exported but the header is kept private. Change-Id: I399bc52688c126a061dc29d66029bfe66d993c47 --- api/yaca/error.h | 20 ++------------------ examples/digest.c | 3 ++- examples/encrypt.c | 3 ++- examples/encrypt_aes_gcm.c | 3 ++- examples/key_exchange.c | 3 ++- examples/key_import_export.c | 3 ++- examples/seal.c | 3 ++- examples/sign.c | 3 ++- examples/test.c | 3 ++- src/{error.c => debug.c} | 13 +++++++------ src/debug.h | 32 ++++++++++++++++++++++++++++++++ todo.txt | 1 + 12 files changed, 58 insertions(+), 32 deletions(-) rename src/{error.c => debug.c} (91%) create mode 100644 src/debug.h diff --git a/api/yaca/error.h b/api/yaca/error.h index 64de6f7..22030dd 100644 --- a/api/yaca/error.h +++ b/api/yaca/error.h @@ -29,7 +29,7 @@ extern "C" { #endif /** - * @defgroup Error Yet another Crypto API - error enums and debug functions. + * @defgroup Error Yet another Crypto API - error enums. * * @{ */ @@ -45,25 +45,9 @@ enum __yaca_error_code { YACA_ERROR_TOO_BIG_ARGUMENT = -4, YACA_ERROR_OUT_OF_MEMORY = -5, YACA_ERROR_SIGNATURE_INVALID = -6, - YACA_ERROR_PASSWORD_INVALID = -7, + YACA_ERROR_PASSWORD_INVALID = -7 }; -// TODO disable debug function in release? - -/** - * @brief Debug callback type. - */ -typedef void (*yaca_debug_func)(const char*); - -/** - * @brief 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 diff --git a/examples/digest.c b/examples/digest.c index a5ef093..68c6bcb 100644 --- a/examples/digest.c +++ b/examples/digest.c @@ -28,6 +28,7 @@ #include #include "lorem.h" #include "misc.h" +#include "../src/debug.h" void digest_simple(void) { @@ -80,7 +81,7 @@ exit_ctx: int main() { - yaca_error_set_debug_func(debug_func); + yaca_debug_set_error_cb(debug_func); int ret = yaca_init(); if (ret < 0) diff --git a/examples/encrypt.c b/examples/encrypt.c index fe686ce..c01ab04 100644 --- a/examples/encrypt.c +++ b/examples/encrypt.c @@ -30,6 +30,7 @@ #include #include "lorem.h" #include "misc.h" +#include "../src/debug.h" void encrypt_simple(const yaca_enc_algo_e algo, const yaca_block_cipher_mode_e bcm, @@ -182,7 +183,7 @@ ex_key: int main() { - yaca_error_set_debug_func(debug_func); + yaca_debug_set_error_cb(debug_func); int ret = yaca_init(); if (ret < 0) diff --git a/examples/encrypt_aes_gcm.c b/examples/encrypt_aes_gcm.c index 86da336..1e61bc3 100644 --- a/examples/encrypt_aes_gcm.c +++ b/examples/encrypt_aes_gcm.c @@ -31,6 +31,7 @@ #include "lorem.h" #include "misc.h" +#include "../src/debug.h" // Symmetric aes gcm encryption using advanced API void encrypt_decrypt_aes_gcm(void) @@ -180,7 +181,7 @@ clean: int main() { - yaca_error_set_debug_func(debug_func); + yaca_debug_set_error_cb(debug_func); int ret = yaca_init(); if (ret < 0) diff --git a/examples/key_exchange.c b/examples/key_exchange.c index 9464732..542beb8 100644 --- a/examples/key_exchange.c +++ b/examples/key_exchange.c @@ -28,6 +28,7 @@ #include #include #include "misc.h" +#include "../src/debug.h" void key_exchange_dh(void) { @@ -150,7 +151,7 @@ clean: int main() { - yaca_error_set_debug_func(debug_func); + yaca_debug_set_error_cb(debug_func); int ret = yaca_init(); if (ret < 0) diff --git a/examples/key_import_export.c b/examples/key_import_export.c index 9d005c2..183068c 100644 --- a/examples/key_import_export.c +++ b/examples/key_import_export.c @@ -24,6 +24,7 @@ #include #include "misc.h" +#include "../src/debug.h" #include #include @@ -259,7 +260,7 @@ int main() if (ret != 0) return ret; - yaca_error_set_debug_func(debug_func); + yaca_debug_set_error_cb(debug_func); ret = yaca_key_gen(&sym, YACA_KEY_TYPE_SYMMETRIC, YACA_KEY_1024BIT); if (ret != 0) diff --git a/examples/seal.c b/examples/seal.c index 4da8228..5d34da1 100644 --- a/examples/seal.c +++ b/examples/seal.c @@ -29,6 +29,7 @@ #include #include "lorem.h" #include "misc.h" +#include "../src/debug.h" void encrypt_seal(void) { @@ -139,7 +140,7 @@ ex_prvk: int main() { - yaca_error_set_debug_func(debug_func); + yaca_debug_set_error_cb(debug_func); int ret = yaca_init(); if (ret < 0) diff --git a/examples/sign.c b/examples/sign.c index faf0131..f2ba25e 100644 --- a/examples/sign.c +++ b/examples/sign.c @@ -29,6 +29,7 @@ #include "lorem.h" #include "misc.h" +#include "../src/debug.h" // Signature creation and verification using advanced API void sign_verify_asym(yaca_key_type_e type, const char *algo) @@ -202,7 +203,7 @@ finish: int main() { - yaca_error_set_debug_func(debug_func); + yaca_debug_set_error_cb(debug_func); int ret = yaca_init(); if (ret < 0) diff --git a/examples/test.c b/examples/test.c index 4e6f7f0..a9992b2 100644 --- a/examples/test.c +++ b/examples/test.c @@ -22,12 +22,13 @@ #include #include #include "misc.h" +#include "../src/debug.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_debug_set_error_cb(debug_func); yaca_key_h key; char *k; diff --git a/src/error.c b/src/debug.c similarity index 91% rename from src/error.c rename to src/debug.c index 140d1b4..2bdaa74 100644 --- a/src/error.c +++ b/src/debug.c @@ -14,7 +14,7 @@ * limitations under the License */ /* - * @file error.c + * @file debug.c * @author Krzysztof Jackiewicz (k.jackiewicz@samsung.com) */ @@ -26,14 +26,15 @@ #include #include "internal.h" +#include "debug.h" // TODO any better idea than to use __thread? -static __thread yaca_debug_func debug_fn = NULL; +static __thread yaca_error_cb error_cb = NULL; static bool error_strings_loaded = false; -API void yaca_error_set_debug_func(yaca_debug_func fn) +API void yaca_debug_set_error_cb(yaca_error_cb fn) { - debug_fn = fn; + error_cb = fn; } // TODO use peeking function to intercept common errors @@ -41,7 +42,7 @@ API void yaca_error_set_debug_func(yaca_debug_func fn) void error_dump(const char *file, int line, const char *function, int code) { - if (debug_fn == NULL) + if (error_cb == NULL) return; static const size_t BUF_SIZE = 512; @@ -81,6 +82,6 @@ void error_dump(const char *file, int line, const char *function, int code) } buf[written] = '\0'; - (*debug_fn)(buf); + (*error_cb)(buf); } diff --git a/src/debug.h b/src/debug.h new file mode 100644 index 0000000..f748d31 --- /dev/null +++ b/src/debug.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Krzysztof Jackiewicz + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +/** + * @file debug.h + * @brief + */ + +#ifndef YACA_DEBUG_H +#define YACA_DEBUG_H + +typedef void (*yaca_error_cb)(const char*); + +void yaca_debug_set_error_cb(yaca_error_cb cb); + + +#endif /* YACA_DEBUG_H */ diff --git a/todo.txt b/todo.txt index 3ed8333..216c413 100644 --- a/todo.txt +++ b/todo.txt @@ -3,3 +3,4 @@ Global: In other words check whether the user won't cause a buffer overflow. - Importing/exporting encrypted (passphrased) RSA keys - Support for OCB mode was added in OpenSSL 1.1.0 +- Remove debug function from examples -- 2.7.4 From 5e205eca2631457bbbc1af51323cc28586c81bd8 Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Tue, 17 May 2016 11:57:12 +0200 Subject: [PATCH 15/16] Add separate API function stubs for HMAC/CMAC context initialization. MACs are symmetric equivalent for asymmetric signatures. For asymmetric signatures the signing algorithm can be easily deduced from the key. This is not the case for MAC's where plain symmetric key tells us nothing about the MAC algorithm we want to use. Considered solutions: 1. Introducing new key types for MACs. Cons: - unclear how to handle plain symmetric keys, - introduces an artificial division in symmetric keys, - new enum values, - CMAC cipher has to be set via ctx params. 2. Deducing MAC algorithm from digest algorithm. Digest->HMAC, no digest->CMAC. Cons: - unclear which algorithm will be used, - adding new MAC algorithm may require a significant API change, - CMAC cipher has to be set via ctx params. 3. Leaving CMAC as a digest algorithm. Cons: - CMAC is not a digest algorithm. It's an equivalent of HMAC, RSA, DSA,...etc, - CMAC can't be used for calculating message digest alone, - CMAC can't be used as a digest algorithm for HMAC - CMAC cipher has to be set via ctx params. 4. Adding new API for CMAC and HMAC context creation. Cons: - 1 new functions per MAC algo for context initalization, - 1 function for signature comparison - low API flexibility This is an initial commit for solution 4. Change-Id: I745854fd7b7d87f2c114475b709566ec512d7bbd --- api/yaca/crypto.h | 11 ++++++ api/yaca/error.h | 2 +- api/yaca/sign.h | 105 ++++++++++++++++++++++++++++++++++++++++++------------ src/crypto.c | 8 +++++ src/sign.c | 28 +++++++-------- 5 files changed, 116 insertions(+), 38 deletions(-) diff --git a/api/yaca/crypto.h b/api/yaca/crypto.h index 9959df0..76a2897 100644 --- a/api/yaca/crypto.h +++ b/api/yaca/crypto.h @@ -181,6 +181,17 @@ int yaca_get_output_length(const yaca_ctx_h ctx, size_t input_len, size_t *outpu */ #define yaca_get_block_length(ctxa, output_len) yaca_get_output_length((ctxa), 0, (output_len)) +/** + * @brief Safely compares first @b len bytes of two buffers. + * + * @param[in] first Pointer to the first buffer. + * @param[in] second Pointer to the second buffer. + * @param[in] len Length to compare. + * + * @return 0 when buffers are equal otherwise #YACA_ERROR_DATA_MISMATCH + */ +int yaca_memcmp(const void *first, const void *second, size_t len); + /**@}*/ #ifdef __cplusplus diff --git a/api/yaca/error.h b/api/yaca/error.h index 22030dd..8aa150b 100644 --- a/api/yaca/error.h +++ b/api/yaca/error.h @@ -44,7 +44,7 @@ enum __yaca_error_code { YACA_ERROR_INTERNAL = -3, YACA_ERROR_TOO_BIG_ARGUMENT = -4, YACA_ERROR_OUT_OF_MEMORY = -5, - YACA_ERROR_SIGNATURE_INVALID = -6, + YACA_ERROR_DATA_MISMATCH = -6, YACA_ERROR_PASSWORD_INVALID = -7 }; diff --git a/api/yaca/sign.h b/api/yaca/sign.h index f018a31..9dcbe43 100644 --- a/api/yaca/sign.h +++ b/api/yaca/sign.h @@ -41,57 +41,115 @@ extern "C" { */ /** - * @brief Initializes a signature context. + * @brief Initializes a signature context for asymmetric signatures. + * + * For verification use yaca_verify_init(), yaca_verify_update() and + * yaca_verify_final() functions with matching public key. * * @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). + * @param[in] key Private key that will be used. Algorithm is deduced based + * on key type. Supported key types: + * - #YACA_KEY_TYPE_RSA_PRIV, + * - #YACA_KEY_TYPE_DSA_PRIV, + * - #YACA_KEY_TYPE_ECDSA_PRIV. * * @return 0 on success, negative on error. - * @see #yaca_digest_algo_e, yaca_sign_update(), yaca_sign_final() + * @see #yaca_key_type_e, #yaca_digest_algo_e, yaca_sign_update(), + * yaca_sign_final(), yaca_verify_init(), yaca_verify_update(), + * yaca_verify_final() */ int yaca_sign_init(yaca_ctx_h *ctx, yaca_digest_algo_e algo, const yaca_key_h key); /** - * @brief Feeds the data into the digital signature algorithm. + * @brief Initializes a signature context for HMAC. + * + * For verification, calculate message HMAC and compare with received MAC using + * yaca_memcmp(). + * + * @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 Symmetric key that will be used. Supported key types: + * - #YACA_KEY_TYPE_SYMMETRIC, + * - #YACA_KEY_TYPE_DES. + * + * @return 0 on success, negative on error. + * @see #yaca_key_type_e, #yaca_digest_algo_e, yaca_sign_update(), + * yaca_sign_final(), yaca_memcmp() + */ +int yaca_sign_hmac_init(yaca_ctx_h *ctx, + yaca_digest_algo_e algo, + const yaca_key_h key); + +/** + * @brief Initializes a signature context for CMAC. * - * @param[in,out] ctx Context created by yaca_sign_init(). + * For verification, calculate message CMAC and compare with received MAC using + * yaca_memcmp(). + * + * @param[out] ctx Newly created context (must be freed with yaca_ctx_free()). + * @param[in] algo Encryption algorithm that will be used. + * @param[in] key Symmetric key that will be used. Supported key types: + * - #YACA_KEY_TYPE_SYMMETRIC, + * - #YACA_KEY_TYPE_DES. + * + * @return 0 on success, negative on error. + * @see #yaca_key_type_e, #yaca_enc_algo_e, yaca_sign_update(), + * yaca_sign_final(), yaca_memcmp() + */ +int yaca_sign_cmac_init(yaca_ctx_h *ctx, + yaca_enc_algo_e algo, + const yaca_key_h key); + +/** + * @brief Feeds the data into the digital signature or MAC algorithm. + * + * @param[in,out] ctx Context created by yaca_sign_init(), + * yaca_sign_hmac_init() or yaca_sign_cmac_init(). * @param[in] data Data to be signed. * @param[in] data_len Length of the data. * * @return 0 on success, negative on error. - * @see yaca_sign_init(), yaca_sign_final() + * @see yaca_sign_init(), yaca_sign_final(), yaca_sign_hmac_init(), + * yaca_sign_cmac_init() */ int yaca_sign_update(yaca_ctx_h ctx, const char *data, size_t data_len); /** - * @brief Calculates the final signature. + * @brief Calculates the final signature or MAC. * - * @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_len Length of the MAC or the signature, actual number of bytes written will be returned here. + * @param[in,out] ctx A valid sign context. + * @param[out] signature Buffer for the MAC or the signature, + * (must be allocated by client, see yaca_get_sign_length()). + * @param[out] signature_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 yaca_sign_init(), yaca_sign_update() + * @see yaca_sign_init(), yaca_sign_update(), yaca_sign_hmac_init(), + * yaca_sign_cmac_init() */ int yaca_sign_final(yaca_ctx_h ctx, - char *mac, - size_t *mac_len); + char *signature, + size_t *signature_len); /** - * @brief Initializes a signature verification context. + * @brief Initializes a signature verification context for asymmetric signatures * * @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). + * @param[in] key Public key that will be used. Algorithm is deduced based on + * key type. Supported key types: + * - #YACA_KEY_TYPE_RSA_PUB, + * - #YACA_KEY_TYPE_DSA_PUB, + * - #YACA_KEY_TYPE_ECDSA_PUB. * * @return 0 on success, negative on error. - * @see #yaca_digest_algo_e, yaca_verify_update(), yaca_verify_final() + * @see #yaca_key_type_e, #yaca_digest_algo_e, yaca_verify_update(), + * yaca_verify_final() */ int yaca_verify_init(yaca_ctx_h *ctx, yaca_digest_algo_e algo, @@ -114,16 +172,17 @@ int yaca_verify_update(yaca_ctx_h ctx, /** * @brief Performs the verification. * - * @param[in,out] ctx A valid verify context. - * @param[in] mac Input MAC or signature (returned by yaca_sign_final()). - * @param[in] mac_len Size of the MAC or the signature. + * @param[in,out] ctx A valid verify context. + * @param[in] signature Input signature (returned by yaca_sign_final()). + * @param[in] signature_len Size of the signature. * - * @return 0 on success, negative on error. + * @return 0 on success, YACA_ERROR_DATA_MISMATCH if verification fails, + * 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 *signature, + size_t signature_len); /**@}*/ diff --git a/src/crypto.c b/src/crypto.c index df5ba7d..bca42a8 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -127,3 +127,11 @@ API int yaca_get_output_length(const yaca_ctx_h ctx, size_t input_len, size_t *o return ctx->get_output_length(ctx, input_len, output_len); } + +API int yaca_memcmp(const void *first, const void *second, size_t len) +{ + if (CRYPTO_memcmp(first, second, len) == 0) + return 0; + + return YACA_ERROR_DATA_MISMATCH; +} diff --git a/src/sign.c b/src/sign.c index 9573c4c..e47c839 100644 --- a/src/sign.c +++ b/src/sign.c @@ -356,17 +356,17 @@ API int yaca_sign_update(yaca_ctx_h ctx, } API int yaca_sign_final(yaca_ctx_h ctx, - char *mac, - size_t *mac_len) + char *signature, + size_t *signature_len) { 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) + signature == NULL || signature_len == NULL || *signature_len == 0) return YACA_ERROR_INVALID_ARGUMENT; - ret = EVP_DigestSignFinal(c->mdctx, (unsigned char *)mac, mac_len); + ret = EVP_DigestSignFinal(c->mdctx, (unsigned char *)signature, signature_len); if(ret != 1) { ret = YACA_ERROR_INTERNAL; ERROR_DUMP(ret); @@ -499,15 +499,15 @@ API int yaca_verify_update(yaca_ctx_h ctx, } API int yaca_verify_final(yaca_ctx_h ctx, - const char *mac, - size_t mac_len) + const char *signature, + size_t signature_len) { struct yaca_sign_ctx_s *c = get_sign_ctx(ctx); - char mac_cmp[mac_len]; - size_t mac_cmp_len = mac_len; + char mac_cmp[signature_len]; + size_t mac_cmp_len = signature_len; int ret; - if (c == NULL || mac == NULL || mac_len == 0) + if (c == NULL || signature == NULL || signature_len == 0) return YACA_ERROR_INVALID_ARGUMENT; switch (c->op_type) @@ -522,19 +522,19 @@ API int yaca_verify_final(yaca_ctx_h ctx, return ret; } - if (mac_len != mac_cmp_len || CRYPTO_memcmp(mac, mac_cmp, mac_len) != 0) - return YACA_ERROR_SIGNATURE_INVALID; + if (signature_len != mac_cmp_len || CRYPTO_memcmp(signature, mac_cmp, signature_len) != 0) + return YACA_ERROR_DATA_MISMATCH; return 0; case OP_VERIFY_ASYMMETRIC: ret = EVP_DigestVerifyFinal(c->mdctx, - (unsigned char *)mac, - mac_len); + (unsigned char *)signature, + signature_len); if (ret == 1) return 0; if (ret == 0) - ret = YACA_ERROR_SIGNATURE_INVALID; + ret = YACA_ERROR_DATA_MISMATCH; else ret = YACA_ERROR_INTERNAL; -- 2.7.4 From aff97e9576a188849aa42beace30b8dc6f83053f Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Fri, 13 May 2016 09:37:10 +0200 Subject: [PATCH 16/16] Remove CMAC from digest algorithms. Change-Id: I3bb2ddd69b3f7d052cf2fbaea5feaf1b88be9795 --- api/yaca/types.h | 3 +-- examples/sign.c | 3 +++ src/digest.c | 3 --- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/api/yaca/types.h b/api/yaca/types.h index 3284ede..b6068a9 100644 --- a/api/yaca/types.h +++ b/api/yaca/types.h @@ -115,7 +115,7 @@ typedef enum { } yaca_key_bits_e; /** - * @brief Message digest algorithms. CMAC is included to simplify API + * @brief Message digest algorithms. */ typedef enum { YACA_DIGEST_MD5, /**< Message digest algorithm MD5 */ @@ -124,7 +124,6 @@ typedef enum { YACA_DIGEST_SHA256, /**< Message digest algorithm SHA2, 256bit */ YACA_DIGEST_SHA384, /**< Message digest algorithm SHA2, 384bit */ YACA_DIGEST_SHA512, /**< Message digest algorithm SHA2, 512bit */ - YACA_DIGEST_CMAC /**< TODO: perhaps CMAC should be handled differently */ } yaca_digest_algo_e; /** diff --git a/examples/sign.c b/examples/sign.c index f2ba25e..5612ead 100644 --- a/examples/sign.c +++ b/examples/sign.c @@ -150,6 +150,8 @@ finish: void sign_verify_cmac(void) { + // TODO rewrite it +#if 0 char* signature = NULL; size_t signature_len; @@ -199,6 +201,7 @@ finish: yaca_free(signature); yaca_key_free(key); yaca_ctx_free(ctx); +#endif } int main() diff --git a/src/digest.c b/src/digest.c index 10d4dbf..09fbd34 100644 --- a/src/digest.c +++ b/src/digest.c @@ -100,9 +100,6 @@ int digest_get_algorithm(yaca_digest_algo_e algo, const EVP_MD **md) case YACA_DIGEST_SHA512: *md = EVP_sha512(); break; - case YACA_DIGEST_CMAC: - ret = YACA_ERROR_NOT_IMPLEMENTED; - break; default: ret = YACA_ERROR_INVALID_ARGUMENT; break; -- 2.7.4