update crypto helper

Change-Id: Ia9232c352b012c54be86e76e01fe598c8fc1dee0
diff --git a/src/detail/crypto-helpers.cpp b/src/detail/crypto-helpers.cpp
index f2024c1..e719d89 100644
--- a/src/detail/crypto-helpers.cpp
+++ b/src/detail/crypto-helpers.cpp
@@ -94,99 +94,129 @@
 ECDHState::getSelfPubKey()
 {
   auto privECKey = EVP_PKEY_get1_EC_KEY(m_privkey);
-  if (privECKey == nullptr) {
-    NDN_THROW(std::runtime_error("Could not get key when calling EVP_PKEY_get1_EC_KEY()"));
-  }
   auto ecPoint = EC_KEY_get0_public_key(privECKey);
   auto group = EC_KEY_get0_group(privECKey);
   auto requiredBufLen = EC_POINT_point2oct(group, ecPoint, POINT_CONVERSION_UNCOMPRESSED, nullptr, 0, nullptr);
   m_pubKey.resize(requiredBufLen);
-  auto rev = EC_POINT_point2oct(group, ecPoint, POINT_CONVERSION_UNCOMPRESSED,
-                                m_pubKey.data(), requiredBufLen, nullptr);
+  auto resultCode = EC_POINT_point2oct(group, ecPoint, POINT_CONVERSION_UNCOMPRESSED,
+                                       m_pubKey.data(), requiredBufLen, nullptr);
   EC_KEY_free(privECKey);
-  if (rev == 0) {
-    NDN_THROW(std::runtime_error("Could not convert EC_POINTS to octet string when calling EC_POINT_point2oct()"));
+  if (resultCode == 0) {
+    NDN_THROW(std::runtime_error("Error in getting EC Public Key in the format of octet string"));
   }
   return m_pubKey;
 }
 
-const std::vector <uint8_t>&
+const std::vector<uint8_t>&
 ECDHState::deriveSecret(const std::vector <uint8_t>& peerKey)
 {
   // prepare self private key
   auto privECKey = EVP_PKEY_get1_EC_KEY(m_privkey);
-  if (privECKey == nullptr) {
-    NDN_THROW(std::runtime_error("Cannot not get key when calling EVP_PKEY_get1_EC_KEY()"));
-  }
   auto group = EC_KEY_get0_group(privECKey);
   EC_KEY_free(privECKey);
   // prepare the peer public key
   auto peerPoint = EC_POINT_new(group);
-  if (peerPoint == nullptr) {
-    NDN_THROW(std::runtime_error("Cannot create the EC_POINT for peer key when calling EC_POINT_new()"));
-  }
-  if (EC_POINT_oct2point(group, peerPoint, peerKey.data(), peerKey.size(), nullptr) == 0) {
-    EC_POINT_free(peerPoint);
-    NDN_THROW(std::runtime_error("Cannot convert peer's key into a EC point when calling EC_POINT_oct2point()"));
-  }
+  EC_POINT_oct2point(group, peerPoint, peerKey.data(), peerKey.size(), nullptr);
   EC_KEY* ecPeerkey = EC_KEY_new();
-  if (ecPeerkey == nullptr) {
-    EC_POINT_free(peerPoint);
-    NDN_THROW(std::runtime_error("Cannot create EC_KEY for peer key when calling EC_KEY_new()"));
-  }
-  if (EC_KEY_set_group(ecPeerkey, group) != 1) {
-    EC_POINT_free(peerPoint);
-    NDN_THROW(std::runtime_error("Cannot set group for peer key's EC_KEY when calling EC_KEY_set_group()"));
-  }
-  if (EC_KEY_set_public_key(ecPeerkey, peerPoint) == 0) {
-    EC_KEY_free(ecPeerkey);
-    EC_POINT_free(peerPoint);
-    NDN_THROW(
-      std::runtime_error("Cannot initialize peer EC_KEY with the EC_POINT when calling EC_KEY_set_public_key()"));
-  }
+  EC_KEY_set_group(ecPeerkey, group);
+  EC_KEY_set_public_key(ecPeerkey, peerPoint);
   EVP_PKEY* evpPeerkey = EVP_PKEY_new();
-  if (EVP_PKEY_set1_EC_KEY(evpPeerkey, ecPeerkey) == 0) {
-    EC_KEY_free(ecPeerkey);
-    EC_POINT_free(peerPoint);
-    NDN_THROW(std::runtime_error("Cannot create EVP_PKEY for peer key when calling EVP_PKEY_new()"));
-  }
+  EVP_PKEY_set1_EC_KEY(evpPeerkey, ecPeerkey);
   EC_KEY_free(ecPeerkey);
   EC_POINT_free(peerPoint);
   // ECDH context
   EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new(m_privkey, nullptr);
-  if (ctx == nullptr) {
-    EVP_PKEY_free(evpPeerkey);
-    NDN_THROW(std::runtime_error("Cannot create context for ECDH when calling EVP_PKEY_CTX_new()"));
-  }
   // Initialize
-  if (1 != EVP_PKEY_derive_init(ctx)) {
-    EVP_PKEY_CTX_free(ctx);
-    EVP_PKEY_free(evpPeerkey);
-    NDN_THROW(std::runtime_error("Cannot initialize context for ECDH when calling EVP_PKEY_derive_init()"));
-  }
+  EVP_PKEY_derive_init(ctx);
   // Provide the peer public key
-  if (1 != EVP_PKEY_derive_set_peer(ctx, evpPeerkey)) {
-    EVP_PKEY_CTX_free(ctx);
-    EVP_PKEY_free(evpPeerkey);
-    NDN_THROW(std::runtime_error("Cannot set peer key for ECDH when calling EVP_PKEY_derive_set_peer()"));
-  }
+  EVP_PKEY_derive_set_peer(ctx, evpPeerkey);
   // Determine buffer length for shared secret
   size_t secretLen = 0;
-  if (1 != EVP_PKEY_derive(ctx, nullptr, &secretLen)) {
-    EVP_PKEY_CTX_free(ctx);
-    EVP_PKEY_free(evpPeerkey);
-    NDN_THROW(std::runtime_error("Cannot determine the needed buffer length when calling EVP_PKEY_derive()"));
-  }
+  EVP_PKEY_derive(ctx, nullptr, &secretLen);
   m_secret.resize(secretLen);
   // Derive the shared secret
-  if (1 != (EVP_PKEY_derive(ctx, m_secret.data(), &secretLen))) {
-    EVP_PKEY_CTX_free(ctx);
-    EVP_PKEY_free(evpPeerkey);
-    NDN_THROW(std::runtime_error("Cannot derive ECDH secret when calling EVP_PKEY_derive()"));
-  }
+  auto resultCode = EVP_PKEY_derive(ctx, m_secret.data(), &secretLen);
   EVP_PKEY_CTX_free(ctx);
   EVP_PKEY_free(evpPeerkey);
+  if (resultCode == 0) {
+    NDN_THROW(std::runtime_error("Error when calling ECDH"));
+  }
   return m_secret;
+
+//  // prepare self private key
+//  auto privECKey = EVP_PKEY_get1_EC_KEY(m_privkey);
+//  if (privECKey == nullptr) {
+//    NDN_THROW(std::runtime_error("Cannot not get key when calling EVP_PKEY_get1_EC_KEY()"));
+//  }
+//  auto group = EC_KEY_get0_group(privECKey);
+//  EC_KEY_free(privECKey);
+//  // prepare the peer public key
+//  auto peerPoint = EC_POINT_new(group);
+//  if (peerPoint == nullptr) {
+//    NDN_THROW(std::runtime_error("Cannot create the EC_POINT for peer key when calling EC_POINT_new()"));
+//  }
+//  if (EC_POINT_oct2point(group, peerPoint, peerKey.data(), peerKey.size(), nullptr) == 0) {
+//    EC_POINT_free(peerPoint);
+//    NDN_THROW(std::runtime_error("Cannot convert peer's key into a EC point when calling EC_POINT_oct2point()"));
+//  }
+//  EC_KEY* ecPeerkey = EC_KEY_new();
+//  if (ecPeerkey == nullptr) {
+//    EC_POINT_free(peerPoint);
+//    NDN_THROW(std::runtime_error("Cannot create EC_KEY for peer key when calling EC_KEY_new()"));
+//  }
+//  if (EC_KEY_set_group(ecPeerkey, group) != 1) {
+//    EC_POINT_free(peerPoint);
+//    NDN_THROW(std::runtime_error("Cannot set group for peer key's EC_KEY when calling EC_KEY_set_group()"));
+//  }
+//  if (EC_KEY_set_public_key(ecPeerkey, peerPoint) == 0) {
+//    EC_KEY_free(ecPeerkey);
+//    EC_POINT_free(peerPoint);
+//    NDN_THROW(
+//      std::runtime_error("Cannot initialize peer EC_KEY with the EC_POINT when calling EC_KEY_set_public_key()"));
+//  }
+//  EVP_PKEY* evpPeerkey = EVP_PKEY_new();
+//  if (EVP_PKEY_set1_EC_KEY(evpPeerkey, ecPeerkey) == 0) {
+//    EC_KEY_free(ecPeerkey);
+//    EC_POINT_free(peerPoint);
+//    NDN_THROW(std::runtime_error("Cannot create EVP_PKEY for peer key when calling EVP_PKEY_new()"));
+//  }
+//  EC_KEY_free(ecPeerkey);
+//  EC_POINT_free(peerPoint);
+//  // ECDH context
+//  EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new(m_privkey, nullptr);
+//  if (ctx == nullptr) {
+//    EVP_PKEY_free(evpPeerkey);
+//    NDN_THROW(std::runtime_error("Cannot create context for ECDH when calling EVP_PKEY_CTX_new()"));
+//  }
+//  // Initialize
+//  if (1 != EVP_PKEY_derive_init(ctx)) {
+//    EVP_PKEY_CTX_free(ctx);
+//    EVP_PKEY_free(evpPeerkey);
+//    NDN_THROW(std::runtime_error("Cannot initialize context for ECDH when calling EVP_PKEY_derive_init()"));
+//  }
+//  // Provide the peer public key
+//  if (1 != EVP_PKEY_derive_set_peer(ctx, evpPeerkey)) {
+//    EVP_PKEY_CTX_free(ctx);
+//    EVP_PKEY_free(evpPeerkey);
+//    NDN_THROW(std::runtime_error("Cannot set peer key for ECDH when calling EVP_PKEY_derive_set_peer()"));
+//  }
+//  // Determine buffer length for shared secret
+//  size_t secretLen = 0;
+//  if (1 != EVP_PKEY_derive(ctx, nullptr, &secretLen)) {
+//    EVP_PKEY_CTX_free(ctx);
+//    EVP_PKEY_free(evpPeerkey);
+//    NDN_THROW(std::runtime_error("Cannot determine the needed buffer length when calling EVP_PKEY_derive()"));
+//  }
+//  m_secret.resize(secretLen);
+//  // Derive the shared secret
+//  if (1 != (EVP_PKEY_derive(ctx, m_secret.data(), &secretLen))) {
+//    EVP_PKEY_CTX_free(ctx);
+//    EVP_PKEY_free(evpPeerkey);
+//    NDN_THROW(std::runtime_error("Cannot derive ECDH secret when calling EVP_PKEY_derive()"));
+//  }
+//  EVP_PKEY_CTX_free(ctx);
+//  EVP_PKEY_free(evpPeerkey);
+//  return m_secret;
 }
 
 void
@@ -194,8 +224,7 @@
            const uint8_t* key, size_t keyLen,
            uint8_t* result)
 {
-  auto ret = HMAC(EVP_sha256(), key, keyLen,
-                  data, dataLen, result, nullptr);
+  auto ret = HMAC(EVP_sha256(), key, keyLen, data, dataLen, result, nullptr);
   if (ret == nullptr) {
     NDN_THROW(std::runtime_error("Error computing HMAC when calling HMAC()"));
   }
@@ -207,123 +236,152 @@
      const uint8_t* info, size_t infoLen)
 {
   EVP_PKEY_CTX* pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, nullptr);
