Add support for cipher suite 17

cipher suite 17 uses RAKP_HMAC_SHA256 for authentication and
RAKP_HMAC_SHA256_128 for integrity. This adds those in and fixes up the
lookups so the stack knows about the new algorithms.

Change-Id: Icdc66563d08060fc0e541ceaf3bee9dd5f89fdb2
Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
diff --git a/integrity_algo.cpp b/integrity_algo.cpp
index 62c2653..0c3efe8 100644
--- a/integrity_algo.cpp
+++ b/integrity_algo.cpp
@@ -77,6 +77,73 @@
     return Kn;
 }
 
+AlgoSHA256::AlgoSHA256(const std::vector<uint8_t>& sik)
+    : Interface(SHA256_128_AUTHCODE_LENGTH)
+{
+    k1 = generateKn(sik, rmcp::const_1);
+}
+
+std::vector<uint8_t> AlgoSHA256::generateHMAC(const uint8_t* input,
+        const size_t len) const
+{
+    std::vector<uint8_t> output(SHA256_DIGEST_LENGTH);
+    unsigned int mdLen = 0;
+
+    if (HMAC(EVP_sha256(), k1.data(), k1.size(), input, len,
+             output.data(), &mdLen) == NULL)
+    {
+        throw std::runtime_error("Generating HMAC_SHA256_128 failed");
+    }
+
+    // HMAC generates Message Digest to the size of SHA256_DIGEST_LENGTH, the
+    // AuthCode field length is based on the integrity algorithm. So we are
+    // interested only in the AuthCode field length of the generated Message
+    // digest.
+    output.resize(authCodeLength);
+
+    return output;
+}
+
+bool AlgoSHA256::verifyIntegrityData(
+        const std::vector<uint8_t>& packet,
+        const size_t length,
+        std::vector<uint8_t>::const_iterator integrityData) const
+{
+
+    auto output = generateHMAC(
+            packet.data() + message::parser::RMCP_SESSION_HEADER_SIZE,
+            length);
+
+    // Verify if the generated integrity data for the packet and the received
+    // integrity data matches.
+    return (std::equal(output.begin(), output.end(), integrityData));
+}
+
+std::vector<uint8_t> AlgoSHA256::generateIntegrityData(
+        const std::vector<uint8_t>& packet) const
+{
+    return generateHMAC(
+            packet.data() + message::parser::RMCP_SESSION_HEADER_SIZE,
+            packet.size() - message::parser::RMCP_SESSION_HEADER_SIZE);
+}
+
+std::vector<uint8_t> AlgoSHA256::generateKn(const std::vector<uint8_t>& sik,
+        const rmcp::Const_n& const_n) const
+{
+    unsigned int mdLen = 0;
+    std::vector<uint8_t> Kn(sik.size());
+
+    // Generated Kn for the integrity algorithm with the additional key keyed
+    // with SIK.
+    if (HMAC(EVP_sha256(), sik.data(), sik.size(), const_n.data(),
+             const_n.size(), Kn.data(), &mdLen) == NULL)
+    {
+        throw std::runtime_error("Generating KeyN for integrity "
+                                 "algorithm HMAC_SHA256 failed");
+    }
+    return Kn;
+}
+
 }// namespace integrity
 
 }// namespace cipher