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