-  if (EVP_PKEY_derive_init(pctx) <= 0) {
-    EVP_PKEY_CTX_free(pctx);
-    NDN_THROW(std::runtime_error("HKDF: Cannot init ctx when calling EVP_PKEY_derive_init()"));
-  }
-  if (EVP_PKEY_CTX_set_hkdf_md(pctx, EVP_sha256()) <= 0) {
-    EVP_PKEY_CTX_free(pctx);
-    NDN_THROW(std::runtime_error("HKDF: Cannot set md when calling EVP_PKEY_CTX_set_hkdf_md()"));
-  }
-  if (EVP_PKEY_CTX_set1_hkdf_salt(pctx, salt, saltLen) <= 0) {
-    EVP_PKEY_CTX_free(pctx);
-    NDN_THROW(std::runtime_error("HKDF: Cannot set salt when calling EVP_PKEY_CTX_set1_hkdf_salt()"));
-  }
-  if (EVP_PKEY_CTX_set1_hkdf_key(pctx, secret, secretLen) <= 0) {
-    EVP_PKEY_CTX_free(pctx);
-    NDN_THROW(std::runtime_error("HKDF: Cannot set secret when calling EVP_PKEY_CTX_set1_hkdf_key()"));
-  }
-  if (EVP_PKEY_CTX_add1_hkdf_info(pctx, info, infoLen) <= 0) {
-    EVP_PKEY_CTX_free(pctx);
-    NDN_THROW(std::runtime_error("HKDF: Cannot set info when calling EVP_PKEY_CTX_add1_hkdf_info()"));
-  }
+  EVP_PKEY_derive_init(pctx);
+  EVP_PKEY_CTX_set_hkdf_md(pctx, EVP_sha256());
+  EVP_PKEY_CTX_set1_hkdf_salt(pctx, salt, saltLen);
+  EVP_PKEY_CTX_set1_hkdf_key(pctx, secret, secretLen);
+  EVP_PKEY_CTX_add1_hkdf_info(pctx, info, infoLen);
   size_t outLen = outputLen;
