Merge "Clean comments, namespace, and variable names"

This commit is contained in:
Jeff Tinker
2014-05-19 02:25:54 +00:00
committed by Android (Google) Code Review
38 changed files with 154 additions and 1064 deletions

View File

@@ -1,7 +1,7 @@
// Copyright 2012 Google Inc. All Rights Reserved.
#ifndef CDM_BASE_BUFFER_READER_H_
#define CDM_BASE_BUFFER_READER_H_
#ifndef WVCDM_CORE_BUFFER_READER_H_
#define WVCDM_CORE_BUFFER_READER_H_
#include <stdint.h>
#include <string>
@@ -65,4 +65,4 @@ class BufferReader {
} // namespace wvcdm
#endif // CDM_BASE_BUFFER_READER_H_
#endif // WVCDM_CORE_BUFFER_READER_H_

View File

@@ -1,7 +1,7 @@
// Copyright 2013 Google Inc. All Rights Reserved.
#ifndef CDM_BASE_CDM_CLIENT_PROPERTY_SET_H_
#define CDM_BASE_CDM_CLIENT_PROPERTY_SET_H_
#ifndef WVCDM_CORE_CDM_CLIENT_PROPERTY_SET_H_
#define WVCDM_CORE_CDM_CLIENT_PROPERTY_SET_H_
#include <string>
#include <vector>
@@ -23,4 +23,4 @@ class CdmClientPropertySet {
} // namespace wvcdm
#endif // CDM_BASE_CDM_CLIENT_PROPERTY_SET_H_
#endif // WVCDM_CORE_CDM_CLIENT_PROPERTY_SET_H_

View File

@@ -1,7 +1,7 @@
// Copyright 2013 Google Inc. All Rights Reserved.
#ifndef CDM_BASE_CDM_ENGINE_H_
#define CDM_BASE_CDM_ENGINE_H_
#ifndef WVCDM_CORE_CDM_ENGINE_H_
#define WVCDM_CORE_CDM_ENGINE_H_
#include "certificate_provisioning.h"
#include "initialization_data.h"
@@ -132,4 +132,4 @@ class CdmEngine {
} // namespace wvcdm
#endif // CDM_BASE_CDM_ENGINE_H_
#endif // WVCDM_CORE_CDM_ENGINE_H_

View File

@@ -1,7 +1,7 @@
// Copyright 2012 Google Inc. All Rights Reserved.
#ifndef CDM_BASE_CDM_SESSION_H_
#define CDM_BASE_CDM_SESSION_H_
#ifndef WVCDM_CORE_CDM_SESSION_H_
#define WVCDM_CORE_CDM_SESSION_H_
#include <set>
@@ -131,4 +131,4 @@ class CdmSession {
} // namespace wvcdm
#endif // CDM_BASE_CDM_SESSION_H_
#endif // WVCDM_CORE_CDM_SESSION_H_

View File

@@ -1,7 +1,7 @@
// Copyright 2013 Google Inc. All Rights Reserved.
#ifndef CDM_BASE_CERTIFICATE_PROVISIONING_H_
#define CDM_BASE_CERTIFICATE_PROVISIONING_H_
#ifndef WVCDM_CORE_CERTIFICATE_PROVISIONING_H_
#define WVCDM_CORE_CERTIFICATE_PROVISIONING_H_
#include "crypto_session.h"
#include "oemcrypto_adapter.h"
@@ -40,4 +40,4 @@ class CertificateProvisioning {
};
} // namespace wvcdm
#endif // CDM_BASE_CERTIFICATE_PROVISIONING_H_
#endif // WVCDM_CORE_CERTIFICATE_PROVISIONING_H_

View File

@@ -2,8 +2,8 @@
//
// Clock - Platform independent interface for a time library
//
#ifndef CDM_BASE_CLOCK_H_
#define CDM_BASE_CLOCK_H_
#ifndef WVCDM_CORE_CLOCK_H_
#define WVCDM_CORE_CLOCK_H_
#include <stdint.h>
@@ -22,4 +22,4 @@ class Clock {
}; // namespace wvcdm
#endif // CDM_BASE_CLOCK_H_
#endif // WVCDM_CORE_CLOCK_H_

View File

@@ -1,9 +1,7 @@
// Copyright 2012 Google Inc. All Rights Reserved.
//
// OEMCrypto Client - wrapper class for C-style OEMCrypto interface
//
#ifndef CDM_BASE_CRYPTO_KEY_H_
#define CDM_BASE_CRYPTO_KEY_H_
#ifndef WVCDM_CORE_CRYPTO_KEY_H_
#define WVCDM_CORE_CRYPTO_KEY_H_
#include "wv_cdm_types.h"
@@ -39,4 +37,4 @@ private:
}; // namespace wvcdm
#endif // CDM_BASE_CRYPTO_KEY_H_
#endif // WVCDM_CORE_CRYPTO_KEY_H_

View File

@@ -1,9 +1,7 @@
// Copyright 2012 Google Inc. All Rights Reserved.
//
// OEMCrypto Client - wrapper class for C-style OEMCrypto interface
//
#ifndef CDM_BASE_CRYPTO_SESSSION_H_
#define CDM_BASE_CRYPTO_SESSSION_H_
#ifndef WVCDM_CORE_CRYPTO_SESSSION_H_
#define WVCDM_CORE_CRYPTO_SESSSION_H_
#include <string>
#include <map>
@@ -103,4 +101,4 @@ class CryptoSession {
}; // namespace wvcdm
#endif // CDM_BASE_CRYPTO_SESSSION_H_
#endif // WVCDM_CORE_CRYPTO_SESSSION_H_

View File

@@ -1,7 +1,7 @@
// Copyright 2013 Google Inc. All Rights Reserved.
//
#ifndef CDM_BASE_DEVICE_FILES_H_
#define CDM_BASE_DEVICE_FILES_H_
#ifndef WVCDM_CORE_DEVICE_FILES_H_
#define WVCDM_CORE_DEVICE_FILES_H_
#include "wv_cdm_types.h"
@@ -73,4 +73,4 @@ class DeviceFiles {
} // namespace wvcdm
#endif // CDM_BASE_DEVICE_FILES_H_
#endif // WVCDM_CORE_DEVICE_FILES_H_

View File

@@ -2,8 +2,8 @@
//
// File - Platform independent interface for a File class
//
#ifndef CDM_BASE_FILE_STORE_H_
#define CDM_BASE_FILE_STORE_H_
#ifndef WVCDM_CORE_FILE_STORE_H_
#define WVCDM_CORE_FILE_STORE_H_
#include "wv_cdm_types.h"
@@ -48,4 +48,4 @@ class File {
} // namespace wvcdm
#endif // CDM_BASE_FILE_STORE_H_
#endif // WVCDM_CORE_FILE_STORE_H_

View File

@@ -1,7 +1,7 @@
// Copyright 2012 Google Inc. All Rights Reserved.
#ifndef CDM_BASE_LICENSE_H_
#define CDM_BASE_LICENSE_H_
#ifndef WVCDM_CORE_LICENSE_H_
#define WVCDM_CORE_LICENSE_H_
#include <set>
@@ -76,4 +76,4 @@ class CdmLicense {
} // namespace wvcdm
#endif // CDM_BASE_LICENSE_H_
#endif // WVCDM_CORE_LICENSE_H_

View File

@@ -2,8 +2,8 @@
//
// Lock - Platform independent interface for a Mutex class
//
#ifndef CDM_BASE_LOCK_H_
#define CDM_BASE_LOCK_H_
#ifndef WVCDM_CORE_LOCK_H_
#define WVCDM_CORE_LOCK_H_
#include "wv_cdm_types.h"
@@ -58,4 +58,4 @@ class AutoLock {
}; // namespace wvcdm
#endif // CDM_BASE_LOCK_H_
#endif // WVCDM_CORE_LOCK_H_

View File

