*/
#include "ies.h"
-#include <iostream>
+#include <new>
#include <vector>
#define SET_ERROR(string) \
#define SET_OSSL_ERROR(string) \
sprintf(error, "%s {error = %s} %s:%d", (string), ERR_error_string(ERR_get_error(), NULL), __FILE__, __LINE__)
+const size_t nEnvKeyLen = 16 + 20; // EVP_CIPHER_key_length(EVP_aes_128_cbc()) + EVP_MD_size(EVP_ripemd160())
+
/* Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved.
* Taken from openssl/crypto/ecdh/ech_kdf.c in github:openssl/openssl
* ffa08b3242e0f10f1fef3c93ef3f0b51de8c27a9 */
return rv;
}
-static size_t envelope_key_len(const ies_ctx_t *ctx)
-{
- return EVP_CIPHER_key_length(ctx->cipher) + EVP_MD_size(ctx->md);
-}
-
static EC_KEY * ecies_key_create(const EC_KEY *user, char *error) {
const EC_GROUP *group;
static unsigned char *prepare_envelope_key(const ies_ctx_t *ctx, cryptogram_t *cryptogram, char *error)
{
- const size_t key_buf_len = envelope_key_len(ctx);
const size_t ecdh_key_len = (EC_GROUP_get_degree(EC_KEY_get0_group(ctx->user_key)) + 7) / 8;
unsigned char *envelope_key = NULL, *ktmp = NULL;
EC_KEY *ephemeral = NULL;
/* High-level ECDH via EVP does not allow use of arbitrary KDF function.
* We should use low-level API for KDF2
* c.f. openssl/crypto/ec/ec_pmeth.c */
- if ((envelope_key = (unsigned char *) OPENSSL_malloc(key_buf_len)) == NULL) {
+ if ((envelope_key = (unsigned char *) OPENSSL_malloc(nEnvKeyLen)) == NULL) {
SET_ERROR("Failed to allocate memory for envelope_key");
goto err;
}
}
/* equals to ISO 18033-2 KDF2 */
- if (!ECDH_KDF_X9_62(envelope_key, key_buf_len, ktmp, ecdh_key_len, 0, 0, ctx->kdf_md)) {
+ if (!ECDH_KDF_X9_62(envelope_key, nEnvKeyLen, ktmp, ecdh_key_len, 0, 0, ctx->kdf_md)) {
SET_OSSL_ERROR("Failed to stretch with KDF2");
goto err;
}
if (ephemeral)
EC_KEY_free(ephemeral);
if (envelope_key) {
- OPENSSL_cleanse(envelope_key, key_buf_len);
+ OPENSSL_cleanse(envelope_key, nEnvKeyLen);
OPENSSL_free(envelope_key);
}
if (ktmp) {
if (EVP_EncryptFinal_ex(&cipher, body, &out_len) != 1) {
SET_OSSL_ERROR("Error while finalizing the data using the symmetric cipher");
EVP_CIPHER_CTX_cleanup(&cipher);
- cryptogram_free(cryptogram);
return 0;
}
goto err;
}
- OPENSSL_cleanse(envelope_key, envelope_key_len(ctx));
+ OPENSSL_cleanse(envelope_key, nEnvKeyLen);
OPENSSL_free(envelope_key);
return cryptogram;
if (cryptogram)
cryptogram_free(cryptogram);
if (envelope_key) {
- OPENSSL_cleanse(envelope_key, envelope_key_len(ctx));
+ OPENSSL_cleanse(envelope_key, nEnvKeyLen);
OPENSSL_free(envelope_key);
}
return NULL;
unsigned char *restore_envelope_key(const ies_ctx_t *ctx, const cryptogram_t *cryptogram, char *error)
{
- const size_t key_buf_len = envelope_key_len(ctx);
const size_t ecdh_key_len = (EC_GROUP_get_degree(EC_KEY_get0_group(ctx->user_key)) + 7) / 8;
EC_KEY *ephemeral = NULL, *user_copy = NULL;
unsigned char *envelope_key = NULL, *ktmp = NULL;
- if ((envelope_key = (unsigned char *) OPENSSL_malloc(key_buf_len)) == NULL) {
+ if ((envelope_key = (unsigned char *) OPENSSL_malloc(nEnvKeyLen)) == NULL) {
SET_ERROR("Failed to allocate memory for envelope_key");
goto err;
}
}
/* equals to ISO 18033-2 KDF2 */
- if (!ECDH_KDF_X9_62(envelope_key, key_buf_len, ktmp, ecdh_key_len, 0, 0, ctx->kdf_md)) {
+ if (!ECDH_KDF_X9_62(envelope_key, nEnvKeyLen, ktmp, ecdh_key_len, 0, 0, ctx->kdf_md)) {
SET_OSSL_ERROR("Failed to stretch with KDF2");
goto err;
}
if (user_copy)
EC_KEY_free(user_copy);
if (envelope_key) {
- OPENSSL_cleanse(envelope_key, key_buf_len);
+ OPENSSL_cleanse(envelope_key, nEnvKeyLen);
OPENSSL_free(envelope_key);
}
if (ktmp) {
{
unsigned char *envelope_key = NULL, *output = NULL;
- if (!ctx || !cryptogram || !length || !error) {
+ if (!ctx || !cryptogram || !length) {
SET_ERROR("Invalid argument");
goto err;
}
}
err:
- OPENSSL_cleanse(envelope_key, envelope_key_len(ctx));
+ OPENSSL_cleanse(envelope_key, nEnvKeyLen);
OPENSSL_free(envelope_key);
return output;
ies_ctx_t *create_context(EC_KEY *user_key)
{
- ies_ctx_t* ctx = (ies_ctx_t*) malloc(sizeof(ies_ctx_t));
- ctx->cipher = EVP_aes_128_cbc();
- ctx->md = EVP_sha1();
- ctx->kdf_md = EVP_sha1();
- ctx->stored_key_length = 33;
- ctx->user_key = user_key;
-
- return ctx;
+ try {
+ ies_ctx_t* ctx = new ies_ctx_t;
+ ctx->cipher = EVP_aes_128_cbc();
+ ctx->md = EVP_ripemd160();
+ ctx->kdf_md = EVP_ripemd160();
+ ctx->stored_key_length = 33;
+ ctx->user_key = user_key;
+ return ctx;
+ }
+ catch (const std::bad_alloc& e) {
+ printf("Error: %s in %s:%d\n", e.what(), __FILE__, __LINE__);
+// TODO: add checking to NULL where necessary
+ return NULL;
+ }
}