-  if (EVP_PKEY_derive(pctx, output, &outLen) <= 0) {
-    EVP_PKEY_CTX_free(pctx);
-    NDN_THROW(std::runtime_error("HKDF: Cannot derive result when calling EVP_PKEY_derive()"));
-  }
+  auto resultCode = EVP_PKEY_derive(pctx, output, &outLen);
   EVP_PKEY_CTX_free(pctx);
+  if (resultCode == 0) {
+    NDN_THROW(std::runtime_error("Error when calling HKDF"));
+  }
   return outLen;
+
+//  if (EVP_PKEY_derive_init(pctx) <= 0) {
+//    EVP_PKEY_CTX_free(pctx);
+//    NDN_THROW(std::runtime_error("HKDF: Cannot init ctx when calling EVP_PKEY_derive_init()"));
+//  }
+//  if (EVP_PKEY_CTX_set_hkdf_md(pctx, EVP_sha256()) <= 0) {
+//    EVP_PKEY_CTX_free(pctx);
+//    NDN_THROW(std::runtime_error("HKDF: Cannot set md when calling EVP_PKEY_CTX_set_hkdf_md()"));
+//  }
+//  if (EVP_PKEY_CTX_set1_hkdf_salt(pctx, salt, saltLen) <= 0) {
+//    EVP_PKEY_CTX_free(pctx);
+//    NDN_THROW(std::runtime_error("HKDF: Cannot set salt when calling EVP_PKEY_CTX_set1_hkdf_salt()"));
+//  }
+//  if (EVP_PKEY_CTX_set1_hkdf_key(pctx, secret, secretLen) <= 0) {
+//    EVP_PKEY_CTX_free(pctx);
+//    NDN_THROW(std::runtime_error("HKDF: Cannot set secret when calling EVP_PKEY_CTX_set1_hkdf_key()"));
+//  }
+//  if (EVP_PKEY_CTX_add1_hkdf_info(pctx, info, infoLen) <= 0) {
+//    EVP_PKEY_CTX_free(pctx);
+//    NDN_THROW(std::runtime_error("HKDF: Cannot set info when calling EVP_PKEY_CTX_add1_hkdf_info()"));
+//  }
+//  size_t outLen = outputLen;
+//  if (EVP_PKEY_derive(pctx, output, &outLen) <= 0) {
+//    EVP_PKEY_CTX_free(pctx);
+//    NDN_THROW(std::runtime_error("HKDF: Cannot derive result when calling EVP_PKEY_derive()"));
+//  }
 }
 
 size_t
 aesGcm128Encrypt(const uint8_t* plaintext, size_t plaintextLen, const uint8_t* associated, size_t associatedLen,
                  const uint8_t* key, const uint8_t* iv, uint8_t* ciphertext, uint8_t* tag)
 {
-  EVP_CIPHER_CTX* ctx;
-  int len;
-  size_t ciphertextLen;
-  if (!(ctx = EVP_CIPHER_CTX_new())) {
-    NDN_THROW(std::runtime_error("Cannot create and initialise the context when calling EVP_CIPHER_CTX_new()"));
-  }
-  if (1 != EVP_EncryptInit_ex(ctx, EVP_aes_128_gcm(), nullptr, nullptr, nullptr)) {
-    EVP_CIPHER_CTX_free(ctx);
-    NDN_THROW(std::runtime_error("Cannot initialize the encryption operation when calling EVP_EncryptInit_ex()"));
-  }
-  if (1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 12, nullptr)) {
-    EVP_CIPHER_CTX_free(ctx);
-    NDN_THROW(std::runtime_error("Cannot set IV length when calling EVP_CIPHER_CTX_ctrl()"));
-  }
-  if (1 != EVP_EncryptInit_ex(ctx, nullptr, nullptr, key, iv)) {
-    EVP_CIPHER_CTX_free(ctx);
-    NDN_THROW(std::runtime_error("Cannot initialize key and IV when calling EVP_EncryptInit_ex()"));
-  }
-  if (1 != EVP_EncryptUpdate(ctx, nullptr, &len, associated, associatedLen)) {
-    EVP_CIPHER_CTX_free(ctx);
-    NDN_THROW(std::runtime_error("Cannot set associated authentication data when calling EVP_EncryptUpdate()"));
-  }
-  if (1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintextLen)) {
-    EVP_CIPHER_CTX_free(ctx);
-    NDN_THROW(std::runtime_error("Cannot encrypt when calling EVP_EncryptUpdate()"));
-  }
+  int len = 0;
+  size_t ciphertextLen = 0;
+  EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
+  EVP_EncryptInit_ex(ctx, EVP_aes_128_gcm(), nullptr, nullptr, nullptr);
+  EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 12, nullptr);
+  EVP_EncryptInit_ex(ctx, nullptr, nullptr, key, iv);
+  EVP_EncryptUpdate(ctx, nullptr, &len, associated, associatedLen);
+  EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintextLen);
   ciphertextLen = len;
