use unique ECDH state / Encryption key for request in CA

Change-Id: If9f5471664d2eec7562b963c40f404ecfa3e5269
diff --git a/src/ca-module.cpp b/src/ca-module.cpp
index 0c5373f..0cd35cc 100644
--- a/src/ca-module.cpp
+++ b/src/ca-module.cpp
@@ -247,9 +247,10 @@
   }
 
   // get server's ECDH pub key
-  auto myEcdhPubKeyBase64 = m_ecdh.getBase64PubKey();
+  ECDHState ecdh;
+  auto myEcdhPubKeyBase64 = ecdh.getBase64PubKey();
   try {
-    m_ecdh.deriveSecret(peerKeyBase64);
+    ecdh.deriveSecret(peerKeyBase64);
   }
   catch (const std::exception& e) {
     _LOG_ERROR("Cannot derive a shared secret using the provided ECDH key: " << e.what());
@@ -260,8 +261,9 @@
   // 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));
+  uint8_t aesKey[AES_128_KEY_LEN];
+  hkdf(ecdh.context->sharedSecret, ecdh.context->sharedSecretLen,
+       (uint8_t*)&saltInt, sizeof(saltInt), aesKey, sizeof(aesKey));
 
   shared_ptr<security::v2::Certificate> clientCert = nullptr;
   // parse certificate request
@@ -334,7 +336,8 @@
 
   // create new request instance
   std::string requestId = std::to_string(random::generateWord64());
-  RequestState certRequest(m_config.m_caPrefix, requestId, requestType, Status::BEFORE_CHALLENGE, *clientCert);
+  RequestState certRequest(m_config.m_caPrefix, requestId, requestType, Status::BEFORE_CHALLENGE, *clientCert,
+          makeBinaryBlock(tlv::ContentType_Key, aesKey, sizeof(aesKey)));
   m_storage->addRequest(certRequest);
   Data result;
   result.setName(request.getName());
@@ -379,7 +382,7 @@
   // decrypt the parameters
   Buffer paramTLVPayload;
   try {
-    paramTLVPayload = decodeBlockWithAesGcm128(request.getApplicationParameters(), m_aesKey,
+    paramTLVPayload = decodeBlockWithAesGcm128(request.getApplicationParameters(), certRequest.m_encryptionKey.value(),
                                                (uint8_t*)"test", strlen("test"));
   }
   catch (const std::exception& e) {
@@ -450,7 +453,7 @@
   Data result;
   result.setName(request.getName());
   result.setFreshnessPeriod(DEFAULT_DATA_FRESHNESS_PERIOD);
-  auto contentBlock = encodeBlockWithAesGcm128(tlv::Content, m_aesKey, payload.value(),
+  auto contentBlock = encodeBlockWithAesGcm128(tlv::Content, certRequest.m_encryptionKey.value(), payload.value(),
                                                payload.value_size(), (uint8_t*)"test", strlen("test"));
   result.setContent(contentBlock);
   m_keyChain.sign(result, signingByIdentity(m_config.m_caPrefix));
diff --git a/src/ca-module.hpp b/src/ca-module.hpp
index 3bb3a1e..c6b3e71 100644
--- a/src/ca-module.hpp
+++ b/src/ca-module.hpp
@@ -113,8 +113,6 @@
   std::list<RegisteredPrefixHandle> m_registeredPrefixHandles;
   std::list<InterestFilterHandle> m_interestFilterHandles;
 
-  ECDHState m_ecdh;
-  uint8_t m_aesKey[16] = {0};
 };
 
 } // namespace ndncert
diff --git a/src/ca-storage-detail/ca-sqlite.cpp b/src/ca-storage-detail/ca-sqlite.cpp
index 905bfa5..a0f24ec 100644
--- a/src/ca-storage-detail/ca-sqlite.cpp
+++ b/src/ca-storage-detail/ca-sqlite.cpp
@@ -50,7 +50,8 @@
     challenge_tp TEXT,
     remaining_tries INTEGER,
     remaining_time INTEGER,
-    challenge_secrets TEXT
+    challenge_secrets TEXT,
+    encryption_key BLOB NOT NULL
   );
 CREATE UNIQUE INDEX IF NOT EXISTS
   CertRequestIdIndex ON CertRequests(request_id);
@@ -120,7 +121,7 @@
                              R"_SQLTEXT_(SELECT id, ca_name, status,
                              challenge_status, cert_request,
                              challenge_type, challenge_secrets,
-                             challenge_tp, remaining_tries, remaining_time, request_type
+                             challenge_tp, remaining_tries, remaining_time, request_type, encryption_key
                              FROM CertRequests where request_id = ?)_SQLTEXT_");
   statement.bind(1, requestId, SQLITE_TRANSIENT);
 
