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 12*70fd29cfSVernon Mauery Interface::Interface(const std::vector<uint8_t>& sik, 13*70fd29cfSVernon Mauery const Key& addKey, size_t authLength) 1477531db5STom Joseph { 1577531db5STom Joseph unsigned int mdLen = 0; 1677531db5STom Joseph 1777531db5STom Joseph // Generated K1 for the integrity algorithm with the additional key keyed 1877531db5STom Joseph // with SIK. 1977531db5STom Joseph if (HMAC(EVP_sha1(), sik.data(), sik.size(), addKey.data(), 2077531db5STom Joseph addKey.size(), K1.data(), &mdLen) == NULL) 2177531db5STom Joseph { 2277531db5STom Joseph throw std::runtime_error("Generating Key1 for integrity " 2377531db5STom Joseph "algorithm failed"); 2477531db5STom Joseph } 2577531db5STom Joseph 2677531db5STom Joseph authCodeLength = authLength; 2777531db5STom Joseph } 2877531db5STom Joseph 29*70fd29cfSVernon Mauery std::vector<uint8_t> AlgoSHA1::generateHMAC(const uint8_t* input, 30*70fd29cfSVernon Mauery const size_t len) const 31d212a6dcSTom Joseph { 32*70fd29cfSVernon Mauery std::vector<uint8_t> output(SHA_DIGEST_LENGTH); 33d212a6dcSTom Joseph unsigned int mdLen = 0; 34d212a6dcSTom Joseph 35d212a6dcSTom Joseph if (HMAC(EVP_sha1(), K1.data(), K1.size(), input, len, 36d212a6dcSTom Joseph output.data(), &mdLen) == NULL) 37d212a6dcSTom Joseph { 38d212a6dcSTom Joseph throw std::runtime_error("Generating integrity data failed"); 39d212a6dcSTom Joseph } 40d212a6dcSTom Joseph 41d212a6dcSTom Joseph // HMAC generates Message Digest to the size of SHA_DIGEST_LENGTH, the 42d212a6dcSTom Joseph // AuthCode field length is based on the integrity algorithm. So we are 43d212a6dcSTom Joseph // interested only in the AuthCode field length of the generated Message 44d212a6dcSTom Joseph // digest. 45d212a6dcSTom Joseph output.resize(authCodeLength); 46d212a6dcSTom Joseph 47d212a6dcSTom Joseph return output; 48d212a6dcSTom Joseph } 49d212a6dcSTom Joseph 50*70fd29cfSVernon Mauery bool AlgoSHA1::verifyIntegrityData( 51*70fd29cfSVernon Mauery const std::vector<uint8_t>& packet, 52d212a6dcSTom Joseph const size_t length, 53*70fd29cfSVernon Mauery std::vector<uint8_t>::const_iterator integrityData) const 54d212a6dcSTom Joseph { 55d212a6dcSTom Joseph 56d212a6dcSTom Joseph auto output = generateHMAC( 57d212a6dcSTom Joseph packet.data() + message::parser::RMCP_SESSION_HEADER_SIZE, 58d212a6dcSTom Joseph length); 59d212a6dcSTom Joseph 60d212a6dcSTom Joseph // Verify if the generated integrity data for the packet and the received 61d212a6dcSTom Joseph // integrity data matches. 62d212a6dcSTom Joseph return (std::equal(output.begin(), output.end(), integrityData)); 63d212a6dcSTom Joseph } 64d212a6dcSTom Joseph 65*70fd29cfSVernon Mauery std::vector<uint8_t> AlgoSHA1::generateIntegrityData( 66*70fd29cfSVernon Mauery const std::vector<uint8_t>& packet) const 67d212a6dcSTom Joseph { 68d212a6dcSTom Joseph return generateHMAC( 69d212a6dcSTom Joseph packet.data() + message::parser::RMCP_SESSION_HEADER_SIZE, 70d212a6dcSTom Joseph packet.size() - message::parser::RMCP_SESSION_HEADER_SIZE); 71d212a6dcSTom Joseph } 72d212a6dcSTom Joseph 7377531db5STom Joseph }// namespace integrity 7477531db5STom Joseph 7577531db5STom Joseph }// namespace cipher 76