xref: /openbmc/phosphor-net-ipmid/integrity_algo.cpp (revision d212a6dc85e0dcfb481e5925c46869804dbf2d87)
177531db5STom Joseph #include <openssl/hmac.h>
277531db5STom Joseph #include <openssl/sha.h>
377531db5STom Joseph #include "integrity_algo.hpp"
477531db5STom Joseph #include "message_parsers.hpp"
577531db5STom Joseph 
677531db5STom Joseph namespace cipher
777531db5STom Joseph {
877531db5STom Joseph 
977531db5STom Joseph namespace integrity
1077531db5STom Joseph {
1177531db5STom Joseph 
1277531db5STom Joseph Interface::Interface(const Buffer& sik, const Key& addKey, size_t authLength)
1377531db5STom Joseph {
1477531db5STom Joseph     unsigned int mdLen = 0;
1577531db5STom Joseph 
1677531db5STom Joseph     // Generated K1 for the integrity algorithm with the additional key keyed
1777531db5STom Joseph     // with SIK.
1877531db5STom Joseph     if (HMAC(EVP_sha1(), sik.data(), sik.size(), addKey.data(),
1977531db5STom Joseph              addKey.size(), K1.data(), &mdLen) == NULL)
2077531db5STom Joseph     {
2177531db5STom Joseph         throw std::runtime_error("Generating Key1 for integrity "
2277531db5STom Joseph                                  "algorithm failed");
2377531db5STom Joseph     }
2477531db5STom Joseph 
2577531db5STom Joseph     authCodeLength = authLength;
2677531db5STom Joseph }
2777531db5STom Joseph 
28*d212a6dcSTom Joseph Buffer AlgoSHA1::generateHMAC(const uint8_t* input, const size_t len) const
29*d212a6dcSTom Joseph {
30*d212a6dcSTom Joseph     Buffer output(SHA_DIGEST_LENGTH);
31*d212a6dcSTom Joseph     unsigned int mdLen = 0;
32*d212a6dcSTom Joseph 
33*d212a6dcSTom Joseph     if (HMAC(EVP_sha1(), K1.data(), K1.size(), input, len,
34*d212a6dcSTom Joseph              output.data(), &mdLen) == NULL)
35*d212a6dcSTom Joseph     {
36*d212a6dcSTom Joseph         throw std::runtime_error("Generating integrity data failed");
37*d212a6dcSTom Joseph     }
38*d212a6dcSTom Joseph 
39*d212a6dcSTom Joseph     // HMAC generates Message Digest to the size of SHA_DIGEST_LENGTH, the
40*d212a6dcSTom Joseph     // AuthCode field length is based on the integrity algorithm. So we are
41*d212a6dcSTom Joseph     // interested only in the AuthCode field length of the generated Message
42*d212a6dcSTom Joseph     // digest.
43*d212a6dcSTom Joseph     output.resize(authCodeLength);
44*d212a6dcSTom Joseph 
45*d212a6dcSTom Joseph     return output;
46*d212a6dcSTom Joseph }
47*d212a6dcSTom Joseph 
48*d212a6dcSTom Joseph bool AlgoSHA1::verifyIntegrityData(const Buffer& packet,
49*d212a6dcSTom Joseph                                    const size_t length,
50*d212a6dcSTom Joseph                                    Buffer::const_iterator integrityData) const
51*d212a6dcSTom Joseph {
52*d212a6dcSTom Joseph 
53*d212a6dcSTom Joseph     auto output = generateHMAC(
54*d212a6dcSTom Joseph             packet.data() + message::parser::RMCP_SESSION_HEADER_SIZE,
55*d212a6dcSTom Joseph             length);
56*d212a6dcSTom Joseph 
57*d212a6dcSTom Joseph     // Verify if the generated integrity data for the packet and the received
58*d212a6dcSTom Joseph     // integrity data matches.
59*d212a6dcSTom Joseph     return (std::equal(output.begin(), output.end(), integrityData));
60*d212a6dcSTom Joseph }
61*d212a6dcSTom Joseph 
62*d212a6dcSTom Joseph Buffer AlgoSHA1::generateIntegrityData(const Buffer& packet) const
63*d212a6dcSTom Joseph {
64*d212a6dcSTom Joseph     return generateHMAC(
65*d212a6dcSTom Joseph             packet.data() + message::parser::RMCP_SESSION_HEADER_SIZE,
66*d212a6dcSTom Joseph             packet.size() - message::parser::RMCP_SESSION_HEADER_SIZE);
67*d212a6dcSTom Joseph }
68*d212a6dcSTom Joseph 
6977531db5STom Joseph }// namespace integrity
7077531db5STom Joseph 
7177531db5STom Joseph }// namespace cipher
72