* @brief Returns the output length for a given algorithm. Can only be called
* on an initialized context.
*
- * @param[in] ctx Previously initialized crypto context.
- * @param[in] input_len Length of the input data to be processed.
+ * @param[in] ctx Previously initialized crypto context.
+ * @param[in] input_len Length of the input data to be processed.
+ * @param[in] output_len Required length of the 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
-int yaca_get_output_length(const yaca_ctx_h ctx, size_t input_len);
+int yaca_get_output_length(const yaca_ctx_h ctx, size_t input_len, size_t *output_len);
/**
* @brief Wrapper - returns the length of the digest (for a given context).
*/
-#define yaca_get_digest_length(ctxa) yaca_get_output_length((ctxa), 0)
+#define yaca_get_digest_length(ctxa, output_len) yaca_get_output_length((ctxa), 0, (output_len))
/**
* @brief Wrapper - returns the length of the signature (for a given context).
*/
-#define yaca_get_sign_length(ctxa) yaca_get_output_length((ctxa), 0)
+#define yaca_get_sign_length(ctxa, output_len) yaca_get_output_length((ctxa), 0, (output_len))
/**
* @brief Wrapper - returns the length of the block (for a given context).
*/
-#define yaca_get_block_length(ctxa) yaca_get_output_length((ctxa), 0)
+#define yaca_get_block_length(ctxa, output_len) yaca_get_output_length((ctxa), 0, (output_len))
/**@}*/
if (ret < 0)
goto exit_ctx;
- // TODO: rename to yaca_digest_get_length??
size_t digest_len;
- digest_len = yaca_get_digest_length(ctx);
- if (digest_len <= 0)
+ ret = yaca_get_digest_length(ctx, &digest_len);
+ if (ret != 0)
goto exit_ctx;
{
if (ret)
goto ex_iv;
- ret = yaca_get_block_length(ctx);
- if (ret < 0)
+ ret = yaca_get_block_length(ctx, &block_len);
+ if (ret != 0)
goto ex_ctx;
- block_len = ret;
-
- ret = yaca_get_output_length(ctx, LOREM4096_SIZE);
- if (ret < 0)
+ ret = yaca_get_output_length(ctx, LOREM4096_SIZE, &output_len);
+ if (ret != 0)
goto ex_ctx;
- output_len = ret;
-
/* Calculate max output: size of update + final chunks */
enc_size = output_len + block_len;
enc = yaca_malloc(enc_size);
goto ex_of;
}
- ret = yaca_get_block_length(ctx);
- if (ret < 0)
+ ret = yaca_get_block_length(ctx, &block_len);
+ if (ret != 0)
goto ex_of;
- block_len = ret;
-
- ret = yaca_get_output_length(ctx, LOREM4096_SIZE);
- if (ret < 0)
+ ret = yaca_get_output_length(ctx, LOREM4096_SIZE, &output_len);
+ if (ret != 0)
goto ex_ctx;
- output_len = ret;
-
/* Calculate max output: size of update + final chunks */
dec_size = output_len + block_len;
dec = yaca_malloc(dec_size);
size_t aad_len;
size_t tag_len;
- printf("Plain data (16 of %zu bytes): %.16s\n", (size_t)4096, lorem4096);
+ printf("Plain data (16 of %zu bytes): %.16s\n", LOREM4096_SIZE, lorem4096);
/// Key generation
/// Encryption
{
+ size_t len;
+
ret = yaca_encrypt_init(&ctx, YACA_ENC_AES, YACA_BCM_GCM, key, iv);
if (ret < 0)
goto clean;
if (ret < 0)
goto clean;
- ret = yaca_encrypt_update(ctx, lorem4096, 4096, NULL, &ciphertext_len);
- if (ret != 42)
- goto clean;// TODO: what error code?
+ ret = yaca_get_output_length(ctx, LOREM4096_SIZE, &ciphertext_len);
+ if (ret != 0)
+ goto clean;
- ret = yaca_get_block_length(ctx);
- if (ret < 0)
+ ret = yaca_get_block_length(ctx, &len);
+ if (ret != 0)
goto clean;
- ciphertext_len += ret ; // Add block size for finalize
+ ciphertext_len += len ; // Add block size for finalize
ciphertext = yaca_malloc(ciphertext_len);
if (ciphertext == NULL)
goto clean;
- size_t len;
- ret = yaca_encrypt_update(ctx, lorem4096, 4096, ciphertext, &len);
+ ret = yaca_encrypt_update(ctx, lorem4096, LOREM4096_SIZE, ciphertext, &len);
if (ret < 0)
goto clean;
if (ret < 0)
goto clean;
- ret = yaca_decrypt_update(ctx, ciphertext, ciphertext_len, NULL, &plaintext_len);
- if (ret != 42)
- goto clean; // TODO: what error code?
+ ret = yaca_get_output_length(ctx, ciphertext_len, &plaintext_len);
+ if (ret != 0)
+ goto clean;
- ret = yaca_get_block_length(ctx);
- if (ret < 0)
+ ret = yaca_get_block_length(ctx, &len);
+ if (ret != 0)
goto clean;
- plaintext_len += ret; // Add block size for finalize
+ plaintext_len += len; // Add block size for finalize
plaintext = yaca_malloc(plaintext_len);
if (plaintext == NULL)
goto clean;
if (yaca_seal_init(&ctx, key_pub, algo, bcm, key_bits, &aes_key, &iv) != 0)
goto ex_pubk;
- if ((block_len = yaca_get_block_length(ctx)) <= 0)
+ if (yaca_get_block_length(ctx, &block_len) != 0)
goto ex_ak;
- if ((output_len = yaca_get_output_length(ctx, LOREM4096_SIZE)) <= 0)
+ if (yaca_get_output_length(ctx, LOREM4096_SIZE, &output_len) != 0)
goto ex_ak;
/* Calculate max output: size of update + final chunks */
if (yaca_open_init(&ctx, key_priv, algo, bcm, key_bits, aes_key, iv) != 0)
goto ex_of;
- if ((block_len = yaca_get_block_length(ctx)) <= 0)
+ if (yaca_get_block_length(ctx, &block_len) != 0)
goto ex_of;
- if ((output_len = yaca_get_output_length(ctx, LOREM4096_SIZE)) <= 0)
+ if (yaca_get_output_length(ctx, LOREM4096_SIZE, &output_len) != 0)
goto ex_of;
/* Calculate max output: size of update + final chunks */
if (yaca_sign_update(ctx, lorem4096, LOREM4096_SIZE) != 0)
goto finish;
- if ((signature_len = yaca_get_sign_length(ctx)) <= 0)
+ if (yaca_get_sign_length(ctx, &signature_len) != 0)
goto finish;
if ((signature = yaca_malloc(signature_len)) == NULL)
if (yaca_sign_update(ctx, lorem4096, LOREM4096_SIZE) != 0)
goto finish;
- if ((signature_len = yaca_get_sign_length(ctx)) <= 0)
+ if (yaca_get_sign_length(ctx, &signature_len) != 0)
goto finish;
if ((signature = yaca_malloc(signature_len)) == NULL)
if (yaca_sign_update(ctx, lorem4096, LOREM4096_SIZE))
goto finish;
- if ((signature_len = yaca_get_sign_length(ctx)) <= 0)
+ if (yaca_get_sign_length(ctx, &signature_len) != 0)
goto finish;
if ((signature = yaca_malloc(signature_len)) == NULL)
}
}
-API int yaca_get_output_length(const yaca_ctx_h ctx, size_t input_len)
+API int yaca_get_output_length(const yaca_ctx_h ctx, size_t input_len, size_t *output_len)
{
if (ctx == YACA_CTX_NULL)
return YACA_ERROR_INVALID_ARGUMENT;
- return ctx->get_output_length(ctx, input_len);
+ return ctx->get_output_length(ctx, input_len, output_len);
}
}
}
-static int get_digest_output_length(const yaca_ctx_h ctx, size_t input_len)
+static int get_digest_output_length(const yaca_ctx_h ctx, size_t input_len, size_t *output_len)
{
struct yaca_digest_ctx_s *c = get_digest_ctx(ctx);
if (c == NULL)
return YACA_ERROR_INVALID_ARGUMENT;
- return EVP_MD_CTX_size(c->mdctx);
+ *output_len = EVP_MD_CTX_size(c->mdctx);
+ return 0;
}
static void destroy_digest_context(yaca_ctx_h ctx)
nc->cipher_ctx = NULL;
}
-static int get_encrypt_output_length(const yaca_ctx_h ctx, size_t input_len)
+static int get_encrypt_output_length(const yaca_ctx_h ctx, size_t input_len, size_t *output_len)
{
struct yaca_encrypt_ctx_s *nc = get_encrypt_ctx(ctx);
int block_size;
return YACA_ERROR_INVALID_ARGUMENT;
block_size = EVP_CIPHER_CTX_block_size(nc->cipher_ctx);
- if (block_size == 0) {
+ if (block_size <= 0) {
ERROR_DUMP(YACA_ERROR_INTERNAL);
return YACA_ERROR_INTERNAL;
}
- if (input_len > 0)
- return block_size + input_len - 1;
- return block_size;
+ if (input_len > 0) {
+ if ((size_t)block_size > SIZE_MAX - input_len + 1)
+ return YACA_ERROR_TOO_BIG_ARGUMENT;
+
+ *output_len = block_size + input_len - 1;
+ } else {
+ *output_len = block_size;
+ }
+
+ return 0;
}
static const char *encrypt_algo_to_str(yaca_enc_algo_e algo)
enum yaca_ctx_type_e type;
void (*ctx_destroy)(const yaca_ctx_h ctx);
- int (*get_output_length)(const yaca_ctx_h ctx, size_t input_len);
+ int (*get_output_length)(const yaca_ctx_h ctx, size_t input_len, size_t *output_len);
int (*set_param)(yaca_ctx_h ctx, yaca_ex_param_e param,
const void *value, size_t value_len);
int (*get_param)(const yaca_ctx_h ctx, yaca_ex_param_e param,
nc->cipher_ctx = NULL;
}
-static int get_seal_output_length(const yaca_ctx_h ctx, size_t input_len)
+static int get_seal_output_length(const yaca_ctx_h ctx, size_t input_len, size_t *output_len)
{
struct yaca_seal_ctx_s *nc = get_seal_ctx(ctx);
int block_size;
return YACA_ERROR_INTERNAL;
}
- if (input_len > 0)
- return block_size + input_len - 1;
- return block_size;
+ if (input_len > 0) {
+ if ((size_t)block_size > SIZE_MAX - input_len + 1)
+ return YACA_ERROR_TOO_BIG_ARGUMENT;
+
+ *output_len = block_size + input_len - 1;
+ } else {
+ *output_len = block_size;
+ }
+
+ return 0;
}
static int seal_init(yaca_ctx_h *ctx,
}
}
-static int get_sign_output_length(const yaca_ctx_h ctx, size_t input_len)
+static int get_sign_output_length(const yaca_ctx_h ctx, size_t input_len, size_t *output_len)
{
struct yaca_sign_ctx_s *c = get_sign_ctx(ctx);
return YACA_ERROR_INVALID_ARGUMENT;
}
- return len;
+ *output_len = len;
+ return 0;
}
static void destroy_sign_context(yaca_ctx_h ctx)
#include <assert.h>
#include <limits.h>
+#include <stdint.h>
#include <openssl/crypto.h>
#include <openssl/rand.h>
if (ret < 0)
goto err;
- ret = yaca_get_digest_length(ctx);
- if (ret < 0)
+ ret = yaca_get_digest_length(ctx, &ldigest_len);
+ if (ret != 0)
goto err;
- ldigest_len = ret;
ldigest = yaca_malloc(ldigest_len);
if (!ldigest)
goto err;
sym_key == YACA_KEY_NULL)
return YACA_ERROR_INVALID_ARGUMENT;
- if (plain_len > INT_MAX) /* TODO: this is because get_output_length returns signed int - perhaps we should change that */
- return YACA_ERROR_TOO_BIG_ARGUMENT;
-
ret = yaca_encrypt_init(&ctx, algo, bcm, sym_key, iv);
if (ret != 0)
return ret;
- ret = yaca_get_block_length(ctx);
- if (ret <= 0)
+ ret = yaca_get_block_length(ctx, &lcipher_len);
+ if (ret != 0)
goto err;
- lcipher_len = ret;
+ ret = yaca_get_output_length(ctx, plain_len, &out_len);
+ if (ret != 0)
+ goto err;
- ret = yaca_get_output_length(ctx, plain_len);
- if (ret <= 0)
+ if (out_len > SIZE_MAX - lcipher_len) {
+ ret = YACA_ERROR_TOO_BIG_ARGUMENT;
goto err;
+ }
- lcipher_len += ret;
+ lcipher_len += out_len;
lcipher = yaca_malloc(lcipher_len);
if (lcipher == NULL)
sym_key == YACA_KEY_NULL)
return YACA_ERROR_INVALID_ARGUMENT;
- if (cipher_len > INT_MAX) /* TODO: this is because get_output_length returns signed int - perhaps we should change that */
- return YACA_ERROR_TOO_BIG_ARGUMENT;
-
ret = yaca_decrypt_init(&ctx, algo, bcm, sym_key, iv);
if (ret != 0)
return ret;
- ret = yaca_get_block_length(ctx);
- if (ret <= 0)
+ ret = yaca_get_block_length(ctx, &lplain_len);
+ if (ret != 0)
goto err;
- lplain_len = ret;
+ ret = yaca_get_output_length(ctx, cipher_len, &out_len);
+ if (ret != 0)
+ goto err;
- ret = yaca_get_output_length(ctx, cipher_len);
- if (ret <= 0)
+ if (out_len > SIZE_MAX - lplain_len) {
+ ret = YACA_ERROR_TOO_BIG_ARGUMENT;
goto err;
+ }
- lplain_len += ret;
+ lplain_len += out_len;
lplain = yaca_malloc(lplain_len);
if (!lplain)