refactor the HKDF State class

Change-Id: I819c9a8dcb7b3b13c1a63269a18ceadfa2b80c50
diff --git a/src/ca-module.cpp b/src/ca-module.cpp
index 807baf8..f332183 100644
--- a/src/ca-module.cpp
+++ b/src/ca-module.cpp
@@ -190,7 +190,7 @@
   // REVOKE Naming Convention: /<CA-prefix>/CA/REVOKE/[SignedInterestParameters_Digest]
   // get ECDH pub key and cert request
   const auto& parameterTLV = request.getApplicationParameters();
-  std::string ecdhPub;
+  std::vector<uint8_t> ecdhPub;
   shared_ptr<security::Certificate> clientCert;
   try {
     NewRenewRevokeEncoder::decodeApplicationParameters(parameterTLV, requestType, ecdhPub, clientCert);
@@ -209,7 +209,7 @@
     return;
   }
 
-  if (ecdhPub == "") {
+  if (ecdhPub.empty()) {
     NDN_LOG_ERROR("Empty ECDH PUB obtained from the Interest parameter.");
     m_face.put(generateErrorDataPacket(request.getName(), ErrorCode::INVALID_PARAMETER,
                                        "Empty ECDH PUB obtained from the Interest parameter."));
@@ -218,9 +218,10 @@
 
   // get server's ECDH pub key
   ECDHState ecdh;
-  auto myEcdhPubKeyBase64 = ecdh.getBase64PubKey();
+  auto myEcdhPubKeyBase64 = ecdh.getSelfPubKey();
+  std::vector<uint8_t> sharedSecret;
   try {
-    ecdh.deriveSecret(ecdhPub);
+    sharedSecret = ecdh.deriveSecret(ecdhPub);
   }
   catch (const std::exception& e) {
     NDN_LOG_ERROR("Cannot derive a shared secret using the provided ECDH key: " << e.what());
@@ -233,7 +234,7 @@
   random::generateSecureBytes(salt.data(), salt.size());
   // hkdf
   uint8_t aesKey[AES_128_KEY_LEN];
-  hkdf(ecdh.m_sharedSecret, ecdh.m_sharedSecretLen, salt.data(), salt.size(), aesKey, sizeof(aesKey));
+  hkdf(sharedSecret.data(), sharedSecret.size(), salt.data(), salt.size(), aesKey, sizeof(aesKey));
 
   // verify identity name
   if (!m_config.m_caItem.m_caPrefix.isPrefixOf(clientCert->getIdentity())
diff --git a/src/detail/crypto-helpers.cpp b/src/detail/crypto-helpers.cpp
index d69c2dd..63a9877 100644
--- a/src/detail/crypto-helpers.cpp
+++ b/src/detail/crypto-helpers.cpp
@@ -30,7 +30,6 @@
 #include <ndn-cxx/util/random.hpp>
 #include <openssl/ec.h>
 #include <openssl/err.h>
-#include <openssl/evp.h>
 #include <openssl/hmac.h>
 #include <openssl/kdf.h>
 #include <openssl/pem.h>
@@ -38,143 +37,183 @@
 namespace ndn {
 namespace ndncert {
 
-struct ECDHState::ECDH_CTX
-{
-  ~ECDH_CTX()
-  {
-    // contexts
-    if (ctx_params != nullptr) {
-      EVP_PKEY_CTX_free(ctx_params);
-    }
-    if (ctx_keygen != nullptr) {
-      EVP_PKEY_CTX_free(ctx_keygen);
-    }
-    // Keys
-    if (privkey != nullptr) {
-      EVP_PKEY_free(privkey);
-    }
-    if (peerkey != nullptr) {
-      EVP_PKEY_free(peerkey);
-    }
-    if (params != nullptr) {
-      EVP_PKEY_free(params);
-    }
-  }
-  EVP_PKEY_CTX* ctx_params = nullptr;
-  EVP_PKEY_CTX* ctx_keygen = nullptr;
-  EVP_PKEY* privkey = nullptr;
-  EVP_PKEY* peerkey = nullptr;
-  EVP_PKEY* params = nullptr;
-};
-
 ECDHState::ECDHState()
 {
-  m_context = std::make_unique<ECDH_CTX>();
   auto EC_NID = NID_X9_62_prime256v1;
-
-  if (nullptr == (m_context->ctx_params = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, nullptr))) {
+  // params context
+  EVP_PKEY_CTX* ctx_params = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, nullptr);
+  if (ctx_params == nullptr) {
     NDN_THROW(std::runtime_error("Could not create context."));
   }
-  if (EVP_PKEY_paramgen_init(m_context->ctx_params) != 1) {
-    m_context.reset();
+  if (EVP_PKEY_paramgen_init(ctx_params) != 1) {
+    EVP_PKEY_CTX_free(ctx_params);
     NDN_THROW(std::runtime_error("Could not initialize parameter generation."));
   }
-  if (1 != EVP_PKEY_CTX_set_ec_paramgen_curve_nid(m_context->ctx_params, EC_NID)) {
-    m_context.reset();
+  if (1 != EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx_params, EC_NID)) {
+    EVP_PKEY_CTX_free(ctx_params);
     NDN_THROW(std::runtime_error("Likely unknown elliptical curve ID specified."));
   }
-  if (!EVP_PKEY_paramgen(m_context->ctx_params, &m_context->params)) {
-    m_context.reset();
+  // generate params
+  EVP_PKEY* params = nullptr;
+  if (!EVP_PKEY_paramgen(ctx_params, &params)) {
+    EVP_PKEY_CTX_free(ctx_params);
     NDN_THROW(std::runtime_error("Could not create parameter object parameters."));
   }
-  if (nullptr == (m_context->ctx_keygen = EVP_PKEY_CTX_new(m_context->params, nullptr))) {
-    m_context.reset();
+  // key generation context
+  EVP_PKEY_CTX *ctx_keygen = EVP_PKEY_CTX_new(params, nullptr);
+  if (ctx_keygen == nullptr) {
+    EVP_PKEY_free(params);
+    EVP_PKEY_CTX_free(ctx_params);
     NDN_THROW(std::runtime_error("Could not create the context for the key generation"));
   }
-  if (1 != EVP_PKEY_keygen_init(m_context->ctx_keygen)) {
-    m_context.reset();
+  if (1 != EVP_PKEY_keygen_init(ctx_keygen)) {
+    EVP_PKEY_CTX_free(ctx_keygen);
+    EVP_PKEY_free(params);
+    EVP_PKEY_CTX_free(ctx_params);
     NDN_THROW(std::runtime_error("Could not init context for key generation."));
   }
-  if (1 != EVP_PKEY_keygen(m_context->ctx_keygen, &m_context->privkey)) {
-    m_context.reset();
+  if (1 != EVP_PKEY_keygen(ctx_keygen, &m_privkey)) {
+    EVP_PKEY_CTX_free(ctx_keygen);
+    EVP_PKEY_free(params);
+    EVP_PKEY_CTX_free(ctx_params);
     NDN_THROW(std::runtime_error("Could not generate DHE keys in final step"));
   }
+  EVP_PKEY_CTX_free(ctx_keygen);
+  EVP_PKEY_free(params);
+  EVP_PKEY_CTX_free(ctx_params);
 }
 
 ECDHState::~ECDHState()
-{}
-
-uint8_t*
-ECDHState::getRawSelfPubKey()
 {
-  auto privECKey = EVP_PKEY_get1_EC_KEY(m_context->privkey);
+  if (m_privkey != nullptr) {
+    EVP_PKEY_free(m_privkey);
+  }
+}
+
+const std::vector<uint8_t>&
+ECDHState::getSelfPubKey()
+{
+  auto privECKey = EVP_PKEY_get1_EC_KEY(m_privkey);
   if (privECKey == nullptr) {
-    m_context.reset();
     NDN_THROW(std::runtime_error("Could not get key when calling EVP_PKEY_get1_EC_KEY()."));
   }
   auto ecPoint = EC_KEY_get0_public_key(privECKey);
-  const EC_GROUP* group = EC_KEY_get0_group(privECKey);
-  m_publicKeyLen = EC_POINT_point2oct(group, ecPoint, POINT_CONVERSION_COMPRESSED,
-                                      m_publicKey, sizeof(m_publicKey), nullptr);
+  auto group = EC_KEY_get0_group(privECKey);
+  auto requiredBufLen = EC_POINT_point2oct(group, ecPoint, POINT_CONVERSION_COMPRESSED, nullptr, 0, nullptr);
+  m_pubKey.resize(requiredBufLen);
+  auto rev = EC_POINT_point2oct(group, ecPoint, POINT_CONVERSION_COMPRESSED,
+                                m_pubKey.data(), requiredBufLen, nullptr);
   EC_KEY_free(privECKey);
-  if (m_publicKeyLen == 0) {
-    m_context.reset();
+  if (rev == 0) {
     NDN_THROW(std::runtime_error("Could not convert EC_POINTS to octet string when calling EC_POINT_point2oct."));
   }
-  return m_publicKey;
+  return m_pubKey;
 }
 
-std::string
-ECDHState::getBase64PubKey()
+const std::vector<uint8_t>&
+ECDHState::deriveSecret(const std::vector<uint8_t>& peerKey)
 {
-  if (m_publicKeyLen == 0) {
-    this->getRawSelfPubKey();
-  }
-  std::ostringstream os;
-  namespace t = ndn::security::transform;
-  t::bufferSource(m_publicKey, m_publicKeyLen) >> t::base64Encode(false) >> t::streamSink(os);
-  return os.str();
+  return deriveSecret(peerKey.data(), peerKey.size());
 }
 
-uint8_t*
-ECDHState::deriveSecret(const uint8_t* peerkey, size_t peerKeySize)
+const std::vector<uint8_t>&
+ECDHState::deriveSecret(const uint8_t* peerKey, size_t peerKeySize)
 {
-  auto privECKey = EVP_PKEY_get1_EC_KEY(m_context->privkey);
+  // prepare self private key
+  auto privECKey = EVP_PKEY_get1_EC_KEY(m_privkey);
   if (privECKey == nullptr) {
-    m_context.reset();
     NDN_THROW(std::runtime_error("Could 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);
-  int result = EC_POINT_oct2point(group, peerPoint, peerkey, peerKeySize, nullptr);
-  if (result == 0) {
+  if (peerPoint == nullptr) {
+    NDN_THROW(std::runtime_error("TBD"));
+  }
+  if (EC_POINT_oct2point(group, peerPoint, peerKey, peerKeySize, nullptr) == 0) {
     EC_POINT_free(peerPoint);
-    EC_KEY_free(privECKey);
-    m_context.reset();
     NDN_THROW(std::runtime_error("Cannot convert peer's key into a EC point when calling EC_POINT_oct2point()"));
   }
-  result = ECDH_compute_key(m_sharedSecret, sizeof(m_sharedSecret), peerPoint, privECKey, nullptr);
-  if (result == -1) {
+  EC_KEY *ecPeerkey = EC_KEY_new();
+  if (ecPeerkey == nullptr) {
     EC_POINT_free(peerPoint);
-    EC_KEY_free(privECKey);
-    m_context.reset();
-    NDN_THROW(std::runtime_error("Cannot generate ECDH secret when calling ECDH_compute_key()"));
+    NDN_THROW(std::runtime_error("TBD"));
   }
-  m_sharedSecretLen = static_cast<size_t>(result);
+  if (EC_KEY_set_group(ecPeerkey, group) != 1) {
+    EC_POINT_free(peerPoint);
+    NDN_THROW(std::runtime_error("TBD"));
+  }
+  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."));
+  }
+  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("TBD."));
+  }
+  EC_KEY_free(ecPeerkey);
   EC_POINT_free(peerPoint);
-  EC_KEY_free(privECKey);
-  return m_sharedSecret;
+  // ECDH context
+  EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new(m_privkey, NULL);
+  if (ctx == nullptr) {
+    EVP_PKEY_free(evpPeerkey);
+    NDN_THROW(std::runtime_error("TBD"));
+  }
+	/* Initialise */
+	if(1 != EVP_PKEY_derive_init(ctx)) {
+    EVP_PKEY_CTX_free(ctx);
+    EVP_PKEY_free(evpPeerkey);
+    NDN_THROW(std::runtime_error("TBD"));
+  }
+	/* 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("TBD"));
+  }
+	/* Determine buffer length for shared secret */
+  size_t secretLen = 0;
+	if(1 != EVP_PKEY_derive(ctx, NULL, &secretLen)) {
+    EVP_PKEY_CTX_free(ctx);
+    EVP_PKEY_free(evpPeerkey);
+    NDN_THROW(std::runtime_error("TBD"));
+  }
+	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("TBD"));
+  }
+  // result = ECDH_compute_key(m_sharedSecret, sizeof(m_sharedSecret), peerPoint, privECKey, nullptr);
+  // if (result == -1) {
+  //   EC_POINT_free(peerPoint);
+  //   EC_KEY_free(privECKey);
+  //   EVP_PKEY_free(m_privkey);
+  //   NDN_THROW(std::runtime_error("Cannot generate ECDH secret when calling ECDH_compute_key()"));
+  // }
+  // m_sharedSecretLen = static_cast<size_t>(result);
+  // EC_POINT_free(peerPoint);
+  // EC_KEY_free(privECKey);
+  // return m_sharedSecret;
+  EVP_PKEY_CTX_free(ctx);
+  EVP_PKEY_free(evpPeerkey);
+  return m_secret;
 }
 
-uint8_t*
-ECDHState::deriveSecret(const std::string& peerKeyStr)
-{
-  namespace t = ndn::security::transform;
-  OBufferStream os;
-  t::bufferSource(peerKeyStr) >> t::base64Decode(false) >> t::streamSink(os);
-  auto result = os.buf();
-  return this->deriveSecret(result->data(), result->size());
-}
+// uint8_t*
+// ECDHState::deriveSecret(const std::string& peerKeyStr)
+// {
+//   namespace t = ndn::security::transform;
+//   OBufferStream os;
+//   t::bufferSource(peerKeyStr) >> t::base64Decode(false) >> t::streamSink(os);
+//   auto result = os.buf();
+//   return this->deriveSecret(result->data(), result->size());
+// }
 
 void
 hmacSha256(const uint8_t* data, size_t dataLen,
diff --git a/src/detail/crypto-helpers.hpp b/src/detail/crypto-helpers.hpp
index db7c061..d3b0e18 100644
--- a/src/detail/crypto-helpers.hpp
+++ b/src/detail/crypto-helpers.hpp
@@ -22,6 +22,7 @@
 #define NDNCERT_DETAIL_CRYPTO_HELPER_HPP
 
 #include "ndncert-common.hpp"
+#include <openssl/evp.h>
 
 namespace ndn {
 namespace ndncert {
@@ -31,34 +32,31 @@
  *
  * The ECDH is based on prime256v1.
  */
-class ECDHState
+class ECDHState : noncopyable
 {
 public:
   ECDHState();
   ~ECDHState();
 
-  std::string
-  getBase64PubKey();
+  // std::string
+  // getBase64PubKey();
 
-  uint8_t*
-  deriveSecret(const std::string& peerKeyStr);
+  // uint8_t*
+  // deriveSecret(const std::string& peerKeyStr);
 
-NDNCERT_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
-  uint8_t*
+  const std::vector<uint8_t>&
   deriveSecret(const uint8_t* peerkey, size_t peerKeySize);
 
-  uint8_t*
-  getRawSelfPubKey();
+  const std::vector<uint8_t>&
+  deriveSecret(const std::vector<uint8_t>& peerkey);
 
-public:
-  uint8_t m_publicKey[256];
-  size_t m_publicKeyLen = 0;
-  uint8_t m_sharedSecret[256];
-  size_t m_sharedSecretLen = 0;
+  const std::vector<uint8_t>&
+  getSelfPubKey();
 
 private:
-  struct ECDH_CTX;
-  unique_ptr<ECDH_CTX> m_context;
+  EVP_PKEY* m_privkey = nullptr;
+  std::vector<uint8_t> m_pubKey;
+  std::vector<uint8_t> m_secret;
 };
 
 /**
diff --git a/src/detail/new-renew-revoke-encoder.cpp b/src/detail/new-renew-revoke-encoder.cpp
index 77717bd..27c630e 100644
--- a/src/detail/new-renew-revoke-encoder.cpp
+++ b/src/detail/new-renew-revoke-encoder.cpp
@@ -29,7 +29,8 @@
 NDN_LOG_INIT(ndncert.encoding.new_renew_revoke);
 
 Block
-NewRenewRevokeEncoder::encodeApplicationParameters(RequestType requestType, const std::string& ecdhPub, const security::Certificate& certRequest)
+NewRenewRevokeEncoder::encodeApplicationParameters(RequestType requestType, const std::vector<uint8_t>& ecdhPub,
+                                                   const security::Certificate& certRequest)
 {
   Block request = makeEmptyBlock(ndn::tlv::ApplicationParameters);
   std::stringstream ss;
@@ -43,7 +44,7 @@
     return request;
   }
 
-  request.push_back(makeStringBlock(tlv::EcdhPub, ecdhPub));
+  request.push_back(makeBinaryBlock(tlv::EcdhPub, ecdhPub.data(), ecdhPub.size()));
   if (requestType == RequestType::NEW || requestType == RequestType::RENEW) {
     request.push_back(makeNestedBlock(tlv::CertRequest, certRequest));
   } else if (requestType == RequestType::REVOKE) {
@@ -54,12 +55,16 @@
 }
 
 void
-NewRenewRevokeEncoder::decodeApplicationParameters(const Block& payload, RequestType requestType, std::string& ecdhPub,
+NewRenewRevokeEncoder::decodeApplicationParameters(const Block& payload, RequestType requestType,
+                                                   std::vector<uint8_t>& ecdhPub,
                                                    shared_ptr<security::Certificate>& clientCert)
 {
   payload.parse();
 
-  ecdhPub = readString(payload.get(tlv::EcdhPub));
+  const auto& ecdhBlock = payload.get(tlv::EcdhPub);
+  ecdhPub.resize(ecdhBlock.value_size());
+  std::memcpy(ecdhPub.data(), ecdhBlock.value(), ecdhBlock.value_size());
+
   Block requestPayload;
   if (requestType == RequestType::NEW) {
     requestPayload = payload.get(tlv::CertRequest);
@@ -74,12 +79,12 @@
 }
 
 Block
-NewRenewRevokeEncoder::encodeDataContent(const std::string& ecdhKey, const std::array<uint8_t, 32>& salt,
+NewRenewRevokeEncoder::encodeDataContent(const std::vector<uint8_t>& ecdhKey, const std::array<uint8_t, 32>& salt,
                                          const CaState& request,
                                          const std::list<std::string>& challenges)
 {
   Block response = makeEmptyBlock(ndn::tlv::Content);
-  response.push_back(makeStringBlock(tlv::EcdhPub, ecdhKey));
+  response.push_back(makeBinaryBlock(tlv::EcdhPub, ecdhKey.data(), ecdhKey.size()));
   response.push_back(makeBinaryBlock(tlv::Salt, salt.data(), salt.size()));
   response.push_back(makeBinaryBlock(tlv::RequestId, request.m_requestId.data(), request.m_requestId.size()));
   response.push_back(makeNonNegativeIntegerBlock(tlv::Status, static_cast<size_t>(request.m_status)));
@@ -90,19 +95,21 @@
   return response;
 }
 
-NewRenewRevokeEncoder::DecodedData
-NewRenewRevokeEncoder::decodeDataContent(const Block& content)
+std::list<std::string>
+NewRenewRevokeEncoder::decodeDataContent(const Block& content, std::vector<uint8_t>& ecdhKey,
+                                         std::array<uint8_t, 32>& salt, RequestID& requestId, Status& status)
 {
   content.parse();
-  const auto& requestStatus = static_cast<Status>(readNonNegativeInteger(content.get(tlv::Status)));
-  const auto& ecdhKey = readString(content.get(tlv::EcdhPub));
+  status = static_cast<Status>(readNonNegativeInteger(content.get(tlv::Status)));
+
+  const auto& ecdhBlock = content.get(tlv::EcdhPub);
+  ecdhKey.resize(ecdhBlock.value_size());
+  std::memcpy(ecdhKey.data(), ecdhBlock.value(), ecdhBlock.value_size());
 
   const auto& saltBlock = content.get(tlv::Salt);
-  std::array<uint8_t, 32> salt;
   std::memcpy(salt.data(), saltBlock.value(), saltBlock.value_size());
 
   const auto& requestIdBlock = content.get(tlv::RequestId);
-  RequestID requestId;
   std::memcpy(requestId.data(), requestIdBlock.value(), requestIdBlock.value_size());
 
   std::list<std::string> challenges;
@@ -111,7 +118,7 @@
       challenges.push_back(readString(element));
     }
   }
-  return DecodedData{ecdhKey, salt, requestId, requestStatus, challenges};
+  return challenges;
 }
 
 } // namespace ndncert
diff --git a/src/detail/new-renew-revoke-encoder.hpp b/src/detail/new-renew-revoke-encoder.hpp
index 72194db..de61e2e 100644
--- a/src/detail/new-renew-revoke-encoder.hpp
+++ b/src/detail/new-renew-revoke-encoder.hpp
@@ -30,25 +30,22 @@
 {
 public:
   static Block
-  encodeApplicationParameters(RequestType requestType, const std::string& ecdhPub, const security::Certificate& certRequest);
+  encodeApplicationParameters(RequestType requestType, const std::vector<uint8_t>& ecdhPub,
+                              const security::Certificate& certRequest);
 
   static void
-  decodeApplicationParameters(const Block& block, RequestType requestType, std::string& ecdhPub, shared_ptr<security::Certificate>& certRequest);
+  decodeApplicationParameters(const Block& block, RequestType requestType, std::vector<uint8_t>& ecdhPub,
+                              shared_ptr<security::Certificate>& certRequest);
 
   static Block
-  encodeDataContent(const std::string& ecdhKey, const std::array<uint8_t, 32>& salt,
+  encodeDataContent(const std::vector<uint8_t>& ecdhKey,
+                    const std::array<uint8_t, 32>& salt,
                     const CaState& request,
                     const std::list<std::string>& challenges);
 
-  struct DecodedData {
-    std::string ecdhKey;
-    std::array<uint8_t, 32> salt;
-    RequestID requestId;
-    Status requestStatus;
-    std::list<std::string> challenges;
-  };
-  static DecodedData
-  decodeDataContent(const Block& content);
+  static std::list<std::string>
+  decodeDataContent(const Block& content, std::vector<uint8_t>& ecdhKey,
+                    std::array<uint8_t, 32>& salt, RequestID& requestId, Status& status);
 };
 
 } // namespace ndncert
diff --git a/src/requester.cpp b/src/requester.cpp
index b4cc929..8ae64eb 100644
--- a/src/requester.cpp
+++ b/src/requester.cpp
@@ -165,7 +165,7 @@
   interest->setMustBeFresh(true);
   interest->setCanBePrefix(false);
   interest->setApplicationParameters(
-      NewRenewRevokeEncoder::encodeApplicationParameters(RequestType::NEW, state.m_ecdh.getBase64PubKey(), certRequest));
+      NewRenewRevokeEncoder::encodeApplicationParameters(RequestType::NEW, state.m_ecdh.getSelfPubKey(), certRequest));
 
   // sign the Interest packet
   state.m_keyChain.sign(*interest, signingByKey(keyName));
@@ -185,7 +185,7 @@
   interest->setMustBeFresh(true);
   interest->setCanBePrefix(false);
   interest->setApplicationParameters(
-      NewRenewRevokeEncoder::encodeApplicationParameters(RequestType::REVOKE, state.m_ecdh.getBase64PubKey(), certificate));
+      NewRenewRevokeEncoder::encodeApplicationParameters(RequestType::REVOKE, state.m_ecdh.getSelfPubKey(), certificate));
   return interest;
 }
 
@@ -199,17 +199,17 @@
   processIfError(reply);
 
   auto contentTLV = reply.getContent();
-  const auto& content = NewRenewRevokeEncoder::decodeDataContent(contentTLV);
+  std::vector<uint8_t> ecdhKey;
+  std::array<uint8_t, 32> salt;
+  auto challenges = NewRenewRevokeEncoder::decodeDataContent(contentTLV, ecdhKey, salt, state.m_requestId, state.m_status);
 
   // ECDH and HKDF
-  state.m_ecdh.deriveSecret(content.ecdhKey);
-  hkdf(state.m_ecdh.m_sharedSecret, state.m_ecdh.m_sharedSecretLen,
-       (uint8_t*)&content.salt, sizeof(content.salt), state.m_aesKey, sizeof(state.m_aesKey));
+  auto sharedSecret = state.m_ecdh.deriveSecret(ecdhKey);
+  hkdf(sharedSecret.data(), sharedSecret.size(),
+       salt.data(), salt.size(), state.m_aesKey, sizeof(state.m_aesKey));
 
   // update state
-  state.m_status = content.requestStatus;
-  state.m_requestId = content.requestId;
-  return content.challenges;
+  return challenges;
 }
 
 std::vector<std::tuple<std::string, std::string>>