1 #include <openssl/evp.h> 2 #include <openssl/hmac.h> 3 #include <openssl/sha.h> 4 #include "integrity_algo.hpp" 5 #include "message_parsers.hpp" 6 7 namespace cipher 8 { 9 10 namespace integrity 11 { 12 13 AlgoSHA1::AlgoSHA1(const std::vector<uint8_t>& sik) 14 : Interface(SHA1_96_AUTHCODE_LENGTH) 15 { 16 k1 = generateKn(sik, rmcp::const_1); 17 } 18 19 std::vector<uint8_t> AlgoSHA1::generateHMAC(const uint8_t* input, 20 const size_t len) const 21 { 22 std::vector<uint8_t> output(SHA_DIGEST_LENGTH); 23 unsigned int mdLen = 0; 24 25 if (HMAC(EVP_sha1(), k1.data(), k1.size(), input, len, 26 output.data(), &mdLen) == NULL) 27 { 28 throw std::runtime_error("Generating integrity data failed"); 29 } 30 31 // HMAC generates Message Digest to the size of SHA_DIGEST_LENGTH, the 32 // AuthCode field length is based on the integrity algorithm. So we are 33 // interested only in the AuthCode field length of the generated Message 34 // digest. 35 output.resize(authCodeLength); 36 37 return output; 38 } 39 40 bool AlgoSHA1::verifyIntegrityData( 41 const std::vector<uint8_t>& packet, 42 const size_t length, 43 std::vector<uint8_t>::const_iterator integrityData) const 44 { 45 46 auto output = generateHMAC( 47 packet.data() + message::parser::RMCP_SESSION_HEADER_SIZE, 48 length); 49 50 // Verify if the generated integrity data for the packet and the received 51 // integrity data matches. 52 return (std::equal(output.begin(), output.end(), integrityData)); 53 } 54 55 std::vector<uint8_t> AlgoSHA1::generateIntegrityData( 56 const std::vector<uint8_t>& packet) const 57 { 58 return generateHMAC( 59 packet.data() + message::parser::RMCP_SESSION_HEADER_SIZE, 60 packet.size() - message::parser::RMCP_SESSION_HEADER_SIZE); 61 } 62 63 std::vector<uint8_t> AlgoSHA1::generateKn(const std::vector<uint8_t>& sik, 64 const rmcp::Const_n& const_n) const 65 { 66 unsigned int mdLen = 0; 67 std::vector<uint8_t> Kn(sik.size()); 68 69 // Generated Kn for the integrity algorithm with the additional key keyed 70 // with SIK. 71 if (HMAC(EVP_sha1(), sik.data(), sik.size(), const_n.data(), 72 const_n.size(), Kn.data(), &mdLen) == NULL) 73 { 74 throw std::runtime_error("Generating KeyN for integrity " 75 "algorithm failed"); 76 } 77 return Kn; 78 } 79 80 }// namespace integrity 81 82 }// namespace cipher 83