Revocation: fixes and combine with New

Change-Id: I68bc117d1ae35d7dc4c754c76bf88003ebc637b5
diff --git a/src/ca-module.cpp b/src/ca-module.cpp
index 5201e31..9e9bf61 100644
--- a/src/ca-module.cpp
+++ b/src/ca-module.cpp
@@ -226,7 +226,20 @@
 void
 CaModule::onNew(const Interest& request)
 {
-  // NEW Naming Convention: /<CA-prefix>/CA/NEW/[SignedInterestParameters_Digest]
+    // NEW Naming Convention: /<CA-prefix>/CA/NEW/[SignedInterestParameters_Digest]
+    onRequestInit(request, REQUEST_TYPE_NEW);
+}
+
+void
+CaModule::onRevoke(const Interest& request)
+{
+    // REVOKE Naming Convention: /<CA-prefix>/CA/REVOKE/[SignedInterestParameters_Digest]
+    onRequestInit(request, REQUEST_TYPE_REVOKE);
+}
+
+void
+CaModule::onRequestInit(const Interest& request, int requestType)
+{
   // get ECDH pub key and cert request
   const auto& parameterTLV = request.getApplicationParameters();
   parameterTLV.parse();
@@ -258,52 +271,80 @@
   hkdf(m_ecdh.context->sharedSecret, m_ecdh.context->sharedSecretLen,
        (uint8_t*)&saltInt, sizeof(saltInt), m_aesKey, sizeof(m_aesKey));
 
-  // parse certificate request
-  Block cert_req = parameterTLV.get(tlv_cert_request);
-  cert_req.parse();
-
   shared_ptr<security::v2::Certificate> clientCert = nullptr;
 
-  try {
-    security::v2::Certificate cert = security::v2::Certificate(cert_req.get(tlv::Data));
-    clientCert = make_shared<security::v2::Certificate>(cert);
-  }
-  catch (const std::exception& e) {
-    _LOG_ERROR("Unrecognized certificate request: " << e.what());
-    return;
-  }
-  // check the validity period
-  auto expectedPeriod = clientCert->getValidityPeriod().getPeriod();
-  auto currentTime = time::system_clock::now();
-  if (expectedPeriod.first < currentTime - REQUEST_VALIDITY_PERIOD_NOT_BEFORE_GRACE_PERIOD) {
-    _LOG_ERROR("Client requests a too old notBefore timepoint.");
-    return;
-  }
-  if (expectedPeriod.second > currentTime + m_config.m_maxValidityPeriod ||
-      expectedPeriod.second <= expectedPeriod.first) {
-    _LOG_ERROR("Client requests an invalid validity period or a notAfter timepoint beyond the allowed time period.");
-    return;
-  }
+  if (requestType == REQUEST_TYPE_NEW) {
+    // parse certificate request
+    Block cert_req = parameterTLV.get(tlv_cert_request);
+    cert_req.parse();
 
-  // verify the self-signed certificate, the request, and the token
-  if (!m_config.m_caPrefix.isPrefixOf(clientCert->getName()) // under ca prefix
-      || !security::v2::Certificate::isValidName(clientCert->getName()) // is valid cert name
-      || clientCert->getName().size() < m_config.m_caName.size() + IS_SUBNAME_MIN_OFFSET) {
-    _LOG_ERROR("Invalid self-signed certificate name " << clientCert->getName());
-    return;
-  }
-  if (!security::verifySignature(*clientCert, *clientCert)) {
-    _LOG_ERROR("Cert request with bad signature.");
-    return;
-  }
-  if (!security::verifySignature(request, *clientCert)) {
-    _LOG_ERROR("Interest with bad signature.");
-    return;
+    try {
+      security::v2::Certificate cert = security::v2::Certificate(cert_req.get(tlv::Data));
+      clientCert = make_shared<security::v2::Certificate>(cert);
+    }
+    catch (const std::exception &e) {
+      _LOG_ERROR("Unrecognized certificate request: " << e.what());
+      return;
+    }
+    // check the validity period
+    auto expectedPeriod = clientCert->getValidityPeriod().getPeriod();
+    auto currentTime = time::system_clock::now();
+    if (expectedPeriod.first < currentTime - REQUEST_VALIDITY_PERIOD_NOT_BEFORE_GRACE_PERIOD) {
+      _LOG_ERROR("Client requests a too old notBefore timepoint.");
+      return;
+    }
+    if (expectedPeriod.second > currentTime + m_config.m_maxValidityPeriod ||
+      expectedPeriod.second <= expectedPeriod.first) {
+      _LOG_ERROR("Client requests an invalid validity period or a notAfter timepoint beyond the allowed time period.");
+      return;
+    }
+
+    // verify the self-signed certificate, the request, and the token
+    if (!m_config.m_caPrefix.isPrefixOf(clientCert->getName()) // under ca prefix
+        || !security::v2::Certificate::isValidName(clientCert->getName()) // is valid cert name
+        || clientCert->getName().size() < m_config.m_caName.size() + IS_SUBNAME_MIN_OFFSET) {
+      _LOG_ERROR("Invalid self-signed certificate name " << clientCert->getName());
+      return;
+    }
+    if (!security::verifySignature(*clientCert, *clientCert)) {
+      _LOG_ERROR("Cert request with bad signature.");
+      return;
+    }
+    if (!security::verifySignature(request, *clientCert)) {
+      _LOG_ERROR("Interest with bad signature.");
+      return;
+    }
+  } else if (requestType == REQUEST_TYPE_REVOKE) {
+    // parse certificate request
+    Block cert_revoke = parameterTLV.get(tlv_cert_to_revoke);
+    cert_revoke.parse();
+
+    try {
+      security::v2::Certificate cert = security::v2::Certificate(cert_revoke.get(tlv::Data));
+      clientCert = make_shared<security::v2::Certificate>(cert);
+    }
+    catch (const std::exception &e) {
+      _LOG_ERROR("Unrecognized certificate: " << e.what());
+      return;
+    }
+
+    // verify the certificate
+    if (!m_config.m_caName.isPrefixOf(clientCert->getName()) // under ca prefix
+        || !security::v2::Certificate::isValidName(clientCert->getName()) // is valid cert name
+        || clientCert->getName().size() < m_config.m_caName.size() + IS_SUBNAME_MIN_OFFSET) {
+      _LOG_ERROR("Invalid certificate name " << clientCert->getName());
+      return;
+    }
+    const auto& cert = m_keyChain.getPib().getIdentity(m_config.m_caName).getDefaultKey().getDefaultCertificate();
+    if (!security::verifySignature(*clientCert, cert)) {
+      _LOG_ERROR("Cert request with bad signature.");
+      return;
+    }
   }
 
   // create new request instance
   std::string requestId = std::to_string(random::generateWord64());
-  CertificateRequest certRequest(m_config.m_caPrefix, requestId, REQUEST_TYPE_NEW, STATUS_BEFORE_CHALLENGE, *clientCert);
+  CertificateRequest certRequest(m_config.m_caPrefix, requestId, requestType, STATUS_BEFORE_CHALLENGE, *clientCert);
 
   try {
     m_storage->addRequest(certRequest);
@@ -316,10 +357,17 @@
   Data result;
   result.setName(request.getName());
   result.setFreshnessPeriod(DEFAULT_DATA_FRESHNESS_PERIOD);
-  result.setContent(NEW::encodeDataContent(myEcdhPubKeyBase64,
-                                      std::to_string(saltInt),
-                                      certRequest,
-                                      m_config.m_supportedChallenges));
+  if (requestType == REQUEST_TYPE_NEW) {
+    result.setContent(NEW::encodeDataContent(myEcdhPubKeyBase64,
+                                               std::to_string(saltInt),
+                                               certRequest,
+                                               m_config.m_supportedChallenges));
+  } else if (requestType == REQUEST_TYPE_REVOKE) {
+    result.setContent(REVOKE::encodeDataContent(myEcdhPubKeyBase64,
+                                                std::to_string(saltInt),
+                                                certRequest,
+                                                m_config.m_supportedChallenges));
+  }
   m_keyChain.sign(result, signingByIdentity(m_config.m_caPrefix));
   m_face.put(result);
 
@@ -452,91 +500,6 @@
   }
 }
 
-void
-CaModule::onRevoke(const Interest& request)
-{
-  // NEW Naming Convention: /<CA-prefix>/CA/REVOKE/[SignedInterestParameters_Digest]
-  // get ECDH pub key and cert request
-  const auto& parameterJson = jsonFromBlock(request.getApplicationParameters());
-  if (parameterJson.empty()) {
-    _LOG_ERROR("Empty JSON obtained from the Interest parameter.");
-    return;
-  }
-  std::string peerKeyBase64 = parameterJson.get(JSON_CLIENT_ECDH, "");
-  if (peerKeyBase64 == "") {
-    _LOG_ERROR("Empty JSON_CLIENT_ECDH obtained from the Interest parameter.");
-    return;
-  }
-
-  // get server's ECDH pub key
-  auto myEcdhPubKeyBase64 = m_ecdh.getBase64PubKey();
-  try {
-    m_ecdh.deriveSecret(peerKeyBase64);
-  }
-  catch (const std::exception& e) {
-    _LOG_ERROR("Cannot derive a shared secret using the provided ECDH key: " << e.what());
-    return;
-  }
-
-  // parse certificate request
-  std::string certRevokeStr = parameterJson.get(JSON_CLIENT_CERT_REVOKE, "");
-  shared_ptr<security::v2::Certificate> clientCert = nullptr;
-  try {
-    std::stringstream ss(certRevokeStr);
-    clientCert = io::load<security::v2::Certificate>(ss);
-  }
-  catch (const std::exception& e) {
-    _LOG_ERROR("Unrecognized revocation request: " << e.what());
-    return;
-  }
-
-  // verify the certificate
-  if (!m_config.m_caName.isPrefixOf(clientCert->getName()) // under ca prefix
-        || !security::v2::Certificate::isValidName(clientCert->getName()) // is valid cert name
-        || clientCert->getName().size() != m_config.m_caName.size() + IS_SUBNAME_MIN_OFFSET) {
-        _LOG_ERROR("Invalid certificate name " << clientCert->getName());
-        return;
-  }
-  const auto& cert = m_keyChain.getPib().getIdentity(m_config.m_caName).getDefaultKey().getDefaultCertificate();
-  if (!security::verifySignature(*clientCert, cert)) {
-    _LOG_ERROR("Cert request with bad signature.");
-    return;
-  }
-
-  // generate salt for HKDF
-  auto saltInt = random::generateSecureWord64();
-  // hkdf
-  hkdf(m_ecdh.context->sharedSecret, m_ecdh.context->sharedSecretLen,
-         (uint8_t*)&saltInt, sizeof(saltInt), m_aesKey, sizeof(m_aesKey));
-
-  // create new request instance
-  std::string requestId = std::to_string(random::generateWord64());
-  CertificateRequest certRequest(m_config.m_caName, requestId, REQUEST_TYPE_REVOKE, STATUS_BEFORE_CHALLENGE,
-                                   *clientCert);
-  try {
-    m_storage->addRequest(certRequest);
-  }
-  catch (const std::exception& e) {
-    _LOG_ERROR("Cannot add new request instance into the storage: " << e.what());
-    return;
-  }
-
-  Data result;
-  result.setName(request.getName());
-  result.setFreshnessPeriod(DEFAULT_DATA_FRESHNESS_PERIOD);
-  result.setContent(REVOKE::encodeDataContent(myEcdhPubKeyBase64,
-                                              std::to_string(saltInt),
-                                              certRequest,
-                                              m_config.m_supportedChallenges));
-  m_keyChain.sign(result, signingByIdentity(m_config.m_caPrefix));
-  m_face.put(result);
-
-  if (m_config.m_statusUpdateCallback) {
-    m_config.m_statusUpdateCallback(certRequest);
-  }
-}
-
-
 security::v2::Certificate
 CaModule::issueCertificate(const CertificateRequest& certRequest)
 {
diff --git a/src/ca-module.hpp b/src/ca-module.hpp
index fad6296..1e17e2b 100644
--- a/src/ca-module.hpp
+++ b/src/ca-module.hpp
@@ -84,13 +84,16 @@
   onProbe(const Interest& request);
 
   void
+  onRequestInit(const Interest& request, int requestType);
+
+  void
   onNew(const Interest& request);
 
   void
-  onChallenge(const Interest& request);
+  onRevoke(const Interest& request);
 
   void
-  onRevoke(const Interest& request);
+  onChallenge(const Interest& request);
 
   void
   onRegisterFailed(const std::string& reason);
diff --git a/src/client-module.cpp b/src/client-module.cpp
index 1e01dc0..52cb62c 100644
--- a/src/client-module.cpp
+++ b/src/client-module.cpp
@@ -214,6 +214,12 @@
 std::list<std::string>
 ClientModule::onNewResponse(const Data& reply)
 {
+    return onRequestInitResponse(reply, REQUEST_TYPE_NEW);
+}
+
+std::list<std::string>
+ClientModule::onRequestInitResponse(const Data& reply, int requestType)
+{
   if (!security::verifySignature(reply, m_ca.m_anchor)) {
     _LOG_ERROR("Cannot verify data signature from " << m_ca.m_caPrefix.toUri());
     return std::list<std::string>();
@@ -276,33 +282,7 @@
 std::list<std::string>
 ClientModule::onRevokeResponse(const Data& reply)
 {
-    if (!security::verifySignature(reply, m_ca.m_anchor)) {
-        _LOG_ERROR("Cannot verify data signature from " << m_ca.m_caName.toUri());
-        return std::list<std::string>();
-    }
-    auto contentTLV = reply.getContent();
-    contentTLV.parse();
-
-    // ECDH
-    const auto& peerKeyBase64Str = readString(contentTLV.get(tlv_ecdh_pub));
-    const auto& saltStr = readString(contentTLV.get(tlv_salt));
-    uint64_t saltInt = std::stoull(saltStr);
-    m_ecdh.deriveSecret(peerKeyBase64Str);
-
-    // HKDF
-    hkdf(m_ecdh.context->sharedSecret, m_ecdh.context->sharedSecretLen,
-         (uint8_t*)&saltInt, sizeof(saltInt), m_aesKey, sizeof(m_aesKey));
-
-    // update state
-    m_status = readNonNegativeInteger(contentTLV.get(tlv_status));
-    m_requestId = readString(contentTLV.get(tlv_request_id));
-    m_challengeList.clear();
-    for (auto const& element : contentTLV.elements()) {
-        if (element.type() == tlv_challenge) {
-            m_challengeList.push_back(readString(element));
-        }
-    }
-    return m_challengeList;
+    return onRequestInitResponse(reply, REQUEST_TYPE_REVOKE);
 }
 
 shared_ptr<Interest>
diff --git a/src/client-module.hpp b/src/client-module.hpp
index f6d706f..eefccad 100644
--- a/src/client-module.hpp
+++ b/src/client-module.hpp
@@ -97,6 +97,15 @@
   onNewResponse(const Data& reply);
 
   shared_ptr<Interest>
+  generateRevokeInterest(const security::v2::Certificate& certificate);
+
+  std::list<std::string>
+  onRevokeResponse(const Data& reply);
+
+  std::list<std::string>
+  onRequestInitResponse(const Data& reply, int requestType);
+
+  shared_ptr<Interest>
   generateChallengeInterest(const Block& paramTLV);
 
   void
@@ -108,12 +117,6 @@
   shared_ptr<Interest>
   generateCertFetchInterest();
 
-  shared_ptr<Interest>
-  generateRevokeInterest(const security::v2::Certificate& certificate);
-
-  std::list<std::string>
-  onRevokeResponse(const Data& reply);
-
   void
   onCertFetchResponse(const Data& reply);