Allow Apps to Voluntarily Downgrade to L3 Crypto

This merges the following changes from the Widevine CDM repository:

564f4cc  Add CdmClientPropertySet to CDM
  Adds an interface to the CDM that allows it to query its client for
  certain properties.  In this case, this includes the ability to
  specify what security level is desired, as well as support for
  service ceritifcate privacy mode.

9cfbd3e  Force Level 3 fallback
  Adds support for voluntarily invoking L3 crypto to the OEMCrypto
  wrapper.

95d12c1  Add pointer to CdmClientPropertySet class to OpenSession.
  Adds support for storing the property set on a session-by-session
  basis and choosing the appropriate crypto level.

17de442  Add Settable Properties for Clank to Android
  Adds support for setting the aforementioned properties to the
  DrmEngine

bbe704d  Fixes to force fallback to level three security
  Corrections to invoke provisioning, OEMCrypto API with configured
  security level rather than the default. Unit tests were also revised.

Note that some parts of this are also support for the ability to use
a service certificate-based privacy mode. The remaining code for
supporting this mode is still forthcoming.

Bug: 10109249
Change-Id: I2755e4dea1de3e8a56cff237360298f7b7f1bddc
This commit is contained in:
Rahul Frias
2013-08-15 10:59:42 -07:00
parent 0fa3e16999
commit f6c2a60485
45 changed files with 2359 additions and 906 deletions

View File

@@ -0,0 +1,23 @@
// Copyright 2013 Google Inc. All Rights Reserved.
#ifndef CDM_BASE_CDM_CLIENT_PROPERTY_SET_H_
#define CDM_BASE_CDM_CLIENT_PROPERTY_SET_H_
#include <string>
#include <vector>
#include <stdint.h>
namespace wvcdm {
class CdmClientPropertySet {
public:
virtual ~CdmClientPropertySet() {}
virtual std::string security_level() const = 0;
virtual bool use_privacy_mode() const = 0;
virtual std::vector<uint8_t> service_certificate() const = 0;
};
} // namespace wvcdm
#endif // CDM_BASE_CDM_CLIENT_PROPERTY_SET_H_

View File

