Use MediaDrm property to ignore installed keybox
Merge from Widevine repo of http://go/wvgerrit/135984 If the MediaDrm property string debugIgnoreKeyboxCount is set to 1, then the keybox will be ignored on the next initialization. This will force an OTA keybox reprovisioning. Equivalently, a 1 may be written to the file L1/debug_ignore_keybox_count.txt. In order to test a failed reprovisioning step, a value of 2 may be used. Bug: 187646550 Merged-In: Ie7d34a8b355398855f4ec43dd95dd73c5907bdeb Change-Id: Ie7d34a8b355398855f4ec43dd95dd73c5907bdeb
This commit is contained in:
committed by
Alex Dale
parent
5975b4e70a
commit
c21b756451
@@ -303,6 +303,12 @@ class CdmEngine {
|
||||
|
||||
virtual size_t SessionSize() const { return session_map_.Size(); }
|
||||
|
||||
// This tells the OEMCrypto adapter to ignore the next |count| keyboxes and
|
||||
// report that it needs provisioning instead.
|
||||
static CdmResponseType SetDebugIgnoreKeyboxCount(uint32_t count) {
|
||||
return CryptoSession::SetDebugIgnoreKeyboxCount(count);
|
||||
}
|
||||
|
||||
static CdmResponseType ParseDecryptHashString(const std::string& hash_string,
|
||||
CdmSessionId* id,
|
||||
uint32_t* frame_number,
|
||||
|
||||
@@ -295,6 +295,10 @@ class CryptoSession {
|
||||
|
||||
bool needs_keybox_provisioning() const { return needs_keybox_provisioning_; }
|
||||
|
||||
// This tells the OEMCrypto adapter to ignore the next |count| keyboxes and
|
||||
// report that it needs provisioning instead.
|
||||
static CdmResponseType SetDebugIgnoreKeyboxCount(uint32_t count);
|
||||
|
||||
// Returns a system-wide singleton instance of SystemFallbackPolicy
|
||||
// to be used for communicating OTA keybox provisioning state between
|
||||
// apps. Returns a null pointer if OTA provisioning is not supported,
|
||||
|
||||
@@ -16,6 +16,10 @@ namespace wvcdm {
|
||||
OEMCryptoResult OEMCrypto_InitializeAndCheckKeybox(
|
||||
bool* needs_keybox_provisioning);
|
||||
|
||||
// This tells the OEMCrypto adapter to ignore the next |count| keyboxes and
|
||||
// report that it needs provisioning instead.
|
||||
OEMCryptoResult OEMCrypto_SetDebugIgnoreKeyboxCount(uint32_t count);
|
||||
|
||||
// This attempts to open a session at the desired security level.
|
||||
// If one level is not available, the other will be used instead.
|
||||
OEMCryptoResult OEMCrypto_OpenSession(OEMCrypto_SESSION* session,
|
||||
|
||||
@@ -3031,6 +3031,11 @@ OEMCryptoResult CryptoSession::LegacyDecryptInChunks(
|
||||
return sts;
|
||||
}
|
||||
|
||||
CdmResponseType CryptoSession::SetDebugIgnoreKeyboxCount(uint32_t count) {
|
||||
OEMCryptoResult status = OEMCrypto_SetDebugIgnoreKeyboxCount(count);
|
||||
return MapOEMCryptoResult(status, UNKNOWN_ERROR, "SetDebugIgnoreKeyboxCount");
|
||||
}
|
||||
|
||||
okp::SystemFallbackPolicy* CryptoSession::GetOkpFallbackPolicy() {
|
||||
const auto getter = [&]() -> okp::SystemFallbackPolicy* {
|
||||
// If not set, then OTA keybox provisioning is not supported or
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
@@ -626,6 +627,70 @@ class WatchDog {
|
||||
uint32_t uid_;
|
||||
};
|
||||
|
||||
// The DebugIgnoreKeyboxCount functions are related to testing the Keybox OTA
|
||||
// Reprovisioning solution. If a positive counter is set, then the keybox will
|
||||
// be ignored through that many initializations.
|
||||
std::string GetIgnoreCountFile() {
|
||||
std::string path;
|
||||
if (!wvcdm::Properties::GetDeviceFilesBasePath(wvcdm::kSecurityLevelL1,
|
||||
&path)) {
|
||||
LOGW("DebugIgnoreKeyboxCount: Unable to get base path");
|
||||
path = "/data/";
|
||||
}
|
||||
path += "debug_ignore_keybox_count.txt";
|
||||
return path;
|
||||
}
|
||||
|
||||
uint32_t GetDebugIgnoreKeyboxCount() {
|
||||
const std::string filename = GetIgnoreCountFile();
|
||||
wvcdm::FileSystem file_system;
|
||||
if (!file_system.Exists(filename)) {
|
||||
return 0;
|
||||
}
|
||||
auto file = file_system.Open(filename, file_system.kReadOnly);
|
||||
if (!file) {
|
||||
LOGE("Error opening %s", filename.c_str());
|
||||
return 0;
|
||||
}
|
||||
ssize_t size = file_system.FileSize(filename);
|
||||
std::string contents(size, ' ');
|
||||
ssize_t size_read = file->Read(const_cast<char*>(contents.data()), size);
|
||||
if (size != size_read) {
|
||||
LOGE("Short ignore_debug_keybox_count = %zu", size_read);
|
||||
return 0;
|
||||
}
|
||||
std::istringstream ss(contents);
|
||||
uint32_t count = 0;
|
||||
ss >> count;
|
||||
if (ss.fail()) {
|
||||
LOGE("Could not parse an integer from '%s'", contents.c_str());
|
||||
count = 0;
|
||||
}
|
||||
LOGD("Using IgnoreDebugKeyboxCount = %u", count);
|
||||
return count;
|
||||
}
|
||||
|
||||
OEMCryptoResult SetDebugIgnoreKeyboxCount(uint32_t count) {
|
||||
const std::string filename = GetIgnoreCountFile();
|
||||
wvcdm::FileSystem file_system;
|
||||
auto file =
|
||||
file_system.Open(filename, file_system.kCreate | file_system.kTruncate);
|
||||
if (!file) {
|
||||
LOGE("Could not create file %s", filename.c_str());
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
const std::string contents = std::to_string(count);
|
||||
ssize_t size = contents.size();
|
||||
ssize_t size_written = file->Write(contents.data(), size);
|
||||
if (size != size_written) {
|
||||
LOGE("Wrote %zd bytes of %s, not %zd, to file %s", size_written,
|
||||
contents.c_str(), size, filename.c_str());
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
LOGD("Wrote %u to %s", count, filename.c_str());
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
struct LevelSession {
|
||||
FunctionPointers* fcn;
|
||||
OEMCrypto_SESSION session;
|
||||
@@ -1218,7 +1283,12 @@ OEMCryptoResult OEMCrypto_InitializeAndCheckKeybox(
|
||||
if (status != OEMCrypto_SUCCESS) return status;
|
||||
const OEMCryptoResult keybox_status =
|
||||
gAdapter->ValidateOrInstallKeyboxOrCert();
|
||||
if (keybox_status == OEMCrypto_ERROR_NEEDS_KEYBOX_PROVISIONING) {
|
||||
uint32_t ignore_count = GetDebugIgnoreKeyboxCount();
|
||||
if (keybox_status == OEMCrypto_ERROR_NEEDS_KEYBOX_PROVISIONING ||
|
||||
ignore_count > 0) {
|
||||
if (ignore_count > 0) {
|
||||
LOGD("Ignoring keybox status %d", static_cast<int>(keybox_status));
|
||||
}
|
||||
*needs_keybox_provisioning = true;
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
@@ -1494,6 +1564,10 @@ OEMCryptoResult OEMCrypto_GetOEMPublicCertificate(uint8_t* public_cert,
|
||||
}
|
||||
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
OEMCryptoResult OEMCrypto_SetDebugIgnoreKeyboxCount(uint32_t count) {
|
||||
return SetDebugIgnoreKeyboxCount(count);
|
||||
}
|
||||
} // namespace wvcdm
|
||||
|
||||
extern "C" OEMCryptoResult OEMCrypto_SetSandbox(const uint8_t* sandbox_id,
|
||||
@@ -2818,5 +2892,23 @@ extern "C" OEMCryptoResult OEMCrypto_ProcessOTAKeybox(OEMCrypto_SESSION session,
|
||||
const FunctionPointers* fcn = gAdapter->GetFunctionPointers(kLevelDefault);
|
||||
if (!fcn) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
if (fcn->ProcessOTAKeybox == nullptr) return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||
return fcn->ProcessOTAKeybox(session, buffer, buffer_length, use_test_key);
|
||||
const OEMCryptoResult result =
|
||||
fcn->ProcessOTAKeybox(session, buffer, buffer_length, use_test_key);
|
||||
if (result == OEMCrypto_SUCCESS) {
|
||||
// If the new keybox was installed, and we had been told to ignore a valid
|
||||
// keybox, then we should now decrement the ignore counter.
|
||||
int32_t ignore_count = GetDebugIgnoreKeyboxCount();
|
||||
if (ignore_count > 0) {
|
||||
ignore_count--;
|
||||
const OEMCryptoResult save_result =
|
||||
SetDebugIgnoreKeyboxCount(ignore_count);
|
||||
if (save_result == OEMCrypto_SUCCESS) {
|
||||
LOGD("Installed OTA keybox. Ignore count is now %u", ignore_count);
|
||||
} else {
|
||||
LOGE("Installed OTA keybox. save ignore count failed %d, count=%u",
|
||||
static_cast<int>(save_result), ignore_count);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -159,6 +159,8 @@ class WvContentDecryptionModule : public android::RefBase, public TimerHandler {
|
||||
// Closes the CdmEngine and sessions associated with the given CdmIdentifier.
|
||||
virtual CdmResponseType CloseCdm(const CdmIdentifier& identifier);
|
||||
|
||||
virtual CdmResponseType SetDebugIgnoreKeyboxCount(uint32_t count);
|
||||
|
||||
virtual CdmResponseType SetDecryptHash(const std::string& hash_data,
|
||||
CdmSessionId* session_id);
|
||||
virtual CdmResponseType GetDecryptHashError(const CdmSessionId& session_id,
|
||||
|
||||
@@ -500,6 +500,11 @@ CdmResponseType WvContentDecryptionModule::CloseCdm(
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
CdmResponseType WvContentDecryptionModule::SetDebugIgnoreKeyboxCount(
|
||||
uint32_t count) {
|
||||
return CdmEngine::SetDebugIgnoreKeyboxCount(count);
|
||||
}
|
||||
|
||||
CdmResponseType WvContentDecryptionModule::SetDecryptHash(
|
||||
const std::string& hash_data, CdmSessionId* id) {
|
||||
if (id == nullptr) {
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <endian.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -667,6 +668,17 @@ status_t WVDrmPlugin::setPropertyString(const String8& name,
|
||||
} else {
|
||||
mCdmIdentifier.origin = value.string();
|
||||
}
|
||||
} else if (name == "debugIgnoreKeyboxCount") {
|
||||
std::istringstream ss(value.string());
|
||||
uint32_t count = 0;
|
||||
ss >> count;
|
||||
if (ss.fail()) {
|
||||
ALOGE("Could not parse an integer from '%s'", value.string());
|
||||
count = 0;
|
||||
return Status::BAD_VALUE;
|
||||
}
|
||||
CdmResponseType res = mCDM->SetDebugIgnoreKeyboxCount(count);
|
||||
return mapCdmResponseType(res);
|
||||
} else if (name == "decryptHash") {
|
||||
CdmSessionId sessionId;
|
||||
CdmResponseType res =
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <cstring>
|
||||
#include <list>
|
||||
#include <stdlib.h>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include "WVDrmPlugin.h"
|
||||
@@ -1431,6 +1432,17 @@ Return<Status> WVDrmPlugin::setPropertyString(const hidl_string& propertyName,
|
||||
return Status::BAD_VALUE;
|
||||
}
|
||||
}
|
||||
} else if (name == "debugIgnoreKeyboxCount") {
|
||||
std::istringstream ss(_value);
|
||||
uint32_t count = 0;
|
||||
ss >> count;
|
||||
if (ss.fail()) {
|
||||
ALOGE("Could not parse an integer from '%s'", _value.c_str());
|
||||
count = 0;
|
||||
return Status::BAD_VALUE;
|
||||
}
|
||||
CdmResponseType res = mCDM->SetDebugIgnoreKeyboxCount(count);
|
||||
return mapCdmResponseType(res);
|
||||
} else if (name == "decryptHash") {
|
||||
wvcdm::CdmSessionId sessionId;
|
||||
CdmResponseType res =
|
||||
|
||||
Reference in New Issue
Block a user