@@ -135,14 +136,15 @@
     auto remainingTries = statement.getInt(8);
     auto remainingTime = statement.getInt(9);
     auto requestType = static_cast<RequestType>(statement.getInt(10));
+    auto encryptionKey = statement.getBlock(11);
     if (challengeType != "") {
       return RequestState(caName, requestId, requestType, status, cert,
                                 challengeType, challengeStatus, time::fromIsoString(challengeTp),
                                 remainingTries, time::seconds(remainingTime),
-                                convertString2Json(challengeSecrets));
+                                convertString2Json(challengeSecrets), encryptionKey);
     }
     else {
-      return RequestState(caName, requestId, requestType, status, cert);
+      return RequestState(caName, requestId, requestType, status, cert, encryptionKey);
     }
   }
   else {
@@ -174,14 +176,15 @@
       m_database,
       R"_SQLTEXT_(INSERT INTO CertRequests (request_id, ca_name, status, request_type,
                   cert_key_name, cert_request, challenge_type, challenge_status, challenge_secrets,
-                  challenge_tp, remaining_tries, remaining_time)
-                  values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?))_SQLTEXT_");
+                  challenge_tp, remaining_tries, remaining_time, encryption_key)
+                  values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?))_SQLTEXT_");
   statement.bind(1, request.m_requestId, SQLITE_TRANSIENT);
   statement.bind(2, request.m_caPrefix.wireEncode(), SQLITE_TRANSIENT);
   statement.bind(3, static_cast<int>(request.m_status));
   statement.bind(4, static_cast<int>(request.m_requestType));
   statement.bind(5, keyNameTlv, SQLITE_TRANSIENT);
   statement.bind(6, request.m_cert.wireEncode(), SQLITE_TRANSIENT);
+  statement.bind(13, request.m_encryptionKey, SQLITE_TRANSIENT);
   if (request.m_challengeState) {
     statement.bind(7, request.m_challengeType, SQLITE_TRANSIENT);
     statement.bind(8, request.m_challengeState->m_challengeStatus, SQLITE_TRANSIENT);
@@ -234,7 +237,7 @@
   std::list<RequestState> result;
   Sqlite3Statement statement(m_database, R"_SQLTEXT_(SELECT id, request_id, ca_name, status,
                              challenge_status, cert_key_name, cert_request, challenge_type, challenge_secrets,
-                             challenge_tp, remaining_tries, remaining_time, request_type
+                             challenge_tp, remaining_tries, remaining_time, request_type, encryption_key
                              FROM CertRequests)_SQLTEXT_");
   while (statement.step() == SQLITE_ROW) {
     auto requestId = statement.getString(1);
@@ -248,14 +251,15 @@
     auto remainingTries = statement.getInt(10);
     auto remainingTime = statement.getInt(11);
     auto requestType = static_cast<RequestType>(statement.getInt(12));
+    auto encryptionKey = statement.getBlock(13);
     if (challengeType != "") {
       result.push_back(RequestState(caName, requestId, requestType, status, cert,
                                           challengeType, challengeStatus, time::fromIsoString(challengeTp),
                                           remainingTries, time::seconds(remainingTime),
-                                          convertString2Json(challengeSecrets)));
+                                          convertString2Json(challengeSecrets), encryptionKey));
     }
     else {
-      result.push_back(RequestState(caName, requestId, requestType, status, cert));
+      result.push_back(RequestState(caName, requestId, requestType, status, cert, encryptionKey));
     }
   }
   return result;
@@ -268,7 +272,7 @@
   Sqlite3Statement statement(m_database,
                              R"_SQLTEXT_(SELECT id, request_id, ca_name, status,
                              challenge_status, cert_key_name, cert_request, challenge_type, challenge_secrets,
-                             challenge_tp, remaining_tries, remaining_time, request_type
+                             challenge_tp, remaining_tries, remaining_time, request_type, encryption_key
                              FROM CertRequests WHERE ca_name = ?)_SQLTEXT_");
   statement.bind(1, caName.wireEncode(), SQLITE_TRANSIENT);
 
