blob: abb26eb6616d2071e30a3397654c21976ca39acd [file] [log] [blame]
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Original code copied from NDK Native-media sample code */
//#define LOG_NDEBUG 0
#define TAG "NativeMediaCrypto"
#include <log/log.h>
#include <android_media_MediaCrypto.h>
#include <assert.h>
#include <binder/MemoryDealer.h>
#include <jni.h>
#include <media/ICrypto.h>
#include <media/stagefright/foundation/AString.h>
#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <utils/StrongPointer.h>
#include <semaphore.h>
static const size_t kBufferSize = 1024;
using namespace android;
static jboolean testCrypto(sp<ICrypto> icrypto,
const CryptoPlugin::SubSample *subSample, CryptoPlugin::Mode mode)
{
// Allocate source buffer
sp<MemoryDealer> memDealer = new MemoryDealer(kBufferSize, "MediaCryptoTest");
sp<IMemory> srcBuffer = memDealer->allocate(kBufferSize);
if (!srcBuffer->pointer()) {
ALOGE("Failed to allocate source buffer");
return false;
}
memset(srcBuffer->pointer(), 's', kBufferSize);
// Invalid dest pointer should fault if mediaserver attempts
// to write to it. Don't use NULL because that's probably
// checked for.
void *dstPtr = reinterpret_cast<void *>(1);
// Spoof the device as being secure
bool secure = true;
uint8_t key[16] = {0};
uint8_t iv[16] = {0};
uint32_t offset = 0;
AString errorDetailMsg;
ssize_t result = icrypto->decrypt(secure, key, iv, mode, srcBuffer, offset,
subSample, 1, dstPtr, &errorDetailMsg);
// call should return an error and shouldn't kill media server
return (result != OK && result != DEAD_OBJECT);
}
// Test for icrypto interface vulnerabilities
extern "C" jboolean Java_android_security_cts_MediaCryptoTest_validateCryptoNative(JNIEnv *env,
jclass /*clazz*/, jobject crypto)
{
bool result = false;
sp<ICrypto> icrypto = JCrypto::GetCrypto(env, crypto);
if (icrypto != NULL) {
if (icrypto->requiresSecureDecoderComponent("video/avc")) {
ALOGI("device is secure, bypassing test");
return true;
}
CryptoPlugin::Mode unencryptedMode = CryptoPlugin::kMode_Unencrypted;
CryptoPlugin::Mode aesCtrMode = CryptoPlugin::kMode_AES_CTR;
CryptoPlugin::SubSample clrSubSample = {kBufferSize, 0};
CryptoPlugin::SubSample encSubSample = {0, kBufferSize};
result =
testCrypto(icrypto, &clrSubSample, unencryptedMode) &&
testCrypto(icrypto, &clrSubSample, aesCtrMode) &&
testCrypto(icrypto, &encSubSample, unencryptedMode) &&
testCrypto(icrypto, &encSubSample, aesCtrMode);
} else {
ALOGE("Failed to get icrypto interface");
}
return result;
}