diff options
26 files changed, 258 insertions, 135 deletions
diff --git a/3rdparty/arc4random-src/arc4random_uniform.cpp b/3rdparty/arc4random-src/arc4random_uniform.cpp index cb7307668..4ac1b6724 100644 --- a/3rdparty/arc4random-src/arc4random_uniform.cpp +++ b/3rdparty/arc4random-src/arc4random_uniform.cpp @@ -32,7 +32,7 @@ // - Disable MSVC warning 4146. #include <stdint.h> -#include "CryptographicRandom.h" +#include "crypto/CryptographicRandom.h" #if defined(_MSC_VER) // Disable "unary minus operator applied to unsigned type, result still unsigned" diff --git a/src/Connection.cpp b/src/Connection.cpp index a01a6b19d..8771f39b7 100644 --- a/src/Connection.cpp +++ b/src/Connection.cpp @@ -29,6 +29,7 @@ Connection::Connection(QObject *p, QSslSocket *qtsSock) : QObject(p) { qtsSocket->setParent(this); iPacketLength = -1; bDisconnectedEmitted = false; + csCrypt = std::make_unique<CryptStateOCB2>(); static bool bDeclared = false; if (! bDeclared) { diff --git a/src/Connection.h b/src/Connection.h index 9928ef8a1..37ba15f0f 100644 --- a/src/Connection.h +++ b/src/Connection.h @@ -12,13 +12,15 @@ # include "win.h" #endif -#include "CryptState.h" +#include "crypto/CryptState.h" +#include "crypto/CryptStateOCB2.h" #include <QtCore/QElapsedTimer> #include <QtCore/QList> #include <QtCore/QMutex> #include <QtCore/QObject> #include <QtNetwork/QSslSocket> +#include <memory> #ifdef Q_OS_WIN # include <ws2tcpip.h> @@ -70,7 +72,7 @@ class Connection : public QObject { /// qmCrypt locks access to csCrypt. QMutex qmCrypt; #endif - CryptState csCrypt; + std::unique_ptr<CryptState> csCrypt; QList<QSslCertificate> peerCertificateChain() const; QSslCipher sessionCipher() const; diff --git a/src/PasswordGenerator.cpp b/src/PasswordGenerator.cpp index 8e4a7e332..995c8d133 100644 --- a/src/PasswordGenerator.cpp +++ b/src/PasswordGenerator.cpp @@ -3,7 +3,7 @@ // that can be found in the LICENSE file at the root of the // Mumble source tree or at <https://www.mumble.info/LICENSE>. -#include "CryptographicRandom.h" +#include "crypto/CryptographicRandom.h" #include "PasswordGenerator.h" #include <QtCore/QVector> diff --git a/src/crypto/CryptState.h b/src/crypto/CryptState.h new file mode 100644 index 000000000..292652e80 --- /dev/null +++ b/src/crypto/CryptState.h @@ -0,0 +1,47 @@ +// Copyright 2005-2020 The Mumble Developers. All rights reserved. +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file at the root of the +// Mumble source tree or at <https://www.mumble.info/LICENSE>. + +#ifndef MUMBLE_CRYPTSTATE_H_ +#define MUMBLE_CRYPTSTATE_H_ + +#include "Timer.h" +#include <string> + +class CryptState { + private: + Q_DISABLE_COPY(CryptState) + public: + unsigned int uiGood = 0; + unsigned int uiLate = 0; + unsigned int uiLost = 0; + unsigned int uiResync = 0; + + unsigned int uiRemoteGood = 0; + unsigned int uiRemoteLate = 0; + unsigned int uiRemoteLost = 0; + unsigned int uiRemoteResync = 0; + + Timer tLastGood; + Timer tLastRequest; + bool bInit = false; + CryptState() {}; + virtual ~CryptState() {}; + + virtual bool isValid() const = 0; + virtual void genKey() = 0; + virtual void setKey(const std::string& rkey, const std::string& eiv, const std::string& div) = 0; + virtual void setRawKey(const std::string& rkey) = 0; + virtual void setEncryptIV(const std::string& iv) = 0; + virtual void setDecryptIV(const std::string& iv) = 0; + virtual std::string getRawKey() = 0; + virtual std::string getEncryptIV() = 0; + virtual std::string getDecryptIV() = 0; + + virtual bool decrypt(const unsigned char *source, unsigned char *dst, unsigned int crypted_length) = 0; + virtual bool encrypt(const unsigned char *source, unsigned char *dst, unsigned int plain_length) = 0; +}; + + +#endif diff --git a/src/CryptState.cpp b/src/crypto/CryptStateOCB2.cpp index 519688fd7..5d85e7f97 100644 --- a/src/CryptState.cpp +++ b/src/crypto/CryptStateOCB2.cpp @@ -23,30 +23,25 @@ # endif #endif -#include "CryptState.h" - +#include "CryptStateOCB2.h" #include "ByteSwap.h" #include <cstring> - #include <openssl/rand.h> -CryptState::CryptState() { +CryptStateOCB2::CryptStateOCB2() : CryptState() { for (int i=0;i<0x100;i++) decrypt_history[i] = 0; - bInit = false; memset(raw_key, 0, AES_KEY_SIZE_BYTES); memset(encrypt_iv, 0, AES_BLOCK_SIZE); memset(decrypt_iv, 0, AES_BLOCK_SIZE); - uiGood=uiLate=uiLost=uiResync=0; - uiRemoteGood=uiRemoteLate=uiRemoteLost=uiRemoteResync=0; } -bool CryptState::isValid() const { +bool CryptStateOCB2::isValid() const { return bInit; } -void CryptState::genKey() { +void CryptStateOCB2::genKey() { RAND_bytes(raw_key, AES_KEY_SIZE_BYTES); RAND_bytes(encrypt_iv, AES_BLOCK_SIZE); RAND_bytes(decrypt_iv, AES_BLOCK_SIZE); @@ -55,20 +50,48 @@ void CryptState::genKey() { bInit = true; } -void CryptState::setKey(const unsigned char *rkey, const unsigned char *eiv, const unsigned char *div) { - memcpy(raw_key, rkey, AES_KEY_SIZE_BYTES); - memcpy(encrypt_iv, eiv, AES_BLOCK_SIZE); - memcpy(decrypt_iv, div, AES_BLOCK_SIZE); - AES_set_encrypt_key(raw_key, AES_KEY_SIZE_BITS, &encrypt_key); - AES_set_decrypt_key(raw_key, AES_KEY_SIZE_BITS, &decrypt_key); - bInit = true; +void CryptStateOCB2::setKey(const std::string& rkey, const std::string& eiv, const std::string& div) { + if(rkey.length() == AES_KEY_SIZE_BYTES && eiv.length() == AES_BLOCK_SIZE && div.length() == AES_BLOCK_SIZE) { + memcpy(raw_key, rkey.data(), AES_KEY_SIZE_BYTES); + memcpy(encrypt_iv, eiv.data(), AES_BLOCK_SIZE); + memcpy(decrypt_iv, div.data(), AES_BLOCK_SIZE); + AES_set_encrypt_key(raw_key, AES_KEY_SIZE_BITS, &encrypt_key); + AES_set_decrypt_key(raw_key, AES_KEY_SIZE_BITS, &decrypt_key); + bInit = true; + } +} + +void CryptStateOCB2::setRawKey(const std::string& rkey) { + if(rkey.length() == AES_KEY_SIZE_BYTES){ + memcpy(raw_key, rkey.data(), AES_KEY_SIZE_BYTES); + } +} + +void CryptStateOCB2::setEncryptIV(const std::string& iv) { + if(iv.length() == AES_BLOCK_SIZE) { + memcpy(encrypt_iv, iv.data(), AES_BLOCK_SIZE); + } +} + +void CryptStateOCB2::setDecryptIV(const std::string& iv) { + if(iv.length() == AES_BLOCK_SIZE) { + memcpy(decrypt_iv, iv.data(), AES_BLOCK_SIZE); + } +} + +std::string CryptStateOCB2::getRawKey() { + return std::string(reinterpret_cast<const char*>(raw_key), AES_KEY_SIZE_BYTES); +} + +std::string CryptStateOCB2::getEncryptIV() { + return std::string(reinterpret_cast<const char*>(encrypt_iv), AES_BLOCK_SIZE); } -void CryptState::setDecryptIV(const unsigned char *iv) { - memcpy(decrypt_iv, iv, AES_BLOCK_SIZE); +std::string CryptStateOCB2::getDecryptIV() { + return std::string(reinterpret_cast<const char*>(decrypt_iv), AES_BLOCK_SIZE); } -bool CryptState::encrypt(const unsigned char *source, unsigned char *dst, unsigned int plain_length) { +bool CryptStateOCB2::encrypt(const unsigned char *source, unsigned char *dst, unsigned int plain_length) { unsigned char tag[AES_BLOCK_SIZE]; // First, increase our IV. @@ -87,7 +110,7 @@ bool CryptState::encrypt(const unsigned char *source, unsigned char *dst, unsign return true; } -bool CryptState::decrypt(const unsigned char *source, unsigned char *dst, unsigned int crypted_length) { +bool CryptStateOCB2::decrypt(const unsigned char *source, unsigned char *dst, unsigned int crypted_length) { if (crypted_length < 4) return false; @@ -227,7 +250,7 @@ static void inline ZERO(keyblock &block) { #define AESencrypt(src,dst,key) AES_encrypt(reinterpret_cast<const unsigned char *>(src),reinterpret_cast<unsigned char *>(dst), key); #define AESdecrypt(src,dst,key) AES_decrypt(reinterpret_cast<const unsigned char *>(src),reinterpret_cast<unsigned char *>(dst), key); -bool CryptState::ocb_encrypt(const unsigned char *plain, unsigned char *encrypted, unsigned int len, const unsigned char *nonce, unsigned char *tag) { +bool CryptStateOCB2::ocb_encrypt(const unsigned char *plain, unsigned char *encrypted, unsigned int len, const unsigned char *nonce, unsigned char *tag) { keyblock checksum, delta, tmp, pad; bool success = true; @@ -276,7 +299,7 @@ bool CryptState::ocb_encrypt(const unsigned char *plain, unsigned char *encrypte return success; } -bool CryptState::ocb_decrypt(const unsigned char *encrypted, unsigned char *plain, unsigned int len, const unsigned char *nonce, unsigned char *tag) { +bool CryptStateOCB2::ocb_decrypt(const unsigned char *encrypted, unsigned char *plain, unsigned int len, const unsigned char *nonce, unsigned char *tag) { keyblock checksum, delta, tmp, pad; bool success = true; diff --git a/src/crypto/CryptStateOCB2.h b/src/crypto/CryptStateOCB2.h new file mode 100644 index 000000000..4009264c2 --- /dev/null +++ b/src/crypto/CryptStateOCB2.h @@ -0,0 +1,49 @@ +// Copyright 2005-2020 The Mumble Developers. All rights reserved. +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file at the root of the +// Mumble source tree or at <https://www.mumble.info/LICENSE>. + +#ifndef MUMBLE_CRYPTSTATEOCB2_H +#define MUMBLE_CRYPTSTATEOCB2_H + +#include "CryptState.h" + +#include <openssl/aes.h> + +#define AES_KEY_SIZE_BITS 128 +#define AES_KEY_SIZE_BYTES (AES_KEY_SIZE_BITS/8) + + +class CryptStateOCB2 : public CryptState { +public: + CryptStateOCB2(); + ~CryptStateOCB2() {}; + + virtual bool isValid() const Q_DECL_OVERRIDE; + virtual void genKey() Q_DECL_OVERRIDE; + virtual void setKey(const std::string& rkey, const std::string& eiv, const std::string& div) Q_DECL_OVERRIDE; + virtual void setRawKey(const std::string& rkey) Q_DECL_OVERRIDE; + virtual void setEncryptIV(const std::string& iv) Q_DECL_OVERRIDE; + virtual void setDecryptIV(const std::string& iv) Q_DECL_OVERRIDE; + virtual std::string getRawKey() Q_DECL_OVERRIDE; + virtual std::string getEncryptIV() Q_DECL_OVERRIDE; + virtual std::string getDecryptIV() Q_DECL_OVERRIDE; + + virtual bool decrypt(const unsigned char *source, unsigned char *dst, unsigned int crypted_length) Q_DECL_OVERRIDE; + virtual bool encrypt(const unsigned char *source, unsigned char *dst, unsigned int plain_length) Q_DECL_OVERRIDE; + + bool ocb_encrypt(const unsigned char *plain, unsigned char *encrypted, unsigned int len, const unsigned char *nonce, unsigned char *tag); + bool ocb_decrypt(const unsigned char *encrypted, unsigned char *plain, unsigned int len, const unsigned char *nonce, unsigned char *tag); + +private: + unsigned char raw_key[AES_KEY_SIZE_BYTES]; + unsigned char encrypt_iv[AES_BLOCK_SIZE]; + unsigned char decrypt_iv[AES_BLOCK_SIZE]; + unsigned char decrypt_history[0x100]; + + AES_KEY encrypt_key; + AES_KEY decrypt_key; +}; + + +#endif //MUMBLE_CRYPTSTATEOCB2_H diff --git a/src/CryptographicHash.cpp b/src/crypto/CryptographicHash.cpp index 650e7ca53..650e7ca53 100644 --- a/src/CryptographicHash.cpp +++ b/src/crypto/CryptographicHash.cpp diff --git a/src/CryptographicHash.h b/src/crypto/CryptographicHash.h index d5af2871c..d5af2871c 100644 --- a/src/CryptographicHash.h +++ b/src/crypto/CryptographicHash.h diff --git a/src/CryptographicRandom.cpp b/src/crypto/CryptographicRandom.cpp index 4881e4147..4881e4147 100644 --- a/src/CryptographicRandom.cpp +++ b/src/crypto/CryptographicRandom.cpp diff --git a/src/CryptographicRandom.h b/src/crypto/CryptographicRandom.h index e46e22dcf..e46e22dcf 100644 --- a/src/CryptographicRandom.h +++ b/src/crypto/CryptographicRandom.h diff --git a/src/mumble.pri b/src/mumble.pri index ddcfe810b..4dd03aad9 100644 --- a/src/mumble.pri +++ b/src/mumble.pri @@ -9,7 +9,7 @@ include(../qmake/rcc.pri) include(../qmake/pkgconfig.pri) VERSION = 1.4.0 -DIST = mumble.pri Message.h PacketDataStream.h CryptState.h Timer.h Version.h OSInfo.h SSL.h +DIST = mumble.pri Message.h PacketDataStream.h crypto/CryptState.h crypto/CryptStateOCB2.h Timer.h Version.h OSInfo.h SSL.h CONFIG += qt thread debug_and_release warn_on DEFINES *= MUMBLE_VERSION_STRING=$$VERSION INCLUDEPATH += $$PWD . ../mumble_proto @@ -19,7 +19,8 @@ HEADERS *= \ ACL.h \ Channel.h \ ChannelListener.h \ - CryptState.h \ + crypto/CryptState.h \ + crypto/CryptStateOCB2.h \ Connection.h \ Group.h \ HTMLFilter.h \ @@ -34,8 +35,8 @@ HEADERS *= \ licenses.h \ License.h \ LogEmitter.h \ - CryptographicHash.h \ - CryptographicRandom.h \ + crypto/CryptographicHash.h \ + crypto/CryptographicRandom.h \ PasswordGenerator.h \ ByteSwap.h \ HostAddress.cpp \ @@ -60,15 +61,15 @@ SOURCES *= \ HTMLFilter.cpp \ User.cpp \ Timer.cpp \ - CryptState.cpp \ + crypto/CryptStateOCB2.cpp \ OSInfo.cpp \ SSL.cpp \ Version.cpp \ SSLCipherInfo.cpp \ License.cpp \ LogEmitter.cpp \ - CryptographicHash.cpp \ - CryptographicRandom.cpp \ + crypto/CryptographicHash.cpp \ + crypto/CryptographicRandom.cpp \ PasswordGenerator.cpp \ HostAddress.cpp \ Ban.cpp \ diff --git a/src/mumble/MainWindow.cpp b/src/mumble/MainWindow.cpp index ba7a56768..41c6669e4 100644 --- a/src/mumble/MainWindow.cpp +++ b/src/mumble/MainWindow.cpp @@ -1353,7 +1353,6 @@ void MainWindow::on_qaServerInformation_triggered() { if (! c) return; - CryptState &cs = c->csCrypt; QSslCipher qsc = g.sh->qscCipher; QString qsVersion=tr("<h2>Version</h2><p>Protocol %1</p>").arg(MumbleVersion::toString(g.sh->uiVersion)); @@ -1438,8 +1437,8 @@ void MainWindow::on_qaServerInformation_triggered() { "<tr><th>%7</th><td>%11</td><td>%15</td></tr>" "</table>") .arg(tr("UDP Statistics")).arg(tr("To Server")).arg(tr("From Server")).arg(tr("Good")).arg(tr("Late")).arg(tr("Lost")).arg(tr("Resync")) - .arg(cs.uiRemoteGood).arg(cs.uiRemoteLate).arg(cs.uiRemoteLost).arg(cs.uiRemoteResync) - .arg(cs.uiGood).arg(cs.uiLate).arg(cs.uiLost).arg(cs.uiResync); + .arg(c->csCrypt->uiRemoteGood).arg(c->csCrypt->uiRemoteLate).arg(c->csCrypt->uiRemoteLost).arg(c->csCrypt->uiRemoteResync) + .arg(c->csCrypt->uiGood).arg(c->csCrypt->uiLate).arg(c->csCrypt->uiLost).arg(c->csCrypt->uiResync); } qsAudio=tr("<h2>Audio bandwidth</h2><p>Maximum %1 kbit/s<br />Current %2 kbit/s<br />Codec: %3</p>").arg(g.iMaxBandwidth / 1000.0,0,'f',1).arg(g.iAudioBandwidth / 1000.0,0,'f',1).arg(currentCodec()); diff --git a/src/mumble/Messages.cpp b/src/mumble/Messages.cpp index 4d6a11bff..37eae7a07 100644 --- a/src/mumble/Messages.cpp +++ b/src/mumble/Messages.cpp @@ -31,7 +31,7 @@ #include "UserModel.h" #include "VersionCheck.h" #include "ViewCert.h" -#include "CryptState.h" +#include "crypto/CryptState.h" #include "Utils.h" #include "ChannelListener.h" #include "TalkingUI.h" @@ -947,17 +947,16 @@ void MainWindow::msgCryptSetup(const MumbleProto::CryptSetup &msg) { const std::string &key = msg.key(); const std::string &client_nonce = msg.client_nonce(); const std::string &server_nonce = msg.server_nonce(); - if (key.size() == AES_KEY_SIZE_BYTES && client_nonce.size() == AES_BLOCK_SIZE && server_nonce.size() == AES_BLOCK_SIZE) - c->csCrypt.setKey(reinterpret_cast<const unsigned char *>(key.data()), reinterpret_cast<const unsigned char *>(client_nonce.data()), reinterpret_cast<const unsigned char *>(server_nonce.data())); + c->csCrypt->setKey(key, client_nonce, server_nonce); } else if (msg.has_server_nonce()) { const std::string &server_nonce = msg.server_nonce(); if (server_nonce.size() == AES_BLOCK_SIZE) { - c->csCrypt.uiResync++; - memcpy(c->csCrypt.decrypt_iv, server_nonce.data(), AES_BLOCK_SIZE); + c->csCrypt->uiResync++; + c->csCrypt->setDecryptIV(server_nonce); } } else { MumbleProto::CryptSetup mpcs; - mpcs.set_client_nonce(std::string(reinterpret_cast<const char *>(c->csCrypt.encrypt_iv), AES_BLOCK_SIZE)); + mpcs.set_client_nonce(c->csCrypt->getEncryptIV()); g.sh->sendMessage(mpcs); } } diff --git a/src/mumble/ServerHandler.cpp b/src/mumble/ServerHandler.cpp index a5bd943de..f9e774057 100644 --- a/src/mumble/ServerHandler.cpp +++ b/src/mumble/ServerHandler.cpp @@ -195,16 +195,16 @@ void ServerHandler::udpReady() { if (! connection) continue; - if (! connection->csCrypt.isValid()) + if (! connection->csCrypt->isValid()) continue; if (buflen < 5) continue; - if (! connection->csCrypt.decrypt(reinterpret_cast<const unsigned char *>(encrypted), reinterpret_cast<unsigned char *>(buffer), buflen)) { - if (connection->csCrypt.tLastGood.elapsed() > 5000000ULL) { - if (connection->csCrypt.tLastRequest.elapsed() > 5000000ULL) { - connection->csCrypt.tLastRequest.restart(); + if (! connection->csCrypt->decrypt(reinterpret_cast<const unsigned char *>(encrypted), reinterpret_cast<unsigned char *>(buffer), buflen)) { + if (connection->csCrypt->tLastGood.elapsed() > 5000000ULL) { + if (connection->csCrypt->tLastRequest.elapsed() > 5000000ULL) { + connection->csCrypt->tLastRequest.restart(); MumbleProto::CryptSetup mpcs; sendMessage(mpcs); } @@ -261,7 +261,7 @@ void ServerHandler::sendMessage(const char *data, int len, bool force) { return; ConnectionPtr connection(cConnection); - if (!connection || !connection->csCrypt.isValid()) + if (!connection || !connection->csCrypt->isValid()) return; if (!force && (NetworkConfig::TcpModeEnabled() || !bUdp)) { @@ -275,7 +275,7 @@ void ServerHandler::sendMessage(const char *data, int len, bool force) { QApplication::postEvent(this, new ServerHandlerMessageEvent(qba, MessageHandler::UDPTunnel, true)); } else { - if (!connection->csCrypt.encrypt(reinterpret_cast<const unsigned char *>(data), crypto, len)) { + if (!connection->csCrypt->encrypt(reinterpret_cast<const unsigned char *>(data), crypto, len)) { return; } qusUdp->writeDatagram(reinterpret_cast<const char *>(crypto), len + 4, qhaRemote, usResolvedPort); @@ -511,8 +511,6 @@ void ServerHandler::sendPingInternal() { return; } - CryptState &cs = connection->csCrypt; - quint64 t = tTimestamp.elapsed(); if (qusUdp) { @@ -526,10 +524,10 @@ void ServerHandler::sendPingInternal() { MumbleProto::Ping mpp; mpp.set_timestamp(t); - mpp.set_good(cs.uiGood); - mpp.set_late(cs.uiLate); - mpp.set_lost(cs.uiLost); - mpp.set_resync(cs.uiResync); + mpp.set_good(connection->csCrypt->uiGood); + mpp.set_late(connection->csCrypt->uiLate); + mpp.set_lost(connection->csCrypt->uiLost); + mpp.set_resync(connection->csCrypt->uiResync); if (boost::accumulators::count(accUDP)) { @@ -580,26 +578,25 @@ void ServerHandler::message(unsigned int msgType, const QByteArray &qbaMsg) { // connection is still OK. iInFlightTCPPings = 0; - CryptState &cs = connection->csCrypt; - cs.uiRemoteGood = msg.good(); - cs.uiRemoteLate = msg.late(); - cs.uiRemoteLost = msg.lost(); - cs.uiRemoteResync = msg.resync(); + connection->csCrypt->uiRemoteGood = msg.good(); + connection->csCrypt->uiRemoteLate = msg.late(); + connection->csCrypt->uiRemoteLost = msg.lost(); + connection->csCrypt->uiRemoteResync = msg.resync(); accTCP(static_cast<double>(tTimestamp.elapsed() - msg.timestamp()) / 1000.0); - if (((cs.uiRemoteGood == 0) || (cs.uiGood == 0)) && bUdp && (tTimestamp.elapsed() > 20000000ULL)) { + if (((connection->csCrypt->uiRemoteGood == 0) || (connection->csCrypt->uiGood == 0)) && bUdp && (tTimestamp.elapsed() > 20000000ULL)) { bUdp = false; if (! NetworkConfig::TcpModeEnabled()) { - if ((cs.uiRemoteGood == 0) && (cs.uiGood == 0)) + if ((connection->csCrypt->uiRemoteGood == 0) && (connection->csCrypt->uiGood == 0)) g.mw->msgBox(tr("UDP packets cannot be sent to or received from the server. Switching to TCP mode.")); - else if (cs.uiRemoteGood == 0) + else if (connection->csCrypt->uiRemoteGood == 0) g.mw->msgBox(tr("UDP packets cannot be sent to the server. Switching to TCP mode.")); else g.mw->msgBox(tr("UDP packets cannot be received from the server. Switching to TCP mode.")); database->setUdp(qbaDigest, false); } - } else if (!bUdp && (cs.uiRemoteGood > 3) && (cs.uiGood > 3)) { + } else if (!bUdp && (connection->csCrypt->uiRemoteGood > 3) && (connection->csCrypt->uiGood > 3)) { bUdp = true; if (! NetworkConfig::TcpModeEnabled()) { g.mw->msgBox(tr("UDP packets can be sent to and received from the server. Switching back to UDP mode.")); diff --git a/src/murmur/Messages.cpp b/src/murmur/Messages.cpp index 66472320d..43a29fb7c 100644 --- a/src/murmur/Messages.cpp +++ b/src/murmur/Messages.cpp @@ -13,7 +13,7 @@ #include "Server.h" #include "ServerUser.h" #include "Version.h" -#include "CryptState.h" +#include "crypto/CryptState.h" #include "Meta.h" #include "ChannelListener.h" @@ -292,12 +292,12 @@ void Server::msgAuthenticate(ServerUser *uSource, MumbleProto::Authenticate &msg { QMutexLocker l(&uSource->qmCrypt); - uSource->csCrypt.genKey(); + uSource->csCrypt->genKey(); MumbleProto::CryptSetup mpcrypt; - mpcrypt.set_key(std::string(reinterpret_cast<const char *>(uSource->csCrypt.raw_key), AES_KEY_SIZE_BYTES)); - mpcrypt.set_server_nonce(std::string(reinterpret_cast<const char *>(uSource->csCrypt.encrypt_iv), AES_BLOCK_SIZE)); - mpcrypt.set_client_nonce(std::string(reinterpret_cast<const char *>(uSource->csCrypt.decrypt_iv), AES_BLOCK_SIZE)); + mpcrypt.set_key(uSource->csCrypt->getRawKey()); + mpcrypt.set_server_nonce(uSource->csCrypt->getEncryptIV()); + mpcrypt.set_client_nonce(uSource->csCrypt->getDecryptIV()); sendMessage(uSource, mpcrypt); } @@ -1748,12 +1748,10 @@ void Server::msgPing(ServerUser *uSource, MumbleProto::Ping &msg) { QMutexLocker l(&uSource->qmCrypt); - CryptState &cs=uSource->csCrypt; - - cs.uiRemoteGood = msg.good(); - cs.uiRemoteLate = msg.late(); - cs.uiRemoteLost = msg.lost(); - cs.uiRemoteResync = msg.resync(); + uSource->csCrypt->uiRemoteGood = msg.good(); + uSource->csCrypt->uiRemoteLate = msg.late(); + uSource->csCrypt->uiRemoteLost = msg.lost(); + uSource->csCrypt->uiRemoteResync = msg.resync(); uSource->dUDPPingAvg = msg.udp_ping_avg(); uSource->dUDPPingVar = msg.udp_ping_var(); @@ -1766,10 +1764,10 @@ void Server::msgPing(ServerUser *uSource, MumbleProto::Ping &msg) { msg.Clear(); msg.set_timestamp(ts); - msg.set_good(cs.uiGood); - msg.set_late(cs.uiLate); - msg.set_lost(cs.uiLost); - msg.set_resync(cs.uiResync); + msg.set_good(uSource->csCrypt->uiGood); + msg.set_late(uSource->csCrypt->uiLate); + msg.set_lost(uSource->csCrypt->uiLost); + msg.set_resync(uSource->csCrypt->uiResync); sendMessage(uSource, msg); } @@ -1781,14 +1779,12 @@ void Server::msgCryptSetup(ServerUser *uSource, MumbleProto::CryptSetup &msg) { if (! msg.has_client_nonce()) { log(uSource, "Requested crypt-nonce resync"); - msg.set_server_nonce(std::string(reinterpret_cast<const char *>(uSource->csCrypt.encrypt_iv), AES_BLOCK_SIZE)); + msg.set_server_nonce(uSource->csCrypt->getEncryptIV()); sendMessage(uSource, msg); } else { const std::string &str = msg.client_nonce(); - if (str.size() == AES_BLOCK_SIZE) { - uSource->csCrypt.uiResync++; - memcpy(uSource->csCrypt.decrypt_iv, str.data(), AES_BLOCK_SIZE); - } + uSource->csCrypt->uiResync++; + uSource->csCrypt->setDecryptIV(str); } } @@ -2006,19 +2002,18 @@ void Server::msgUserStats(ServerUser*uSource, MumbleProto::UserStats &msg) { MumbleProto::UserStats_Stats *mpusss; QMutexLocker l(&pDstServerUser->qmCrypt); - const CryptState &cs = pDstServerUser->csCrypt; mpusss = msg.mutable_from_client(); - mpusss->set_good(cs.uiGood); - mpusss->set_late(cs.uiLate); - mpusss->set_lost(cs.uiLost); - mpusss->set_resync(cs.uiResync); + mpusss->set_good(pDstServerUser->csCrypt->uiGood); + mpusss->set_late(pDstServerUser->csCrypt->uiLate); + mpusss->set_lost(pDstServerUser->csCrypt->uiLost); + mpusss->set_resync(pDstServerUser->csCrypt->uiResync); mpusss = msg.mutable_from_server(); - mpusss->set_good(cs.uiRemoteGood); - mpusss->set_late(cs.uiRemoteLate); - mpusss->set_lost(cs.uiRemoteLost); - mpusss->set_resync(cs.uiRemoteResync); + mpusss->set_good(pDstServerUser->csCrypt->uiRemoteGood); + mpusss->set_late(pDstServerUser->csCrypt->uiRemoteLate); + mpusss->set_lost(pDstServerUser->csCrypt->uiRemoteLost); + mpusss->set_resync(pDstServerUser->csCrypt->uiRemoteResync); } msg.set_udp_packets(pDstServerUser->uiUDPPackets); diff --git a/src/murmur/Server.cpp b/src/murmur/Server.cpp index 6b6bf8948..6f3c2f57f 100644 --- a/src/murmur/Server.cpp +++ b/src/murmur/Server.cpp @@ -920,12 +920,12 @@ void Server::run() { bool Server::checkDecrypt(ServerUser *u, const char *encrypt, char *plain, unsigned int len) { QMutexLocker l(&u->qmCrypt); - if (u->csCrypt.isValid() && u->csCrypt.decrypt(reinterpret_cast<const unsigned char *>(encrypt), reinterpret_cast<unsigned char *>(plain), len)) + if (u->csCrypt->isValid() && u->csCrypt->decrypt(reinterpret_cast<const unsigned char *>(encrypt), reinterpret_cast<unsigned char *>(plain), len)) return true; - if (u->csCrypt.tLastGood.elapsed() > 5000000ULL) { - if (u->csCrypt.tLastRequest.elapsed() > 5000000ULL) { - u->csCrypt.tLastRequest.restart(); + if (u->csCrypt->tLastGood.elapsed() > 5000000ULL) { + if (u->csCrypt->tLastRequest.elapsed() > 5000000ULL) { + u->csCrypt->tLastRequest.restart(); emit reqSync(u->uiSession); } } @@ -948,11 +948,11 @@ void Server::sendMessage(ServerUser *u, const char *data, int len, QByteArray &c { QMutexLocker wl(&u->qmCrypt); - if (!u->csCrypt.isValid()) { + if (!u->csCrypt->isValid()) { return; } - if (!u->csCrypt.encrypt(reinterpret_cast<const unsigned char *>(data), reinterpret_cast<unsigned char *>(buffer), len)) { + if (!u->csCrypt->encrypt(reinterpret_cast<const unsigned char *>(data), reinterpret_cast<unsigned char *>(buffer), len)) { return; } } diff --git a/src/tests/Benchmark.cpp b/src/tests/Benchmark.cpp index 7a5413db8..95495a5af 100644 --- a/src/tests/Benchmark.cpp +++ b/src/tests/Benchmark.cpp @@ -24,7 +24,7 @@ #include "PacketDataStream.h" #include "Timer.h" #include "Message.h" -#include "CryptState.h" +#include "crypto/CryptState.h" #include "Mumble.pb.h" class Client : public QThread { @@ -34,7 +34,7 @@ class Client : public QThread { bool sender; struct sockaddr_in srv; unsigned int uiSession; - CryptState crypt; + CryptStateOCB2 crypt; int rcvd; int socket; int seq; @@ -220,16 +220,16 @@ void Client::readyRead() { const std::string &client_nonce = msg.client_nonce(); const std::string &server_nonce = msg.server_nonce(); if (key.size() == AES_BLOCK_SIZE && client_nonce.size() == AES_BLOCK_SIZE && server_nonce.size() == AES_BLOCK_SIZE) - crypt.setKey(reinterpret_cast<const unsigned char *>(key.data()), reinterpret_cast<const unsigned char *>(client_nonce.data()), reinterpret_cast<const unsigned char *>(server_nonce.data())); + crypt.setKey(key, client_nonce, server_nonce); } else if (msg.has_server_nonce()) { const std::string &server_nonce = msg.server_nonce(); if (server_nonce.size() == AES_BLOCK_SIZE) { crypt.uiResync++; - memcpy(crypt.decrypt_iv, server_nonce.data(), AES_BLOCK_SIZE); + crypt.setDecryptIV(server_nonce); } } else { MumbleProto::CryptSetup mpcs; - mpcs.set_client_nonce(std::string(reinterpret_cast<const char *>(crypt.encrypt_iv), AES_BLOCK_SIZE)); + mpcs.set_client_nonce(crypt.getEncryptIV()); sendMessage(mpcs, MessageHandler::CryptSetup); } break; diff --git a/src/tests/Benchmark.pro b/src/tests/Benchmark.pro index 5d1cf4fed..30a3376ee 100644 --- a/src/tests/Benchmark.pro +++ b/src/tests/Benchmark.pro @@ -6,8 +6,8 @@ CONFIG -= app_bundle QT *= network xml LANGUAGE = C++ TARGET = Benchmark -SOURCES *= Benchmark.cpp Timer.cpp CryptState.cpp -HEADERS *= Timer.h CryptState.h +SOURCES *= Benchmark.cpp Timer.cpp crypto/CryptStateOCB2.cpp +HEADERS *= Timer.h crypto/CryptState.h crypto/CryptStateOCB2.h VPATH *= .. INCLUDEPATH *= .. ../murmur ../mumble !win32 { diff --git a/src/tests/TestCrypt/TestCrypt.cpp b/src/tests/TestCrypt/TestCrypt.cpp index 1b621967f..1021f8aec 100644 --- a/src/tests/TestCrypt/TestCrypt.cpp +++ b/src/tests/TestCrypt/TestCrypt.cpp @@ -6,9 +6,10 @@ #include <QtCore> #include <QtTest> +#include <string> #include "SSL.h" #include "Timer.h" -#include "CryptState.h" +#include "crypto/CryptStateOCB2.h" #include "Utils.h" class TestCrypt : public QObject { @@ -33,13 +34,14 @@ void TestCrypt::cleanupTestCase() { } void TestCrypt::reverserecovery() { - CryptState enc, dec; + CryptStateOCB2 enc, dec; enc.genKey(); // For our testcase, we're going to FORCE iv - memset(enc.encrypt_iv, 0x55, AES_BLOCK_SIZE); - - dec.setKey(enc.raw_key, enc.decrypt_iv, enc.encrypt_iv); + char encrypt_iv[AES_BLOCK_SIZE]; + memset(encrypt_iv, 0x55, AES_BLOCK_SIZE); + enc.setEncryptIV(std::string(reinterpret_cast<const char*>(encrypt_iv), AES_BLOCK_SIZE)); + dec.setKey(enc.getRawKey(), enc.getDecryptIV(), enc.getEncryptIV()); unsigned char secret[10] = "abcdefghi"; unsigned char crypted[512][14]; @@ -89,13 +91,14 @@ void TestCrypt::reverserecovery() { } void TestCrypt::ivrecovery() { - CryptState enc, dec; + CryptStateOCB2 enc, dec; enc.genKey(); // For our testcase, we're going to FORCE iv - memset(enc.encrypt_iv, 0x55, AES_BLOCK_SIZE); - - dec.setKey(enc.raw_key, enc.decrypt_iv, enc.encrypt_iv); + char encrypt_iv[AES_BLOCK_SIZE]; + memset(encrypt_iv, 0x55, AES_BLOCK_SIZE); + enc.setEncryptIV(std::string(reinterpret_cast<const char*>(encrypt_iv), AES_BLOCK_SIZE)); + dec.setKey(enc.getRawKey(), enc.getDecryptIV(), enc.getEncryptIV()); unsigned char secret[10] = "abcdefghi"; unsigned char crypted[14]; @@ -126,7 +129,7 @@ void TestCrypt::ivrecovery() { QCOMPARE(dec.uiLost, 14U); } - QVERIFY(memcmp(enc.encrypt_iv, dec.decrypt_iv, AES_BLOCK_SIZE)==0); + QVERIFY(enc.getEncryptIV() == dec.getDecryptIV()); // Wrap too far for (int i=0;i<257;i++) @@ -135,7 +138,7 @@ void TestCrypt::ivrecovery() { QVERIFY(! dec.decrypt(crypted, decr, 14)); // Sync it - dec.setDecryptIV(enc.encrypt_iv); + dec.setDecryptIV(enc.getEncryptIV()); enc.encrypt(secret, crypted, 10); QVERIFY(dec.decrypt(crypted, decr, 14)); @@ -145,8 +148,9 @@ void TestCrypt::testvectors() { // Test vectors are from draft-krovetz-ocb-00.txt const unsigned char rawkey[AES_BLOCK_SIZE] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f}; - CryptState cs; - cs.setKey(rawkey, rawkey, rawkey); + CryptStateOCB2 cs; + std::string rawkey_str = std::string(reinterpret_cast<const char*>(rawkey), AES_BLOCK_SIZE); + cs.setKey(rawkey_str, rawkey_str, rawkey_str); unsigned char tag[16]; QVERIFY(cs.ocb_encrypt(NULL, NULL, 0, rawkey, tag)); @@ -176,8 +180,10 @@ void TestCrypt::authcrypt() { for (int len=0;len<128;len++) { const unsigned char rawkey[AES_BLOCK_SIZE] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f}; const unsigned char nonce[AES_BLOCK_SIZE] = {0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00}; - CryptState cs; - cs.setKey(rawkey, nonce, nonce); + std::string rawkey_str = std::string(reinterpret_cast<const char*>(rawkey), AES_BLOCK_SIZE); + std::string nonce_str = std::string(reinterpret_cast<const char*>(nonce), AES_BLOCK_SIZE); + CryptStateOCB2 cs; + cs.setKey(rawkey_str, nonce_str, nonce_str); STACKVAR(unsigned char, src, len); for (int i=0;i<len;i++) @@ -203,8 +209,10 @@ void TestCrypt::authcrypt() { void TestCrypt::xexstarAttack() { const unsigned char rawkey[AES_BLOCK_SIZE] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f}; const unsigned char nonce[AES_BLOCK_SIZE] = {0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00}; - CryptState cs; - cs.setKey(rawkey, nonce, nonce); + std::string rawkey_str = std::string(reinterpret_cast<const char*>(rawkey), AES_BLOCK_SIZE); + std::string nonce_str = std::string(reinterpret_cast<const char*>(nonce), AES_BLOCK_SIZE); + CryptStateOCB2 cs; + cs.setKey(rawkey_str, nonce_str, nonce_str); STACKVAR(unsigned char, src, 2 * AES_BLOCK_SIZE); // Set first block to `len(secondBlock)` @@ -240,8 +248,10 @@ void TestCrypt::xexstarAttack() { void TestCrypt::tamper() { const unsigned char rawkey[AES_BLOCK_SIZE] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f}; const unsigned char nonce[AES_BLOCK_SIZE] = {0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00}; - CryptState cs; - cs.setKey(rawkey, nonce, nonce); + std::string rawkey_str = std::string(reinterpret_cast<const char*>(rawkey), AES_BLOCK_SIZE); + std::string nonce_str = std::string(reinterpret_cast<const char*>(nonce), AES_BLOCK_SIZE); + CryptStateOCB2 cs; + cs.setKey(rawkey_str, nonce_str, nonce_str); const unsigned char msg[] = "It was a funky funky town!"; int len = sizeof(msg); diff --git a/src/tests/TestCrypt/TestCrypt.pro b/src/tests/TestCrypt/TestCrypt.pro index 83ea84f6e..6535e4b19 100644 --- a/src/tests/TestCrypt/TestCrypt.pro +++ b/src/tests/TestCrypt/TestCrypt.pro @@ -8,7 +8,7 @@ include(../test.pri) QT *= network TARGET = TestCrypt -HEADERS *= SSL.h SSLLocks.h Timer.h CryptState.h -SOURCES *= SSL.cpp SSLLocks.cpp TestCrypt.cpp CryptState.cpp Timer.cpp +HEADERS *= SSL.h SSLLocks.h Timer.h crypto/CryptState.h crypto/CryptStateOCB2.h +SOURCES *= SSL.cpp SSLLocks.cpp TestCrypt.cpp crypto/CryptStateOCB2.cpp Timer.cpp win32:LIBS *= -lws2_32 diff --git a/src/tests/TestCryptographicHash/TestCryptographicHash.cpp b/src/tests/TestCryptographicHash/TestCryptographicHash.cpp index 653a9b72a..90be99485 100644 --- a/src/tests/TestCryptographicHash/TestCryptographicHash.cpp +++ b/src/tests/TestCryptographicHash/TestCryptographicHash.cpp @@ -9,7 +9,7 @@ #include "SSL.h" -#include "CryptographicHash.h" +#include "crypto/CryptographicHash.h" class TestCryptographicHash : public QObject { Q_OBJECT diff --git a/src/tests/TestCryptographicHash/TestCryptographicHash.pro b/src/tests/TestCryptographicHash/TestCryptographicHash.pro index bda9506dc..dc5b256c8 100644 --- a/src/tests/TestCryptographicHash/TestCryptographicHash.pro +++ b/src/tests/TestCryptographicHash/TestCryptographicHash.pro @@ -8,5 +8,5 @@ include(../test.pri) QT += network TARGET = TestCryptographicHash -SOURCES *= SSL.cpp SSLLocks.cpp TestCryptographicHash.cpp CryptographicHash.cpp -HEADERS *= SSL.h SSLLocks.h CryptographicHash.h +SOURCES *= SSL.cpp SSLLocks.cpp TestCryptographicHash.cpp crypto/CryptographicHash.cpp +HEADERS *= SSL.h SSLLocks.h crypto/CryptographicHash.h diff --git a/src/tests/TestCryptographicRandom/TestCryptographicRandom.cpp b/src/tests/TestCryptographicRandom/TestCryptographicRandom.cpp index be9d04fa5..ee1a2edd7 100644 --- a/src/tests/TestCryptographicRandom/TestCryptographicRandom.cpp +++ b/src/tests/TestCryptographicRandom/TestCryptographicRandom.cpp @@ -8,7 +8,7 @@ #include "SSL.h" -#include "CryptographicRandom.h" +#include "crypto/CryptographicRandom.h" #include <stdint.h> #include <stdlib.h> diff --git a/src/tests/TestCryptographicRandom/TestCryptographicRandom.pro b/src/tests/TestCryptographicRandom/TestCryptographicRandom.pro index 5d04255f0..c6625f3f9 100644 --- a/src/tests/TestCryptographicRandom/TestCryptographicRandom.pro +++ b/src/tests/TestCryptographicRandom/TestCryptographicRandom.pro @@ -8,8 +8,8 @@ include(../test.pri) QT += network TARGET = TestCryptographicRandom -SOURCES *= SSL.cpp SSLLocks.cpp TestCryptographicRandom.cpp CryptographicRandom.cpp arc4random_uniform.cpp -HEADERS *= SSL.h SSLLocks.h CryptographicHash.h +SOURCES *= SSL.cpp SSLLocks.cpp TestCryptographicRandom.cpp crypto/CryptographicRandom.cpp arc4random_uniform.cpp +HEADERS *= SSL.h SSLLocks.h crypto/CryptographicHash.h VPATH *= ../../../3rdparty/arc4random-src INCLUDEPATH *= ../../../3rdparty/arc4random-src diff --git a/src/tests/TestPasswordGenerator/TestPasswordGenerator.pro b/src/tests/TestPasswordGenerator/TestPasswordGenerator.pro index 3bb6df3cd..77a30e92c 100644 --- a/src/tests/TestPasswordGenerator/TestPasswordGenerator.pro +++ b/src/tests/TestPasswordGenerator/TestPasswordGenerator.pro @@ -8,8 +8,8 @@ include(../test.pri) QT += network TARGET = TestPasswordGenerator -SOURCES *= SSL.cpp SSLLocks.cpp TestPasswordGenerator.cpp PasswordGenerator.cpp CryptographicRandom.cpp arc4random_uniform.cpp -HEADERS *= SSL.h SSLLocks.h PasswordGenerator.h CryptographicHash.h +SOURCES *= SSL.cpp SSLLocks.cpp TestPasswordGenerator.cpp PasswordGenerator.cpp crypto/CryptographicRandom.cpp arc4random_uniform.cpp +HEADERS *= SSL.h SSLLocks.h PasswordGenerator.h crypto/CryptographicHash.h VPATH *= ../../../3rdparty/arc4random-src INCLUDEPATH *= ../../../3rdparty/arc4random-src |