Merge "Increment IV in WVCryptoPlugin" into jb-mr2-dev
This commit is contained in:
@@ -36,6 +36,7 @@ class WVCryptoPlugin : public android::CryptoPlugin {
|
|||||||
const wvcdm::CdmSessionId mSessionId;
|
const wvcdm::CdmSessionId mSessionId;
|
||||||
|
|
||||||
wvcdm::CdmSessionId configureTestMode(const void* data, size_t size);
|
wvcdm::CdmSessionId configureTestMode(const void* data, size_t size);
|
||||||
|
static void incrementIV(uint64_t increaseBy, std::vector<uint8_t>* ivPtr);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace wvdrm
|
} // namespace wvdrm
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include "WVCryptoPlugin.h"
|
#include "WVCryptoPlugin.h"
|
||||||
|
|
||||||
|
#include <endian.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -78,13 +79,14 @@ ssize_t WVCryptoPlugin::decrypt(bool secure, const uint8_t key[KEY_ID_SIZE],
|
|||||||
|
|
||||||
// Convert parameters to the form the CDM wishes to consume them in.
|
// Convert parameters to the form the CDM wishes to consume them in.
|
||||||
const KeyId keyId(reinterpret_cast<const char*>(key), KEY_ID_SIZE);
|
const KeyId keyId(reinterpret_cast<const char*>(key), KEY_ID_SIZE);
|
||||||
const vector<uint8_t> ivVector(iv, iv + KEY_IV_SIZE);
|
vector<uint8_t> ivVector(iv, iv + KEY_IV_SIZE);
|
||||||
const uint8_t* const source = static_cast<const uint8_t*>(srcPtr);
|
const uint8_t* const source = static_cast<const uint8_t*>(srcPtr);
|
||||||
uint8_t* const dest = static_cast<uint8_t*>(dstPtr);
|
uint8_t* const dest = static_cast<uint8_t*>(dstPtr);
|
||||||
|
|
||||||
// Iterate through subsamples, sending them to the CDM serially.
|
// Iterate through subsamples, sending them to the CDM serially.
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
size_t encrypted_offset = 0;
|
static const size_t kAESBlockSize = 16;
|
||||||
|
size_t blockOffset = 0;
|
||||||
|
|
||||||
for (size_t i = 0; i < numSubSamples; ++i) {
|
for (size_t i = 0; i < numSubSamples; ++i) {
|
||||||
const SubSample &subSample = subSamples[i];
|
const SubSample &subSample = subSamples[i];
|
||||||
@@ -119,8 +121,7 @@ ssize_t WVCryptoPlugin::decrypt(bool secure, const uint8_t key[KEY_ID_SIZE],
|
|||||||
CdmResponseType res = mCDM->Decrypt(mSessionId, true, keyId,
|
CdmResponseType res = mCDM->Decrypt(mSessionId, true, keyId,
|
||||||
source + offset,
|
source + offset,
|
||||||
subSample.mNumBytesOfEncryptedData,
|
subSample.mNumBytesOfEncryptedData,
|
||||||
ivVector, encrypted_offset % 16, dest,
|
ivVector, blockOffset, dest, offset);
|
||||||
offset);
|
|
||||||
|
|
||||||
if (!isCdmResponseTypeSuccess(res)) {
|
if (!isCdmResponseTypeSuccess(res)) {
|
||||||
ALOGE("Decrypt error result in session %s during encrypted block: %d",
|
ALOGE("Decrypt error result in session %s during encrypted block: %d",
|
||||||
@@ -130,7 +131,10 @@ ssize_t WVCryptoPlugin::decrypt(bool secure, const uint8_t key[KEY_ID_SIZE],
|
|||||||
}
|
}
|
||||||
|
|
||||||
offset += subSample.mNumBytesOfEncryptedData;
|
offset += subSample.mNumBytesOfEncryptedData;
|
||||||
encrypted_offset += subSample.mNumBytesOfEncryptedData;
|
|
||||||
|
blockOffset += subSample.mNumBytesOfEncryptedData;
|
||||||
|
incrementIV(blockOffset / kAESBlockSize, &ivVector);
|
||||||
|
blockOffset %= kAESBlockSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,4 +162,10 @@ ssize_t WVCryptoPlugin::decrypt(bool secure, const uint8_t key[KEY_ID_SIZE],
|
|||||||
return static_cast<ssize_t>(offset);
|
return static_cast<ssize_t>(offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WVCryptoPlugin::incrementIV(uint64_t increaseBy, vector<uint8_t>* ivPtr) {
|
||||||
|
vector<uint8_t>& iv = *ivPtr;
|
||||||
|
uint64_t* counterBuffer = reinterpret_cast<uint64_t*>(&iv[8]);
|
||||||
|
(*counterBuffer) = htonq(ntohq(*counterBuffer) + increaseBy);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace wvdrm
|
} // namespace wvdrm
|
||||||
|
|||||||
@@ -36,32 +36,11 @@ class WVCryptoPluginTest : public Test {
|
|||||||
static const uint32_t kSessionIdSize = 16;
|
static const uint32_t kSessionIdSize = 16;
|
||||||
uint8_t sessionId[kSessionIdSize];
|
uint8_t sessionId[kSessionIdSize];
|
||||||
|
|
||||||
uint8_t keyId[KEY_ID_SIZE];
|
|
||||||
uint8_t iv[KEY_IV_SIZE];
|
|
||||||
|
|
||||||
static const uint32_t kDataSize = 64;
|
|
||||||
uint8_t in[kDataSize];
|
|
||||||
uint8_t out[kDataSize];
|
|
||||||
|
|
||||||
static const uint32_t kSubSampleCount = 3;
|
|
||||||
CryptoPlugin::SubSample subSamples[kSubSampleCount];
|
|
||||||
|
|
||||||
virtual void SetUp() {
|
virtual void SetUp() {
|
||||||
FILE* fp = fopen("/dev/urandom", "r");
|
FILE* fp = fopen("/dev/urandom", "r");
|
||||||
fread(sessionId, sizeof(uint8_t), kSessionIdSize, fp);
|
fread(sessionId, sizeof(uint8_t), kSessionIdSize, fp);
|
||||||
fread(keyId, sizeof(uint8_t), KEY_ID_SIZE, fp);
|
|
||||||
fread(iv, sizeof(uint8_t), KEY_IV_SIZE, fp);
|
|
||||||
fread(in, sizeof(uint8_t), kDataSize, fp);
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|
||||||
memset(out, 0, sizeof(out));
|
|
||||||
|
|
||||||
memset(subSamples, 0, sizeof(subSamples));
|
|
||||||
subSamples[0].mNumBytesOfEncryptedData = 16;
|
|
||||||
subSamples[1].mNumBytesOfClearData = 16;
|
|
||||||
subSamples[1].mNumBytesOfEncryptedData = 24;
|
|
||||||
subSamples[2].mNumBytesOfEncryptedData = 8;
|
|
||||||
|
|
||||||
// Set default CdmResponseType value for gMock
|
// Set default CdmResponseType value for gMock
|
||||||
DefaultValue<CdmResponseType>::Set(wvcdm::NO_ERROR);
|
DefaultValue<CdmResponseType>::Set(wvcdm::NO_ERROR);
|
||||||
}
|
}
|
||||||
@@ -95,34 +74,96 @@ TEST_F(WVCryptoPluginTest, AttemptsToDecrypt) {
|
|||||||
MockCDM cdm;
|
MockCDM cdm;
|
||||||
WVCryptoPlugin plugin(sessionId, kSessionIdSize, &cdm);
|
WVCryptoPlugin plugin(sessionId, kSessionIdSize, &cdm);
|
||||||
|
|
||||||
// Specify the expected calls to Decrypt
|
uint8_t keyId[KEY_ID_SIZE];
|
||||||
|
uint8_t baseIv[KEY_IV_SIZE];
|
||||||
|
|
||||||
|
static const size_t kDataSize = 185;
|
||||||
|
uint8_t in[kDataSize];
|
||||||
|
uint8_t out[kDataSize];
|
||||||
|
|
||||||
|
FILE* fp = fopen("/dev/urandom", "r");
|
||||||
|
fread(keyId, sizeof(uint8_t), KEY_ID_SIZE, fp);
|
||||||
|
fread(baseIv, sizeof(uint8_t), KEY_IV_SIZE, fp);
|
||||||
|
fread(in, sizeof(uint8_t), kDataSize, fp);
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
static const size_t kSubSampleCount = 6;
|
||||||
|
CryptoPlugin::SubSample subSamples[kSubSampleCount];
|
||||||
|
memset(subSamples, 0, sizeof(subSamples));
|
||||||
|
subSamples[0].mNumBytesOfEncryptedData = 16; // 0
|
||||||
|
subSamples[1].mNumBytesOfClearData = 16; // 1
|
||||||
|
subSamples[1].mNumBytesOfEncryptedData = 16; // 1
|
||||||
|
subSamples[2].mNumBytesOfEncryptedData = 8; // 2
|
||||||
|
subSamples[3].mNumBytesOfClearData = 29; // 2
|
||||||
|
subSamples[3].mNumBytesOfEncryptedData = 24; // 2
|
||||||
|
subSamples[4].mNumBytesOfEncryptedData = 60; // 3
|
||||||
|
subSamples[5].mNumBytesOfEncryptedData = 16; // 4
|
||||||
|
|
||||||
|
uint8_t iv[5][KEY_IV_SIZE];
|
||||||
|
memcpy(iv[0], baseIv, sizeof(baseIv));
|
||||||
|
iv[0][15] = 0;
|
||||||
|
memcpy(iv[1], baseIv, sizeof(baseIv));
|
||||||
|
iv[1][15] = 1;
|
||||||
|
memcpy(iv[2], baseIv, sizeof(baseIv));
|
||||||
|
iv[2][15] = 2;
|
||||||
|
memcpy(iv[3], baseIv, sizeof(baseIv));
|
||||||
|
iv[3][15] = 4;
|
||||||
|
memcpy(iv[4], baseIv, sizeof(baseIv));
|
||||||
|
iv[4][15] = 7;
|
||||||
|
|
||||||
{
|
{
|
||||||
InSequence calls;
|
InSequence calls;
|
||||||
|
|
||||||
|
// SubSample 0
|
||||||
EXPECT_CALL(cdm, Decrypt(ElementsAreArray(sessionId, kSessionIdSize), true,
|
EXPECT_CALL(cdm, Decrypt(ElementsAreArray(sessionId, kSessionIdSize), true,
|
||||||
ElementsAreArray(keyId, KEY_ID_SIZE), in, 16,
|
ElementsAreArray(keyId, KEY_ID_SIZE), in, 16,
|
||||||
ElementsAreArray(iv, KEY_IV_SIZE), 0, out, 0))
|
ElementsAreArray(iv[0], KEY_IV_SIZE), 0, out, 0))
|
||||||
.WillOnce(Return(wvcdm::NO_ERROR));
|
.Times(1);
|
||||||
|
|
||||||
|
// SubSample 1
|
||||||
EXPECT_CALL(cdm, Decrypt(ElementsAreArray(sessionId, kSessionIdSize), false,
|
EXPECT_CALL(cdm, Decrypt(ElementsAreArray(sessionId, kSessionIdSize), false,
|
||||||
ElementsAreArray(keyId, KEY_ID_SIZE), in + 16, 16,
|
ElementsAreArray(keyId, KEY_ID_SIZE), in + 16, 16,
|
||||||
ElementsAreArray(iv, KEY_IV_SIZE), 0, out, 16))
|
ElementsAreArray(iv[1], KEY_IV_SIZE), 0, out, 16))
|
||||||
.WillOnce(Return(wvcdm::NO_ERROR));
|
.Times(1);
|
||||||
|
|
||||||
EXPECT_CALL(cdm, Decrypt(ElementsAreArray(sessionId, kSessionIdSize), true,
|
EXPECT_CALL(cdm, Decrypt(ElementsAreArray(sessionId, kSessionIdSize), true,
|
||||||
ElementsAreArray(keyId, KEY_ID_SIZE), in + 32, 24,
|
ElementsAreArray(keyId, KEY_ID_SIZE), in + 32, 16,
|
||||||
ElementsAreArray(iv, KEY_IV_SIZE), 0, out, 32))
|
ElementsAreArray(iv[1], KEY_IV_SIZE), 0, out, 32))
|
||||||
.WillOnce(Return(wvcdm::NO_ERROR));
|
.Times(1);
|
||||||
|
|
||||||
|
// SubSample 2
|
||||||
|
EXPECT_CALL(cdm, Decrypt(ElementsAreArray(sessionId, kSessionIdSize), true,
|
||||||
|
ElementsAreArray(keyId, KEY_ID_SIZE), in + 48, 8,
|
||||||
|
ElementsAreArray(iv[2], KEY_IV_SIZE), 0, out, 48))
|
||||||
|
.Times(1);
|
||||||
|
|
||||||
|
// SubSample 3
|
||||||
|
EXPECT_CALL(cdm, Decrypt(ElementsAreArray(sessionId, kSessionIdSize), false,
|
||||||
|
ElementsAreArray(keyId, KEY_ID_SIZE), in + 56, 29,
|
||||||
|
ElementsAreArray(iv[2], KEY_IV_SIZE), 0, out, 56))
|
||||||
|
.Times(1);
|
||||||
|
|
||||||
EXPECT_CALL(cdm, Decrypt(ElementsAreArray(sessionId, kSessionIdSize), true,
|
EXPECT_CALL(cdm, Decrypt(ElementsAreArray(sessionId, kSessionIdSize), true,
|
||||||
ElementsAreArray(keyId, KEY_ID_SIZE), in + 56, 8,
|
ElementsAreArray(keyId, KEY_ID_SIZE), in + 85, 24,
|
||||||
ElementsAreArray(iv, KEY_IV_SIZE), 8, out, 56))
|
ElementsAreArray(iv[2], KEY_IV_SIZE), 8, out, 85))
|
||||||
.WillOnce(Return(wvcdm::NO_ERROR));
|
.Times(1);
|
||||||
|
|
||||||
|
// SubSample 4
|
||||||
|
EXPECT_CALL(cdm, Decrypt(ElementsAreArray(sessionId, kSessionIdSize), true,
|
||||||
|
ElementsAreArray(keyId, KEY_ID_SIZE), in + 109, 60,
|
||||||
|
ElementsAreArray(iv[3], KEY_IV_SIZE), 0, out, 109))
|
||||||
|
.Times(1);
|
||||||
|
|
||||||
|
// SubSample 5
|
||||||
|
EXPECT_CALL(cdm, Decrypt(ElementsAreArray(sessionId, kSessionIdSize), true,
|
||||||
|
ElementsAreArray(keyId, KEY_ID_SIZE), in + 169, 16,
|
||||||
|
ElementsAreArray(iv[4], KEY_IV_SIZE), 12, out, 169))
|
||||||
|
.Times(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
AString errorDetailMessage;
|
AString errorDetailMessage;
|
||||||
|
|
||||||
ssize_t res = plugin.decrypt(false, keyId, iv, CryptoPlugin::kMode_AES_CTR,
|
ssize_t res = plugin.decrypt(false, keyId, iv[0], CryptoPlugin::kMode_AES_CTR,
|
||||||
in, subSamples, kSubSampleCount, out,
|
in, subSamples, kSubSampleCount, out,
|
||||||
&errorDetailMessage);
|
&errorDetailMessage);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user