This check is excessive since we don't support walletless mode for now.
[novacoin.git] / src / ecies.cpp
index f2a86dd..502bc96 100644 (file)
@@ -9,7 +9,7 @@
  */
 
 #include "ies.h"
-#include <iostream>
+#include <new>
 #include <vector>
 
 #define SET_ERROR(string) \
@@ -17,6 +17,8 @@
 #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 */
@@ -76,11 +78,6 @@ int ECDH_KDF_X9_62(unsigned char *out, size_t outlen,
     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;
@@ -115,7 +112,6 @@ static EC_KEY * ecies_key_create(const EC_KEY *user, char *error) {
 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;
@@ -124,7 +120,7 @@ static unsigned char *prepare_envelope_key(const ies_ctx_t *ctx, cryptogram_t *c
     /* 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;
     }
@@ -148,7 +144,7 @@ static unsigned char *prepare_envelope_key(const ies_ctx_t *ctx, cryptogram_t *c
     }
 
     /* 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;
     }
@@ -180,7 +176,7 @@ static unsigned char *prepare_envelope_key(const ies_ctx_t *ctx, cryptogram_t *c
     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) {
@@ -228,7 +224,6 @@ static int store_cipher_body(
     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;
     }
 
@@ -272,16 +267,16 @@ static int store_mac_tag(const ies_ctx_t *ctx, const unsigned char *envelope_key
 
 cryptogram_t * ecies_encrypt(const ies_ctx_t *ctx, const unsigned char *data, size_t length, char *error) {
 
-    const size_t block_length = EVP_CIPHER_block_size(ctx->cipher);
-    const size_t mac_length = EVP_MD_size(ctx->md);
-    cryptogram_t *cryptogram = NULL;
-    unsigned char *envelope_key = NULL;
-
     if (!ctx || !data || !length) {
         SET_ERROR("Invalid arguments");
         return NULL;
     }
 
+    const size_t block_length = EVP_CIPHER_block_size(ctx->cipher);
+    const size_t mac_length = EVP_MD_size(ctx->md);
+    cryptogram_t *cryptogram = NULL;
+    unsigned char *envelope_key = NULL;
+
     if (block_length == 0 || block_length > EVP_MAX_BLOCK_LENGTH) {
         SET_ERROR("Derived block size is incorrect");
         return NULL;
@@ -307,7 +302,7 @@ cryptogram_t * ecies_encrypt(const ies_ctx_t *ctx, const unsigned char *data, si
         goto err;
     }
 
-    OPENSSL_cleanse(envelope_key, envelope_key_len(ctx));
+    OPENSSL_cleanse(envelope_key, nEnvKeyLen);
     OPENSSL_free(envelope_key);
 
     return cryptogram;
@@ -316,7 +311,7 @@ cryptogram_t * ecies_encrypt(const ies_ctx_t *ctx, const unsigned char *data, si
     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;
@@ -378,12 +373,11 @@ static EC_KEY *ecies_key_create_public_octets(EC_KEY *user, unsigned char *octet
 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;
     }
@@ -417,7 +411,7 @@ unsigned char *restore_envelope_key(const ies_ctx_t *ctx, const cryptogram_t *cr
     }
 
     /* 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;
     }
@@ -435,7 +429,7 @@ unsigned char *restore_envelope_key(const ies_ctx_t *ctx, const cryptogram_t *cr
     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) {
@@ -529,7 +523,7 @@ unsigned char * ecies_decrypt(const ies_ctx_t *ctx, const cryptogram_t *cryptogr
 {
     unsigned char *envelope_key = NULL, *output = NULL;
 
-    if (!ctx || !cryptogram || !length || !error) {
+    if (!ctx || !cryptogram || !length) {
         SET_ERROR("Invalid argument");
         goto err;
     }
@@ -548,7 +542,7 @@ unsigned char * ecies_decrypt(const ies_ctx_t *ctx, const cryptogram_t *cryptogr
     }
 
   err:
-    OPENSSL_cleanse(envelope_key, envelope_key_len(ctx));
+    OPENSSL_cleanse(envelope_key, nEnvKeyLen);
     OPENSSL_free(envelope_key);
 
     return output;
@@ -556,12 +550,18 @@ unsigned char * ecies_decrypt(const ies_ctx_t *ctx, const cryptogram_t *cryptogr
 
 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;
+    }
 }