-  if (1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) {
-    EVP_CIPHER_CTX_free(ctx);
-    NDN_THROW(std::runtime_error("Cannot finalise the encryption when calling EVP_EncryptFinal_ex()"));
-  }
-  ciphertextLen += len;
-  if (1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag)) {
-    EVP_CIPHER_CTX_free(ctx);
-    NDN_THROW(std::runtime_error("Cannot get tag when calling EVP_CIPHER_CTX_ctrl()"));
-  }
+  EVP_EncryptFinal_ex(ctx, ciphertext + len, &len);
+  auto resultCode = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag);
   EVP_CIPHER_CTX_free(ctx);
+  if (resultCode == 0) {
+    NDN_THROW(std::runtime_error("Error in encryption plaintext with AES GCM"));
+  }
   return ciphertextLen;
+
+//  if (!(ctx = EVP_CIPHER_CTX_new())) {
+//    NDN_THROW(std::runtime_error("Cannot create and initialise the context when calling EVP_CIPHER_CTX_new()"));
+//  }
+//  if (1 != EVP_EncryptInit_ex(ctx, EVP_aes_128_gcm(), nullptr, nullptr, nullptr)) {
+//    EVP_CIPHER_CTX_free(ctx);
+//    NDN_THROW(std::runtime_error("Cannot initialize the encryption operation when calling EVP_EncryptInit_ex()"));
+//  }
+//  if (1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 12, nullptr)) {
+//    EVP_CIPHER_CTX_free(ctx);
+//    NDN_THROW(std::runtime_error("Cannot set IV length when calling EVP_CIPHER_CTX_ctrl()"));
+//  }
+//  if (1 != EVP_EncryptInit_ex(ctx, nullptr, nullptr, key, iv)) {
+//    EVP_CIPHER_CTX_free(ctx);
+//    NDN_THROW(std::runtime_error("Cannot initialize key and IV when calling EVP_EncryptInit_ex()"));
+//  }
+//  if (1 != EVP_EncryptUpdate(ctx, nullptr, &len, associated, associatedLen)) {
+//    EVP_CIPHER_CTX_free(ctx);
+//    NDN_THROW(std::runtime_error("Cannot set associated authentication data when calling EVP_EncryptUpdate()"));
+//  }
+//  if (1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintextLen)) {
+//    EVP_CIPHER_CTX_free(ctx);
+//    NDN_THROW(std::runtime_error("Cannot encrypt when calling EVP_EncryptUpdate()"));
+//  }
+//  ciphertextLen = len;
+//  if (1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) {
+//    EVP_CIPHER_CTX_free(ctx);
+//    NDN_THROW(std::runtime_error("Cannot finalise the encryption when calling EVP_EncryptFinal_ex()"));
+//  }
+//  ciphertextLen += len;
+//  if (1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag)) {
+//    EVP_CIPHER_CTX_free(ctx);
+//    NDN_THROW(std::runtime_error("Cannot get tag when calling EVP_CIPHER_CTX_ctrl()"));
+//  }
 }
 
 size_t
 aesGcm128Decrypt(const uint8_t* ciphertext, size_t ciphertextLen, const uint8_t* associated, size_t associatedLen,
                  const uint8_t* tag, const uint8_t* key, const uint8_t* iv, uint8_t* plaintext)
 {
-  EVP_CIPHER_CTX* ctx;
-  int len;
-  size_t plaintextLen;
-  if (!(ctx = EVP_CIPHER_CTX_new())) {
-    NDN_THROW(std::runtime_error("Cannot create and initialise the context when calling EVP_CIPHER_CTX_new()"));
-  }
-  if (!EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), nullptr, nullptr, nullptr)) {
-    EVP_CIPHER_CTX_free(ctx);
-    NDN_THROW(std::runtime_error("Cannot initialise the decryption operation when calling EVP_DecryptInit_ex()"));
-  }
-  if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 12, nullptr)) {
-    EVP_CIPHER_CTX_free(ctx);
-    NDN_THROW(std::runtime_error("Cannot set IV length when calling EVP_CIPHER_CTX_ctrl"));
-  }
-  if (!EVP_DecryptInit_ex(ctx, nullptr, nullptr, key, iv)) {
-    EVP_CIPHER_CTX_free(ctx);
-    NDN_THROW(std::runtime_error("Cannot initialise key and IV when calling EVP_DecryptInit_ex()"));
-  }
-  if (!EVP_DecryptUpdate(ctx, nullptr, &len, associated, associatedLen)) {
-    EVP_CIPHER_CTX_free(ctx);
-    NDN_THROW(std::runtime_error("Cannot set associated authentication data when calling EVP_EncryptUpdate()"));
-  }
-  if (!EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertextLen)) {
-    EVP_CIPHER_CTX_free(ctx);
-    NDN_THROW(std::runtime_error("Cannot decrypt when calling EVP_DecryptUpdate()"));
-  }
+  int len = 0;
+  size_t plaintextLen = 0;
+  EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
+  EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), nullptr, nullptr, nullptr);
+  EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 12, nullptr);
+  EVP_DecryptInit_ex(ctx, nullptr, nullptr, key, iv);
+  EVP_DecryptUpdate(ctx, nullptr, &len, associated, associatedLen);
+  EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertextLen);
   plaintextLen = len;
