Fix for b/8594163 [SelectContentKey(): No key matches key id]

...when playing clear parts of encrypted content.

Change-Id: I5fb027d22212f07b43deced2da77c98cb3800e7f
This commit is contained in:
Jeff Tinker
2013-04-11 14:14:55 -07:00
parent 3711ca87ae
commit 2f980d7d7e
4 changed files with 109 additions and 14 deletions

View File

@@ -138,12 +138,14 @@ CdmResponseType CdmSession::Decrypt(bool is_encrypted,
return UNKNOWN_ERROR;
// Check if key needs to be selected
if (key_id_.compare(key_id) != 0) {
if (crypto_session_->SelectKey(key_id)) {
key_id_ = key_id;
}
else {
return UNKNOWN_ERROR;
if (is_encrypted) {
if (key_id_.compare(key_id) != 0) {
if (crypto_session_->SelectKey(key_id)) {
key_id_ = key_id;
}
else {
return UNKNOWN_ERROR;
}
}
}

View File

@@ -856,6 +856,12 @@ bool CryptoEngine::DecryptCTR(SessionContext* session,
void* clear_data,
BufferType buffer_type) {
if (! is_encrypted) {
memcpy(reinterpret_cast<uint8_t*>(clear_data),
&cipher_data[0], cipher_data.size());
return true;
}
// Check there is a content key
if (session->current_content_key() == NULL) {
LOGE("[DecryptCTR(): OEMCrypto_ERROR_NO_CONTENT_KEY]");
@@ -902,12 +908,6 @@ bool CryptoEngine::DecryptCTR(SessionContext* session,
return true;
}
if (! is_encrypted) {
memcpy(reinterpret_cast<uint8_t*>(clear_data),
&cipher_data[0], cipher_data.size());
return true;
}
// Local copy (will be modified).
uint8_t aes_iv[AES_BLOCK_SIZE];
if (static_cast<int>(iv.size()) != AES_BLOCK_SIZE) {

View File

@@ -7,7 +7,8 @@ LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_PACKAGE_NAME := MediaDrmAPITest
LOCAL_SDK_VERSION := current
# TODO: Uncomment this line when the MediaDrm APIs are unhidden
#LOCAL_SDK_VERSION := current
include $(BUILD_PACKAGE)

View File

@@ -154,6 +154,11 @@ public class MediaDrmAPITest extends TabActivity {
listDecoders();
testClearContentNoKeys();
testEncryptedContent();
}
private void testEncryptedContent() {
try {
MediaDrm drm = new MediaDrm(kWidevineScheme);
byte[] sessionId = drm.openSession();
@@ -167,6 +172,19 @@ public class MediaDrmAPITest extends TabActivity {
}
}
private void testClearContentNoKeys() {
try {
MediaDrm drm = new MediaDrm(kWidevineScheme);
byte[] sessionId = drm.openSession();
testClear(sessionId);
drm.closeSession(sessionId);
} catch (Exception e) {
e.printStackTrace();
}
}
public void doLicenseExchange(MediaDrm drm, byte[] sessionId) throws Exception {
MediaDrm.KeyRequest drmRequest;
drmRequest = drm.getKeyRequest(sessionId, kKeyId, "video/avc",
@@ -207,6 +225,7 @@ public class MediaDrmAPITest extends TabActivity {
// do minimal codec setup to pass an encrypted buffer down the stack to see if it gets
// decrypted correctly.
public void testDecrypt(byte[] sessionId) throws Exception {
Log.i(TAG, "testDecrypt");
MediaCrypto crypto;
try {
@@ -287,7 +306,80 @@ public class MediaDrmAPITest extends TabActivity {
codec.stop();
codec.release();
Log.i(TAG, "all done!");
Log.i(TAG, "testDecrypt: all done!");
}
// do minimal codec setup to pass a clear buffer down the stack to see if it gets
// passed through correctly.
public void testClear(byte[] sessionId) throws Exception {
Log.i(TAG, "testClear");
MediaCrypto crypto;
try {
crypto = new MediaCrypto(kWidevineScheme, getTestModeSessionId(sessionId));
} catch (MediaCryptoException e) {
throw e;
}
String mime = "video/avc";
MediaCodec codec;
if (crypto.requiresSecureDecoderComponent(mime)) {
codec = MediaCodec.createByCodecName(getSecureDecoderNameForMime(mime));
} else {
codec = MediaCodec.createDecoderByType(mime);
}
MediaFormat format = MediaFormat.createVideoFormat(mime, 640, 480);
codec.configure(format, null, crypto, 0);
codec.start();
ByteBuffer[] inputBuffers = codec.getInputBuffers();
ByteBuffer[] outputBuffers = codec.getOutputBuffers();
int index;
Log.i(TAG, "waiting for buffer...");
while ((index = codec.dequeueInputBuffer(0 /* timeoutUs */)) < 0) {
Thread.sleep(10);
}
Log.i(TAG, "Got index " + index);
LinkedList<TestVector> vectors = TestVectors.GetTestVectors();
ListIterator<TestVector> iter = vectors.listIterator(0);
while (iter.hasNext()) {
TestVector tv = iter.next();
inputBuffers[index].clear();
inputBuffers[index].put(tv.mClearBuf, 0, tv.mClearBuf.length);
try {
codec.queueInputBuffer(index, 0 /* offset */, tv.mClearBuf.length,
0 /* sampleTime */, 0 /* flags */);
} catch (CryptoException e) {
ByteBuffer refBuffer = ByteBuffer.allocate(tv.mClearBuf.length);
refBuffer.put(tv.mClearBuf, 0, tv.mClearBuf.length);
// in test mode, the WV CryptoPlugin throws a CryptoException where the
// message string contains a SHA256 hash of the decrypted data, for verification
// purposes.
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] sha256 = digest.digest(refBuffer.array());
if (Arrays.equals(sha256, hex2ba(e.getMessage()))) {
Log.i(TAG, "sha256: " + e.getMessage() + " matches OK");
} else {
Log.i(TAG, "MediaCrypto sha256: " + e.getMessage() +
"does not match test vector sha256: ");
for (int i = 0; i < sha256.length; i++) {
System.out.printf("%02x", sha256[i]);
}
}
}
}
codec.stop();
codec.release();
Log.i(TAG, "testClear: all done!");
}
private String getSecureDecoderNameForMime(String mime) {