@@ -4,11 +4,13 @@
#define CDM_BASE_CDM_ENGINE_H_
#include "certificate_provisioning.h"
#include "oemcrypto_adapter.h"
#include "timer.h"
#include "wv_cdm_types.h"
namespace wvcdm {
class CdmClientPropertySet;
class CdmSession;
class CryptoEngine;
class WvCdmEventListener;
@@ -22,8 +24,10 @@ class CdmEngine : public TimerHandler {
virtual ~CdmEngine();
// Session related methods
virtual CdmResponseType OpenSession(const CdmKeySystem& key_system,
CdmSessionId* session_id);
virtual CdmResponseType OpenSession(
const CdmKeySystem& key_system,
const CdmClientPropertySet* property_set,
CdmSessionId* session_id);
virtual CdmResponseType CloseSession(const CdmSessionId& session_id);
virtual CdmResponseType OpenKeySetSession(const CdmKeySetId& key_set_id);
@@ -116,9 +120,11 @@ class CdmEngine : public TimerHandler {
// instance variables
CdmSessionMap sessions_;
CertificateProvisioning cert_provisioning_;
CdmReleaseKeySetMap release_key_sets_;
CertificateProvisioning cert_provisioning_;
SecurityLevel cert_provisioning_requested_security_level_;
// policy timer
Timer policy_timer_;

View File

@@ -8,23 +8,20 @@
#include "crypto_session.h"
#include "device_files.h"
#include "license.h"
#include "oemcrypto_adapter.h"
#include "policy_engine.h"
#include "scoped_ptr.h"
#include "wv_cdm_types.h"
namespace wvcdm {
class CdmClientPropertySet;
class WvCdmEventListener;
class CdmSession {
public:
CdmSession()
: session_id_(GenerateSessionId()),
crypto_session_(NULL),
license_received_(false),
reinitialize_session_(false),
license_type_(kLicenseTypeStreaming) {}
~CdmSession() {}
explicit CdmSession(const CdmClientPropertySet* cdm_client_property_set);
~CdmSession();
CdmResponseType Init();
@@ -87,13 +84,14 @@ class CdmSession {
void OnTimerEvent();
void OnKeyReleaseEvent(const CdmKeySetId& key_set_id);
SecurityLevel GetRequestedSecurityLevel();
private:
// Generate unique ID for each new session.
CdmSessionId GenerateSessionId();
bool GenerateKeySetId(CdmKeySetId* key_set_id);
bool LoadDeviceCertificate(std::string* cert, std::string* wrapped_key);
bool StoreLicense(DeviceFiles::LicenseState state);
// instance variables

View File

@@ -4,6 +4,7 @@
#define CDM_BASE_CERTIFICATE_PROVISIONING_H_
#include "crypto_session.h"
#include "oemcrypto_adapter.h"
#include "wv_cdm_types.h"
namespace wvcdm {
@@ -16,7 +17,8 @@ class CertificateProvisioning {
~CertificateProvisioning() {};
// Provisioning related methods
CdmResponseType GetProvisioningRequest(CdmProvisioningRequest* request,
CdmResponseType GetProvisioningRequest(SecurityLevel requested_security_level,
CdmProvisioningRequest* request,
std::string* default_url);
CdmResponseType HandleProvisioningResponse(CdmProvisioningResponse& response);

View File

@@ -9,6 +9,7 @@
#include <map>
#include "lock.h"
#include "oemcrypto_adapter.h"
#include "OEMCryptoCENC.h"
#include "wv_cdm_types.h"
@@ -29,7 +30,8 @@ class CryptoSession {
bool GetSystemId(uint32_t* system_id);
bool GetProvisioningId(std::string* provisioning_id);
CdmResponseType Open();
CdmResponseType Open() { return Open(kLevelDefault); }
CdmResponseType Open(SecurityLevel requested_security_level);
void Close();
bool IsOpen() { return open_; }
@@ -64,7 +66,7 @@ class CryptoSession {
bool SelectKey(const std::string& key_id);
CdmResponseType Decrypt(const CdmDecryptionParameters& parameters);
bool GetRandom(uint8_t* random_data, size_t data_length);
bool GetRandom(size_t data_length, uint8_t* random_data);
private:
void Init();
@@ -88,7 +90,7 @@ class CryptoSession {
OEMCryptoBufferType destination_buffer_type_;
bool is_destination_buffer_type_valid_;
CdmSecurityLevel security_level_;
SecurityLevel requested_security_level_;
CORE_DISALLOW_COPY_AND_ASSIGN(CryptoSession);
};

View File

@@ -45,6 +45,7 @@ class DeviceFiles {
CdmKeyResponse* key_renewal_response,
std::string* release_server_url);
virtual bool DeleteLicense(const std::string& key_set_id);
virtual bool DeleteAllFiles();
virtual bool DeleteAllLicenses();
virtual bool LicenseExists(const std::string& key_set_id);

View File

@@ -19,8 +19,11 @@ class PolicyEngine;
class CdmLicense {
public:
CdmLicense();
~CdmLicense();
CdmLicense()
: session_(NULL),
initialized_(false),
service_certificate_response_pending_(false) {};
~CdmLicense() {};
bool Init(const std::string& token, CryptoSession* session,
PolicyEngine* policy_engine);
@@ -28,28 +31,37 @@ class CdmLicense {
bool PrepareKeyRequest(const CdmInitData& pssh_data,
const CdmLicenseType license_type,
const CdmAppParameterMap& app_parameters,
const CdmSessionId& session_id,
CdmKeyMessage* signed_request,
std::string* server_url);
bool PrepareKeyUpdateRequest(bool is_renewal,
CdmKeyMessage* signed_request,
bool PrepareKeyUpdateRequest(bool is_renewal, CdmKeyMessage* signed_request,
std::string* server_url);
CdmResponseType HandleKeyResponse(const CdmKeyResponse& license_response);
CdmResponseType HandleKeyUpdateResponse(
bool is_renewal,
const CdmKeyResponse& license_response);
bool is_renewal, const CdmKeyResponse& license_response);
bool RestoreOfflineLicense(CdmKeyMessage& license_request,
CdmKeyResponse& license_response,
CdmKeyResponse& license_renewal_response);
bool HasInitData() { return !init_data_.empty(); }
private:
CdmResponseType HandleKeyErrorResponse(
const video_widevine_server::sdk::SignedMessage& signed_message);
private:
bool PrepareServiceCertificateRequest(CdmKeyMessage* signed_request,
std::string* server_url);
CdmResponseType HandleServiceCertificateResponse(
const CdmKeyResponse& service_certificate_response);
CdmResponseType HandleKeyErrorResponse(
const video_widevine_server::sdk::SignedMessage& signed_message);
CryptoSession* session_;
PolicyEngine* policy_engine_;
std::string server_url_;
std::string token_;
std::string service_certificate_;
std::string init_data_;
bool initialized_;
bool service_certificate_response_pending_;
// Used for certificate based licensing
CdmKeyMessage key_request_;

View File

@@ -0,0 +1,39 @@
/*********************************************************************
* 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_
#include "OEMCryptoCENC.h"
namespace wvcdm {
enum SecurityLevel {
kLevelDefault,
kLevel3
};
/* 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,
SecurityLevel level);
OEMCryptoResult OEMCrypto_IsKeyboxValid(SecurityLevel level);
OEMCryptoResult OEMCrypto_GetDeviceID(uint8_t* deviceID, size_t* idLength,
SecurityLevel level);
OEMCryptoResult OEMCrypto_GetKeyData(uint8_t* keyData, size_t* keyDataLength,
SecurityLevel level);
OEMCryptoResult OEMCrypto_InstallKeybox(const uint8_t* keybox,
size_t keyBoxLength,
SecurityLevel level);
uint32_t OEMCrypto_APIVersion(SecurityLevel level);
const char* OEMCrypto_SecurityLevel(SecurityLevel level);
} // namespace wvcdm
#endif // OEMCRYPTO_ADAPTER_H_

View File

@@ -0,0 +1,77 @@
// 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.
//
// AES encryption details:
// Algorithm: AES-CBC
//
// RSA signature details:
// Algorithm: RSASSA-PSS
// Hash algorithm: SHA1
// Mask generation function: mgf1SHA1
// Salt length: 20 bytes
// Trailer field: 0xbc
//
// RSA encryption details:
// Algorithm: RSA-OAEP
// Mask generation function: mgf1SHA1
// Label (encoding paramter): empty string
#ifndef CDM_BASE_PRIVACY_CRYPTO_H_
#define CDM_BASE_PRIVACY_CRYPTO_H_
#include <string>
#include "openssl/aes.h"
#include "openssl/rsa.h"
#include "wv_cdm_types.h"
namespace wvcdm {
class AesCbcKey {
public:
AesCbcKey() : initialized_(false) {};
~AesCbcKey() {};
bool Init(const std::string& key);
bool Encrypt(const std::string& in, std::string* out, std::string* iv);
private:
AES_KEY key_;
bool initialized_;
CORE_DISALLOW_COPY_AND_ASSIGN(AesCbcKey);
};
class RsaPublicKey {
public:
RsaPublicKey() : key_(NULL) {}
~RsaPublicKey();
// Initializes an RsaPublicKey object using a DER encoded PKCS#1 RSAPublicKey
bool Init(const std::string& serialized_key);
// Encrypt a message using RSA-OAEP. Caller retains ownership of all
// parameters. Returns true if successful, false otherwise.
bool Encrypt(const std::string& clear_message,
std::string* encrypted_message);
// Verify RSSASSA-PSS signature. Caller retains ownership of all parameters.
// Returns true if validation succeeds, false otherwise.
bool VerifySignature(const std::string& message,
const std::string& signature);
private:
RSA* key_;
CORE_DISALLOW_COPY_AND_ASSIGN(RsaPublicKey);
};
} // namespace wvcdm
#endif // CDM_BASE_PRIVACY_CRYPTO_H_

View File

@@ -6,11 +6,16 @@
#include <map>
#include <string>
#include "cdm_client_property_set.h"
#include "lock.h"
#include "scoped_ptr.h"
#include "wv_cdm_types.h"
namespace wvcdm {
typedef std::map<CdmSessionId, const CdmClientPropertySet*>
CdmClientPropertySetMap;
// This class saves information about features and properties enabled
// for a given platform. At initialization it initializes properties from
// property_configuration.h. That file specifies features selected for each
@@ -40,6 +45,9 @@ class Properties {
static inline bool extract_pssh_data() {
return extract_pssh_data_;
}
static inline bool decrypt_with_empty_session_support() {
return decrypt_with_empty_session_support_;
}
static bool GetCompanyName(std::string* company_name);
static bool GetModelName(std::string* model_name);
static bool GetArchitectureName(std::string* arch_name);
@@ -49,8 +57,20 @@ class Properties {
static bool GetDeviceFilesBasePath(CdmSecurityLevel security_level,
std::string* base_path);
static bool GetFactoryKeyboxPath(std::string* keybox);
static bool GetOEMCryptoPath(std::string* library_name);
static const std::string GetSecurityLevel(const CdmSessionId& session_id);
static const std::vector<uint8_t> GetServiceCertificate(
const CdmSessionId& session_id);
static bool UsePrivacyMode(const CdmSessionId& session_id);
static bool AddSessionPropertySet(
const CdmSessionId& session_id,
const CdmClientPropertySet* property_set);
static bool RemoveSessionPropertySet(const CdmSessionId& session_id);
private:
static const CdmClientPropertySet* GetCdmClientPropertySet(
const CdmSessionId& session_id);
static void set_begin_license_usage_when_received(bool flag) {
begin_license_usage_when_received_ = flag;
}
@@ -72,6 +92,9 @@ class Properties {
static void set_extract_pssh_data(bool flag) {
extract_pssh_data_ = flag;
}
static void set_decrypt_with_empty_session_support(bool flag) {
decrypt_with_empty_session_support_ = flag;
}
static bool begin_license_usage_when_received_;
static bool require_explicit_renew_request_;
@@ -80,6 +103,8 @@ class Properties {
static bool oem_crypto_use_userspace_buffers_;
static bool use_certificates_as_identification_;
static bool extract_pssh_data_;
static bool decrypt_with_empty_session_support_;
static scoped_ptr<CdmClientPropertySetMap> session_property_set_;
CORE_DISALLOW_COPY_AND_ASSIGN(Properties);
};