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:
Fred Gylys-Colwell
2016-09-14 12:44:09 -07:00
parent 24124ea6e3
commit eb3f8b786a
56 changed files with 4632 additions and 2083 deletions

View File

@@ -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.

View File

@@ -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 \

View File

@@ -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)) {

View File

@@ -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.

View File

@@ -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 =

View File

@@ -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;
}

View File

@@ -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;