diff --git a/app/backend/nvhttp.cpp b/app/backend/nvhttp.cpp index 49cf6b96..c542b748 100644 --- a/app/backend/nvhttp.cpp +++ b/app/backend/nvhttp.cpp @@ -109,7 +109,7 @@ NvHTTP::getCurrentGame(QString serverInfo) // has the semantics that its name would indicate. To contain the effects of this change as much // as possible, we'll force the current game to zero if the server isn't in a streaming session. QString serverState = getXmlString(serverInfo, "state"); - if (serverState != nullptr && serverState.endsWith("_SERVER_BUSY")) + if (serverState.endsWith("_SERVER_BUSY")) { return getXmlString(serverInfo, "currentgame").toInt(); } @@ -269,14 +269,16 @@ NvHTTP::getDisplayModeList(QString serverInfo) if (name == QString("DisplayMode")) { modes.append(NvDisplayMode()); } - else if (name == QString("Width")) { - modes.last().width = xmlReader.readElementText().toInt(); - } - else if (name == QString("Height")) { - modes.last().height = xmlReader.readElementText().toInt(); - } - else if (name == QString("RefreshRate")) { - modes.last().refreshRate = xmlReader.readElementText().toInt(); + else if (!modes.isEmpty()) { + if (name == QString("Width")) { + modes.last().width = xmlReader.readElementText().toInt(); + } + else if (name == QString("Height")) { + modes.last().height = xmlReader.readElementText().toInt(); + } + else if (name == QString("RefreshRate")) { + modes.last().refreshRate = xmlReader.readElementText().toInt(); + } } } } @@ -307,17 +309,19 @@ NvHTTP::getAppList() } apps.append(NvApp()); } - else if (name == QString("AppTitle")) { - apps.last().name = xmlReader.readElementText(); - } - else if (name == QString("ID")) { - apps.last().id = xmlReader.readElementText().toInt(); - } - else if (name == QString("IsHdrSupported")) { - apps.last().hdrSupported = xmlReader.readElementText() == "1"; - } - else if (name == QString("IsAppCollectorGame")) { - apps.last().isAppCollectorGame = xmlReader.readElementText() == "1"; + else if (!apps.isEmpty()) { + if (name == QString("AppTitle")) { + apps.last().name = xmlReader.readElementText(); + } + else if (name == QString("ID")) { + apps.last().id = xmlReader.readElementText().toInt(); + } + else if (name == QString("IsHdrSupported")) { + apps.last().hdrSupported = xmlReader.readElementText() == "1"; + } + else if (name == QString("IsAppCollectorGame")) { + apps.last().isAppCollectorGame = xmlReader.readElementText() == "1"; + } } } } @@ -383,13 +387,7 @@ QByteArray NvHTTP::getXmlStringFromHex(QString xml, QString tagName) { - QString str = getXmlString(xml, tagName); - if (str == nullptr) - { - return nullptr; - } - - return QByteArray::fromHex(str.toUtf8()); + return QByteArray::fromHex(getXmlString(xml, tagName).toUtf8()); } QString @@ -411,7 +409,7 @@ NvHTTP::getXmlString(QString xml, } } - return nullptr; + return QString(); } void NvHTTP::handleSslErrors(QNetworkReply* reply, const QList& errors) diff --git a/app/backend/nvpairingmanager.cpp b/app/backend/nvpairingmanager.cpp index 9aa3a0d7..82a67b7e 100644 --- a/app/backend/nvpairingmanager.cpp +++ b/app/backend/nvpairingmanager.cpp @@ -54,16 +54,18 @@ NvPairingManager::generateRandomBytes(int length) QByteArray NvPairingManager::encrypt(const QByteArray& plaintext, const QByteArray& key) { - QByteArray ciphertext(plaintext.size(), 0); - EVP_CIPHER_CTX* cipher; - int ciphertextLen; + if (plaintext.isEmpty()) { + return QByteArray(); + } - cipher = EVP_CIPHER_CTX_new(); + EVP_CIPHER_CTX* cipher = EVP_CIPHER_CTX_new(); THROW_BAD_ALLOC_IF_NULL(cipher); EVP_EncryptInit(cipher, EVP_aes_128_ecb(), reinterpret_cast(key.data()), NULL); EVP_CIPHER_CTX_set_padding(cipher, 0); + QByteArray ciphertext(plaintext.size(), 0); + int ciphertextLen; EVP_EncryptUpdate(cipher, reinterpret_cast(ciphertext.data()), &ciphertextLen, @@ -79,16 +81,18 @@ NvPairingManager::encrypt(const QByteArray& plaintext, const QByteArray& key) QByteArray NvPairingManager::decrypt(const QByteArray& ciphertext, const QByteArray& key) { - QByteArray plaintext(ciphertext.size(), 0); - EVP_CIPHER_CTX* cipher; - int plaintextLen; + if (ciphertext.isEmpty()) { + return QByteArray(); + } - cipher = EVP_CIPHER_CTX_new(); + EVP_CIPHER_CTX* cipher = EVP_CIPHER_CTX_new(); THROW_BAD_ALLOC_IF_NULL(cipher); EVP_DecryptInit(cipher, EVP_aes_128_ecb(), reinterpret_cast(key.data()), NULL); EVP_CIPHER_CTX_set_padding(cipher, 0); + QByteArray plaintext(ciphertext.size(), 0); + int plaintextLen; EVP_DecryptUpdate(cipher, reinterpret_cast(plaintext.data()), &plaintextLen, @@ -239,8 +243,7 @@ NvPairingManager::pair(QString appVersion, QString pin, QSslCertificate& serverC } QByteArray serverCertStr = NvHTTP::getXmlStringFromHex(getCert, "plaincert"); - if (serverCertStr == nullptr) - { + if (serverCertStr.isEmpty()) { qCritical() << "Server likely already pairing"; m_Http.openConnectionToString(m_Http.m_BaseUrlHttp, "unpair", nullptr, REQUEST_TIMEOUT_MS); return PairState::ALREADY_IN_PROGRESS; @@ -275,6 +278,12 @@ NvPairingManager::pair(QString appVersion, QString pin, QSslCertificate& serverC } QByteArray challengeResponseData = decrypt(m_Http.getXmlStringFromHex(challengeXml, "challengeresponse"), aesKey); + if (challengeResponseData.size() < hashLength) { + qCritical() << "Invalid challengeresponse at stage #2"; + m_Http.openConnectionToString(m_Http.m_BaseUrlHttp, "unpair", nullptr, REQUEST_TIMEOUT_MS); + return PairState::FAILED; + } + QByteArray clientSecretData = generateRandomBytes(16); QByteArray challengeResponse; QByteArray serverResponse(challengeResponseData.data(), hashLength); @@ -300,6 +309,12 @@ NvPairingManager::pair(QString appVersion, QString pin, QSslCertificate& serverC } QByteArray pairingSecret = NvHTTP::getXmlStringFromHex(respXml, "pairingsecret"); + if (pairingSecret.size() <= 16) { + qCritical() << "Invalid pairingsecret at stage #3"; + m_Http.openConnectionToString(m_Http.m_BaseUrlHttp, "unpair", nullptr, REQUEST_TIMEOUT_MS); + return PairState::FAILED; + } + QByteArray serverSecret = pairingSecret.left(16); QByteArray serverSignature = pairingSecret.mid(16);