File util, generic crypto, and key query
This CL merges several CLs from the widevine repo: http://go/wvgerrit/18012 Add support for querying allowed usage for key. http://go/wvgerrit/17971 Add per-origin storage. http://go/wvgerrit/18152 Add OEMCrypto's generic crypto operations to CDM. http://go/wvgerrit/17911 QueryKeyControlInfo => QueryOemCryptoSessionId Note: numbering in wv_cdm_types.h was added in this CL and will be back ported to wvgerrit in a future CL. Change-Id: Idb9e9a67e94f62f25dc16c5307f75a08b3430b64
This commit is contained in:
@@ -397,7 +397,8 @@ OEMCryptoResult OEMCrypto_OpenSession(OEMCrypto_SESSION *session);
|
||||
* OEMCrypto_CloseSession
|
||||
*
|
||||
* Description:
|
||||
* Closes the crypto security engine session and frees any associated resources.
|
||||
* Closes the crypto security engine session and frees any associated
|
||||
* resources.
|
||||
*
|
||||
* Parameters:
|
||||
* session (in) - handle for the session to be closed.
|
||||
|
||||
@@ -21,8 +21,6 @@ LOCAL_C_INCLUDES += \
|
||||
$(LOCAL_PATH)/src \
|
||||
vendor/widevine/libwvdrmengine/cdm/core/include \
|
||||
vendor/widevine/libwvdrmengine/third_party/stringencoders/src \
|
||||
external/openssl/include \
|
||||
external/openssl/include/openssl \
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libcutils \
|
||||
|
||||
@@ -1182,9 +1182,12 @@ bool SessionContext::IsUsageEntryValid() {
|
||||
|
||||
void SessionContext::ReleaseUsageEntry() { usage_entry_ = NULL; }
|
||||
|
||||
CryptoEngine::CryptoEngine()
|
||||
: current_session_(NULL), use_test_keybox_(false),
|
||||
usage_table_(new UsageTable(this)), rsa_key_(NULL) {
|
||||
CryptoEngine::CryptoEngine(wvcdm::FileSystem* file_system)
|
||||
: current_session_(NULL),
|
||||
use_test_keybox_(false),
|
||||
file_system_(file_system),
|
||||
usage_table_(new UsageTable(this)),
|
||||
rsa_key_(NULL) {
|
||||
ERR_load_crypto_strings();
|
||||
|
||||
if (!supports_keybox() && !LoadPkcs8RsaKey(kPrivateKey, kPrivateKeySize)) {
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include <openssl/rsa.h>
|
||||
|
||||
#include "file_store.h"
|
||||
#include "lock.h"
|
||||
#include "oemcrypto_key_mock.h"
|
||||
#include "oemcrypto_keybox_mock.h"
|
||||
@@ -231,7 +232,7 @@ class SessionContext {
|
||||
|
||||
class CryptoEngine {
|
||||
public:
|
||||
CryptoEngine();
|
||||
CryptoEngine(wvcdm::FileSystem* file_system);
|
||||
~CryptoEngine();
|
||||
|
||||
bool Initialized() { return true; }
|
||||
@@ -267,6 +268,7 @@ class CryptoEngine {
|
||||
OEMCrypto_HDCP_Capability maximum_hdcp_capability();
|
||||
|
||||
UsageTable* usage_table() { return usage_table_; }
|
||||
wvcdm::FileSystem* file_system() { return file_system_; }
|
||||
bool local_display();
|
||||
bool closed_platform();
|
||||
bool supports_storage();
|
||||
@@ -284,6 +286,7 @@ class CryptoEngine {
|
||||
WvTestKeybox test_keybox_;
|
||||
bool use_test_keybox_;
|
||||
wvcdm::Lock session_table_lock_;
|
||||
wvcdm::FileSystem* file_system_;
|
||||
UsageTable* usage_table_;
|
||||
RSA* rsa_key_; // If no keybox, this is baked in certificate.
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "file_store.h"
|
||||
#include "log.h"
|
||||
#include "oemcrypto_engine_mock.h"
|
||||
#include "oemcrypto_logging.h"
|
||||
@@ -45,7 +46,9 @@ OEMCryptoResult OEMCrypto_Initialize(void) {
|
||||
LOGI("------------------------- OEMCrypto_Initialize(void)\n");
|
||||
}
|
||||
|
||||
crypto_engine = new CryptoEngine;
|
||||
// NOTE: This requires a compatible Filesystem implementation.
|
||||
wvcdm::FileSystem* fs = new wvcdm::FileSystem();
|
||||
crypto_engine = new CryptoEngine(fs);
|
||||
|
||||
if (!crypto_engine || !crypto_engine->Initialized()) {
|
||||
LOGE("[OEMCrypto_Initialize(): failed]");
|
||||
@@ -1321,17 +1324,17 @@ OEMCryptoResult OEMCrypto_Generic_Encrypt(OEMCrypto_SESSION session,
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
if (NO_ERROR != crypto_engine->ValidateKeybox()) {
|
||||
LOGE("[OEMCrypto_Generic_Enrypt(): ERROR_KEYBOX_INVALID]");
|
||||
LOGE("[OEMCrypto_Generic_Enrcypt(): ERROR_KEYBOX_INVALID]");
|
||||
return OEMCrypto_ERROR_KEYBOX_INVALID;
|
||||
}
|
||||
SessionContext* session_ctx = crypto_engine->FindSession(session);
|
||||
if (!session_ctx || !session_ctx->isValid()) {
|
||||
LOGE("[OEMCrypto_Generic_Enrypt(): ERROR_INVALID_SESSION]");
|
||||
LOGE("[OEMCrypto_Generic_Encrypt(): ERROR_INVALID_SESSION]");
|
||||
return OEMCrypto_ERROR_INVALID_SESSION;
|
||||
}
|
||||
if (in_buffer == NULL || buffer_length == 0 ||
|
||||
iv == NULL || out_buffer == NULL) {
|
||||
LOGE("[OEMCrypto_Generic_Enrypt(): OEMCrypto_ERROR_INVALID_CONTEXT]");
|
||||
LOGE("[OEMCrypto_Generic_Encrypt(): OEMCrypto_ERROR_INVALID_CONTEXT]");
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
}
|
||||
OEMCryptoResult sts =
|
||||
|
||||
@@ -144,7 +144,8 @@ UsageTable::UsageTable(CryptoEngine *ce) {
|
||||
table_.clear();
|
||||
|
||||
// Load saved table.
|
||||
wvcdm::File file;
|
||||
wvcdm::FileSystem *file_system = ce->file_system();
|
||||
wvcdm::File *file;
|
||||
std::string path;
|
||||
// Note: this path is OK for a real implementation, but using security level 1
|
||||
// would be better.
|
||||
@@ -155,14 +156,14 @@ UsageTable::UsageTable(CryptoEngine *ce) {
|
||||
}
|
||||
|
||||
std::string filename = path + "UsageTable.dat";
|
||||
if (!file.Exists(filename)) {
|
||||
if (!file_system->Exists(filename)) {
|
||||
if (LogCategoryEnabled(kLoggingTraceUsageTable)) {
|
||||
LOGI("UsageTable: No saved usage table. Creating new table.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
size_t file_size = file.FileSize(filename);
|
||||
size_t file_size = file_system->FileSize(filename);
|
||||
std::vector<uint8_t> encrypted_buffer(file_size);
|
||||
std::vector<uint8_t> buffer(file_size);
|
||||
StoredUsageTable *stored_table =
|
||||
@@ -170,12 +171,13 @@ UsageTable::UsageTable(CryptoEngine *ce) {
|
||||
StoredUsageTable *encrypted_table =
|
||||
reinterpret_cast<StoredUsageTable *>(&encrypted_buffer[0]);
|
||||
|
||||
if (!file.Open(filename, wvcdm::File::kReadOnly | wvcdm::File::kBinary)) {
|
||||
file = file_system->Open(filename, wvcdm::FileSystem::kReadOnly);
|
||||
if (!file) {
|
||||
LOGE("UsageTable: File open failed: %s", path.c_str());
|
||||
return;
|
||||
}
|
||||
file.Read(reinterpret_cast<char *>(&encrypted_buffer[0]), file_size);
|
||||
file.Close();
|
||||
file->Read(reinterpret_cast<char *>(&encrypted_buffer[0]), file_size);
|
||||
file->Close();
|
||||
|
||||
// First, verify the signature of the usage table file.
|
||||
std::vector<uint8_t> &key = ce_->real_keybox().device_key();
|
||||
@@ -213,15 +215,15 @@ UsageTable::UsageTable(CryptoEngine *ce) {
|
||||
// a file in user space. It should be stored in secure memory. For the
|
||||
// reference implementation, we'll just pretend this is secure.
|
||||
std::string filename2 = path + "GenerationNumber.dat";
|
||||
if (!file.Exists(filename2) ||
|
||||
!file.Open(filename2, wvcdm::File::kReadOnly | wvcdm::File::kBinary)) {
|
||||
file = file_system->Open(filename2, wvcdm::FileSystem::kReadOnly);
|
||||
if (!file) {
|
||||
LOGE("UsageTable: File open failed: %s (clearing table)", path.c_str());
|
||||
generation_ = 0;
|
||||
table_.clear();
|
||||
return;
|
||||
}
|
||||
file.Read(reinterpret_cast<char *>(&generation_), sizeof(int64_t));
|
||||
file.Close();
|
||||
file->Read(reinterpret_cast<char *>(&generation_), sizeof(int64_t));
|
||||
file->Close();
|
||||
if (stored_table->generation == generation_ + 1) {
|
||||
if (LogCategoryEnabled(kLoggingTraceUsageTable)) {
|
||||
LOGW("UsageTable: File is one generation old. Acceptable rollback.");
|
||||
@@ -297,7 +299,8 @@ bool UsageTable::SaveToFile() {
|
||||
return false;
|
||||
}
|
||||
|
||||
wvcdm::File file;
|
||||
wvcdm::FileSystem *file_system = ce_->file_system();
|
||||
wvcdm::File *file;
|
||||
std::string path;
|
||||
// Note: this path is OK for a real implementation, but using security level 1
|
||||
// would be better.
|
||||
@@ -306,38 +309,34 @@ bool UsageTable::SaveToFile() {
|
||||
LOGE("UsageTable: Unable to get base path");
|
||||
return false;
|
||||
}
|
||||
if (!file.IsDirectory(path)) {
|
||||
if (!file.CreateDirectory(path)) {
|
||||
LOGE("UsageTable: could not create directory: %s", path.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::string filename = path + "UsageTable.dat";
|
||||
if (!file.Exists(filename)) {
|
||||
if (!file_system->Exists(filename)) {
|
||||
if (LogCategoryEnabled(kLoggingTraceUsageTable)) {
|
||||
LOGI("UsageTable: No saved usage table. Creating new table.");
|
||||
}
|
||||
}
|
||||
|
||||
if (!file.Open(filename, wvcdm::File::kCreate | wvcdm::File::kTruncate |
|
||||
wvcdm::File::kBinary)) {
|
||||
file = file_system->Open(
|
||||
filename, wvcdm::FileSystem::kCreate | wvcdm::FileSystem::kTruncate);
|
||||
if (!file) {
|
||||
LOGE("UsageTable: Could not save usage table: %s", path.c_str());
|
||||
return false;
|
||||
}
|
||||
file.Write(reinterpret_cast<char *>(&encrypted_buffer[0]), file_size);
|
||||
file.Close();
|
||||
file->Write(reinterpret_cast<char *>(&encrypted_buffer[0]), file_size);
|
||||
file->Close();
|
||||
|
||||
// On a real implementation, you should NOT put the generation number in
|
||||
// a file in user space. It should be stored in secure memory.
|
||||
std::string filename2 = path + "GenerationNumber.dat";
|
||||
if (!file.Open(filename2, wvcdm::File::kCreate | wvcdm::File::kTruncate |
|
||||
wvcdm::File::kBinary)) {
|
||||
file = file_system->Open(
|
||||
filename2, wvcdm::FileSystem::kCreate | wvcdm::FileSystem::kTruncate);
|
||||
if (!file) {
|
||||
LOGE("UsageTable: File open failed: %s", path.c_str());
|
||||
return false;
|
||||
}
|
||||
file.Write(reinterpret_cast<char *>(&generation_), sizeof(int64_t));
|
||||
file.Close();
|
||||
file->Write(reinterpret_cast<char *>(&generation_), sizeof(int64_t));
|
||||
file->Close();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1293,7 +1293,7 @@ class OEMCryptoSessionTestsDecryptTests
|
||||
}
|
||||
|
||||
void TestDecryptCENC(const vector<uint8_t>& key,
|
||||
const vector<uint8_t>& encryptionIv,
|
||||
const vector<uint8_t>& /* encryptionIv */,
|
||||
const vector<uint8_t>& encryptedData,
|
||||
const vector<uint8_t>& unencryptedData) {
|
||||
OEMCryptoResult sts;
|
||||
|
||||
Reference in New Issue
Block a user