client: fetch ca profile and validate with preconfigured ca cert

Change-Id: I0e6819d9f8030a960e20d0a545f5c29c5f9589ce
diff --git a/client.conf.sample b/client.conf.sample
index 53dbd95..f3bf724 100644
--- a/client.conf.sample
+++ b/client.conf.sample
@@ -2,16 +2,8 @@
   "ca-list":
   [
     {
-      "ca-prefix": "/ndncert-demo",
-      "ca-info": "NDN Testbed NDNCERT CA (Demo)",
-      "max-validity-period": "1296000",
-      "max-suffix-length": "5",
-      "probe-parameters": [
-        {
-          "probe-parameter-key": "email"
-        }
-      ],
-      "certificate": "Bv0BLwctCAxuZG5jZXJ0LWRlbW8IA0tFWQgI92c9QI8lJGoIBHNlbGY2CAAAAX7YsardFAkYAQIZBAA27oAVWzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABNIu6i4dFU2FwW9641O4XehbwZD3INSgsEehPfZVRnDhQ0l5oRdUGJo6OQhOutExKov7dp+hzmRSAHbiO3dRjdIWThsBAxwfBx0IDG5kbmNlcnQtZGVtbwgDS0VZCAj3Zz1AjyUkav0A/Sb9AP4PMTk3MDAxMDFUMDAwMDAw/QD/DzIwNDIwMjAzVDA5MzcwORdGMEQCIA7CEGlG+KQnJudjqpCzt7IlHRgPV2ni1k5mSu0yZXKtAiAGkqnGwTu1e8LVqZ1XIidt/wDzcYXTQGEoltwhcN6jUw=="
+      "ca-prefix": "/ndn",
+      "certificate": "Bv0BSwcjCANuZG4IA0tFWQgIJ8SyKp97gScIA25kbjYIAAABgHX6c7QUCRgBAhkEADbugBVbMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEPuDnW4oq0mULLT8PDXh0zuBg+0SJ1yPC85jylUU+hgxX9fDNyjlykLrvb1D6IQRJWJHMKWe6TJKPUhGgOT658hZyGwEDHBYHFAgDbmRuCANLRVkICCfEsiqfe4En/QD9Jv0A/g8yMDIyMDQyOVQxNTM5NTD9AP8PMjAyNjEyMzFUMjM1OTU5/QECKf0CACX9AgEIZnVsbG5hbWX9AgIVTkROIFRlc3RiZWQgUm9vdCAyMjA0F0gwRgIhAPYUOjNakdfDGh5j9dcCGOz+Ie1MqoAEsjM9PEUEWbnqAiEApu0rg9GAK1LNExjLYAF6qVgpWQgU+atPn63Gtuubqyg="
     }
   ]
 }
diff --git a/tools/ndncert-client.cpp b/tools/ndncert-client.cpp
index ee22db5..3c7d3de 100644
--- a/tools/ndncert-client.cpp
+++ b/tools/ndncert-client.cpp
@@ -51,6 +51,7 @@
 static ndn::KeyChain keyChain;
 static std::shared_ptr<Request> requesterState;
 static std::shared_ptr<std::multimap<std::string, std::string>> capturedProbeParams;
+static std::shared_ptr<Certificate> trustedCert;
 static Name newlyCreatedIdentityName;
 static Name newlyCreatedKeyName;
 
