diff --git a/components/spotify/cspot/bell/include/CryptoMbedTLS.h b/components/spotify/cspot/bell/include/CryptoMbedTLS.h index 089a3bad..27a4ff42 100644 --- a/components/spotify/cspot/bell/include/CryptoMbedTLS.h +++ b/components/spotify/cspot/bell/include/CryptoMbedTLS.h @@ -56,7 +56,7 @@ public: std::vector sha1HMAC(const std::vector& inputKey, const std::vector& message); // AES CTR - void aesCTRXcrypt(const std::vector& key, std::vector& iv, std::vector& data); + void aesCTRXcrypt(const std::vector& key, std::vector& iv, uint8_t* data, size_t nbytes); // AES ECB void aesECBdecrypt(const std::vector& key, std::vector& data); diff --git a/components/spotify/cspot/bell/include/CryptoOpenSSL.h b/components/spotify/cspot/bell/include/CryptoOpenSSL.h index abc8d01c..56310fd3 100644 --- a/components/spotify/cspot/bell/include/CryptoOpenSSL.h +++ b/components/spotify/cspot/bell/include/CryptoOpenSSL.h @@ -63,7 +63,7 @@ public: std::vector sha1HMAC(const std::vector& inputKey, const std::vector& message); // AES CTR - void aesCTRXcrypt(const std::vector& key, std::vector& iv, std::vector& data); + void aesCTRXcrypt(const std::vector& key, std::vector& iv, uint8_t* buffer, size_t nbytes); // AES ECB void aesECBdecrypt(const std::vector& key, std::vector& data); diff --git a/components/spotify/cspot/bell/src/CryptoMBedTLS.cpp b/components/spotify/cspot/bell/src/CryptoMBedTLS.cpp index 7fbe5c72..fc596762 100644 --- a/components/spotify/cspot/bell/src/CryptoMBedTLS.cpp +++ b/components/spotify/cspot/bell/src/CryptoMBedTLS.cpp @@ -88,7 +88,7 @@ std::vector CryptoMbedTLS::sha1HMAC(const std::vector &inputKe } // AES CTR -void CryptoMbedTLS::aesCTRXcrypt(const std::vector &key, std::vector &iv, std::vector &data) +void CryptoMbedTLS::aesCTRXcrypt(const std::vector &key, std::vector &iv, uint8_t* buffer, size_t nbytes) { // needed for internal cache size_t off = 0; @@ -99,12 +99,12 @@ void CryptoMbedTLS::aesCTRXcrypt(const std::vector &key, std::vector &key, std::vector &data) @@ -115,7 +115,7 @@ void CryptoMbedTLS::aesECBdecrypt(const std::vector &key, std::vector CryptoOpenSSL::sha1HMAC(const std::vector& inputKe } // AES CTR -void CryptoOpenSSL::aesCTRXcrypt(const std::vector& key, std::vector& iv, std::vector &data) +void CryptoOpenSSL::aesCTRXcrypt(const std::vector& key, std::vector& iv, uint8_t* buffer, size_t nbytes) { // Prepare AES_KEY auto cryptoKey = AES_KEY(); @@ -110,9 +110,9 @@ void CryptoOpenSSL::aesCTRXcrypt(const std::vector& key, std::vectorread(buffer, BUF_SIZE); diff --git a/components/spotify/cspot/include/AudioChunk.h b/components/spotify/cspot/include/AudioChunk.h index 3aa46878..3b75e789 100644 --- a/components/spotify/cspot/include/AudioChunk.h +++ b/components/spotify/cspot/include/AudioChunk.h @@ -14,12 +14,15 @@ class AudioChunk { private: /** * @brief Calculates a correct IV by performing bignum addition. - * + * * @param num Number to add to IV. - * @return std::vector + * @return std::vector */ std::vector getIVSum(uint32_t num); + size_t decryptedCount = 0; + size_t oldStartPos; + public: std::unique_ptr crypto; std::vector decryptedData; @@ -41,14 +44,21 @@ public: std::unique_ptr isLoadedSemaphore; /** - * @brief + * @brief */ std::unique_ptr isHeaderFileSizeLoadedSemaphore; + /** + * Decrypts data and writes it to the target buffer + * @param target data buffer to write to + * @param offset data offset + * @param nbytes number of bytes to read + */ + void readData(uint8_t *target, size_t offset, size_t nbytes); /** * @brief AudioChunk handles all audiochunk related operations. - * + * * @param seqId Sequence id of requested chunk * @param audioKey Audio key used for decryption of audio data * @param startPosition Start position of current chunk in audio file @@ -59,16 +69,16 @@ public: /** * @brief Appends incoming chunked data to local cache. - * + * * @param data encrypted binary audio data. */ void appendData(const std::vector &data); /** - * @brief Performs AES CTR decryption of received data. - * + * @brief Sets loaded status on the chunk + * */ - void decrypt(); + void finalize(); }; #endif diff --git a/components/spotify/cspot/include/Shannon.h b/components/spotify/cspot/include/Shannon.h index df9a5eb2..34107bf2 100644 --- a/components/spotify/cspot/include/Shannon.h +++ b/components/spotify/cspot/include/Shannon.h @@ -13,7 +13,7 @@ public: void stream(std::vector &buf); /* stream cipher */ void maconly(std::vector &buf); /* accumulate MAC */ void encrypt(std::vector &buf); /* encrypt + MAC */ - void decrypt(std::vector &buf); /* decrypt + MAC */ + void decrypt(std::vector &buf); /* finalize + MAC */ void finish(std::vector &buf); /* finalise MAC */ private: diff --git a/components/spotify/cspot/src/AudioChunk.cpp b/components/spotify/cspot/src/AudioChunk.cpp index 17ff25b7..407fc425 100644 --- a/components/spotify/cspot/src/AudioChunk.cpp +++ b/components/spotify/cspot/src/AudioChunk.cpp @@ -24,13 +24,28 @@ void AudioChunk::appendData(const std::vector &data) this->decryptedData.insert(this->decryptedData.end(), data.begin(), data.end()); } -void AudioChunk::decrypt() +void AudioChunk::readData(uint8_t *target, size_t offset, size_t nbytes) { + auto readPos = offset + nbytes; + auto modulo = (readPos % 16); + auto ivReadPos = readPos; + if (modulo != 0) { + ivReadPos += (16 - modulo); + } + if (ivReadPos > decryptedCount) { + // calculate the IV for right position + auto calculatedIV = this->getIVSum((oldStartPos + decryptedCount) / 16); + + crypto->aesCTRXcrypt(this->audioKey, calculatedIV, decryptedData.data() + decryptedCount, ivReadPos - decryptedCount); + + decryptedCount = ivReadPos; + } + memcpy(target, this->decryptedData.data() + offset, nbytes); + +} + +void AudioChunk::finalize() { - // calculate the IV for right position - auto calculatedIV = this->getIVSum(startPosition / 16); - - crypto->aesCTRXcrypt(this->audioKey, calculatedIV, decryptedData); - + this->oldStartPos = this->startPosition; this->startPosition = this->endPosition - this->decryptedData.size(); this->isLoaded = true; } diff --git a/components/spotify/cspot/src/AudioChunkManager.cpp b/components/spotify/cspot/src/AudioChunkManager.cpp index 256ee13a..827d2a32 100644 --- a/components/spotify/cspot/src/AudioChunkManager.cpp +++ b/components/spotify/cspot/src/AudioChunkManager.cpp @@ -80,7 +80,7 @@ void AudioChunkManager::runTask() { switch (data.size()) { case DATA_SIZE_HEADER: { - CSPOT_LOG(debug, "ID: %d: header decrypt!", seqId); + CSPOT_LOG(debug, "ID: %d: header finalize!", seqId); auto headerSize = ntohs(extract(data, 2)); // Got file size! chunk->headerFileSize = @@ -92,9 +92,9 @@ void AudioChunkManager::runTask() { if (chunk->endPosition > chunk->headerFileSize) { chunk->endPosition = chunk->headerFileSize; } - CSPOT_LOG(debug, "ID: %d: Starting decrypt!", + CSPOT_LOG(debug, "ID: %d: finalize chunk!", seqId); - chunk->decrypt(); + chunk->finalize(); chunk->isLoadedSemaphore->give(); break; diff --git a/components/spotify/cspot/src/ChunkedByteStream.cpp b/components/spotify/cspot/src/ChunkedByteStream.cpp index 00140ee6..0c92aa84 100644 --- a/components/spotify/cspot/src/ChunkedByteStream.cpp +++ b/components/spotify/cspot/src/ChunkedByteStream.cpp @@ -113,9 +113,7 @@ size_t ChunkedByteStream::attemptRead(uint8_t *buffer, size_t bytes, std::shared toRead = chunk->decryptedData.size() - offset; } - // Copy data - memcpy(buffer, chunk->decryptedData.data() + offset, toRead); - + chunk->readData(buffer, offset, toRead); return toRead; } diff --git a/components/spotify/cspot/src/LoginBlob.cpp b/components/spotify/cspot/src/LoginBlob.cpp index 36143e9f..477b9b94 100644 --- a/components/spotify/cspot/src/LoginBlob.cpp +++ b/components/spotify/cspot/src/LoginBlob.cpp @@ -35,7 +35,7 @@ std::vector LoginBlob::decodeBlob(const std::vector &blob, con } encryptionKey = std::vector(encryptionKey.begin(), encryptionKey.begin() + 16); - crypto->aesCTRXcrypt(encryptionKey, iv, encrypted); + crypto->aesCTRXcrypt(encryptionKey, iv, encrypted.data(), encrypted.size()); return encrypted; }