xref: /openbmc/phosphor-net-ipmid/integrity_algo.cpp (revision 9b307be647ff786f05c03fa742b982d99dd341ae)
1*9b307be6SVernon Mauery #include <openssl/evp.h>
277531db5STom Joseph #include <openssl/hmac.h>
377531db5STom Joseph #include <openssl/sha.h>
477531db5STom Joseph #include "integrity_algo.hpp"
577531db5STom Joseph #include "message_parsers.hpp"
677531db5STom Joseph 
777531db5STom Joseph namespace cipher
877531db5STom Joseph {
977531db5STom Joseph 
1077531db5STom Joseph namespace integrity
1177531db5STom Joseph {
1277531db5STom Joseph 
13*9b307be6SVernon Mauery AlgoSHA1::AlgoSHA1(const std::vector<uint8_t>& sik)
14*9b307be6SVernon Mauery     : Interface(SHA1_96_AUTHCODE_LENGTH)
1577531db5STom Joseph {
16*9b307be6SVernon Mauery     k1 = generateKn(sik, rmcp::const_1);
1777531db5STom Joseph }
1877531db5STom Joseph 
1970fd29cfSVernon Mauery std::vector<uint8_t> AlgoSHA1::generateHMAC(const uint8_t* input,
2070fd29cfSVernon Mauery         const size_t len) const
21d212a6dcSTom Joseph {
2270fd29cfSVernon Mauery     std::vector<uint8_t> output(SHA_DIGEST_LENGTH);
23d212a6dcSTom Joseph     unsigned int mdLen = 0;
24d212a6dcSTom Joseph 
25*9b307be6SVernon Mauery     if (HMAC(EVP_sha1(), k1.data(), k1.size(), input, len,
26d212a6dcSTom Joseph              output.data(), &mdLen) == NULL)
27d212a6dcSTom Joseph     {
28d212a6dcSTom Joseph         throw std::runtime_error("Generating integrity data failed");
29d212a6dcSTom Joseph     }
30d212a6dcSTom Joseph 
31d212a6dcSTom Joseph     // HMAC generates Message Digest to the size of SHA_DIGEST_LENGTH, the
32d212a6dcSTom Joseph     // AuthCode field length is based on the integrity algorithm. So we are
33d212a6dcSTom Joseph     // interested only in the AuthCode field length of the generated Message
34d212a6dcSTom Joseph     // digest.
35d212a6dcSTom Joseph     output.resize(authCodeLength);
36d212a6dcSTom Joseph 
37d212a6dcSTom Joseph     return output;
38d212a6dcSTom Joseph }
39d212a6dcSTom Joseph 
4070fd29cfSVernon Mauery bool AlgoSHA1::verifyIntegrityData(
4170fd29cfSVernon Mauery         const std::vector<uint8_t>& packet,
42d212a6dcSTom Joseph         const size_t length,
4370fd29cfSVernon Mauery         std::vector<uint8_t>::const_iterator integrityData) const
44d212a6dcSTom Joseph {
45d212a6dcSTom Joseph 
46d212a6dcSTom Joseph     auto output = generateHMAC(
47d212a6dcSTom Joseph             packet.data() + message::parser::RMCP_SESSION_HEADER_SIZE,
48d212a6dcSTom Joseph             length);
49d212a6dcSTom Joseph 
50d212a6dcSTom Joseph     // Verify if the generated integrity data for the packet and the received
51d212a6dcSTom Joseph     // integrity data matches.
52d212a6dcSTom Joseph     return (std::equal(output.begin(), output.end(), integrityData));
53d212a6dcSTom Joseph }
54d212a6dcSTom Joseph 
5570fd29cfSVernon Mauery std::vector<uint8_t> AlgoSHA1::generateIntegrityData(
5670fd29cfSVernon Mauery         const std::vector<uint8_t>& packet) const
57d212a6dcSTom Joseph {
58d212a6dcSTom Joseph     return generateHMAC(
59d212a6dcSTom Joseph             packet.data() + message::parser::RMCP_SESSION_HEADER_SIZE,
60d212a6dcSTom Joseph             packet.size() - message::parser::RMCP_SESSION_HEADER_SIZE);
61d212a6dcSTom Joseph }
62d212a6dcSTom Joseph 
63*9b307be6SVernon Mauery std::vector<uint8_t> AlgoSHA1::generateKn(const std::vector<uint8_t>& sik,
64*9b307be6SVernon Mauery         const rmcp::Const_n& const_n) const
65*9b307be6SVernon Mauery {
66*9b307be6SVernon Mauery     unsigned int mdLen = 0;
67*9b307be6SVernon Mauery     std::vector<uint8_t> Kn(sik.size());
68*9b307be6SVernon Mauery 
69*9b307be6SVernon Mauery     // Generated Kn for the integrity algorithm with the additional key keyed
70*9b307be6SVernon Mauery     // with SIK.
71*9b307be6SVernon Mauery     if (HMAC(EVP_sha1(), sik.data(), sik.size(), const_n.data(),
72*9b307be6SVernon Mauery              const_n.size(), Kn.data(), &mdLen) == NULL)
73*9b307be6SVernon Mauery     {
74*9b307be6SVernon Mauery         throw std::runtime_error("Generating KeyN for integrity "
75*9b307be6SVernon Mauery                                  "algorithm failed");
76*9b307be6SVernon Mauery     }
77*9b307be6SVernon Mauery     return Kn;
78*9b307be6SVernon Mauery }
79*9b307be6SVernon Mauery 
8077531db5STom Joseph }// namespace integrity
8177531db5STom Joseph 
8277531db5STom Joseph }// namespace cipher
83