@@ -279,6 +280,9 @@
   std::optional<CaProfile> profile;
   try {
     if (certFullName.empty()) {
+      if (trustedCert && !ndn::security::verifySignature(reply, *trustedCert)) {
+        NDN_THROW(std::runtime_error("Cannot verify replied Data packet signature."));
+      }
       profile = Request::onCaProfileResponse(reply);
     }
     else {
@@ -289,24 +293,31 @@
     std::cerr << "The fetched CA information cannot be used because: " << e.what() << std::endl;
     return;
   }
-  std::cerr << "\n***************************************\n"
-            << "Step " << nStep++
-            << ": Will use a new trust anchor, please double check the identity info:" << std::endl
-            << "> New CA name: " << profile->caPrefix << std::endl
-            << "> This trust anchor information is signed by: " << reply.getSignatureInfo().getKeyLocator() << std::endl
-            << "> The certificate: " << *profile->cert << std::endl
-            << "Do you trust the information? Type in YES or NO" << std::endl;
+  if (!trustedCert)
+  {
+    std::cerr << "\n***************************************\n"
+              << "Step " << nStep++
+              << ": Will use the following CA, please double check the identity info:" << std::endl
+              << "> CA name: " << profile->caPrefix << std::endl
+              << "> This CA information is signed by: " << reply.getSignatureInfo().getKeyLocator() << std::endl
+              << "> The certificate:" << std::endl << *profile->cert << std::endl
+              << "Do you trust the information? Type in YES or NO" << std::endl;
 
-  std::string answer;
-  getline(std::cin, answer);
-  boost::algorithm::to_lower(answer);
-  if (answer == "yes") {
-    std::cerr << "You answered YES: new CA " << profile->caPrefix << " will be used" << std::endl;
-    runProbe(*profile);
+    std::string answer;
+    getline(std::cin, answer);
+    boost::algorithm::to_lower(answer);
+    if (answer == "yes") {
+      std::cerr << "You answered YES: new CA " << profile->caPrefix << " will be used" << std::endl;
+      trustedCert = profile->cert;
+      runProbe(*profile);
+    }
+    else {
+      std::cerr << "You answered NO: new CA " << profile->caPrefix << " will not be used" << std::endl;
+      exit(0);
+    }
   }
   else {
-    std::cerr << "You answered NO: new CA " << profile->caPrefix << " will not be used" << std::endl;
-    exit(0);
+    runProbe(*profile);
   }
 }
 
@@ -435,22 +446,19 @@
   getline(std::cin, caIndexS);
   caIndexSLower = caIndexS;
   boost::algorithm::to_lower(caIndexSLower);
+  Name selectedCaName;
   if (caIndexSLower == "none") {
     std::cerr << "\n***************************************\n"
               << "Step " << nStep << ": ADD NEW CA\nPlease type in the CA's Name:" << std::endl;
-    std::string expectedCAName;
-    getline(std::cin, expectedCAName);
-    face.expressInterest(
-        *Request::genCaProfileDiscoveryInterest(Name(expectedCAName)),
-        [&] (const auto&, const auto& data) {
-          auto fetchingInterest = Request::genCaProfileInterestFromDiscoveryResponse(data);
-          face.expressInterest(*fetchingInterest,
-                               [] (const auto&, const auto& data2) { infoCb(data2, {}); },
-                               [] (auto&&...) { onNackCb(); },
-                               [] (auto&&...) { timeoutCb(); });
-        },
-        [] (auto&&...) { onNackCb(); },
-        [] (auto&&...) { timeoutCb(); });
+    std::string targetCaName;
+    getline(std::cin, targetCaName);
+    try {
+      selectedCaName = Name(targetCaName);
+    }
+    catch (const std::exception&) {
+      std::cerr << "Your input is not a valid name. Exit" << std::endl;
+      exit(1);
+    }
   }
   else {
     size_t caIndex;
@@ -468,8 +476,20 @@
     auto itemIterator = profileStorage.getKnownProfiles().cbegin();
     std::advance(itemIterator, caIndex);
     auto targetCaItem = *itemIterator;
-    runProbe(targetCaItem);
+    trustedCert = targetCaItem.cert;
+    selectedCaName = targetCaItem.caPrefix;
   }
+  face.expressInterest(
+    *Request::genCaProfileDiscoveryInterest(selectedCaName),
+    [&] (const auto&, const auto& data) {
+      auto fetchingInterest = Request::genCaProfileInterestFromDiscoveryResponse(data);
+      face.expressInterest(*fetchingInterest,
+                            [] (const auto&, const auto& data2) { infoCb(data2, {}); },
+                            [] (auto&&...) { onNackCb(); },
+                            [] (auto&&...) { timeoutCb(); });
+    },
+    [] (auto&&...) { onNackCb(); },
+    [] (auto&&...) { timeoutCb(); });
 }
 
 static void