Change request id to be generated by keyed hash function
- So request with same certificate cannot be used again

Change-Id: I8211e4edcb9a86cb5fbd2c0f8e90b9d4c8864326
diff --git a/src/ca-module.cpp b/src/ca-module.cpp
index 802049a..4d055e3 100644
--- a/src/ca-module.cpp
+++ b/src/ca-module.cpp
@@ -48,6 +48,7 @@
   // load the config and create storage
   m_config.load(configPath);
   m_storage = CaStorage::createCaStorage(storageType, m_config.m_caItem.m_caPrefix, "");
+  random::generateSecureBytes(m_requestIdGenKey, 16);
 
   registerPrefix();
 }
@@ -325,7 +326,15 @@
   }
 
   // create new request instance
-  std::string requestId = std::to_string(random::generateWord64());
+  uint64_t requestIdData[2];
+  size_t idDataLen = 16;
+  Block certNameData = clientCert->getName().wireEncode();
+  hmac_sha_256(m_requestIdGenKey, 16, certNameData.value(), certNameData.value_size(), reinterpret_cast<uint8_t *>(requestIdData), &idDataLen);
+  std::stringstream ss;
+  ss << std::hex << std::noshowbase<< requestIdData[0] << requestIdData[1];
+
+  std::string requestId = ss.str();
+
   CaState requestState(m_config.m_caItem.m_caPrefix, requestId, requestType, Status::BEFORE_CHALLENGE, *clientCert,
                        makeBinaryBlock(tlv::ContentType_Key, aesKey, sizeof(aesKey)));
   try {
diff --git a/src/ca-module.hpp b/src/ca-module.hpp
index bcf7b7b..8172688 100644
--- a/src/ca-module.hpp
+++ b/src/ca-module.hpp
@@ -109,6 +109,7 @@
   CaConfig m_config;
   unique_ptr<CaStorage> m_storage;
   security::v2::KeyChain& m_keyChain;
+  uint8_t m_requestIdGenKey[16];
 
   std::list<RegisteredPrefixHandle> m_registeredPrefixHandles;
   std::list<InterestFilterHandle> m_interestFilterHandles;
diff --git a/src/crypto-support/crypto-helper.cpp b/src/crypto-support/crypto-helper.cpp
index 7813187..915dce2 100644
--- a/src/crypto-support/crypto-helper.cpp
+++ b/src/crypto-support/crypto-helper.cpp
@@ -374,6 +374,48 @@
   }
 }
 
+int
+hmac_sha_256(const uint8_t* key, size_t key_len,
+             const uint8_t* cleartext, size_t cleartext_len,
+             uint8_t* output, size_t* output_len)
+{
+    if (!key || !cleartext || !output) {
+        return -1;
+    }
+
+    auto private_key = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, nullptr, key, key_len);
+    auto hmac_context = EVP_MD_CTX_new();
+    if (!private_key || !hmac_context) {
+        handleErrors("Cannot create and initialise the context when calling HMAC_CTX_new()");
+        return -1;
+    }
+
+    if (EVP_DigestSignInit(hmac_context, nullptr, EVP_sha256(), nullptr, private_key) != 1) {
+        handleErrors("Cannot initialize DigestSign when calling EVP_DigestSignInit()");
+        EVP_MD_CTX_free(hmac_context);
+        EVP_PKEY_free(private_key);
+        return -1;
+    }
+
+    if (EVP_DigestSignUpdate(hmac_context, cleartext, cleartext_len) != 1) {
+        handleErrors("Cannot update DigestSign when calling EVP_DigestSignUpdate()");
+        EVP_MD_CTX_free(hmac_context);
+        EVP_PKEY_free(private_key);
+        return -1;
+    }
+
+    if (EVP_DigestSignFinal(hmac_context, output, output_len) != 1) {
+        handleErrors("Cannot finish DigestSign when calling EVP_DigestSignFinal()");
+        EVP_MD_CTX_free(hmac_context);
+        EVP_PKEY_free(private_key);
+        return -1;
+    }
+
+    EVP_MD_CTX_free(hmac_context);
+    EVP_PKEY_free(private_key);
+    return 0;
+}
+
 void
 handleErrors(const std::string& errorInfo)
 {
diff --git a/src/crypto-support/crypto-helper.hpp b/src/crypto-support/crypto-helper.hpp
index aaa4237..88f1519 100644
--- a/src/crypto-support/crypto-helper.hpp
+++ b/src/crypto-support/crypto-helper.hpp
@@ -108,6 +108,21 @@
 aes_gcm_128_decrypt(const uint8_t* ciphertext, size_t ciphertext_len, const uint8_t* associated, size_t associated_len,
                     const uint8_t* tag, const uint8_t* key, const uint8_t* iv, uint8_t* plaintext);
 
+/**
+ * HMAC SHA 256 keyed hash function
+ * @param key the key for the function
+ * @param key_len the length of the key
+ * @param cleartext the cleartext array to be hashed
+ * @param cleartext_len the length of the array
+ * @param output the output array
+ * @param output_len the longest output len possible (changed to actual on return).
+ * @return 0 if successful, -1 if failed
+ */
+int
+hmac_sha_256(const uint8_t* key, size_t key_len,
+             const uint8_t* cleartext, size_t cleartext_len,
+             uint8_t* output, size_t* output_len);
+
 void
 handleErrors(const std::string& errorInfo);