#include "internal.h"
-enum encrypt_op_type {
- OP_ENCRYPT = 0,
- OP_DECRYPT = 1
-};
-
-struct yaca_encrypt_ctx_s {
- struct yaca_context_s ctx;
-
- EVP_CIPHER_CTX *cipher_ctx;
- enum encrypt_op_type op_type; /* Operation context was created for */
- size_t tag_len;
-};
-
-static struct yaca_encrypt_ctx_s *get_encrypt_ctx(const yaca_context_h ctx)
+struct yaca_encrypt_context_s *get_encrypt_context(const yaca_context_h ctx)
{
if (ctx == YACA_CONTEXT_NULL)
return NULL;
switch (ctx->type) {
case YACA_CTX_ENCRYPT:
- return (struct yaca_encrypt_ctx_s *)ctx;
+ return (struct yaca_encrypt_context_s *)ctx;
default:
return NULL;
}
}
-static void destroy_encrypt_ctx(const yaca_context_h ctx)
+void destroy_encrypt_context(const yaca_context_h ctx)
{
- struct yaca_encrypt_ctx_s *nc = get_encrypt_ctx(ctx);
+ struct yaca_encrypt_context_s *nc = get_encrypt_context(ctx);
if (nc == NULL)
return;
nc->cipher_ctx = NULL;
}
-static int get_encrypt_output_length(const yaca_context_h ctx, size_t input_len, size_t *output_len)
+int get_encrypt_output_length(const yaca_context_h ctx, size_t input_len, size_t *output_len)
{
- struct yaca_encrypt_ctx_s *nc = get_encrypt_ctx(ctx);
+ struct yaca_encrypt_context_s *nc = get_encrypt_context(ctx);
int block_size;
if (nc == NULL)
return YACA_ERROR_NONE;
}
-static int set_encrypt_param(yaca_context_h ctx,
- yaca_property_e param,
- const void *value,
- size_t value_len)
+int set_encrypt_property(yaca_context_h ctx, yaca_property_e property,
+ const void *value, size_t value_len)
{
- struct yaca_encrypt_ctx_s *c = get_encrypt_ctx(ctx);
+ struct yaca_encrypt_context_s *c = get_encrypt_context(ctx);
int len;
if (c == NULL || value == NULL)
return YACA_ERROR_INVALID_PARAMETER;
assert(c->cipher_ctx != NULL);
- switch (param) {
+ switch (property) {
case YACA_PROPERTY_GCM_AAD:
case YACA_PROPERTY_CCM_AAD:
- if (EVP_EncryptUpdate(c->cipher_ctx, NULL, &len, value, value_len) != 1) {
- ERROR_DUMP(YACA_ERROR_INTERNAL);
- return YACA_ERROR_INTERNAL;
+ if (c->op_type == OP_ENCRYPT) {
+ if (EVP_EncryptUpdate(c->cipher_ctx, NULL, &len, value, value_len) != 1) {
+ ERROR_DUMP(YACA_ERROR_INTERNAL);
+ return YACA_ERROR_INTERNAL;
+ }
+ }
+ if (c->op_type == OP_DECRYPT) {
+ if (EVP_DecryptUpdate(c->cipher_ctx, NULL, &len, value, value_len) != 1) {
+ ERROR_DUMP(YACA_ERROR_INTERNAL);
+ return YACA_ERROR_INTERNAL;
+ }
+ }
+ if (c->op_type == OP_SEAL) {
+ if (EVP_SealUpdate(c->cipher_ctx, NULL, &len, value, value_len) != 1) {
+ ERROR_DUMP(YACA_ERROR_INTERNAL);
+ return YACA_ERROR_INTERNAL;
+ }
+ }
+ if (c->op_type == OP_OPEN) {
+ if (EVP_OpenUpdate(c->cipher_ctx, NULL, &len, value, value_len) != 1) {
+ ERROR_DUMP(YACA_ERROR_INTERNAL);
+ return YACA_ERROR_INTERNAL;
+ }
}
break;
case YACA_PROPERTY_GCM_TAG:
default:
return YACA_ERROR_INVALID_PARAMETER;
}
+
return YACA_ERROR_NONE;
}
-static int get_encrypt_param(const yaca_context_h ctx,
- yaca_property_e param,
- void **value,
- size_t *value_len)
+int get_encrypt_property(const yaca_context_h ctx, yaca_property_e property,
+ void **value, size_t *value_len)
{
- struct yaca_encrypt_ctx_s *c = get_encrypt_ctx(ctx);
+ struct yaca_encrypt_context_s *c = get_encrypt_context(ctx);
if (c == NULL || value == NULL || value_len == NULL)
return YACA_ERROR_INVALID_PARAMETER;
assert(c->cipher_ctx != NULL);
- switch (param) {
+ switch (property) {
case YACA_PROPERTY_GCM_TAG:
if (c->tag_len == 0)
return YACA_ERROR_INVALID_PARAMETER;
return YACA_ERROR_INVALID_PARAMETER;
break;
}
+
return YACA_ERROR_NONE;
}
return YACA_ERROR_NONE;
}
-static int encrypt_init(yaca_context_h *ctx,
- yaca_encrypt_algorithm_e algo,
- yaca_block_cipher_mode_e bcm,
- const yaca_key_h sym_key,
- const yaca_key_h iv,
- enum encrypt_op_type op_type)
+static int encrypt_initialize(yaca_context_h *ctx,
+ yaca_encrypt_algorithm_e algo,
+ yaca_block_cipher_mode_e bcm,
+ const yaca_key_h sym_key,
+ const yaca_key_h iv,
+ enum encrypt_op_type op_type)
{
const struct yaca_key_simple_s *lkey;
const struct yaca_key_simple_s *liv;
- struct yaca_encrypt_ctx_s *nc;
+ struct yaca_encrypt_context_s *nc;
const EVP_CIPHER *cipher;
size_t key_bits;
unsigned char *iv_data = NULL;
if (lkey == NULL)
return YACA_ERROR_INVALID_PARAMETER;
- ret = yaca_zalloc(sizeof(struct yaca_encrypt_ctx_s), (void**)&nc);
+ ret = yaca_zalloc(sizeof(struct yaca_encrypt_context_s), (void**)&nc);
if (ret != YACA_ERROR_NONE)
return ret;
nc->ctx.type = YACA_CTX_ENCRYPT;
- nc->ctx.ctx_destroy = destroy_encrypt_ctx;
+ nc->ctx.ctx_destroy = destroy_encrypt_context;
nc->ctx.get_output_length = get_encrypt_output_length;
- nc->ctx.set_param = set_encrypt_param;
- nc->ctx.get_param = get_encrypt_param;
+ nc->ctx.set_param = set_encrypt_property;
+ nc->ctx.get_param = get_encrypt_property;
nc->op_type = op_type;
nc->tag_len = 0;
return ret;
}
-static int encrypt_update(yaca_context_h ctx,
- const unsigned char *input,
- size_t input_len,
- unsigned char *output,
- size_t *output_len,
- enum encrypt_op_type op_type)
+int encrypt_update(yaca_context_h ctx,
+ const unsigned char *input, size_t input_len,
+ unsigned char *output, size_t *output_len,
+ enum encrypt_op_type op_type)
{
- struct yaca_encrypt_ctx_s *c = get_encrypt_ctx(ctx);
+ struct yaca_encrypt_context_s *c = get_encrypt_context(ctx);
int ret;
int loutput_len;
if (c == NULL || input_len == 0 || output_len == NULL || op_type != c->op_type)
return YACA_ERROR_INVALID_PARAMETER;
- loutput_len = *output_len;
-
switch (op_type) {
case OP_ENCRYPT:
- ret = EVP_EncryptUpdate(c->cipher_ctx, output, &loutput_len,
- input, input_len);
+ ret = EVP_EncryptUpdate(c->cipher_ctx, output, &loutput_len, input, input_len);
+ break;
+ case OP_SEAL:
+ ret = EVP_SealUpdate(c->cipher_ctx, output, &loutput_len, input, input_len);
break;
case OP_DECRYPT:
- ret = EVP_DecryptUpdate(c->cipher_ctx, output, &loutput_len,
- input, input_len);
+ ret = EVP_DecryptUpdate(c->cipher_ctx, output, &loutput_len, input, input_len);
+ break;
+ case OP_OPEN:
+ ret = EVP_OpenUpdate(c->cipher_ctx, output, &loutput_len, input, input_len);
break;
default:
return YACA_ERROR_INVALID_PARAMETER;
}
- if (ret != 1) {
+ if (ret != 1 || loutput_len < 0) {
ret = YACA_ERROR_INTERNAL;
ERROR_DUMP(ret);
return ret;
return YACA_ERROR_NONE;
}
-static int encrypt_final(yaca_context_h ctx,
- unsigned char *output,
- size_t *output_len,
- enum encrypt_op_type op_type)
+int encrypt_finalize(yaca_context_h ctx,
+ unsigned char *output, size_t *output_len,
+ enum encrypt_op_type op_type)
{
- struct yaca_encrypt_ctx_s *c = get_encrypt_ctx(ctx);
+ struct yaca_encrypt_context_s *c = get_encrypt_context(ctx);
int ret;
int loutput_len;
- if (c == NULL || output == NULL || output_len == NULL ||
- op_type != c->op_type)
+ if (c == NULL || output == NULL || output_len == NULL || op_type != c->op_type)
return YACA_ERROR_INVALID_PARAMETER;
- loutput_len = *output_len;
-
switch (op_type) {
case OP_ENCRYPT:
ret = EVP_EncryptFinal(c->cipher_ctx, output, &loutput_len);
case OP_DECRYPT:
ret = EVP_DecryptFinal(c->cipher_ctx, output, &loutput_len);
break;
+ case OP_SEAL:
+ ret = EVP_SealFinal(c->cipher_ctx, output, &loutput_len);
+ break;
+ case OP_OPEN:
+ ret = EVP_OpenFinal(c->cipher_ctx, output, &loutput_len);
+ break;
default:
return YACA_ERROR_INVALID_PARAMETER;
}
- if (ret != 1) {
+ if (ret != 1 || loutput_len < 0) {
ret = YACA_ERROR_INTERNAL;
ERROR_DUMP(ret);
return ret;
const yaca_key_h sym_key,
const yaca_key_h iv)
{
- return encrypt_init(ctx, algo, bcm, sym_key, iv, OP_ENCRYPT);
+ return encrypt_initialize(ctx, algo, bcm, sym_key, iv, OP_ENCRYPT);
}
API int yaca_encrypt_update(yaca_context_h ctx,
char *ciphertext,
size_t *ciphertext_len)
{
- return encrypt_final(ctx, (unsigned char*)ciphertext,
- ciphertext_len, OP_ENCRYPT);
+ return encrypt_finalize(ctx, (unsigned char*)ciphertext, ciphertext_len, OP_ENCRYPT);
}
API int yaca_decrypt_initialize(yaca_context_h *ctx,
const yaca_key_h sym_key,
const yaca_key_h iv)
{
- return encrypt_init(ctx, algo, bcm, sym_key, iv, OP_DECRYPT);
+ return encrypt_initialize(ctx, algo, bcm, sym_key, iv, OP_DECRYPT);
}
API int yaca_decrypt_update(yaca_context_h ctx,
char *plaintext,
size_t *plaintext_len)
{
- return encrypt_final(ctx, (unsigned char*)plaintext, plaintext_len,
- OP_DECRYPT);
+ return encrypt_finalize(ctx, (unsigned char*)plaintext, plaintext_len, OP_DECRYPT);
}
YACA_CTX_INVALID = 0,
YACA_CTX_DIGEST,
YACA_CTX_SIGN,
- YACA_CTX_ENCRYPT,
- YACA_CTX_SEAL
+ YACA_CTX_ENCRYPT
+};
+
+enum encrypt_op_type {
+ OP_ENCRYPT = 0,
+ OP_DECRYPT = 1,
+ OP_SEAL = 2,
+ OP_OPEN = 3
};
/* Base structure for crypto contexts - to be inherited */
void **value, size_t *value_len);
};
+struct yaca_encrypt_context_s {
+ struct yaca_context_s ctx;
+
+ EVP_CIPHER_CTX *cipher_ctx;
+ enum encrypt_op_type op_type; /* Operation context was created for */
+ size_t tag_len;
+};
/* Base structure for crypto keys - to be inherited */
struct yaca_key_s {
int digest_get_algorithm(yaca_digest_algorithm_e algo, const EVP_MD **md);
+struct yaca_encrypt_context_s *get_encrypt_context(const yaca_context_h ctx);
+
+void destroy_encrypt_context(const yaca_context_h ctx);
+
+int get_encrypt_output_length(const yaca_context_h ctx, size_t input_len, size_t *output_len);
+
+int set_encrypt_property(yaca_context_h ctx, yaca_property_e property,
+ const void *value, size_t value_len);
+
+int get_encrypt_property(const yaca_context_h ctx, yaca_property_e property,
+ void **value, size_t *value_len);
+
int encrypt_get_algorithm(yaca_encrypt_algorithm_e algo,
yaca_block_cipher_mode_e bcm,
size_t key_bits,
const EVP_CIPHER **cipher);
+int encrypt_update(yaca_context_h ctx,
+ const unsigned char *input, size_t input_len,
+ unsigned char *output, size_t *output_len,
+ enum encrypt_op_type op_type);
+
+int encrypt_finalize(yaca_context_h ctx,
+ unsigned char *output, size_t *output_len,
+ enum encrypt_op_type op_type);
+
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);
#include "internal.h"
-enum seal_op_type {
- OP_SEAL = 0,
- OP_OPEN = 1
-};
-
-struct yaca_seal_ctx_s {
- struct yaca_context_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_context_h ctx)
-{
- if (ctx == YACA_CONTEXT_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_context_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_context_h ctx, size_t input_len, size_t *output_len)
-{
- struct yaca_seal_ctx_s *nc = get_seal_ctx(ctx);
- int block_size;
-
- if (nc == NULL)
- return YACA_ERROR_INVALID_PARAMETER;
- assert(nc->cipher_ctx);
-
- block_size = EVP_CIPHER_CTX_block_size(nc->cipher_ctx);
- if (block_size <= 0) {
- ERROR_DUMP(YACA_ERROR_INTERNAL);
- return YACA_ERROR_INTERNAL;
- }
-
- if (input_len > 0) {
- if ((size_t)block_size > SIZE_MAX - input_len + 1)
- return YACA_ERROR_INVALID_PARAMETER;
-
- *output_len = block_size + input_len - 1;
- } else {
- *output_len = block_size;
- }
-
- return YACA_ERROR_NONE;
-}
-
-static int seal_init(yaca_context_h *ctx,
- const yaca_key_h pub_key,
- yaca_encrypt_algorithm_e algo,
- yaca_block_cipher_mode_e bcm,
- size_t sym_key_bits,
- yaca_key_h *sym_key,
- yaca_key_h *iv)
+API int yaca_seal_initialize(yaca_context_h *ctx,
+ const yaca_key_h pub_key,
+ yaca_encrypt_algorithm_e algo,
+ yaca_block_cipher_mode_e bcm,
+ size_t sym_key_bit_len,
+ yaca_key_h *sym_key,
+ yaca_key_h *iv)
{
struct yaca_key_evp_s *lpub;
struct yaca_key_simple_s *lkey = NULL;
struct yaca_key_simple_s *liv = NULL;
- struct yaca_seal_ctx_s *nc;
+ struct yaca_encrypt_context_s *nc;
const EVP_CIPHER *cipher;
int pub_key_length;
unsigned char *key_data = NULL;
lpub = key_get_evp(pub_key);
assert(lpub);
- ret = yaca_zalloc(sizeof(struct yaca_seal_ctx_s), (void**)&nc);
+ ret = yaca_zalloc(sizeof(struct yaca_encrypt_context_s), (void**)&nc);
if (ret != YACA_ERROR_NONE)
return ret;
- nc->ctx.type = YACA_CTX_SEAL;
- nc->ctx.ctx_destroy = destroy_seal_ctx;
- nc->ctx.get_output_length = get_seal_output_length;
+ nc->ctx.type = YACA_CTX_ENCRYPT;
+ nc->ctx.ctx_destroy = destroy_encrypt_context;
+ nc->ctx.get_output_length = get_encrypt_output_length;
+ nc->ctx.set_param = set_encrypt_property;
+ nc->ctx.get_param = get_encrypt_property;
nc->op_type = OP_SEAL;
+ nc->tag_len = 0;
nc->cipher_ctx = EVP_CIPHER_CTX_new();
if (nc->cipher_ctx == NULL) {
goto exit;
key_data = (unsigned char*)lkey->d;
- ret = encrypt_get_algorithm(algo, bcm, sym_key_bits, &cipher);
+ ret = encrypt_get_algorithm(algo, bcm, sym_key_bit_len, &cipher);
if (ret != YACA_ERROR_NONE)
goto exit;
return ret;
}
-static int open_init(yaca_context_h *ctx,
- const yaca_key_h prv_key,
- yaca_encrypt_algorithm_e algo,
- yaca_block_cipher_mode_e bcm,
- size_t sym_key_bits,
- const yaca_key_h sym_key,
- const yaca_key_h iv)
+API int yaca_seal_update(yaca_context_h ctx,
+ const char *plaintext,
+ size_t plaintext_len,
+ char *ciphertext,
+ size_t *ciphertext_len)
+{
+ return encrypt_update(ctx, (const unsigned char*)plaintext, plaintext_len,
+ (unsigned char*)ciphertext, ciphertext_len, OP_SEAL);
+}
+
+API int yaca_seal_finalize(yaca_context_h ctx,
+ char *ciphertext,
+ size_t *ciphertext_len)
+{
+ return encrypt_finalize(ctx, (unsigned char*)ciphertext, ciphertext_len, OP_SEAL);
+}
+
+API int yaca_open_initialize(yaca_context_h *ctx,
+ const yaca_key_h prv_key,
+ yaca_encrypt_algorithm_e algo,
+ yaca_block_cipher_mode_e bcm,
+ size_t sym_key_bit_len,
+ 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;
+ struct yaca_encrypt_context_s *nc;
const EVP_CIPHER *cipher;
unsigned char *iv_data = NULL;
size_t iv_bits;
if (lkey == NULL || lkey->key.type != YACA_KEY_TYPE_SYMMETRIC)
return YACA_ERROR_INVALID_PARAMETER;
- ret = yaca_zalloc(sizeof(struct yaca_seal_ctx_s), (void**)&nc);
+ ret = yaca_zalloc(sizeof(struct yaca_encrypt_context_s), (void**)&nc);
if (ret != YACA_ERROR_NONE)
return ret;
- nc->ctx.type = YACA_CTX_SEAL;
- nc->ctx.ctx_destroy = destroy_seal_ctx;
- nc->ctx.get_output_length = get_seal_output_length;
+ nc->ctx.type = YACA_CTX_ENCRYPT;
+ nc->ctx.ctx_destroy = destroy_encrypt_context;
+ nc->ctx.get_output_length = get_encrypt_output_length;
+ nc->ctx.set_param = set_encrypt_property;
+ nc->ctx.get_param = get_encrypt_property;
nc->op_type = OP_OPEN;
+ nc->tag_len = 0;
- ret = encrypt_get_algorithm(algo, bcm, sym_key_bits, &cipher);
+ ret = encrypt_get_algorithm(algo, bcm, sym_key_bit_len, &cipher);
if (ret != YACA_ERROR_NONE)
goto exit;
return ret;
}
-static int seal_update(yaca_context_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_PARAMETER;
-
- 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_PARAMETER;
- }
-
- if (ret != 1) {
- ret = YACA_ERROR_INTERNAL;
- ERROR_DUMP(ret);
- return ret;
- }
-
- return YACA_ERROR_NONE;
-}
-
-static int seal_final(yaca_context_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_PARAMETER;
-
- 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_PARAMETER;
- }
-
- if (ret != 1) {
- ret = YACA_ERROR_INTERNAL;
- ERROR_DUMP(ret);
- return ret;
- }
-
- return YACA_ERROR_NONE;
-}
-
-API int yaca_seal_initialize(yaca_context_h *ctx,
- const yaca_key_h pub_key,
- yaca_encrypt_algorithm_e algo,
- yaca_block_cipher_mode_e bcm,
- size_t sym_key_bit_len,
- yaca_key_h *sym_key,
- yaca_key_h *iv)
-{
- return seal_init(ctx, pub_key, algo, bcm, sym_key_bit_len, sym_key, iv);
-}
-
-API int yaca_seal_update(yaca_context_h ctx,
- const char *plaintext,
- size_t plaintext_len,
- char *ciphertext,
- size_t *ciphertext_len)
-{
- return seal_update(ctx,
- (const unsigned char*)plaintext,
- plaintext_len,
- (unsigned char*)ciphertext,
- ciphertext_len,
- OP_SEAL);
-}
-
-API int yaca_seal_finalize(yaca_context_h ctx,
- char *ciphertext,
- size_t *ciphertext_len)
-{
- return seal_final(ctx,
- (unsigned char*)ciphertext,
- ciphertext_len,
- OP_SEAL);
-}
-
-API int yaca_open_initialize(yaca_context_h *ctx,
- const yaca_key_h prv_key,
- yaca_encrypt_algorithm_e algo,
- yaca_block_cipher_mode_e bcm,
- size_t sym_key_bit_len,
- const yaca_key_h sym_key,
- const yaca_key_h iv)
-{
- return open_init(ctx, prv_key, algo, bcm, sym_key_bit_len, sym_key, iv);
-}
-
API int yaca_open_update(yaca_context_h ctx,
const char *ciphertext,
size_t ciphertext_len,
char *plaintext,
size_t *plaintext_len)
{
- return seal_update(ctx,
- (const unsigned char*)ciphertext,
- ciphertext_len,
- (unsigned char*)plaintext,
- plaintext_len,
- OP_OPEN);
+ return encrypt_update(ctx, (const unsigned char*)ciphertext, ciphertext_len,
+ (unsigned char*)plaintext, plaintext_len, OP_OPEN);
}
API int yaca_open_finalize(yaca_context_h ctx,
char *plaintext,
size_t *plaintext_len)
{
- return seal_final(ctx, (unsigned char*)plaintext, plaintext_len, OP_OPEN);
+ return encrypt_finalize(ctx, (unsigned char*)plaintext, plaintext_len, OP_OPEN);
}