@@ -284,14 +288,15 @@
     auto remainingTries = statement.getInt(10);
     auto remainingTime = statement.getInt(11);
     auto requestType = static_cast<RequestType>(statement.getInt(12));
+    auto encryptionKey = statement.getBlock(13);
     if (challengeType != "") {
       result.push_back(RequestState(caName, requestId, requestType, status, cert,
                                           challengeType, challengeStatus, time::fromIsoString(challengeTp),
                                           remainingTries, time::seconds(remainingTime),
-                                          convertString2Json(challengeSecrets)));
+                                          convertString2Json(challengeSecrets), encryptionKey));
     }
     else {
-      result.push_back(RequestState(caName, requestId, requestType, status, cert));
+      result.push_back(RequestState(caName, requestId, requestType, status, cert, encryptionKey));
     }
   }
   return result;
diff --git a/src/crypto-support/crypto-helper.hpp b/src/crypto-support/crypto-helper.hpp
index ad8aa22..1ff0149 100644
--- a/src/crypto-support/crypto-helper.hpp
+++ b/src/crypto-support/crypto-helper.hpp
@@ -30,6 +30,7 @@
 
 static const int INFO_LEN = 10;
 static const uint8_t INFO[] = {0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9};
+static const int AES_128_KEY_LEN = 16;
 
 struct ECDH_CTX {
   int EC_NID;
diff --git a/src/request-state.cpp b/src/request-state.cpp
index 1cc696c..7268d0e 100644
--- a/src/request-state.cpp
+++ b/src/request-state.cpp
@@ -43,19 +43,21 @@
 }
 
 RequestState::RequestState(const Name& caName, const std::string& requestId, RequestType requestType, Status status,
-                                       const security::v2::Certificate& cert)
+                                       const security::v2::Certificate& cert, Block encryptionKey)
     : m_caPrefix(caName)
     , m_requestId(requestId)
     , m_requestType(requestType)
     , m_status(status)
     , m_cert(cert)
+    , m_encryptionKey(std::move(encryptionKey))
 {
 }
 
 RequestState::RequestState(const Name& caName, const std::string& requestId, RequestType requestType, Status status,
                                        const security::v2::Certificate& cert, const std::string& challengeType,
                                        const std::string& challengeStatus, const system_clock::TimePoint& challengeTp,
-                                       size_t remainingTries, time::seconds remainingTime, JsonSection&& challengeSecrets)
+                                       size_t remainingTries, time::seconds remainingTime, JsonSection&& challengeSecrets,
+                                       Block encryptionKey)
     : m_caPrefix(caName)
     , m_requestId(requestId)
     , m_requestType(requestType)
@@ -63,6 +65,7 @@
     , m_cert(cert)
     , m_challengeType(challengeType)
     , m_challengeState(ChallengeState(challengeStatus, challengeTp, remainingTries, remainingTime, std::move(challengeSecrets)))
+    , m_encryptionKey(std::move(encryptionKey))
 {
 }
 
diff --git a/src/request-state.hpp b/src/request-state.hpp
index b5dc430..f8c0443 100644
--- a/src/request-state.hpp
+++ b/src/request-state.hpp
@@ -45,14 +45,16 @@
  *
  */
 class RequestState {
+
 public:
   RequestState();
   RequestState(const Name& caName, const std::string& requestId, RequestType requestType, Status status,
-                     const security::v2::Certificate& cert);
+                     const security::v2::Certificate& cert, Block m_encryptionKey);
   RequestState(const Name& caName, const std::string& requestId, RequestType requestType, Status status,
                      const security::v2::Certificate& cert, const std::string& challengeType,
                      const std::string& challengeStatus, const system_clock::TimePoint& challengeTp,
-                     size_t remainingTries, time::seconds remainingTime, JsonSection&& challengeSecrets);
+                     size_t remainingTries, time::seconds remainingTime, JsonSection&& challengeSecrets,
+                     Block m_encryptionKey);
 
 public:
   Name m_caPrefix;
@@ -60,6 +62,7 @@
   RequestType m_requestType;
   Status m_status;
   security::v2::Certificate m_cert;
+  Block m_encryptionKey;
 
   std::string m_challengeType;
   boost::optional<ChallengeState> m_challengeState;