-  if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, const_cast<void*>(reinterpret_cast<const void*>(tag)))) {
-    EVP_CIPHER_CTX_free(ctx);
-    NDN_THROW(std::runtime_error("Cannot set tag value when calling EVP_CIPHER_CTX_ctrl()"));
-  }
-  auto ret = EVP_DecryptFinal_ex(ctx, plaintext + len, &len);
+  EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, const_cast<void*>(reinterpret_cast<const void*>(tag)));
+  auto resultCode = EVP_DecryptFinal_ex(ctx, plaintext + len, &len);
+  plaintextLen += len;
   EVP_CIPHER_CTX_free(ctx);
-  if (ret > 0) {
-    plaintextLen += len;
-    return plaintextLen;
+  if (resultCode == 0) {
+    NDN_THROW(std::runtime_error("Error in decrypting ciphertext with AES GCM"));
   }
-  else {
-    NDN_THROW(std::runtime_error("Cannot finalize the decryption when calling EVP_DecryptFinal_ex()"));
-  }
+  return plaintextLen;
+
+//  if (!(ctx = EVP_CIPHER_CTX_new())) {
+//    NDN_THROW(std::runtime_error("Cannot create and initialise the context when calling EVP_CIPHER_CTX_new()"));
+//  }
+//  if (!EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), nullptr, nullptr, nullptr)) {
+//    EVP_CIPHER_CTX_free(ctx);
+//    NDN_THROW(std::runtime_error("Cannot initialise the decryption operation when calling EVP_DecryptInit_ex()"));
+//  }
+//  if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 12, nullptr)) {
+//    EVP_CIPHER_CTX_free(ctx);
+//    NDN_THROW(std::runtime_error("Cannot set IV length when calling EVP_CIPHER_CTX_ctrl"));
+//  }
+//  if (!EVP_DecryptInit_ex(ctx, nullptr, nullptr, key, iv)) {
+//    EVP_CIPHER_CTX_free(ctx);
+//    NDN_THROW(std::runtime_error("Cannot initialise key and IV when calling EVP_DecryptInit_ex()"));
+//  }
+//  if (!EVP_DecryptUpdate(ctx, nullptr, &len, associated, associatedLen)) {
+//    EVP_CIPHER_CTX_free(ctx);
+//    NDN_THROW(std::runtime_error("Cannot set associated authentication data when calling EVP_EncryptUpdate()"));
+//  }
+//  if (!EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertextLen)) {
+//    EVP_CIPHER_CTX_free(ctx);
+//    NDN_THROW(std::runtime_error("Cannot decrypt when calling EVP_DecryptUpdate()"));
+//  }
+//  plaintextLen = len;
+//  if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, const_cast<void*>(reinterpret_cast<const void*>(tag)))) {
+//    EVP_CIPHER_CTX_free(ctx);
+//    NDN_THROW(std::runtime_error("Cannot set tag value when calling EVP_CIPHER_CTX_ctrl()"));
+//  }
 }
 
 // Can be removed after boost version 1.72, replaced by boost::endian::load_big_u32
@@ -389,7 +447,7 @@
 Buffer
 decodeBlockWithAesGcm128(const Block& block, const uint8_t* key,
                          const uint8_t* associatedData, size_t associatedDataSize,
-                         std::vector<uint8_t>& decryptionIv, const std::vector <uint8_t>& encryptionIv)
+                         std::vector <uint8_t>& decryptionIv, const std::vector <uint8_t>& encryptionIv)
 {
   // The spec of AES encrypted payload TLV used in NDNCERT:
   //   https://github.com/named-data/ndncert/wiki/NDNCERT-Protocol-0.3#242-aes-gcm-encryption