@@ -2,8 +2,8 @@
//
// Log - Platform independent interface for a Logging class
//
#ifndef CDM_BASE_LOG_H_
#define CDM_BASE_LOG_H_
#ifndef WVCDM_CORE_LOG_H_
#define WVCDM_CORE_LOG_H_
namespace wvcdm {
@@ -17,13 +17,10 @@ typedef enum {
LOG_VERBOSE
} LogPriority;
// Required to enable/disable verbose logging (LOGV) in Chromium. In Chromium,
// verbose logging level is controlled using command line switches --v (global)
// or --vmodule (per module). This function calls logging::InitLogging to
// initialize logging, which should have already been included in most Chromium
// based binaries. However, it is typically not included by default in
// unittests, in particular, the unittests in CDM core need to call InitLogging
// to be able to control verbose logging in command line.
// Enable/disable verbose logging (LOGV).
// This function is supplied for cases where the system layer does not
// initialize logging. This is also needed to initialize logging in
// unit tests.
void InitLogging(int argc, const char* const* argv);
void Log(const char* file, int line, LogPriority level, const char* fmt, ...);
@@ -37,4 +34,4 @@ void Log(const char* file, int line, LogPriority level, const char* fmt, ...);
}; // namespace wvcdm
#endif // CDM_BASE_LOG_H_
#endif // WVCDM_CORE_LOG_H_

View File

@@ -1,15 +1,11 @@
/*********************************************************************
* oemcrypto_adapter.h
*
* (c) Copyright 2013 Google, Inc.
*
* This interface allows CDM to open a Level 3 session instead of
* letting the wrapper function choose between level 1 or level 3.
*
*********************************************************************/
#ifndef OEMCRYPTO_ADAPTER_H_
#define OEMCRYPTO_ADAPTER_H_
// Copyright 2013 Google Inc. All Rights Reserved.
//
// oemcrypto_adapter.h
// This interface allows CDM to open a Level 3 session instead of
// letting the wrapper function choose between level 1 or level 3.
//
#ifndef WVCDM_CORE_OEMCRYPTO_ADAPTER_H_
#define WVCDM_CORE_OEMCRYPTO_ADAPTER_H_
#include "OEMCryptoCENC.h"
@@ -37,4 +33,4 @@ const char* OEMCrypto_SecurityLevel(SecurityLevel level);
bool OEMCrypto_SupportsUsageTable(SecurityLevel level);
} // namespace wvcdm
#endif // OEMCRYPTO_ADAPTER_H_
#endif // WVCDM_CORE_OEMCRYPTO_ADAPTER_H_

View File

@@ -1,7 +1,7 @@
// Copyright 2013 Google Inc. All Rights Reserved.
#ifndef CDM_BASE_POLICY_ENGINE_H_
#define CDM_BASE_POLICY_ENGINE_H_
#ifndef WVCDM_CORE_POLICY_ENGINE_H_
#define WVCDM_CORE_POLICY_ENGINE_H_
#include <string>
@@ -25,7 +25,7 @@ class PolicyEngine {
// UpdateLicense/OnTimerEvent/BeginDecryption and may be out of sync
// depending on the amount of time elapsed. The current decryption
// status is not calculated to avoid overhead in the decryption path.
inline bool can_decrypt() { return can_decrypt_; }
inline bool can_decrypt() { return can_decrypt_; }
// OnTimerEvent is called when a timer fires. It notifies the Policy Engine
// that the timer has fired and that it should check whether any events have
@@ -118,5 +118,4 @@ class PolicyEngine {
} // wvcdm
#endif // CDM_BASE_POLICY_ENGINE_H_
#endif // WVCDM_CORE_POLICY_ENGINE_H_

View File

@@ -1,8 +1,5 @@
// Copyright 2013 Google Inc. All Rights Reserved.
//
// RsaPublicKey based on //depot/google3/video/widevine/common/rsa_key.h by
// tinskip@google.com.
//
// Description:
// Declaration of classes representing AES and RSA public keys used
// for signature verification and encryption.
@@ -21,9 +18,9 @@
// Algorithm: RSA-OAEP
// Mask generation function: mgf1SHA1
// Label (encoding paramter): empty string
#ifndef CDM_BASE_PRIVACY_CRYPTO_H_
#define CDM_BASE_PRIVACY_CRYPTO_H_
//
#ifndef WVCDM_CORE_PRIVACY_CRYPTO_H_
#define WVCDM_CORE_PRIVACY_CRYPTO_H_
#include <string>
@@ -74,4 +71,4 @@ class RsaPublicKey {
} // namespace wvcdm
#endif // CDM_BASE_PRIVACY_CRYPTO_H_
#endif // WVCDM_CORE_PRIVACY_CRYPTO_H_

View File

@@ -1,7 +1,7 @@
// Copyright 2013 Google Inc. All Rights Reserved.
#ifndef CDM_BASE_PROPERTIES_H_
#define CDM_BASE_PROPERTIES_H_
#ifndef WVCDM_CORE_PROPERTIES_H_
#define WVCDM_CORE_PROPERTIES_H_
#include <map>
#include <string>
@@ -121,4 +121,4 @@ class Properties {
} // namespace wvcdm
#endif // CDM_BASE_PROPERTIES_H_
#endif // WVCDM_CORE_PROPERTIES_H_

View File

@@ -3,8 +3,8 @@
// A simple and partial implementation of scoped_ptr class.
// The implementation is copied from gtest/include/gtest/internal/gtest-port.h.
//
#ifndef CDM_BASE_SCOPED_PTR_H_
#define CDM_BASE_SCOPED_PTR_H_
#ifndef WVCDM_CORE_SCOPED_PTR_H_
#define WVCDM_CORE_SCOPED_PTR_H_
#include "wv_cdm_types.h"
@@ -61,4 +61,4 @@ class scoped_ptr {
}; // namespace wvcdm
#endif // CDM_BASE_SCOPED_PTR_H_
#endif // WVCDM_CORE_SCOPED_PTR_H_

View File

@@ -1,7 +1,7 @@
// Copyright 2013 Google Inc. All Rights Reserved.
#ifndef CDM_BASE_STRING_CONVERSIONS_H_
#define CDM_BASE_STRING_CONVERSIONS_H_
#ifndef WVCDM_CORE_STRING_CONVERSIONS_H_
#define WVCDM_CORE_STRING_CONVERSIONS_H_
#include <stddef.h>
#include <stdint.h>
@@ -25,4 +25,4 @@ int64_t htonll64(int64_t x);
}; // namespace wvcdm
#endif // CDM_BASE_STRING_CONVERSIONS_H_
#endif // WVCDM_CORE_STRING_CONVERSIONS_H_

View File

@@ -2,8 +2,8 @@
//
// Timer - Platform independent interface for a Timer class
//
#ifndef CDM_BASE_TIMER_H_
#define CDM_BASE_TIMER_H_
#ifndef WVCDM_CORE_TIMER_H_
#define WVCDM_CORE_TIMER_H_
#include "wv_cdm_types.h"
@@ -48,4 +48,4 @@ class Timer {
}; // namespace wvcdm
#endif // CDM_BASE_TIMER_H_
#endif // WVCDM_CORE_TIMER_H_

View File

@@ -1,15 +1,12 @@
// Copyright 2012 Google Inc. All Rights Reserved.
#ifndef CDM_BASE_WV_CDM_CONSTANTS_H_
#define CDM_BASE_WV_CDM_CONSTANTS_H_
#ifndef WVCDM_CORE_WV_CDM_CONSTANTS_H_
#define WVCDM_CORE_WV_CDM_CONSTANTS_H_
#include <string>
namespace wvcdm {
static const size_t KEY_CONTROL_SIZE = 16;
// TODO(kqyang): Key ID size is not fixed in spec, but conventionally we
// always use 16 bytes key id. We'll need to update oemcrypto to support
// variable size key id.
static const size_t KEY_ID_SIZE = 16;
static const size_t KEY_IV_SIZE = 16;
static const size_t KEY_PAD_SIZE = 16;
@@ -64,4 +61,4 @@ static const std::string CENC_INIT_DATA_FORMAT = "cenc";
static const std::string WEBM_INIT_DATA_FORMAT = "webm";
} // namespace wvcdm
#endif // CDM_BASE_WV_CDM_CONSTANTS_H_
#endif // WVCDM_CORE_WV_CDM_CONSTANTS_H_

