diff --git a/libraries/networking/src/NLPacket.cpp b/libraries/networking/src/NLPacket.cpp index 5c5077691b..9df84e6abc 100644 --- a/libraries/networking/src/NLPacket.cpp +++ b/libraries/networking/src/NLPacket.cpp @@ -11,6 +11,8 @@ #include "NLPacket.h" +#include "HmacAuth.h" + int NLPacket::localHeaderSize(PacketType type) { bool nonSourced = PacketTypeEnum::getNonSourcedPackets().contains(type); bool nonVerified = PacketTypeEnum::getNonVerifiedPackets().contains(type); @@ -150,6 +152,14 @@ QByteArray NLPacket::verificationHashInHeader(const udt::Packet& packet) { } QByteArray NLPacket::hashForPacketAndSecret(const udt::Packet& packet, const QUuid& connectionSecret) { + HmacAuth hash; + int offset = Packet::totalHeaderSize(packet.isPartOfMessage()) + sizeof(PacketType) + sizeof(PacketVersion) + + NUM_BYTES_RFC4122_UUID + NUM_BYTES_MD5_HASH; + hash.setKey(connectionSecret); + hash.addData(packet.getData() + offset, packet.getDataSize() - offset); + auto hashResult(hash.result()); + return QByteArray((const char*) hashResult.data(), (int) hashResult.size()); + /* QCryptographicHash hash(QCryptographicHash::Md5); int offset = Packet::totalHeaderSize(packet.isPartOfMessage()) + sizeof(PacketType) + sizeof(PacketVersion) @@ -161,6 +171,8 @@ QByteArray NLPacket::hashForPacketAndSecret(const udt::Packet& packet, const QUu // return the hash return hash.result(); + */ + } void NLPacket::writeTypeAndVersion() { diff --git a/libraries/shared/src/HmacAuth.cpp b/libraries/shared/src/HmacAuth.cpp new file mode 100644 index 0000000000..6cc6835329 --- /dev/null +++ b/libraries/shared/src/HmacAuth.cpp @@ -0,0 +1,55 @@ +// +// HmacAuth.cpp + +#include + +#include "HmacAuth.h" + +#include + +HmacAuth::HmacAuth(AuthMethod authMethod) + : _hmacContext(new(HMAC_CTX)) + , _authMethod(authMethod) { + HMAC_CTX_init(_hmacContext.get()); +} + +HmacAuth::~HmacAuth() { + HMAC_CTX_cleanup(_hmacContext.get()); +} + +bool HmacAuth::setKey(const char * keyValue, int keyLen) { + const EVP_MD * sslStruct = nullptr; + + switch (_authMethod) + { + case SHA1: + sslStruct = EVP_sha1(); + break; + + case RIPEMD160: + sslStruct = EVP_ripemd160(); + break; + + default: + return false; + } + + return (bool) HMAC_Init(_hmacContext.get(), keyValue, keyLen, sslStruct); +} + +bool HmacAuth::setKey(const QUuid& uidKey) { + const QByteArray rfcBytes(uidKey.toRfc4122()); + return setKey(rfcBytes.constData(), rfcBytes.length()); +} + +bool HmacAuth::addData(const char * data, int dataLen) { + return (bool) HMAC_Update(_hmacContext.get(), reinterpret_cast(data), dataLen); +} + +HmacAuth::HmacHash HmacAuth::result() { + HmacHash hashValue(EVP_MAX_MD_SIZE); + unsigned int hashLen; + HMAC_Final(_hmacContext.get(), &hashValue[0], &hashLen); + hashValue.resize((size_t) hashLen); + return hashValue; +} diff --git a/libraries/shared/src/HmacAuth.h b/libraries/shared/src/HmacAuth.h new file mode 100644 index 0000000000..9d90f5fb4d --- /dev/null +++ b/libraries/shared/src/HmacAuth.h @@ -0,0 +1,32 @@ +// +// HmacAuth.h +// libraries/shared/src + +#ifndef hifi_HmacAuth_h +#define hifi_HmacAuth_h + +#include +#include + +struct hmac_ctx_st; +class QUuid; + +class HmacAuth { +public: + enum AuthMethod { SHA1, RIPEMD160 }; + typedef std::vector HmacHash; + + HmacAuth(AuthMethod authMethod = SHA1); + ~HmacAuth(); + + bool setKey(const char * keyValue, int keyLen); + bool setKey(const QUuid& uidKey); + bool addData(const char * data, int dataLen); + HmacHash result(); + +private: + std::unique_ptr _hmacContext; + AuthMethod _authMethod { SHA1 }; +}; + +#endif // hifi_HmacAuth_h