View File

@@ -1,7 +1,7 @@
// Copyright 2012 Google Inc. All Rights Reserved.
#ifndef CDM_BASE_WV_CDM_EVENT_LISTENER_H_
#define CDM_BASE_WV_CDM_EVENT_LISTENER_H_
#ifndef WVCDM_CORE_WV_CDM_EVENT_LISTENER_H_
#define WVCDM_CORE_WV_CDM_EVENT_LISTENER_H_
#include "wv_cdm_types.h"
@@ -25,4 +25,4 @@ class WvCdmEventListener {
} // namespace wvcdm
#endif // CDM_BASE_WV_CDM_EVENT_LISTENER_H_
#endif // WVCDM_CORE_WV_CDM_EVENT_LISTENER_H_

View File

@@ -1,7 +1,7 @@
// Copyright 2013 Google Inc. All Rights Reserved.
#ifndef CDM_BASE_WV_CDM_TYPES_H_
#define CDM_BASE_WV_CDM_TYPES_H_
#ifndef WVCDM_CORE_WV_CDM_TYPES_H_
#define WVCDM_CORE_WV_CDM_TYPES_H_
#include <map>
#include <stdint.h>
@@ -125,4 +125,4 @@ class Key;
} // namespace wvcdm
#endif // CDM_BASE_WV_CDM_TYPES_H_
#endif // WVCDM_CORE_WV_CDM_TYPES_H_

View File

@@ -19,7 +19,8 @@ bool BufferReader::Read1(uint8_t* v) {
// Internal implementation of multi-byte reads
template<typename T> bool BufferReader::Read(T* v) {
if (!HasBytes(sizeof(T))) {
LOGE("BufferReader::Read<T> : Failure while parsing: Not enough bytes (%u)", sizeof(T));
LOGE("BufferReader::Read<T> : Failure during parse: Not enough bytes (%u)",
sizeof(T));
return false;
}
@@ -41,7 +42,8 @@ bool BufferReader::Read8s(int64_t* v) { return Read(v); }
bool BufferReader::ReadString(std::string* str, int count) {
if (!HasBytes(count)) {
LOGE("BufferReader::ReadString : Failure while parsing: Not enough bytes (%d)", count);
LOGE("BufferReader::ReadString : Parse Failure: Not enough bytes (%d)",
count);
return false;
}
@@ -52,7 +54,7 @@ bool BufferReader::ReadString(std::string* str, int count) {
bool BufferReader::ReadVec(std::vector<uint8_t>* vec, int count) {
if (!HasBytes(count)) {
LOGE("BufferReader::ReadVec : Failure while parsing: Not enough bytes (%d)", count);
LOGE("BufferReader::ReadVec : Parse Failure: Not enough bytes (%d)", count);
return false;
}
@@ -64,7 +66,8 @@ bool BufferReader::ReadVec(std::vector<uint8_t>* vec, int count) {
bool BufferReader::SkipBytes(int bytes) {
if (!HasBytes(bytes)) {
LOGE("BufferReader::SkipBytes : Failure while parsing: Not enough bytes (%d)", bytes);
LOGE("BufferReader::SkipBytes : Parse Failure: Not enough bytes (%d)",
bytes);
return false;
}

View File

@@ -57,8 +57,9 @@ CdmResponseType CdmEngine::OpenSession(
if (sts == NEED_PROVISIONING) {
cert_provisioning_requested_security_level_ =
new_session->GetRequestedSecurityLevel();
} else {
LOGE("CdmEngine::OpenSession: bad session init: %u", sts);
}
LOGE("CdmEngine::OpenSession: bad session init: %u", sts);
return sts;
}
*session_id = new_session->session_id();
@@ -278,7 +279,8 @@ CdmResponseType CdmEngine::CancelKeyRequest(const CdmSessionId& session_id) {
CdmSessionMap::iterator iter = sessions_.find(session_id);
if (iter == sessions_.end()) {
LOGE("CdmEngine::CancelKeyRequest: session_id not found = %s", session_id.c_str());
LOGE("CdmEngine::CancelKeyRequest: session_id not found = %s",
session_id.c_str());
return KEY_ERROR;
}
@@ -295,12 +297,13 @@ CdmResponseType CdmEngine::GenerateRenewalRequest(
CdmSessionMap::iterator iter = sessions_.find(session_id);
if (iter == sessions_.end()) {
LOGE("CdmEngine::GenerateRenewalRequest: session_id not found = %s", session_id.c_str());
LOGE("CdmEngine::GenerateRenewalRequest: session_id not found = %s",
session_id.c_str());
return KEY_ERROR;
}
if (!key_request) {
LOGE("CdmEngine::GenerateRenewalRequest: no key request destination provided");
LOGE("CdmEngine::GenerateRenewalRequest: no key request destination");
return KEY_ERROR;
}
@@ -310,7 +313,7 @@ CdmResponseType CdmEngine::GenerateRenewalRequest(
server_url);
if (KEY_MESSAGE != sts) {
LOGE("CdmEngine::GenerateRenewalRequest: key request generation failed, sts=%d",
LOGE("CdmEngine::GenerateRenewalRequest: key request gen. failed, sts=%d",
(int)sts);
return sts;
}
@@ -406,7 +409,8 @@ CdmResponseType CdmEngine::QueryKeyStatus(
LOGI("CdmEngine::QueryKeyStatus");
CdmSessionMap::iterator iter = sessions_.find(session_id);
if (iter == sessions_.end()) {
LOGE("CdmEngine::QueryKeyStatus: session_id not found = %s", session_id.c_str());
LOGE("CdmEngine::QueryKeyStatus: session_id not found = %s",
session_id.c_str());
return KEY_ERROR;
}
return iter->second->QueryKeyStatus(key_info);
@@ -418,7 +422,8 @@ CdmResponseType CdmEngine::QueryKeyControlInfo(
LOGI("CdmEngine::QueryKeyControlInfo");
CdmSessionMap::iterator iter = sessions_.find(session_id);
if (iter == sessions_.end()) {
LOGE("CdmEngine::QueryKeyControlInfo: session_id not found = %s", session_id.c_str());
LOGE("CdmEngine::QueryKeyControlInfo: session_id not found = %s",
session_id.c_str());
return KEY_ERROR;
}
return iter->second->QueryKeyControlInfo(key_info);

View File

@@ -9,7 +9,11 @@
#include "wv_cdm_constants.h"
namespace {
const std::string kDefaultProvisioningServerUrl =
// URL for Google Provisioning Server.
// This server supplies the certificate that is needed
// to communicate with the License Server.
const std::string kProvisioningServerUrl =
"https://www.googleapis.com/"
"certificateprovisioning/v1/devicecertificates/create"
"?key=AIzaSyB-5OLKTx2iU5mko18DfdwK5611JIjbUhE";
@@ -60,7 +64,12 @@ CdmResponseType CertificateProvisioning::GetProvisioningRequest(
const std::string& cert_authority,
CdmProvisioningRequest* request,
std::string* default_url) {
default_url->assign(kDefaultProvisioningServerUrl);
if (!default_url) {
LOGE("GetProvisioningRequest: pointer for returning URL is NULL");
return UNKNOWN_ERROR;
}
default_url->assign(kProvisioningServerUrl);
CdmResponseType sts = crypto_session_.Open(requested_security_level);
if (NO_ERROR != sts) {

View File

@@ -5,7 +5,7 @@
#include "crypto_session.h"
#include <arpa/inet.h> // TODO(fredgc): Add ntoh to wv_cdm_utilities.h
#include <arpa/inet.h> // needed for ntoh()
#include <iostream>
#include "crypto_key.h"

View File

@@ -202,7 +202,6 @@ bool CdmLicense::PrepareKeyRequest(const InitializationData& init_data,
return PrepareServiceCertificateRequest(signed_request, server_url);
}
// TODO(gmorgan): Request ID owned by session?
std::string request_id;
session_->GenerateRequestId(request_id);

View File

@@ -4,20 +4,8 @@
// Copyright 2013 Google Inc. All Rights Reserved.
//
// Description:
// Merges certificate_provisioning.proto and client_identification.proto
// inline to avoid having to hardcode the import path. This is a temporary
// workaround for not getting proto_path to work in Android build envionment.
//
// Origin:
// This file is derived from the authoritative source file at
// https://cs.corp.google.com/#google3/video/widevine/server/sdk/
// license_protocol.proto
//
// Description:
// Definitions of the protocol buffer messages used in the Widevine license
// exchange protocol, which is described in the document
// https://docs.google.com/a/google.com/document/d/
// 1cng6cDnchbDQDymLEd5MxMc_laS3EDv6IsoW3IzpgwQ
// exchange protocol.
syntax = "proto2";
@@ -124,8 +112,6 @@ message License {
}
message KeyControl {
// |key_control| is documented here:
// https://docs.google.com/a/google.com/document/d/17eDxzzGpPc2qSm7zW68_5ensuxbHErYCvD3IxSKETRo/edit#
// If present, the key control must be communicated to the secure
// environment prior to any usage. This message is automatically generated
// by the Widevine License Server SDK.
@@ -233,7 +219,6 @@ message LicenseRequest {
optional EncryptedClientIdentification encrypted_client_id = 8;
}
message LicenseError {
enum Error {
// The device credentials are invalid. The device must re-provision.
@@ -286,17 +271,14 @@ message SessionState {
// certificate_provisioning.proto
// ----------------------------------------------------------------------------
// Copyright 2013 Google Inc. All Rights Reserved.
// Author: tinskip@google.com (Thomas Inskip)
//
// Description:
// Public protocol buffer definitions for Widevine Device Certificate
// Provisioning protocol.
// PROPOSED message for customizing provisioning request.
// This could support requesting specificy types of certificates.
// E.g. Cast X.509 certs.
// ProvisioningOptions specifies the type of certificate to specify and
// in the case of X509 certificates, the certificate authority to use.
message ProvisioningOptions {
// PROPOSED enum identifying the certificate type.
enum CertificateType {
RSA_WIDEVINE = 0; // Default. The original certificate type.
X509 = 1; // X.509 certificate.
@@ -304,8 +286,8 @@ message ProvisioningOptions {
optional CertificateType certificate_type = 1;
// OPEN QUESTION: How does the client specify the cert root authority?
// Should this be the cert authority's domain? E.g. foo.com?
// It is recommended that the certificate_authority specify the X.509
// Subject of the signing certificate.
optional string certificate_authority = 2;
}
@@ -320,10 +302,6 @@ message ProvisioningRequest {
}
// Provisioning response sent by the provisioning server to client devices.
//
// PROPOSAL: The contents of this message vary depending upon the value of
// CertificateType in options. TODO(blueeyes): Determine the right way to
// transfer X.509 certs.
message ProvisioningResponse {
// AES-128 encrypted device private RSA key. PKCS#1 ASN.1 DER-encoded.
// Required.
@@ -349,12 +327,6 @@ message SignedProvisioningMessage {
// client_identification.proto
// ----------------------------------------------------------------------------
// Copyright 2013 Google Inc. All Rights Reserved.
// Author: tinskip@google.com (Thomas Inskip)
//
// Origin:
// This file is derived from the authoritative source file at
// https://cs.corp.google.com/#google3/video/widevine/server/sdk/
// license_protocol.proto
//
// Description:
// ClientIdentification messages used by provisioning and license protocols.
@@ -388,8 +360,8 @@ message EncryptedClientIdentification {
// Serial number for the service certificate for which ClientIdentification is
// encrypted.
optional string service_certificate_serial_number = 2;
// Serialized ClientIdentification message, encrypted with the privacy key using
// AES-128-CBC with PKCS#5 padding.
// Serialized ClientIdentification message, encrypted with the privacy key
// using AES-128-CBC with PKCS#5 padding.
optional bytes encrypted_client_id = 3;
// Initialization vector needed to decrypt encrypted_client_id.
optional bytes encrypted_client_id_iv = 4;
@@ -402,7 +374,6 @@ message EncryptedClientIdentification {
// device_certificate.proto
// ----------------------------------------------------------------------------
// Copyright 2013 Google Inc. All Rights Reserved.
// Author: tinskip@google.com (Thomas Inskip)
//
// Description:
// Device certificate and certificate status list format definitions.
@@ -452,8 +423,8 @@ message SignedDeviceCertificate {
// Contains device model information for a provisioned device.
message ProvisionedDeviceInfo {
enum WvSecurityLevel {
// Defined in Widevine Security Integration Guide for DASH on Android:
// https://docs.google.com/a/google.com/document/d/1Zum-fcJeoIw6KG1kDP_KepIE5h9gAZg0PaMtemBvk9c/edit#heading=h.1t3h5sf
// Defined in "WV Modular DRM Security Integration Guide for
// Common Encryption (CENC)"
LEVEL_UNSPECIFIED = 0;
LEVEL_1 = 1;
LEVEL_2 = 2;

View File

@@ -1,14 +1,11 @@
/*******************************************************************************
*
* Copyright 2013 Google Inc. All Rights Reserved.
*
* Wrapper of OEMCrypto APIs for platforms that support both Levels 1 and 3.
* This should be used when liboemcrypto.so is dynamically loaded at run
* time and not linked with the CDM code at compile time.
* An implementation should compile either oemcrypto_adapter_dynamic.cpp or
* oemcrypto_adapter_static.cpp, but not both.
*
******************************************************************************/
// Copyright 2013 Google Inc. All Rights Reserved.
//
// Wrapper of OEMCrypto APIs for platforms that support both Levels 1 and 3.
// This should be used when liboemcrypto.so is dynamically loaded at run
// time and not linked with the CDM code at compile time.
// An implementation should compile either oemcrypto_adapter_dynamic.cpp or
// oemcrypto_adapter_static.cpp, but not both.
//
#include "oemcrypto_adapter.h"

View File

@@ -1,14 +1,9 @@
/*******************************************************************************
*
* Copyright 2013 Google Inc. All Rights Reserved.
*
* Wrapper of OEMCrypto APIs for platforms that support Level 1 only.
* This should be used when liboemcrypto.so is linked with the CDM code at
* compile time.
* An implementation should compile either oemcrypto_adapter_dynamic.cpp or
* oemcrypto_adapter_static.cpp, but not both.
*
******************************************************************************/
// Copyright 2013 Google Inc. All Rights Reserved.
//
// Wrapper of OEMCrypto APIs for platforms that support Level 1 only.
// This should be used when liboemcrypto.so is linked with the CDM code at
// compile time.
//
#include "OEMCryptoCENC.h"
#include "oemcrypto_adapter.h"

View File

@@ -76,15 +76,15 @@ extern "C" OEMCryptoResult OEMCrypto_LoadKeys(
const uint8_t* enc_mac_key_iv, const uint8_t* enc_mac_key, size_t num_keys,
const OEMCrypto_KeyObject* key_array,
const uint8_t* pst, size_t pst_length) {
return LoadKeys_V8(pair.session, message, message_length, signature,
signature_length, enc_mac_key_iv, enc_mac_key,
num_keys, key_array);
return OEMCrypto_LoadKeys_V8(session, message, message_length, signature,
signature_length, enc_mac_key_iv, enc_mac_key,
num_keys, key_array);
}
extern "C" OEMCryptoResult OEMCrypto_GenerateRSASignature(
OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
uint8_t* signature, size_t* signature_length, RSA_Padding_Scheme padding_scheme) {
return GenerateRSASignature_V8(pair.session, message, message_length,
return OEMCrypto_GenerateRSASignature_V8(session, message, message_length,
signature, signature_length);
}

View File

@@ -127,10 +127,6 @@ void PolicyEngine::UpdateLicense(
return;
}
else {
// TODO(edwingwong, rfrias): Check back with Thomas and see if
// we need to enforce that all duration windows are absent if
// license_start_time is not present. This is a TBD.
// if renewal, discard license if version has not been updated
if (license.id().version() > license_id_.version())
license_id_.CopyFrom(license.id());
@@ -140,9 +136,6 @@ void PolicyEngine::UpdateLicense(
// Update time information
int64_t current_time = clock_->GetCurrentTime();
// TODO(edwingwong, rfrias): Check back with Thomas and see if
// we need to enforce that all duration windows are absent if
// license_start_time is not present. This is a TBD.
if (license.has_license_start_time())
license_start_time_ = license.license_start_time();
license_received_time_ = current_time;
@@ -276,10 +269,9 @@ bool PolicyEngine::IsRenewalDelayExpired(int64_t current_time) {
current_time;
}
// TODO(jfore, edwinwong, rfrias): This field is in flux and currently
// not implemented. Will address after possible updates from Thomas.
bool PolicyEngine::IsRenewalRecoveryDurationExpired(
int64_t current_time) {
// NOTE: Renewal Recovery Duration is currently not used.
return (policy_.renewal_recovery_duration_seconds() > 0) &&
license_received_time_ + policy_.renewal_recovery_duration_seconds() <=
current_time;

View File

@@ -1,8 +1,5 @@
// Copyright 2013 Google Inc. All Rights Reserved.
//
// Original code at //depot/google3/video/widevine/common/rsa_key.cc by
// tinskip@google.com. Modified for core CDM usage.
//
// Description:
// Definition of classes representing RSA public keys used
// for signature verification and encryption and decryption.

View File

@@ -75,10 +75,10 @@ std::string b2a_hex(const std::string& byte) {
byte.length());
}
// Filename-friendly base64 encoding (RFC4648), commonly referred as
// Base64WebSafeEncode.
// This is the encoding required by GooglePlay to interface with the
// provisioning server's Apiary interface as well as for certain license server
// Filename-friendly base64 encoding (RFC4648), commonly referred to
// as Base64WebSafeEncode.
// This is the encoding required to interface with the provisioning
// server's Apiary interface as well as for certain license server
// transactions. It is also used for logging certain strings.
// The difference between web safe encoding vs regular encoding is that
// the web safe version replaces '+' with '-' and '/' with '_'.

View File

@@ -1,861 +0,0 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <string>
#include <vector>
#include <map>
#include <sstream>
#include "base/at_exit.h"
#include "base/basictypes.h"
#include "base/bind.h"
#include "base/message_loop.h"
#include "base/sys_byteorder.h"
#include "crypto/encryptor.h"
#include "crypto/hmac.h"
#include "crypto/symmetric_key.h"
#include "license_protocol.pb.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "eureka/widevine_cdm/oemcrypto/client/oemcrypto_client.h"
#include "eureka/widevine_cdm/oemcrypto/mock/src/cmac.h"
#include "eureka/widevine_cdm/oemcrypto/mock/src/oemcrypto_keybox_mock.h"
#include "wv_cdm_types.h"
#include "wv_content_decryption_module.h"
namespace {
namespace wv_license_protocol = video_widevine_server::sdk;
using wv_license_protocol::License;
using wv_license_protocol::LicenseIdentification;
using wv_license_protocol::LicenseRequest;
using wv_license_protocol::SessionState;
using wv_license_protocol::SignedMessage;
enum PolicyType {
kDefault = 0,
kNoPlay,
kShortDuration
};
struct PolicyItem {
PolicyType type;
bool can_play;
bool can_renew;
int duration_seconds;
int renewal_delay_seconds;
int renewal_retry_interval_seconds;
};
struct PolicyItem PolicyItems[] = {
{
kDefault,
true,
true,
1000,
100,
0
},
{
kShortDuration,
true,
true,
12,
2,
2
},
{
kNoPlay,
false,
false,
0,
0,
0
}
};
// TODO(jfore): Move this into the test class.
/*const*/ char kTestSigningKey[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
};
const int kTestSigningKeySize = arraysize(kTestSigningKey);
const char* kEncryptionKeyLabel = "ENCRYPTION";
const uint32_t kEncryptionKeySizeBits = 128;
const char* kSigningKeyLabel = "AUTHENTICATION";
const uint32_t kSigningKeySizeBits = 256;
// This is a container to hold the info for an encrypted frame.
struct WvCdmEncryptedFrameInfo {
char plain_text[32];
int plain_text_size;
uint8_t key_id[32];
int key_id_size;
uint8_t content_key[32];
int content_key_size;
uint8_t encrypted_data[64];
int encrypted_data_size;
PolicyType policy_type;
};
const WvCdmEncryptedFrameInfo kWvCdmEncryptedFrames[] = {
{
"Original data.", 14,
{ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35
}, 16,
{ 0xeb, 0xdd, 0x62, 0xf1, 0x68, 0x14, 0xd2, 0x7b,
0x68, 0xef, 0x12, 0x2a, 0xfc, 0xe4, 0xae, 0x3c
}, 16,
{ 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x82, 0x54, 0xab, 0x89, 0xa2, 0x75, 0xcd,
0x85, 0x83, 0x61, 0x3f, 0xfe, 0x13, 0x58
}, 23,
kShortDuration
},
{
"Original data.", 14,
{ 0x08, 0x01, 0x12, 0x10, 0x6f, 0x13, 0x33, 0xe7,
0x6e, 0x59, 0x5e, 0xb5, 0x8c, 0x04, 0x30, 0x72,
0xcb, 0xb2, 0x50, 0x68
}, 20,
{ 0xeb, 0xdd, 0x62, 0xf1, 0x68, 0x14, 0xd2, 0x7b,
0x68, 0xef, 0x12, 0x2a, 0xfc, 0xe4, 0xae, 0x3c
}, 16,
{ 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x82, 0x54, 0xab, 0x89, 0xa2, 0x75, 0xcd,
0x85, 0x83, 0x61, 0x3f, 0xfe, 0x13, 0x58
}, 23,
kShortDuration
},
{
"Changed Original data.", 22,
{ 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02
}, 16,
{ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23
}, 16,
{ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x57, 0x66, 0xf4, 0x12, 0x1a, 0xed, 0xb5,
0x79, 0x1c, 0x8e, 0x25, 0xd7, 0x17, 0xe7, 0x5e,
0x16, 0xe3, 0x40, 0x08, 0x27, 0x11, 0xe9
}, 31,
kShortDuration
},
{
"Original data.", 14,
{ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f
}, 16,
{ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40
}, 16,
{ 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x9c, 0x71, 0x26, 0x57, 0x3e, 0x25, 0x37,
0xf7, 0x31, 0x81, 0x19, 0x64, 0xce, 0xbc
}, 23,
kShortDuration
},
// For license renewal test. This has kNoPlay.
{
// Differnent key and key id.
"Original data.", 14,
{ 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33
}, 16,
{ 0xeb, 0xdd, 0x62, 0xf1, 0x68, 0x14, 0xd2, 0x7b,
0x68, 0xef, 0x12, 0x2a, 0xfc, 0xe4, 0xae, 0x3c
}, 16,
{ 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x82, 0x54, 0xab, 0x89, 0xa2, 0x75, 0xcd,
0x85, 0x83, 0x61, 0x3f, 0xfe, 0x13, 0x58
}, 23,
kNoPlay
}
};
bool GetPolicy(PolicyType policy_type, License::Policy* policy) {
DCHECK(policy);
PolicyItem policy_item;
switch (policy_type) {
case kDefault:
policy_item = PolicyItems[0];
DCHECK_EQ(policy_item.type, kDefault);
break;
case kShortDuration:
policy_item = PolicyItems[1];
DCHECK_EQ(policy_item.type, kShortDuration);
break;
case kNoPlay:
policy_item = PolicyItems[2];
DCHECK_EQ(policy_item.type, kNoPlay);
break;
default:
NOTREACHED();
return false;
}
policy->set_can_play(policy_item.can_play);
policy->set_can_renew(policy_item.can_renew);
policy->set_license_duration_seconds(policy_item.duration_seconds);
policy->set_renewal_delay_seconds(policy_item.renewal_delay_seconds);
policy->set_renewal_retry_interval_seconds(
policy_item.renewal_retry_interval_seconds);
return true;
}
SessionState GetTestSessionState() {
static const std::string kTestSessionId = "SomeSessionId";
SessionState session_cache;
session_cache.mutable_license_id()->set_session_id(kTestSessionId);
session_cache.mutable_license_id()->set_version(0);
session_cache.set_signing_key(kTestSigningKey, kTestSigningKeySize);
return session_cache;
}
// Since "GetTime" is used in this test where some functions cannot reach
// Host instance, this will be used as a universal clock for this test.
double GetCurrentTestTime() {
return base::Time::Now().ToDoubleT();
}
// This encrypts the content key using the device key in cdm/base/device_key.h.
std::string EncryptUsingKey(const std::string& input,
const std::string& iv,
const std::string& encryption_key) {
//static const int kAesBlockSize = 16;
crypto::Encryptor aes_ecryptor;
scoped_ptr<crypto::SymmetricKey> device_key(
crypto::SymmetricKey::Import(crypto::SymmetricKey::AES,
encryption_key));
if (!aes_ecryptor.Init(device_key.get(), crypto::Encryptor::CBC, iv))
return "";
std::string encrypted_data;
if (!aes_ecryptor.Encrypt(input, &encrypted_data))
return "";
return encrypted_data;
}
// Takes the license and the session state and generates a SignedMessage. The
// return value is the serialized version of the SignedMessage object.
std::string GenerateSignedLicenseResponse(const License& license,
const std::string& signing_key) {
SignedMessage signed_message;
bool success = license.SerializeToString(
signed_message.mutable_msg());
DCHECK(success);
crypto::HMAC hmacer(crypto::HMAC::SHA256);
if (!hmacer.Init(signing_key))
return "";
static const int kDigestSize = 32;
uint8_t digest[kDigestSize] = { 0 };
if (!hmacer.Sign(signed_message.msg(), digest, kDigestSize))
return "";
signed_message.set_signature(digest, kDigestSize);
std::string signed_message_bytes;
success = signed_message.SerializeToString(&signed_message_bytes);
DCHECK(success);
return signed_message_bytes;
}
// Note: We only use one session. So there aren't any list of sessions stored
// anywhere.
std::string GenerateNewSignedLicense(
const LicenseRequest& license_request,
const License::Policy& policies,
const License::KeyContainer& content_key,
const std::string& encryption_key,
const std::string& signing_key) {
DCHECK(license_request.content_id().has_cenc_id());
SessionState session_cache = GetTestSessionState();
DCHECK(session_cache.has_signing_key());
session_cache.mutable_license_id()->set_request_id(
license_request.content_id().webm_id().request_id());
session_cache.mutable_license_id()->set_type(
license_request.content_id().webm_id().license_type());
License license;
license.mutable_id()->CopyFrom(session_cache.license_id());
license.mutable_policy()->CopyFrom(policies);
license.set_license_start_time(GetCurrentTestTime());
License::KeyContainer* renewal_signing_key = license.add_key();
renewal_signing_key->set_key(session_cache.signing_key());
renewal_signing_key->set_type(License::KeyContainer::SIGNING);
license.add_key()->CopyFrom(content_key);
for (int i = 0; i < license.key_size(); ++i) {
license.mutable_key(i)->set_iv("0123456789012345");
license.mutable_key(i)->set_key(
EncryptUsingKey(license.key(i).key(),
license.key(i).iv(),
encryption_key));
if (license.key(i).key().empty())
return "";
}
return GenerateSignedLicenseResponse(license, signing_key);
}
bool GetContentKeyFromKeyId(const std::string& key_id,
std::string* content_key) {
DCHECK(content_key);
for (unsigned int i = 0; i < arraysize(kWvCdmEncryptedFrames); ++i) {
const WvCdmEncryptedFrameInfo& frame = kWvCdmEncryptedFrames[i];
if (frame.key_id_size != static_cast<int>(key_id.size()))
continue;
if (!memcmp(frame.key_id, key_id.data(), frame.key_id_size)) {
content_key->assign(frame.content_key,
frame.content_key + frame.content_key_size);
return true;
}
}
return false;
}
std::string DeriveKey(const std::string& key,
const std::string& purpose,
const std::string& context,
const uint32_t size_bits) {
if (key.size() != 16)
return "";
// We only handle even multiples of 16 bytes (128 bits) right now.
if ((size_bits % 128) || (size_bits > (128 * 255))) {
return "";
}
std::string result;
const EVP_CIPHER *cipher = EVP_aes_128_cbc();
CMAC_CTX* cmac_ctx = CMAC_CTX_new();
size_t reslen;
unsigned char res[128];
unsigned char counter;
for (counter = 1; counter <= (size_bits / 128); counter++) {
if (!CMAC_Init(cmac_ctx, key.data(), key.size(), cipher, 0))
break;
std::string message;
message.append(1, counter);
message.append(purpose);
message.append(1, '\0');
message.append(context);
uint32_t size_l = htonl(size_bits);
message.append(reinterpret_cast<char*>(&size_l), sizeof(size_l));
if (!CMAC_Update(cmac_ctx, message.data(), message.size()))
break;
if (!CMAC_Final(cmac_ctx, res, &reslen))
break;
result.append((const char*)res, reslen);
}
CMAC_CTX_free(cmac_ctx);
if (counter <= (size_bits / 128))
return "";
return result;
}
bool VerifyTestSignature(const std::string& message,
const std::string& signature,
const std::string& key) {
crypto::HMAC hmacer(crypto::HMAC::SHA256);
if (!hmacer.Init(key))
return false;
if (!hmacer.Verify(message, signature))
return false;
return true;
}
std::string GenerateNewLicenseResponse(const LicenseRequest& license_request,
const PolicyType& policy_type) {
if (!license_request.content_id().has_cenc_id())
return "";
std::string content_key_id = license_request.content_id().cenc_id().pssh(0);
std::string content_key;
if (!GetContentKeyFromKeyId(content_key_id,
&content_key)) {
return "";
}
if (content_key_id.size() > 16)
content_key_id.resize(16);
License::Policy policies;
if (!GetPolicy(policy_type, &policies))
return "";
std::string context;
if (!license_request.SerializeToString(&context))
return "";
wvoec_mock::WvKeybox keybox;
// TODO(): Fix this to use a constant for key length.
std::string widevine_device_key(keybox.device_key().value());
std::string encryption_key = DeriveKey(widevine_device_key,
std::string(kEncryptionKeyLabel),
context,
kEncryptionKeySizeBits);
std::string signing_key = DeriveKey(widevine_device_key,
std::string(kSigningKeyLabel),
context,
kSigningKeySizeBits);
memcpy(kTestSigningKey, &signing_key[0], 32);
License::KeyContainer key_container;
key_container.set_id(content_key_id);
key_container.set_key(content_key);
key_container.set_type(License::KeyContainer::CONTENT);
return GenerateNewSignedLicense(license_request,
policies,
key_container,
encryption_key,
signing_key);
}
std::string GenerateLicenseRenewalResponse(
const SignedMessage& signed_message,
const PolicyType& policy_type) {
SessionState session_cache = GetTestSessionState();
LicenseRequest license_request;
if (!license_request.ParseFromString(signed_message.msg()))
return "";
std::string session_id = license_request.content_id().license().
license_id().session_id();
if (session_id.compare(session_cache.license_id().session_id()))
return "";
if (!VerifyTestSignature(signed_message.msg(),
signed_message.signature(),
session_cache.signing_key())) {
return "";
}
session_cache.mutable_license_id()->set_version(
session_cache.license_id().version() + 1);
License license;
license.mutable_id()->CopyFrom(session_cache.license_id());
// Always get Policy object with kDefault for renewal.
License::Policy policy;
GetPolicy(policy_type, &policy);
license.mutable_policy()->Swap(&policy);
license.set_license_start_time(GetCurrentTestTime());
return GenerateSignedLicenseResponse(license, session_cache.signing_key());
}
std::string GenerateLicenseResponse(const std::string& signed_request,
const PolicyType& policy) {
SignedMessage signed_message;
if (!signed_message.ParseFromString(signed_request))
return "";
LicenseRequest license_request;
if (!license_request.ParseFromString(signed_message.msg()))
return "";
if (license_request.type() == LicenseRequest::NEW) {
return GenerateNewLicenseResponse(license_request, policy);
} else if (license_request.type() == LicenseRequest::RENEWAL) {
return GenerateLicenseRenewalResponse(signed_message, policy);
}
return "";
}
struct WvCdmEncryptedData {
char plain_text[32];
int plain_text_size;
uint8_t key_id[32];
int key_id_size;
uint8_t content_key[32];
int content_key_size;
uint8_t encrypted_data[64];
int encrypted_data_size;
const char* license_response;
int license_response_size;
};
// Container used to pass data from GenerateLicenseRequest to Decrypt.
// TODO(rkuroiwa): This class was made before KeyMessage existed; this
// should be removed.
class LicenseRequestParameter {
public:
explicit LicenseRequestParameter(const WvCdmEncryptedData& frame)
: init_data(new uint8_t[frame.key_id_size]),
init_data_size(frame.key_id_size),
session_id(NULL),
session_id_size(0),
key_request(NULL),
key_request_size(0),
default_url(NULL),
default_url_size(0) {
memcpy(init_data.get(), frame.key_id, frame.key_id_size);
}
~LicenseRequestParameter() {
}
scoped_array<uint8_t> init_data;
int init_data_size;
scoped_array<char> session_id;
int session_id_size;
scoped_array<uint8_t> key_request;
int key_request_size;
scoped_array<char> default_url;
int default_url_size;
private:
DISALLOW_COPY_AND_ASSIGN(LicenseRequestParameter);
};
// |encrypted_data| is encrypted from |plain_text| using |key|. |key_id| is
// used to distinguish |key|.
struct WebmEncryptedData {
uint8 plain_text[32];
int plain_text_size;
uint8 key_id[32];
int key_id_size;
uint8 key[32];
int key_size;
uint8 encrypted_data[64];
int encrypted_data_size;
};
// Frames 0 & 1 are encrypted with the same key. Frame 2 is encrypted with a
// different key. Frame 3 is unencrypted.
const WebmEncryptedData kWebmEncryptedFrames[] = {
{
// plaintext
"Original data.", 14,
// key_id
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13
}, 20,
// key
{ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23
}, 16,
// encrypted_data
{ 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xf0, 0xd1, 0x12, 0xd5, 0x24, 0x81, 0x96,
0x55, 0x1b, 0x68, 0x9f, 0x38, 0x91, 0x85
}, 23
},
{
// plaintext
"Changed Original data.", 22,
// key_id
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13
}, 20,
// key
{ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23
}, 16,
// encrypted_data
{ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x57, 0x66, 0xf4, 0x12, 0x1a, 0xed, 0xb5,
0x79, 0x1c, 0x8e, 0x25, 0xd7, 0x17, 0xe7, 0x5e,
0x16, 0xe3, 0x40, 0x08, 0x27, 0x11, 0xe9
}, 31
},
{
// plaintext
"Original data.", 14,
// key_id
{ 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
0x2c, 0x2d, 0x2e, 0x2f, 0x30
}, 13,
// key
{ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40
}, 16,
// encrypted_data
{ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x9c, 0x71, 0x26, 0x57, 0x3e, 0x25, 0x37,
0xf7, 0x31, 0x81, 0x19, 0x64, 0xce, 0xbc
}, 23
},
{
// plaintext
"Changed Original data.", 22,
// key_id
{ 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
0x2c, 0x2d, 0x2e, 0x2f, 0x30
}, 13,
// key
{ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40
}, 16,
// encrypted_data
{ 0x00, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64,
0x20, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61,
0x6c, 0x20, 0x64, 0x61, 0x74, 0x61, 0x2e
}, 23
}
};
static const uint8 kWebmWrongSizedKey[] = { 0x20, 0x20 };
static const char kClearKeySystem[] = "org.w3.clearkey";
static const char *kWidevineKeySystem = "com.widevine.alpha";
static const char kKeyType[] = "any";
// All three ContentIdentification are supported but cenc_id only supports
// one key for now.
// Using key_id kCencTestRequest will return the content_key kCencTestRequest
//
static const char kCencTestRequest[] = "0123456789ABCDEF";
static const char kCencTestContentKey[] = {
0x16, 0x23, 0xa3, 0x16, 0x67, 0x6d, 0xb7, 0x70,
0xfe, 0x78, 0xf6, 0x58, 0x42, 0xb8, 0x16, 0x3c
};
// System Id of the Widevine DRM system for identification in pssh
static const uint8 kWidevineSystemId[] = {
0xED, 0xEF, 0x8B, 0xA9, 0x79, 0xD6, 0x4A, 0xCE,
0xA3, 0xC8, 0x27, 0xDC, 0xD5, 0x1D, 0x21, 0xED,
};
static std::string EncodeInt32(int i) {
std::string s;
s.resize(sizeof(int));
memcpy(&*s.begin(), &i, sizeof(int));
return s;
}
// Generate PSSH blob from init data
static std::string GeneratePSSHBlob(const uint8* init_data,
int init_data_length) {
std::string output;
// 4 byte size of the PSSH atom, inclusive
int size = 4 + 4 + 4 + sizeof(kWidevineSystemId) + 4 + init_data_length;
output.append(EncodeInt32(base::HostToNet32(size)));
// "pssh"
output.append("pssh");
// 4 byte flags, value 0
int flag = 0;
output.append(EncodeInt32(base::HostToNet32(flag)));
// 16 byte system id
output.append(reinterpret_cast<const char*>(kWidevineSystemId),
sizeof(kWidevineSystemId));
// 4 byte size of PSSH data, exclusive
output.append(EncodeInt32(base::HostToNet32(init_data_length)));
// pssh data
output.append(reinterpret_cast<const char*>(init_data),
init_data_length);
return output;
}
}; // anonymous
namespace wvcdm {
class WvCdmDecryptorTest : public testing::Test {
public:
WvCdmDecryptorTest() {}
~WvCdmDecryptorTest() {}
protected:
void GenerateKeyRequest(const uint8* key_id, int key_id_size,
std::string& message_buffer) {
std::string init_data = GeneratePSSHBlob(key_id, key_id_size);
wvcdm::CdmResponseType res = decryptor_.GenerateKeyRequest(
kWidevineKeySystem, init_data, &message_buffer, &session_id_string_);
EXPECT_TRUE(res == wvcdm::KEY_MESSAGE);
}
void PrepareForRenewalRequest(int i) {
}
void GetRenewalMessage(std::string& message_buffer) {
}
void GetFailedRenewalMessage(std::string& message_buffer) {
}
public:
void AddKeyAndExpectToSucceed(const uint8* key_id, int key_id_size,
const uint8* key, int key_size) {
std::string cma_key((const char*)key, key_size);
std::string init_data = GeneratePSSHBlob(key_id, key_id_size);
wvcdm::CdmResponseType res = decryptor_.AddKey(
kWidevineKeySystem, init_data, cma_key, session_id_string_);
EXPECT_TRUE(res == wvcdm::KEY_ADDED);
}
void AddKeyAndExpectToFail(const uint8* key_id, int key_id_size,
const uint8* key, int key_size) {
std::string cma_key((const char*)key, key_size);
std::string init_data = GeneratePSSHBlob(key_id, key_id_size);
wvcdm::CdmResponseType res = decryptor_.AddKey(
kWidevineKeySystem, init_data, cma_key, session_id_string_);
EXPECT_TRUE(res == wvcdm::KEY_ADDED);
}
protected:
wvcdm::WvContentDecryptionModule decryptor_;
std::string session_id_string_;
};
TEST_F(WvCdmDecryptorTest, RenewalTest) {
std::string response;
std::string message;
const WvCdmEncryptedFrameInfo& frame = kWvCdmEncryptedFrames[3];
License::Policy policies;
DCHECK(GetPolicy(frame.policy_type, &policies));
GenerateKeyRequest(frame.key_id, frame.key_id_size, message);
response = GenerateLicenseResponse(message, kShortDuration);
AddKeyAndExpectToSucceed(frame.key_id, frame.key_id_size,
reinterpret_cast<const uint8*>(response.data()),
response.size());
MessageLoop::current()->RunUntilIdle();
PrepareForRenewalRequest(1);
sleep(policies.renewal_delay_seconds());
MessageLoop::current()->RunUntilIdle();
GetRenewalMessage(message);
response = GenerateLicenseResponse(message, frame.policy_type);
AddKeyAndExpectToSucceed(frame.key_id, frame.key_id_size,
reinterpret_cast<const uint8*>(response.data()),
response.size());
}
TEST_F(WvCdmDecryptorTest, MultiRenewalTest) {
std::string response;
std::string message;
const WvCdmEncryptedFrameInfo& frame = kWvCdmEncryptedFrames[3];
License::Policy policies;
DCHECK(GetPolicy(frame.policy_type, &policies));
GenerateKeyRequest(frame.key_id, frame.key_id_size, message);
response = GenerateLicenseResponse(message, kShortDuration);
AddKeyAndExpectToSucceed(frame.key_id, frame.key_id_size,
reinterpret_cast<const uint8*>(response.data()),
response.size());
MessageLoop::current()->RunUntilIdle();
PrepareForRenewalRequest(1);
sleep(policies.renewal_delay_seconds());
MessageLoop::current()->RunUntilIdle();
GetRenewalMessage(message);
response = GenerateLicenseResponse(message, frame.policy_type);
AddKeyAndExpectToSucceed(frame.key_id, frame.key_id_size,
reinterpret_cast<const uint8*>(response.data()),
response.size());
PrepareForRenewalRequest(2);
sleep(policies.renewal_delay_seconds());
MessageLoop::current()->RunUntilIdle();
GetRenewalMessage(message);
}
TEST_F(WvCdmDecryptorTest, RenewalRetryTest_ExpectSuccess) {
std::string response;
std::string message;
const WvCdmEncryptedFrameInfo& frame = kWvCdmEncryptedFrames[3];
License::Policy policies;
DCHECK(GetPolicy(frame.policy_type, &policies));
GenerateKeyRequest(frame.key_id, frame.key_id_size, message);
response = GenerateLicenseResponse(message, kShortDuration);
AddKeyAndExpectToSucceed(frame.key_id, frame.key_id_size,
reinterpret_cast<const uint8*>(response.data()),
response.size());
MessageLoop::current()->RunUntilIdle();
int loop_seconds =
policies.license_duration_seconds() - policies.renewal_delay_seconds();
int loop_count = loop_seconds / policies.renewal_retry_interval_seconds();
if (loop_seconds % policies.renewal_retry_interval_seconds())
++loop_count;
for (int i = 1; i <= loop_count; ++i) {
PrepareForRenewalRequest(i);
sleep(policies.renewal_delay_seconds());
MessageLoop::current()->RunUntilIdle();
GetRenewalMessage(message);
}
response = GenerateLicenseResponse(message, frame.policy_type);
AddKeyAndExpectToSucceed(frame.key_id, frame.key_id_size,
reinterpret_cast<const uint8*>(response.data()),
response.size());
}
TEST_F(WvCdmDecryptorTest, RenewalRetryTest_ExpectLicenseExpiration) {
std::string response;
std::string message;
const WvCdmEncryptedFrameInfo& frame = kWvCdmEncryptedFrames[3];
License::Policy policies;
DCHECK(GetPolicy(frame.policy_type, &policies));
GenerateKeyRequest(frame.key_id, frame.key_id_size, message);
response = GenerateLicenseResponse(message, kShortDuration);
AddKeyAndExpectToSucceed(frame.key_id, frame.key_id_size,
reinterpret_cast<const uint8*>(response.data()),
response.size());
MessageLoop::current()->RunUntilIdle();
int loop_seconds =
policies.license_duration_seconds() - policies.renewal_delay_seconds();
int loop_count = loop_seconds / policies.renewal_retry_interval_seconds() + 1;
if (loop_seconds % policies.renewal_retry_interval_seconds())
++loop_count;
for (int i = 1; i <= loop_count; ++i) {
PrepareForRenewalRequest(i);
sleep(i > 1 ?
policies.renewal_retry_interval_seconds() :
policies.renewal_delay_seconds());
MessageLoop::current()->RunUntilIdle();
if (i < loop_count)
GetRenewalMessage(message);
}
GetFailedRenewalMessage(message);
}
} // namespace wvcdm
// TODO(rkuroiwa): Find where to put this main function just for Widevine CDM
// unit tests.
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
base::AtExitManager exit;
MessageLoop ttr(MessageLoop::TYPE_IO);
return RUN_ALL_TESTS();
}

View File

@@ -547,11 +547,9 @@ bool SessionContext::RefreshKey(const KeyId& key_id,
// Decrypt encrypted key control block
std::vector<uint8_t> control;
if (key_control_iv.empty()) {
// TODO(fredg): get confirmation from server team this is valid.
LOGD("Key control block is NOT encrypted.");
control = key_control;
} else {
// TODO(fredg): get confirmation from server team this is valid, too.
LOGD("Key control block is encrypted.");
if (!DecryptMessage(content_key_value, key_control_iv, key_control,
&control)) {
@@ -1024,9 +1022,13 @@ OEMCryptoResult SessionContext::DecryptCTR(
size_t cipher_data_length, bool is_encrypted, uint8_t* clear_data,
BufferType buffer_type) {
// If the data is clear, we do not need a current key selected.
if (!is_encrypted && buffer_type != kBufferTypeDirect) {
memcpy(reinterpret_cast<uint8_t*>(clear_data),
cipher_data, cipher_data_length);
if (!is_encrypted) {
if (buffer_type != kBufferTypeDirect) {
memcpy(reinterpret_cast<uint8_t*>(clear_data), cipher_data,
cipher_data_length);
return OEMCrypto_SUCCESS;
}
// For reference implementation, we quietly drop the clear direct video.
return OEMCrypto_SUCCESS;
}
@@ -1083,7 +1085,7 @@ OEMCryptoResult SessionContext::DecryptCTR(
}
if (buffer_type == kBufferTypeDirect) {
// For reference implementation, we quietly drop direct video.
// For reference implementation, we quietly drop the decrypted direct video.
return OEMCrypto_SUCCESS;
}

View File

@@ -39,7 +39,6 @@ static void dump_hex(std::string name, const uint8_t* vector, size_t length) {
printf("NULL;\n");
return;
}
// TODO(fredgc): replace with HEXEncode.
for (size_t i = 0; i < length; i++) {
if (i == 0) {
printf("\n wvcdm::a2b_hex(\"");