Merges to android Pi release (part 12)

These are a set of CLs merged from the wv cdm repo to the android repo.

* Correct error logging

  Author: Rahul Frias <rfrias@google.com>

  [ Merge of http://go/wvgerrit/40000 ]

  In tests, we set the cipher list to avoid using insecure
  ciphers when connecting to the provisioning/license service.
  The result of setting the cipher list was being incorrectly
  validated.

  Bug: 64847919

* Move mips cache headers to clear_cache_function.h

  Author: Srujan Gaddam <srujzs@google.com>

  [ Merge of http://go/wvgerrit/39700 ]

  Since the clear_cache function has been moved away from the dynamic
  adapter, we need these conditional includes to be migrated as well for
  MIPS.

* Comment out Level 3 debug call until merge

  Author: Srujan Gaddam <srujzs@google.com>

  [ Merge of http://go/wvgerrit/39761 ]

  This call was introduced in go/wvgerrit/34260/. Since the haystack tool
  in google3 still needs this merge, this should be commented out so the
  tool can still build until the merge has finished.

* Add logging for MAC keys to mock

  Author: Srujan Gaddam <srujzs@google.com>

  [ Merge of http://go/wvgerrit/39740 ]

  Bug: 70637842

* Move external interfaces into level3.h + refactor

  Author: Srujan Gaddam <srujzs@google.com>

  [ Merge of http://go/wvgerrit/39673 ]

  As part of b/70523618, this CL moves interfaces that partners are
  responsible for in Level 3 to level3.h so they can be visible as
  part of the CDM release process. It also cleans up some of the
  names of the files and adds documentation.

* Corrected close session logging level

  Author: Rahul Frias <rfrias@google.com>

  [ Merge of http://go/wvgerrit/39676 ]

  Bug: 69460963

* Remove Security Level Path Backward Compatibility Support

  Author: Rahul Frias <rfrias@google.com>

  [ Merge of http://go/wvgerrit/39505 ]

  From the android K release onwards certificates were stored in
  security level specific directories. If upgrading from
  previous releases persistent information needed to be moved
  to those directories.

  Since no device is likely to upgrade from J to Pi, comptibility
  support can be removed.

  Bug: 70160032

* Rename privacy_crypto_openssl To privacy_crypto_boringssl

  Author: John W. Bruce <juce@google.com>

  [ Merge of http://go/wvgerrit/37122 ]

  Now that we no longer support OpenSSL in the Shared Source CDM, the name
  of this file can be updated.

  Bug: 67907873
  Test: build.py x86-64
  Test: wv_ce_cdm_unittest
  Test: jenkins/linux_unit_tests

* Remove Conditional Compilation from OpenSSL/BoringSSL

  Author: John W. Bruce <juce@google.com>

  [ Merge of http://go/wvgerrit/39460 ]

  This change removes the usages of conditional compilation to support
  both BoringSSL and OpenSSL, as well as to support multiple versions of
  the OpenSSL API. All code is now compiled against one of the two
  versions of BoringSSL in third_party/.

  Note that in some cases, the kit/ and legacy_kit/ versions of BoringSSL
  had different APIs, so when removing the OpenSSL version compatibility
  conditional compilation, sometimes the older branch was kept and
  sometimes the newer branch was kept.

  Bug: 67907873
  Test: build.py x86-64
  Test: wv_ce_cdm_unittest
  Test: jenkins/linux_unit_tests

* Build CE & Jenkins CDMs With BoringSSL from third_party/

  Author: John W. Bruce <juce@google.com>

  [ Merge of http://go/wvgerrit/37120 ]

  Up until now, integrators have been responsible for providing a
  compatible crypto library for use by the CE CDM. (either OpenSSL or
  BoringSSL) After this change, this decision will no longer be in their
  hands. The CE CDM build will always use the copy of BoringSSL in
  third_party/, which will be statically linked with our library with
  hidden visibility. This allows us to better control what crypto library
  we use and will prevent continuing problems with trying to support both
  OpenSSL and BoringSSL.

  Unfortunately, BoringSSL began using C++11 in mid-2017, and we can't
  support C++11 right now. Until we can, we need to use a C++11-free
  version of BoringSSL for libssl. The CDM itself will continue to use a
  recent BoringSSL, as it only needs libcrypto. But the unit tests that
  need libssl have to use the legacy version.

  Bug: 67907873
  Test: build.py x86-64
  Test: wv_ce_cdm_unittest
  Test: jenkins/linux_unit_tests

* Modified RNG for Level3 to use more entropy

  Author: Srujan Gaddam <srujzs@google.com>

  [ Merge of http://go/wvgerrit/39220 ]

  Bug: 65165076

  Modified seed generation to use an xor of clock_gettime and
  client-implemented code to supply random seeds to the RNG. Modified the RNG
  as well to use xoroshiro128+ instead of xorshift, since it uses more
  than one seed/state (which are 64-bit) and has higher "statistical quality".
  The default implementations for the seed generation use /dev/urandom.

* Configure base path for Level3FileSystem

  Author: Srujan Gaddam <srujzs@google.com>

  [ Merge of http://go/wvgerrit/39506 ]

  This is in response to b/70354006. This change makes the
  Android Level3FileSystem use the existing properties method
  GetDevicesFilesBasePath for binderization. The same is done for the
  Linux implementation.

* Add legacy_kit/ to BoringSSL Directory

  Author: John W. Bruce <juce@google.com>

  [ Merge of http://go/wvgerrit/38861 ]

  This adds a second copy of BoringSSL to the third_party/boringssl/
  directory. This second copy is pinned to the last revision of BoringSSL
  not to require C++11 and is not updated by the UPDATE_BORINGSSL.sh
  script. This second copy will be used to provide libssl to the tests on
  devices that do not support C++11.

  Once we support C++11 in the CDM again, this weight should be removed
  and all targets should use the copy of BoringSSL in the kit/ directory.

  Bug: 67907873

* Use Shared Libraries for Unit Tests

  Author: John W. Bruce <juce@google.com>

  [ Merge of http://go/wvgerrit/38860 ]

  Some unit tests were using a statically-linked CDM instead of a
  dynamically-linked one. (Or, in one case, trying to link both ways into
  the same binary.) For now, we need to only link dynamically, so that the
  unit tests and the CDM can use different versions of BoringSSL.

  Long-term, we would like to test both kinds of linkage. (See b/69548115
  for that.)

  Some unit tests were also using a dynamicaly-linked CDM that was named
  such that it appeared to be statically-linked. This patch renames some
  targets to make the linkage clearer.

  Bug: 67907873

* Change CDM_Backwards_Compatiblity_Tests to dedicated brances

  Author: Fred Gylys-Colwell <fredgc@google.com>

  [ Merge of http://go/wvgerrit/39003 ]

  The build scripts used by CDM_Backwards_Compatiblity_Tests now pull
  old versions of oemcrypto from the dedicated branches oemcrypto-v*,
  which [will eventually] contain old oemcrypto versions, that build
  with the current build system with a current boringssl version.

  bug: 67907873

* Fix spacing on level3 header

  Author: Srujan Gaddam <srujzs@google.com>

  [ Merge of http://go/wvgerrit/38760 ]

* Correct Query status calls

  Author: Rahul Frias <rfrias@google.com>

  [ Merge of http://go/wvgerrit/38640 ]

  Bug: 70160032

* Refactoring to allow encryption of client ID

  Author: Rahul Frias <rfrias@google.com>

  [ Merge of http://go/wvgerrit/37460 ]

  The code has been restructured to allow encryption of client
  identification in provisioning requests. This will be enabled
  when server side changes have been made (b/69427217).

  * Additional information is included in the Client Identification
    portion of the provisioning request.
  * Client identification will be encrypted with a service
    certificate provided by the app/client. Platform changes
    to enable passing this to core are needed. If a service certificate
    is not provided, a default one associated with the production Keysmith
    will be used.
  * Switched APIs in CdmEngine to take a service certificate for
    provisioning rather than licensing. Service certificates for
    licensing are session based and passed as properties from platform
    code.

  Bug: 30737060

* Allow some CDM errors to be reported from multiple locations

  Author: Rahul Frias <rfrias@google.com>

  [ Merge of http://go/wvgerrit/38360 ]

  This creates some CdmResponseType errors which may be reused
  PARAMETER_NULL, NOT_INITIALIZED_ERROR, REINIT_ERROR.

  I have made changes to a few classes to report these errors.
  Will work on additional classes in a separate CL.

  Bug: 69864404

BUG: 71650075
Test: WV Unit/integration tests
Change-Id: Icc048770d424ac537d11ff327cda2cb142da802d
This commit is contained in:
Rahul Frias
2018-01-10 23:54:59 -08:00
parent 5d690be108
commit aac1439dea
79 changed files with 582991 additions and 3305 deletions

View File

@@ -31,6 +31,7 @@ LOCAL_SRC_FILES := \
$(CORE_SRC_DIR)/cdm_session.cpp \
$(CORE_SRC_DIR)/cdm_session_map.cpp \
$(CORE_SRC_DIR)/certificate_provisioning.cpp \
$(CORE_SRC_DIR)/client_identification.cpp \
$(CORE_SRC_DIR)/crypto_session.cpp \
$(CORE_SRC_DIR)/device_files.cpp \
$(CORE_SRC_DIR)/initialization_data.cpp \
@@ -38,7 +39,7 @@ LOCAL_SRC_FILES := \
$(CORE_SRC_DIR)/license_key_status.cpp \
$(CORE_SRC_DIR)/oemcrypto_adapter_dynamic.cpp \
$(CORE_SRC_DIR)/policy_engine.cpp \
$(CORE_SRC_DIR)/privacy_crypto_openssl.cpp \
$(CORE_SRC_DIR)/privacy_crypto_boringssl.cpp \
$(CORE_SRC_DIR)/service_certificate.cpp \
$(CORE_SRC_DIR)/usage_table_header.cpp \
$(SRC_DIR)/wv_content_decryption_module.cpp \

View File

@@ -39,15 +39,14 @@ class CdmEngine {
CdmEngine(FileSystem* file_system, const std::string& spoid = EMPTY_SPOID);
virtual ~CdmEngine();
// Set service certificate for all sessions under this CDM/CdmEngine.
// Setting to the empty string is OK. If the License Service certificate is
// empty and privacy mode is true, the certificate will be fetched from
// the server before the first license request.
virtual CdmResponseType SetServiceCertificate(
// Set service certificate used when provisioning under this CDM/CdmEngine.
// If no valid service certificate is set, a default one associated with
// the WV production provisioning server will be used.
virtual CdmResponseType SetProvisioningServiceCertificate(
const std::string& certificate);
// Report whether the service certificate has been set.
virtual bool HasServiceCertificate();
virtual bool HasProvisioningServiceCertificate();
// Session related methods
virtual CdmResponseType OpenSession(
@@ -323,11 +322,8 @@ class CdmEngine {
static bool seeded_;
// Service certificate for license server and provisioning server.
// It is initially empty. If left empty, the operations that
// require them (getting provider_id, encrypting ClientIdentification)
// are not performed.
ServiceCertificate service_certificate_;
// Service certificate for the provisioning server.
ServiceCertificate provisioning_service_certificate_;
// usage related variables
scoped_ptr<CdmSession> usage_session_;

View File

@@ -0,0 +1,52 @@
// Copyright 2017 Google Inc. All Rights Reserved.
#ifndef WVCDM_CORE_CDM_SESSION_MAP_H_
#define WVCDM_CORE_CDM_SESSION_MAP_H_
#include <list>
#include <memory>
#include <string>
#include "cdm_session.h"
#include "lock.h"
#include "shared_ptr.h"
#include "wv_cdm_types.h"
namespace wvcdm {
typedef std::list<shared_ptr<CdmSession> > CdmSessionList;
class CdmSessionMap {
public:
CdmSessionMap() {}
virtual ~CdmSessionMap();
void Add(const std::string& id, CdmSession* session);
bool CloseSession(const std::string& id);
bool Exists(const std::string& id);
size_t Size() const { return sessions_.size(); }
bool FindSession(const CdmSessionId& id,
shared_ptr<CdmSession>* session);
void GetSessionList(CdmSessionList& sessions);
private:
typedef std::map<CdmSessionId, shared_ptr<CdmSession> >
CdmIdToSessionMap;
bool FindSessionNoLock(const CdmSessionId& session_id,
shared_ptr<CdmSession>* session);
Lock lock_;
CdmIdToSessionMap sessions_;
CORE_DISALLOW_COPY_AND_ASSIGN(CdmSessionMap);
};
} // namespace wvcdm
#endif // WVCDM_CORE_CDM_SESSION_MAP_H_

View File

@@ -10,6 +10,7 @@
#include "metrics_collections.h"
#include "oemcrypto_adapter.h"
#include "scoped_ptr.h"
#include "service_certificate.h"
#include "wv_cdm_types.h"
namespace wvcdm {
@@ -21,13 +22,13 @@ class ServiceCertificate;
class CertificateProvisioning {
public:
CertificateProvisioning(metrics::CryptoMetrics* metrics,
ServiceCertificate* service_certificate) :
CertificateProvisioning(metrics::CryptoMetrics* metrics) :
crypto_session_(metrics),
cert_type_(kCertificateWidevine),
service_certificate_(service_certificate) {}
service_certificate_(new ServiceCertificate()) {}
~CertificateProvisioning() {}
~CertificateProvisioning() {};
CdmResponseType Init(const std::string& service_certificate);
// Construct a valid provisioning request.
// The request will be sent to the provisioning server.
@@ -43,9 +44,6 @@ class CertificateProvisioning {
std::string* cert, std::string* wrapped_key);
private:
bool GetProvisioningTokenType(
video_widevine::ClientIdentification::TokenType* token_type);
bool SetSpoidParameter(const std::string& origin, const std::string& spoid,
video_widevine::ProvisioningRequest* request);
@@ -54,7 +52,7 @@ class CertificateProvisioning {
CryptoSession crypto_session_;
CdmCertificateType cert_type_;
ServiceCertificate* service_certificate_;
scoped_ptr<ServiceCertificate> service_certificate_;
CORE_DISALLOW_COPY_AND_ASSIGN(CertificateProvisioning);
};

View File

@@ -0,0 +1,57 @@
// Copyright 2017 Google Inc. All Rights Reserved.
#ifndef WVCDM_CORE_CLIENT_IDENTIFICATION_H_
#define WVCDM_CORE_CLIENT_IDENTIFICATION_H_
// ClientIdentification fills in the ClientIdentification portion
// of the License or Provisioning request messages.
#include "license_protocol.pb.h"
#include "wv_cdm_types.h"
namespace wvcdm {
class CryptoSession;
class ClientIdentification {
public:
ClientIdentification() : is_license_request_(true) {}
virtual ~ClientIdentification() {}
// Call this method when used with provisioning requests
CdmResponseType Init(CryptoSession* crypto_session);
// Use in conjunction with license requests
// |client_token| must be provided
// |device_id| optional
// |crypto_session| input parameter, mandatory
CdmResponseType Init(const std::string& client_token,
const std::string& device_id,
CryptoSession* crypto_session);
// Fill the ClientIdentification portion of the license or provisioning
// request
// |app_parameters| parameters provided by client/app to be included in
// provisioning/license request. optional, only used
// if |is_license_request| is true
// |client_id| Portion of license/provisioning request that needs to be
// populated.
virtual CdmResponseType Prepare(
const CdmAppParameterMap& app_parameters,
video_widevine::ClientIdentification* client_id);
private:
bool GetProvisioningTokenType(
video_widevine::ClientIdentification::TokenType* token_type);
bool is_license_request_;
std::string client_token_;
std::string device_id_;
CryptoSession* crypto_session_;
CORE_DISALLOW_COPY_AND_ASSIGN(ClientIdentification);
};
} // namespace wvcdm
#endif // WVCDM_CORE_CLIENT_IDENTIFICATION_H_

View File

@@ -77,9 +77,6 @@ class CdmLicense {
CdmResponseType HandleKeyErrorResponse(
const video_widevine::SignedMessage& signed_message);
bool GetClientTokenType(
video_widevine::ClientIdentification::TokenType* token_type);
CdmResponseType PrepareClientId(
const CdmAppParameterMap& app_parameters,
video_widevine::LicenseRequest* license_request);

View File

@@ -0,0 +1,18 @@
// Copyright 2015 Google Inc. All Rights Reserved.
// TODO: Import to core/, use everywhere.
#ifndef WVCDM_CDM_OVERRIDE_H_
#define WVCDM_CDM_OVERRIDE_H_
#define GCC_HAS_OVERRIDE ( \
(__GNUC__ > 4) || \
(__GNUC__ == 4 && __GNUC_MINOR__ >= 7) \
)
#if !defined(DISABLE_OVERRIDE_KEYWORD) && \
(defined(COMPILER_MSVC) || defined(__clang__) || GCC_HAS_OVERRIDE)
#define OVERRIDE override
#else
#define OVERRIDE
#endif
#endif // WVCDM_CDM_OVERRIDE_H_

View File

@@ -46,9 +46,6 @@ class Properties {
static void set_provisioning_messages_are_binary(bool flag) {
provisioning_messages_are_binary_ = flag;
}
static inline bool security_level_path_backward_compatibility_support() {
return security_level_path_backward_compatibility_support_;
}
static bool GetCompanyName(std::string* company_name);
static bool GetModelName(std::string* model_name);
static bool GetArchitectureName(std::string* arch_name);
@@ -96,10 +93,6 @@ class Properties {
static void set_use_certificates_as_identification(bool flag) {
use_certificates_as_identification_ = flag;
}
static void set_security_level_path_backward_compatibility_support(
bool flag) {
security_level_path_backward_compatibility_support_ = flag;
}
#if defined(UNIT_TEST)
FRIEND_TEST(CdmSessionTest, InitWithBuiltInCertificate);
@@ -117,7 +110,6 @@ class Properties {
static bool oem_crypto_use_fifo_;
static bool oem_crypto_use_userspace_buffers_;
static bool use_certificates_as_identification_;
static bool security_level_path_backward_compatibility_support_;
static bool provisioning_messages_are_binary_;
static bool allow_service_certificate_requests_;
static scoped_ptr<CdmClientPropertySetMap> session_property_set_;

View File

@@ -0,0 +1,222 @@
// Copyright 2017 Google Inc. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// from google3/util/gtl/shared_ptr.h
// from protobuf/src/google/protobuf/stubs/shared_ptr.h
#ifndef WVCDM_CORE_SHARED_PTR_H__
#define WVCDM_CORE_SHARED_PTR_H__
#include <algorithm> // for swap
#include <stddef.h>
#include <memory>
#include "wv_cdm_types.h"
namespace {
bool Barrier_AtomicIncrement(volatile uint32_t* ptr, uint32_t value) {
*ptr += value;
return *ptr;
}
bool NoBarrier_AtomicIncrement(volatile uint32_t* ptr, uint32_t value) {
*ptr += value;
return *ptr;
}
inline bool RefCountDec(volatile uint32_t *ptr) {
return Barrier_AtomicIncrement(ptr, -1) != 0;
}
inline void RefCountInc(volatile uint32_t *ptr) {
NoBarrier_AtomicIncrement(ptr, 1);
}
} // namespace
namespace wvcdm {
template <typename T> class shared_ptr;
// This class is an internal implementation detail for shared_ptr. If two
// shared_ptrs point to the same object, they also share a control block.
// An "empty" shared_pointer refers to NULL and also has a NULL control block.
// It contains all of the state that's needed for reference counting or any
// other kind of resource management. In this implementation the control block
// consists of a single reference count (the number of shared_ptrs that
// share ownership of the object).
class SharedPtrControlBlock {
template <typename T> friend class shared_ptr;
private:
SharedPtrControlBlock() : refcount_(1) {}
uint32_t refcount_;
};
// Forward declaration. The class is defined below.
template <typename T> class enable_shared_from_this;
template <typename T>
class shared_ptr {
public:
typedef T element_type;
shared_ptr() : ptr_(NULL), control_block_(NULL) {}
explicit shared_ptr(T* ptr)
: ptr_(ptr),
control_block_(ptr != NULL ? new SharedPtrControlBlock : NULL) {
}
// Copy constructor: makes this object a copy of ptr, and increments
// the reference count.
template <typename U>
shared_ptr(const shared_ptr<U>& ptr)
: ptr_(NULL),
control_block_(NULL) {
Initialize(ptr);
}
// Need non-templated version to prevent the compiler-generated default
shared_ptr(const shared_ptr<T>& ptr)
: ptr_(NULL),
control_block_(NULL) {
Initialize(ptr);
}
// Assignment operator. Replaces the existing shared_ptr with ptr.
// Increment ptr's reference count and decrement the one being replaced.
template <typename U>
shared_ptr<T>& operator=(const shared_ptr<U>& ptr) {
if (ptr_ != ptr.ptr_) {
shared_ptr<T> me(ptr); // will hold our previous state to be destroyed.
swap(me);
}
return *this;
}
// Need non-templated version to prevent the compiler-generated default
shared_ptr<T>& operator=(const shared_ptr<T>& ptr) {
if (ptr_ != ptr.ptr_) {
shared_ptr<T> me(ptr); // will hold our previous state to be destroyed.
swap(me);
}
return *this;
}
~shared_ptr() {
if (ptr_ != NULL) {
if (!RefCountDec(&control_block_->refcount_)) {
delete ptr_;
}
}
}
// Replaces underlying raw pointer with the one passed in. The reference
// count is set to one (or zero if the pointer is NULL) for the pointer
// being passed in and decremented for the one being replaced.
//
// If you have a compilation error with this code, make sure you aren't
// passing NULL, nullptr, or 0 to this function. Call reset without an
// argument to reset to a null ptr.
template <typename Y>
void reset(Y* p) {
if (p != ptr_) {
shared_ptr<T> tmp(p);
tmp.swap(*this);
}
}
void reset() {
reset(static_cast<T*>(NULL));
}
// Exchanges the contents of this with the contents of r. This function
// supports more efficient swapping since it eliminates the need for a
// temporary shared_ptr object.
void swap(shared_ptr<T>& r) {
using std::swap; // http://go/using-std-swap
swap(ptr_, r.ptr_);
swap(control_block_, r.control_block_);
}
// The following function is useful for gaining access to the underlying
// pointer when a shared_ptr remains in scope so the reference-count is
// known to be > 0 (e.g. for parameter passing).
T* get() const {
return ptr_;
}
T& operator*() const {
return *ptr_;
}
T* operator->() const {
return ptr_;
}
long use_count() const {
return control_block_ ? control_block_->refcount_ : 1;
}
bool unique() const {
return use_count() == 1;
}
private:
// If r is non-empty, initialize *this to share ownership with r,
// increasing the underlying reference count.
// If r is empty, *this remains empty.
// Requires: this is empty, namely this->ptr_ == NULL.
template <typename U>
void Initialize(const shared_ptr<U>& r) {
// This performs a static_cast on r.ptr_ to U*, which is a no-op since it
// is already a U*. So initialization here requires that r.ptr_ is
// implicitly convertible to T*.
InitializeWithStaticCast<U>(r);
}
// Initializes *this as described in Initialize, but additionally performs a
// static_cast from r.ptr_ (V*) to U*.
// NOTE(gfc): We'd need a more general form to support const_pointer_cast and
// dynamic_pointer_cast, but those operations are sufficiently discouraged
// that supporting static_pointer_cast is sufficient.
template <typename U, typename V>
void InitializeWithStaticCast(const shared_ptr<V>& r) {
if (r.control_block_ != NULL) {
RefCountInc(&r.control_block_->refcount_);
ptr_ = static_cast<U*>(r.ptr_);
control_block_ = r.control_block_;
}
}
T* ptr_;
SharedPtrControlBlock* control_block_;
};
} // namespace wvcdm
#endif // WVCDM_CORE_SHARED_PTR_H__

View File

@@ -64,11 +64,11 @@ enum CdmResponseType {
CERT_PROVISIONING_RESPONSE_ERROR_6 = 23,
CERT_PROVISIONING_RESPONSE_ERROR_7 = 24,
CERT_PROVISIONING_RESPONSE_ERROR_8 = 25,
CRYPTO_SESSION_OPEN_ERROR_1 = 26,
CRYPTO_SESSION_OPEN_ERROR_2 = 27,
CRYPTO_SESSION_OPEN_ERROR_3 = 28,
CRYPTO_SESSION_OPEN_ERROR_4 = 29,
CRYPTO_SESSION_OPEN_ERROR_5 = 30,
/* previously CRYPTO_SESSION_OPEN_ERROR_1 = 26 */
/* previously CRYPTO_SESSION_OPEN_ERROR_2 = 27 */
/* previously CRYPTO_SESSION_OPEN_ERROR_3 = 28 */
/* previously CRYPTO_SESSION_OPEN_ERROR_4 = 29 */
/* previously CRYPTO_SESSION_OPEN_ERROR_5 = 30 */
DECRYPT_NOT_READY = 31,
DEVICE_CERTIFICATE_ERROR_1 = 32,
DEVICE_CERTIFICATE_ERROR_2 = 33,
@@ -97,11 +97,11 @@ enum CdmResponseType {
GET_USAGE_INFO_ERROR_3 = 56,
GET_USAGE_INFO_ERROR_4 = 57,
INIT_DATA_NOT_FOUND = 58,
INVALID_CRYPTO_SESSION_1 = 59,
INVALID_CRYPTO_SESSION_2 = 60,
INVALID_CRYPTO_SESSION_3 = 61,
INVALID_CRYPTO_SESSION_4 = 62,
INVALID_CRYPTO_SESSION_5 = 63,
/* previously INVALID_CRYPTO_SESSION_1 = 59 */
/* previously INVALID_CRYPTO_SESSION_2 = 60 */
/* previously INVALID_CRYPTO_SESSION_3 = 61 */
/* previously INVALID_CRYPTO_SESSION_4 = 62 */
/* previously INVALID_CRYPTO_SESSION_5 = 63 */
INVALID_DECRYPT_PARAMETERS_ENG_1 = 64,
INVALID_DECRYPT_PARAMETERS_ENG_2 = 65,
INVALID_DECRYPT_PARAMETERS_ENG_3 = 66,
@@ -110,10 +110,10 @@ enum CdmResponseType {
INVALID_KEY_SYSTEM = 69,
INVALID_LICENSE_RESPONSE = 70,
INVALID_LICENSE_TYPE = 71,
INVALID_PARAMETERS_ENG_1 = 72,
INVALID_PARAMETERS_ENG_2 = 73,
INVALID_PARAMETERS_ENG_3 = 74,
INVALID_PARAMETERS_ENG_4 = 75,
PARAMETER_NULL = 72, /* prior to pi, INVALID_PARAMETERS_ENG_1 = 72 */
/* previously INVALID_PARAMETERS_ENG_2 = 73 */
/* previously INVALID_PARAMETERS_ENG_3 = 74 */
/* previously INVALID_PARAMETERS_ENG_4 = 75 */
INVALID_PARAMETERS_LIC_1 = 76,
INVALID_PARAMETERS_LIC_2 = 77,
INVALID_PROVISIONING_PARAMETERS_1 = 78,
@@ -152,8 +152,8 @@ enum CdmResponseType {
LICENSE_RENEWAL_SIGNING_ERROR = 111,
/* previously RESTORE_OFFLINE_LICENSE_ERROR_1 = 112 */
RESTORE_OFFLINE_LICENSE_ERROR_2 = 113,
SESSION_INIT_ERROR_1 = 114,
SESSION_INIT_ERROR_2 = 115,
NOT_INITIALIZED_ERROR = 114, /* prior to pi, SESSION_INIT_ERROR_1 = 114 */
REINIT_ERROR = 115, /* prior to pi, SESSION_INIT_ERROR_2 = 115 */
/* previously SESSION_INIT_GET_KEYBOX_ERROR = 116 */
SESSION_NOT_FOUND_1 = 117,
SESSION_NOT_FOUND_2 = 118,
@@ -223,13 +223,13 @@ enum CdmResponseType {
KEY_NOT_FOUND_1 = 181,
KEY_NOT_FOUND_2 = 182,
KEY_CONFLICT_1 = 183,
INVALID_PARAMETERS_ENG_6 = 184,
INVALID_PARAMETERS_ENG_7 = 185,
INVALID_PARAMETERS_ENG_8 = 186,
INVALID_PARAMETERS_ENG_9 = 187,
INVALID_PARAMETERS_ENG_10 = 188,
INVALID_PARAMETERS_ENG_11 = 189,
INVALID_PARAMETERS_ENG_12 = 190,
/* previously INVALID_PARAMETERS_ENG_6 = 184 */
/* previously INVALID_PARAMETERS_ENG_7 = 185 */
/* previously INVALID_PARAMETERS_ENG_8 = 186 */
/* previously INVALID_PARAMETERS_ENG_9 = 187 */
/* previously INVALID_PARAMETERS_ENG_10 = 188 */
/* previously INVALID_PARAMETERS_ENG_11 = 189 */
/* previously INVALID_PARAMETERS_ENG_12 = 190 */
SESSION_NOT_FOUND_13 = 191,
SESSION_NOT_FOUND_14 = 192,
SESSION_NOT_FOUND_15 = 193,
@@ -247,9 +247,9 @@ enum CdmResponseType {
INVALID_PARAMETERS_ENG_15 = 205,
INVALID_PARAMETERS_ENG_16 = 206,
/* previously DEVICE_CERTIFICATE_ERROR_5 = 207 */
CERT_PROVISIONING_CLIENT_TOKEN_ERROR_1 = 208,
CERT_PROVISIONING_CLIENT_TOKEN_ERROR_2 = 209,
LICENSING_CLIENT_TOKEN_ERROR_1 = 210,
CLIENT_IDENTIFICATION_TOKEN_ERROR_1 = 208,
CLIENT_IDENTIFICATION_TOKEN_ERROR_2 = 209,
/* previously LICENSING_CLIENT_TOKEN_ERROR_1 = 210 */
ANALOG_OUTPUT_ERROR = 211,
UNKNOWN_SELECT_KEY_ERROR_1 = 212,
UNKNOWN_SELECT_KEY_ERROR_2 = 213,
@@ -317,6 +317,7 @@ enum CdmResponseType {
RELEASE_ALL_USAGE_INFO_ERROR_6 = 275,
RELEASE_ALL_USAGE_INFO_ERROR_7 = 276,
LICENSE_REQUEST_INVALID_SUBLICENSE = 277,
CERT_PROVISIONING_EMPTY_SERVICE_CERTIFICATE = 278,
};
enum CdmKeyStatus {

View File

@@ -86,13 +86,13 @@ CdmEngine::~CdmEngine() {
M_RECORD(&metrics_, cdm_engine_life_span_, life_span_.AsMs());
}
CdmResponseType CdmEngine::SetServiceCertificate(
CdmResponseType CdmEngine::SetProvisioningServiceCertificate(
const std::string& certificate) {
return service_certificate_.Init(certificate);
return provisioning_service_certificate_.Init(certificate);
}
bool CdmEngine::HasServiceCertificate() {
return service_certificate_.has_certificate();
bool CdmEngine::HasProvisioningServiceCertificate() {
return provisioning_service_certificate_.has_certificate();
}
CdmResponseType CdmEngine::OpenSession(
@@ -121,7 +121,7 @@ CdmResponseType CdmEngine::OpenSession(
if (!session_id && !forced_session_id) {
LOGE("CdmEngine::OpenSession: no (forced/)session ID destination provided");
return INVALID_PARAMETERS_ENG_1;
return PARAMETER_NULL;
}
if (forced_session_id) {
@@ -190,7 +190,7 @@ CdmResponseType CdmEngine::OpenKeySetSession(
}
CdmResponseType CdmEngine::CloseSession(const CdmSessionId& session_id) {
LOGV("CdmEngine::CloseSession: %s", session_id.c_str());
LOGI("CdmEngine::CloseSession: %s", session_id.c_str());
if (!session_map_.CloseSession(session_id)) {
LOGE("CdmEngine::CloseSession: session not found = %s", session_id.c_str());
return SESSION_NOT_FOUND_1;
@@ -271,7 +271,7 @@ CdmResponseType CdmEngine::GenerateKeyRequest(
if (!key_request) {
LOGE("CdmEngine::GenerateKeyRequest: output destination provided");
return INVALID_PARAMETERS_ENG_2;
return PARAMETER_NULL;
}
key_request->message.clear();
@@ -318,7 +318,7 @@ CdmResponseType CdmEngine::AddKey(const CdmSessionId& session_id,
if (license_type_release) {
if (!key_set_id) {
LOGE("CdmEngine::AddKey: no key set id provided");
return INVALID_PARAMETERS_ENG_3;
return PARAMETER_NULL;
}
if (key_set_id->empty()) {
@@ -428,7 +428,7 @@ CdmResponseType CdmEngine::GenerateRenewalRequest(
if (!key_request) {
LOGE("CdmEngine::GenerateRenewalRequest: no request destination");
return INVALID_PARAMETERS_ENG_4;
return PARAMETER_NULL;
}
key_request->message.clear();
@@ -494,7 +494,7 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level,
if (!query_response) {
LOGE("CdmEngine::QueryStatus: no query response destination");
return INVALID_PARAMETERS_ENG_6;
return PARAMETER_NULL;
}
if (query_token == QUERY_KEY_SECURITY_LEVEL) {
@@ -598,7 +598,7 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level,
*query_response = max_sessions_stream.str();
} else if (query_token == QUERY_KEY_OEMCRYPTO_API_VERSION) {
uint32_t api_version;
if (crypto_session.GetApiVersion(&api_version)) {
if (!crypto_session.GetApiVersion(&api_version)) {
LOGW("CdmEngine::QueryStatus: GetApiVersion failed");
return UNKNOWN_ERROR;
}
@@ -689,7 +689,7 @@ CdmResponseType CdmEngine::QueryKeyAllowedUsage(const CdmSessionId& session_id,
LOGI("CdmEngine::QueryKeyAllowedUsage");
if (!key_usage) {
LOGE("CdmEngine::QueryKeyAllowedUsage: no response destination");
return INVALID_PARAMETERS_ENG_12;
return PARAMETER_NULL;
}
shared_ptr<CdmSession> session;
if (!session_map_.FindSession(session_id, &session)) {
@@ -708,7 +708,7 @@ CdmResponseType CdmEngine::QueryKeyAllowedUsage(const std::string& key_id,
bool found = false;
if (!key_usage) {
LOGE("CdmEngine::QueryKeyAllowedUsage: no response destination");
return INVALID_PARAMETERS_ENG_7;
return PARAMETER_NULL;
}
key_usage->Clear();
@@ -774,8 +774,10 @@ CdmResponseType CdmEngine::GetProvisioningRequest(
if (NULL == cert_provisioning_.get()) {
cert_provisioning_.reset(
new CertificateProvisioning(metrics_.GetCryptoMetrics(),
&service_certificate_));
new CertificateProvisioning(metrics_.GetCryptoMetrics()));
CdmResponseType status = cert_provisioning_->Init(
provisioning_service_certificate_.certificate());
if (status != NO_ERROR) return status;
}
CdmResponseType ret = cert_provisioning_->GetProvisioningRequest(
cert_provisioning_requested_security_level_, cert_type, cert_authority,
@@ -991,7 +993,7 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
}
if (!usage_info) {
LOGE("CdmEngine::GetUsageInfo: no usage info destination");
return INVALID_PARAMETERS_ENG_8;
return PARAMETER_NULL;
}
usage_property_set_->set_security_level(kLevelDefault);
usage_property_set_->set_app_id(app_id);
@@ -1063,7 +1065,7 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
CdmResponseType status = UNKNOWN_ERROR;
if (!usage_info) {
LOGE("CdmEngine::GetUsageInfo: no usage info destination");
return INVALID_PARAMETERS_ENG_9;
return PARAMETER_NULL;
}
do {
status = GetUsageInfo(app_id, security_level, usage_info);
@@ -1115,7 +1117,7 @@ CdmResponseType CdmEngine::GetUsageInfo(const std::string& app_id,
if (!usage_info) {
LOGE("CdmEngine::GetUsageInfo: no usage info destination");
return INVALID_PARAMETERS_ENG_10;
return PARAMETER_NULL;
}
if (0 == usage_data.size()) {
usage_info->resize(0);
@@ -1307,7 +1309,7 @@ CdmResponseType CdmEngine::LoadUsageSession(const CdmKeySetId& key_set_id,
if (!release_message) {
LOGE("CdmEngine::LoadUsageSession: no release message destination");
return INVALID_PARAMETERS_ENG_11;
return PARAMETER_NULL;
}
DeviceFiles handle(file_system_);
@@ -1420,6 +1422,10 @@ CdmResponseType CdmEngine::GenericEncrypt(
const std::string& session_id, const std::string& in_buffer,
const std::string& key_id, const std::string& iv,
CdmEncryptionAlgorithm algorithm, std::string* out_buffer) {
if (out_buffer == NULL) {
LOGE("CdmEngine::GenericEncrypt: no out_buffer provided");
return PARAMETER_NULL;
}
shared_ptr<CdmSession> session;
if (!session_map_.FindSession(session_id, &session)) {
LOGE("CdmEngine::GenericEncrypt: session_id not found = %s ",
@@ -1434,6 +1440,10 @@ CdmResponseType CdmEngine::GenericDecrypt(
const std::string& key_id, const std::string& iv,
CdmEncryptionAlgorithm algorithm,
std::string* out_buffer) {
if (out_buffer == NULL) {
LOGE("CdmEngine::GenericDecrypt: no out_buffer provided");
return PARAMETER_NULL;
}
shared_ptr<CdmSession> session;
if (!session_map_.FindSession(session_id, &session)) {
LOGE("CdmEngine::GenericDecrypt: session_id not found = %s ",
@@ -1447,6 +1457,10 @@ CdmResponseType CdmEngine::GenericSign(
const std::string& session_id, const std::string& message,
const std::string& key_id, CdmSigningAlgorithm algorithm,
std::string* signature) {
if (signature == NULL) {
LOGE("CdmEngine::GenericSign: no signature buffer provided");
return PARAMETER_NULL;
}
shared_ptr<CdmSession> session;
if (!session_map_.FindSession(session_id, &session)) {
LOGE("CdmEngine::GenericSign: session_id not found = %s ",

View File

@@ -74,7 +74,7 @@ CdmResponseType CdmSession::Init(
const CdmSessionId* forced_session_id, WvCdmEventListener* event_listener) {
if (initialized_) {
LOGE("CdmSession::Init: Failed due to previous initialization");
return SESSION_INIT_ERROR_2;
return REINIT_ERROR;
}
if (cdm_client_property_set &&
@@ -186,6 +186,10 @@ CdmResponseType CdmSession::Init(
CdmResponseType CdmSession::RestoreOfflineSession(
const CdmKeySetId& key_set_id, const CdmLicenseType license_type) {
if (!initialized_) {
LOGE("CdmSession::RestoreOfflineSession: not initialized");
return NOT_INITIALIZED_ERROR;
}
if (!key_set_id_.empty()) {
file_handle_->UnreserveLicenseId(key_set_id_);
}
@@ -270,6 +274,10 @@ CdmResponseType CdmSession::RestoreOfflineSession(
CdmResponseType CdmSession::RestoreUsageSession(
const DeviceFiles::CdmUsageData& usage_data) {
if (!initialized_) {
LOGE("CdmSession::RestoreUsageSession: not initialized");
return NOT_INITIALIZED_ERROR;
}
if (!key_set_id_.empty()) {
file_handle_->UnreserveLicenseId(key_set_id_);
}
@@ -321,19 +329,14 @@ CdmResponseType CdmSession::GenerateKeyRequest(
const CdmAppParameterMap& app_parameters,
CdmKeyRequest* key_request) {
if (crypto_session_.get() == NULL) {
LOGW("CdmSession::GenerateKeyRequest: Invalid crypto session");
return INVALID_CRYPTO_SESSION_1;
}
if (!crypto_session_->IsOpen()) {
LOGW("CdmSession::GenerateKeyRequest: Crypto session not open");
return CRYPTO_SESSION_OPEN_ERROR_1;
if (!initialized_) {
LOGE("CdmSession::GenerateKeyRequest: not initialized");
return NOT_INITIALIZED_ERROR;
}
if (!key_request) {
LOGE("CdmSession::GenerateKeyRequest: No output destination provided");
return INVALID_PARAMETERS_ENG_5;
return PARAMETER_NULL;
}
switch (license_type) {
@@ -409,14 +412,9 @@ CdmResponseType CdmSession::GenerateKeyRequest(
// AddKey() - Accept license response and extract key info.
CdmResponseType CdmSession::AddKey(const CdmKeyResponse& key_response) {
if (crypto_session_.get() == NULL) {
LOGW("CdmSession::AddKey: Invalid crypto session");
return INVALID_CRYPTO_SESSION_2;
}
if (!crypto_session_->IsOpen()) {
LOGW("CdmSession::AddKey: Crypto session not open");
return CRYPTO_SESSION_OPEN_ERROR_2;
if (!initialized_) {
LOGE("CdmSession::AddKey: not initialized");
return NOT_INITIALIZED_ERROR;
}
if (is_release_) {
@@ -490,14 +488,9 @@ CdmResponseType CdmSession::AddKey(const CdmKeyResponse& key_response) {
}
CdmResponseType CdmSession::QueryStatus(CdmQueryMap* query_response) {
if (crypto_session_.get() == NULL) {
LOGE("CdmSession::QueryStatus: Invalid crypto session");
return INVALID_CRYPTO_SESSION_3;
}
if (!crypto_session_->IsOpen()) {
LOGE("CdmSession::QueryStatus: Crypto session not open");
return CRYPTO_SESSION_OPEN_ERROR_3;
if (!initialized_) {
LOGE("CdmSession::QueryStatus: not initialized");
return NOT_INITIALIZED_ERROR;
}
switch (security_level_) {
@@ -535,14 +528,9 @@ CdmResponseType CdmSession::QueryKeyAllowedUsage(
CdmResponseType CdmSession::QueryOemCryptoSessionId(
CdmQueryMap* query_response) {
if (crypto_session_.get() == NULL) {
LOGW("CdmSession::QueryOemCryptoSessionId: Invalid crypto session");
return INVALID_CRYPTO_SESSION_4;
}
if (!crypto_session_->IsOpen()) {
LOGW("CdmSession::QueryOemCryptoSessionId: Crypto session not open");
return CRYPTO_SESSION_OPEN_ERROR_4;
if (!initialized_) {
LOGE("CdmSession::QueryOemCryptoSessionId: not initialized");
return NOT_INITIALIZED_ERROR;
}
std::stringstream ss;
@@ -553,14 +541,9 @@ CdmResponseType CdmSession::QueryOemCryptoSessionId(
// Decrypt() - Accept encrypted buffer and return decrypted data.
CdmResponseType CdmSession::Decrypt(const CdmDecryptionParameters& params) {
if (crypto_session_.get() == NULL) {
LOGW("CdmSession::Decrypt: Invalid crypto session");
return INVALID_CRYPTO_SESSION_5;
}
if (!crypto_session_->IsOpen()) {
LOGW("CdmSession::Decrypt: Crypto session not open");
return DECRYPT_NOT_READY;
if (!initialized_) {
LOGE("CdmSession::Decrypt: not initialized");
return NOT_INITIALIZED_ERROR;
}
// Playback may not begin until either the start time passes or the license
@@ -601,6 +584,10 @@ CdmResponseType CdmSession::Decrypt(const CdmDecryptionParameters& params) {
// session keys.
CdmResponseType CdmSession::GenerateRenewalRequest(
CdmKeyRequest* key_request) {
if (!initialized_) {
LOGE("CdmSession::GenerateRenewalRequest: not initialized");
return NOT_INITIALIZED_ERROR;
}
CdmResponseType status = license_parser_->PrepareKeyUpdateRequest(
true, app_parameters_, NULL, &key_request->message, &key_request->url);
@@ -616,6 +603,10 @@ CdmResponseType CdmSession::GenerateRenewalRequest(
// RenewKey() - Accept renewal response and update key info.
CdmResponseType CdmSession::RenewKey(const CdmKeyResponse& key_response) {
if (!initialized_) {
LOGE("CdmSession::RenewKey: not initialized");
return NOT_INITIALIZED_ERROR;
}
CdmResponseType sts =
license_parser_->HandleKeyUpdateResponse(true, key_response);
if (sts != KEY_ADDED) return (sts == KEY_ERROR) ? RENEW_KEY_ERROR_1 : sts;
@@ -630,6 +621,10 @@ CdmResponseType CdmSession::RenewKey(const CdmKeyResponse& key_response) {
CdmResponseType CdmSession::GenerateReleaseRequest(
CdmKeyRequest* key_request) {
if (!initialized_) {
LOGE("CdmSession::GenerateReleaseRequest: not initialized");
return NOT_INITIALIZED_ERROR;
}
is_release_ = true;
CdmResponseType status = license_parser_->PrepareKeyUpdateRequest(
false, app_parameters_, usage_table_header_ == NULL ? NULL : this,
@@ -664,6 +659,10 @@ CdmResponseType CdmSession::GenerateReleaseRequest(
// ReleaseKey() - Accept release response and release license.
CdmResponseType CdmSession::ReleaseKey(const CdmKeyResponse& key_response) {
if (!initialized_) {
LOGE("CdmSession::ReleaseKey: not initialized");
return NOT_INITIALIZED_ERROR;
}
CdmResponseType sts =
license_parser_->HandleKeyUpdateResponse(false, key_response);
if (sts != KEY_ADDED) return (sts == KEY_ERROR) ? RELEASE_KEY_ERROR : sts;
@@ -681,6 +680,10 @@ CdmResponseType CdmSession::ReleaseKey(const CdmKeyResponse& key_response) {
}
CdmResponseType CdmSession::DeleteUsageEntry(uint32_t usage_entry_number) {
if (!initialized_) {
LOGE("CdmSession::DeleteUsageEntry: not initialized");
return NOT_INITIALIZED_ERROR;
}
if (usage_support_type_ != kUsageEntrySupport) {
LOGE("CdmSession::DeleteUsageEntry: Unexpected usage type supported: %d",
usage_support_type_);
@@ -919,7 +922,7 @@ CdmResponseType CdmSession::GenericEncrypt(const std::string& in_buffer,
std::string* out_buffer) {
if (!out_buffer) {
LOGE("CdmSession::GenericEncrypt: No output destination provided");
return INVALID_PARAMETERS_ENG_6;
return PARAMETER_NULL;
}
CdmResponseType sts;
M_TIME(
@@ -944,7 +947,7 @@ CdmResponseType CdmSession::GenericDecrypt(const std::string& in_buffer,
std::string* out_buffer) {
if (!out_buffer) {
LOGE("CdmSession::GenericDecrypt: No output destination provided");
return INVALID_PARAMETERS_ENG_7;
return PARAMETER_NULL;
}
CdmResponseType sts;
M_TIME(
@@ -968,7 +971,7 @@ CdmResponseType CdmSession::GenericSign(const std::string& message,
std::string* signature) {
if (!signature) {
LOGE("CdmSession::GenericSign: No output destination provided");
return INVALID_PARAMETERS_ENG_8;
return PARAMETER_NULL;
}
CdmResponseType sts;
M_TIME(

View File

@@ -1,6 +1,7 @@
// Copyright 2013 Google Inc. All Rights Reserved.
#include "certificate_provisioning.h"
#include "client_identification.h"
#include "device_files.h"
#include "file_store.h"
#include "license_protocol.pb.h"
@@ -20,6 +21,33 @@ const std::string kProvisioningServerUrl =
"certificateprovisioning/v1/devicecertificates/create"
"?key=AIzaSyB-5OLKTx2iU5mko18DfdwK5611JIjbUhE";
// NOTE: Provider ID = staging.google.com
const std::string kCpProductionServiceCertificate = wvcdm::a2bs_hex(
"0ABF020803121028703454C008F63618ADE7443DB6C4C8188BE7F9900522"
"8E023082010A0282010100B52112B8D05D023FCC5D95E2C251C1C649B417"
"7CD8D2BEEF355BB06743DE661E3D2ABC3182B79946D55FDC08DFE9540781"
"5E9A6274B322A2C7F5E067BB5F0AC07A89D45AEA94B2516F075B66EF811D"
"0D26E1B9A6B894F2B9857962AA171C4F66630D3E4C602718897F5E1EF9B6"
"AAF5AD4DBA2A7E14176DF134A1D3185B5A218AC05A4C41F081EFFF80A3A0"
"40C50B09BBC740EEDCD8F14D675A91980F92CA7DDC646A06ADAD5101F74A"
"0E498CC01F00532BAC217850BD905E90923656B7DFEFEF42486767F33EF6"
"283D4F4254AB72589390BEE55808F1D668080D45D893C2BCA2F74D60A0C0"
"D0A0993CEF01604703334C3638139486BC9DAF24FD67A07F9AD943020301"
"00013A1273746167696E672E676F6F676C652E636F6D128003983E303526"
"75F40BA715FC249BDAE5D4AC7249A2666521E43655739529721FF880E0AA"
"EFC5E27BC980DAEADABF3FC386D084A02C82537848CC753FF497B011A7DA"
"97788A00E2AA6B84CD7D71C07A48EBF61602CCA5A3F32030A7295C30DA91"
"5B91DC18B9BC9593B8DE8BB50F0DEDC12938B8E9E039CDDE18FA82E81BB0"
"32630FE955D85A566CE154300BF6D4C1BD126966356B287D657B18CE63D0"
"EFD45FC5269E97EAB11CB563E55643B26FF49F109C2101AFCAF35B832F28"
"8F0D9D45960E259E85FB5D24DBD2CF82764C5DD9BF727EFBE9C861F86932"
"1F6ADE18905F4D92F9A6DA6536DB8475871D168E870BB2303CF70C6E9784"
"C93D2DE845AD8262BE7E0D4E2E4A0759CEF82D109D2592C72429F8C01742"
"BAE2B3DECADBC33C3E5F4BAF5E16ECB74EADBAFCB7C6705F7A9E3B6F3940"
"383F9C5116D202A20C9229EE969C2519718303B50D0130C3352E06B014D8"
"38540F8A0C227C0011E0F5B38E4E298ED2CB301EB4564965F55C5D79757A"
"250A4EB9C84AB3E6539F6B6FDF56899EA29914");
/*
* Provisioning response is a base64-encoded protobuf, optionally within a
* JSON wrapper. If the JSON wrapper is present, extract the embedded response
@@ -70,34 +98,20 @@ void ExtractAndDecodeSignedMessage(const std::string& provisioning_response,
namespace wvcdm {
// Protobuf generated classes.
using video_widevine::ClientIdentification;
using video_widevine::ClientIdentification_ClientCapabilities;
using video_widevine::ClientIdentification_NameValue;
using video_widevine::EncryptedClientIdentification;
using video_widevine::ProvisioningOptions;
using video_widevine::ProvisioningRequest;
using video_widevine::ProvisioningResponse;
using video_widevine::SignedProvisioningMessage;
/*
* Return the ClientIdentification message token type for provisioning request.
* NOTE: a DRM Cert should never be presented to the provisioning server.
*/
bool CertificateProvisioning::GetProvisioningTokenType(
ClientIdentification::TokenType* token_type) {
CdmClientTokenType token = crypto_session_.GetPreProvisionTokenType();
switch (token) {
case kClientTokenKeybox:
*token_type = ClientIdentification::KEYBOX;
return true;
case kClientTokenOemCert:
*token_type = ClientIdentification::OEM_DEVICE_CERTIFICATE;
return true;
case kClientTokenDrmCert:
default:
// shouldn't happen
LOGE("CertificateProvisioning::GetProvisioningTokenType: unexpected "
"provisioning type: %d", token);
return false;
}
CdmResponseType CertificateProvisioning::Init(
const std::string& service_certificate) {
std::string certificate = service_certificate.empty() ?
kCpProductionServiceCertificate : service_certificate;
return service_certificate_->Init(certificate);
}
/*
@@ -177,36 +191,32 @@ CdmResponseType CertificateProvisioning::GetProvisioningRequest(
// Prepare device provisioning request.
ProvisioningRequest provisioning_request;
std::string token;
ClientIdentification* client_id = provisioning_request.mutable_client_id();
ClientIdentification::TokenType token_type;
if (!GetProvisioningTokenType(&token_type)) {
LOGE("GetProvisioningRequest: bad token type");
return CERT_PROVISIONING_CLIENT_TOKEN_ERROR_1;
}
if (!crypto_session_.GetProvisioningToken(&token)) {
LOGE("GetProvisioningRequest: failure getting provisioning token");
return CERT_PROVISIONING_CLIENT_TOKEN_ERROR_2;
}
client_id->set_token(token);
client_id->set_type(token_type);
wvcdm::ClientIdentification id;
status = id.Init(&crypto_session_);
if (status != NO_ERROR) return status;
#if 0 // TODO(gmorgan) Encrypt ClientIdentification. Pending Design.
if (service_certificate_->has_certificate()) {
EncryptedClientIdentification* encrypted_client_id =
provisioning_request.mutable_encrypted_client_id();
CdmResponseType status;
status = service_certificate_->EncryptClientId(&crypto_session_, client_id,
encrypted_client_id);
if (status == NO_ERROR) {
provisioning_request.clear_client_id();
} else {
provisioning_request.clear_encrypted_client_id();
}
return status;
video_widevine::ClientIdentification* client_id =
provisioning_request.mutable_client_id();
CdmAppParameterMap app_parameter;
status = id.Prepare(app_parameter, client_id);
if (status != NO_ERROR) return status;
if (!service_certificate_->has_certificate()) {
LOGE("CertificateProvisioning::GetProvisioningRequest: Service Certificate "
"not staged");
return CERT_PROVISIONING_EMPTY_SERVICE_CERTIFICATE;
}
#endif
// TODO(rfrias): Uncomment when b/69427217 is addressed
/*
EncryptedClientIdentification* encrypted_client_id =
provisioning_request->mutable_encrypted_client_id();
CdmResponseType status =
service_certificate_->EncryptClientId(&crypto_session_, client_id,
encrypted_client_id);
provisioning_request->clear_client_id();
*/
uint32_t nonce;
if (!crypto_session_.GenerateNonce(&nonce)) {

View File

@@ -0,0 +1,259 @@
// Copyright 2017 Google Inc. All Rights Reserved.
#include "client_identification.h"
#include "crypto_session.h"
#include "license_protocol.pb.h"
#include "log.h"
#include "properties.h"
#include "string_conversions.h"
namespace {
const std::string kKeyCompanyName = "company_name";
const std::string kKeyModelName = "model_name";
const std::string kKeyArchitectureName = "architecture_name";
const std::string kKeyDeviceName = "device_name";
const std::string kKeyProductName = "product_name";
const std::string kKeyBuildInfo = "build_info";
const std::string kKeyDeviceId = "device_id";
const std::string kKeyWvCdmVersion = "widevine_cdm_version";
const std::string kKeyOemCryptoSecurityPatchLevel =
"oem_crypto_security_patch_level";
} // unnamed namespace
namespace wvcdm {
// Protobuf generated classes.
using video_widevine::ClientIdentification_ClientCapabilities;
using video_widevine::ClientIdentification_NameValue;
using video_widevine::EncryptedClientIdentification;
using video_widevine::ProvisioningOptions;
using video_widevine::ProvisioningRequest;
using video_widevine::ProvisioningResponse;
using video_widevine::SignedProvisioningMessage;
CdmResponseType ClientIdentification::Init(CryptoSession* crypto_session) {
if (crypto_session == NULL) {
LOGE("ClientIdentification::Init: crypto_session not provided");
return PARAMETER_NULL;
}
is_license_request_ = false;
crypto_session_ = crypto_session;
return NO_ERROR;
}
CdmResponseType ClientIdentification::Init(const std::string& client_token,
const std::string& device_id,
CryptoSession* crypto_session) {
if (crypto_session == NULL) {
LOGE("ClientIdentification::Init: crypto_session not provided");
return PARAMETER_NULL;
}
if (client_token.empty()) {
LOGE("ClientIdentification::Init: crypto_session not provided");
return PARAMETER_NULL;
}
is_license_request_ = true;
device_id_ = device_id;
client_token_ = client_token;
crypto_session_ = crypto_session;
return NO_ERROR;
}
/*
* Return the ClientIdentification message token type for provisioning request.
* NOTE: a DRM Cert should never be presented to the provisioning server.
*/
CdmResponseType ClientIdentification::Prepare(
const CdmAppParameterMap& app_parameters,
video_widevine::ClientIdentification* client_id) {
if (is_license_request_) {
client_id->set_type(
video_widevine::ClientIdentification::DRM_DEVICE_CERTIFICATE);
client_id->set_token(client_token_);
} else {
video_widevine::ClientIdentification::TokenType token_type;
if (!GetProvisioningTokenType(&token_type)) {
LOGE("ClientIdentification::Prepare: failure getting provisioning token "
"type");
return CLIENT_IDENTIFICATION_TOKEN_ERROR_1;
}
client_id->set_type(token_type);
std::string token;
if (!crypto_session_->GetProvisioningToken(&token)) {
LOGE("ClientIdentification::Prepare: failure getting provisioning token");
return CLIENT_IDENTIFICATION_TOKEN_ERROR_2;
}
client_id->set_token(token);
}
ClientIdentification_NameValue* client_info;
if (is_license_request_) {
CdmAppParameterMap::const_iterator iter;
for (iter = app_parameters.begin(); iter != app_parameters.end(); iter++) {
client_info = client_id->add_client_info();
client_info->set_name(iter->first);
client_info->set_value(iter->second);
}
}
std::string value;
if (Properties::GetCompanyName(&value)) {
client_info = client_id->add_client_info();
client_info->set_name(kKeyCompanyName);
client_info->set_value(value);
}
if (Properties::GetModelName(&value)) {
client_info = client_id->add_client_info();
client_info->set_name(kKeyModelName);
client_info->set_value(value);
}
if (Properties::GetArchitectureName(&value)) {
client_info = client_id->add_client_info();
client_info->set_name(kKeyArchitectureName);
client_info->set_value(value);
}
if (Properties::GetDeviceName(&value)) {
client_info = client_id->add_client_info();
client_info->set_name(kKeyDeviceName);
client_info->set_value(value);
}
if (Properties::GetProductName(&value)) {
client_info = client_id->add_client_info();
client_info->set_name(kKeyProductName);
client_info->set_value(value);
}
if (Properties::GetBuildInfo(&value)) {
client_info = client_id->add_client_info();
client_info->set_name(kKeyBuildInfo);
client_info->set_value(value);
}
if (!device_id_.empty()) {
client_info = client_id->add_client_info();
client_info->set_name(kKeyDeviceId);
client_info->set_value(b2a_hex(device_id_));
} else if (crypto_session_->GetInternalDeviceUniqueId(&value)) {
client_info = client_id->add_client_info();
client_info->set_name(kKeyDeviceId);
client_info->set_value(value);
}
if (Properties::GetWVCdmVersion(&value)) {
client_info = client_id->add_client_info();
client_info->set_name(kKeyWvCdmVersion);
client_info->set_value(value);
}
client_info = client_id->add_client_info();
client_info->set_name(kKeyOemCryptoSecurityPatchLevel);
std::stringstream ss;
ss << (uint32_t)crypto_session_->GetSecurityPatchLevel();
client_info->set_value(ss.str());
ClientIdentification_ClientCapabilities* client_capabilities =
client_id->mutable_client_capabilities();
if (is_license_request_) {
bool supports_usage_information;
if (crypto_session_->UsageInformationSupport(&supports_usage_information)) {
client_capabilities->set_session_token(supports_usage_information);
}
client_capabilities->set_anti_rollback_usage_table(
crypto_session_->IsAntiRollbackHwPresent());
}
uint32_t api_version = 0;
if (crypto_session_->GetApiVersion(&api_version)) {
client_capabilities->set_oem_crypto_api_version(api_version);
}
if (is_license_request_) {
CryptoSession::HdcpCapability current_version, max_version;
if (crypto_session_->GetHdcpCapabilities(&current_version, &max_version)) {
switch (max_version) {
case HDCP_NONE:
client_capabilities->set_max_hdcp_version(
video_widevine::
ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_NONE);
break;
case HDCP_V1:
client_capabilities->set_max_hdcp_version(
video_widevine::
ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_V1);
break;
case HDCP_V2:
client_capabilities->set_max_hdcp_version(
video_widevine::
ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_V2);
break;
case HDCP_V2_1:
client_capabilities->set_max_hdcp_version(
video_widevine::
ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_V2_1);
break;
case HDCP_V2_2:
client_capabilities->set_max_hdcp_version(
video_widevine::
ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_V2_2);
break;
case HDCP_NO_DIGITAL_OUTPUT:
client_capabilities->set_max_hdcp_version(
video_widevine::
ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_NO_DIGITAL_OUTPUT);
break;
default:
LOGW(
"ClientIdentification::PrepareClientId: unexpected HDCP max "
"capability version %d", max_version);
}
}
}
CryptoSession::SupportedCertificateTypes supported_certs;
if (crypto_session_->GetSupportedCertificateTypes(&supported_certs)) {
if (supported_certs.rsa_2048_bit) {
client_capabilities->add_supported_certificate_key_type(
video_widevine::
ClientIdentification_ClientCapabilities_CertificateKeyType_RSA_2048);
}
if (supported_certs.rsa_3072_bit) {
client_capabilities->add_supported_certificate_key_type(
video_widevine::
ClientIdentification_ClientCapabilities_CertificateKeyType_RSA_3072);
}
}
if (is_license_request_) {
client_capabilities->set_can_update_srm(
crypto_session_->IsSrmUpdateSupported());
uint16_t srm_version;
if (crypto_session_->GetSrmVersion(&srm_version))
client_capabilities->set_srm_version(srm_version);
}
return NO_ERROR;
}
bool ClientIdentification::GetProvisioningTokenType(
video_widevine::ClientIdentification::TokenType* token_type) {
CdmClientTokenType token = crypto_session_->GetPreProvisionTokenType();
switch (token) {
case kClientTokenKeybox:
*token_type = video_widevine::ClientIdentification::KEYBOX;
return true;
case kClientTokenOemCert:
*token_type =
video_widevine::ClientIdentification::OEM_DEVICE_CERTIFICATE;
return true;
case kClientTokenDrmCert:
default:
// shouldn't happen
LOGE("CertificateProvisioning::GetProvisioningTokenType: unexpected "
"provisioning type: %d", token);
return false;
}
}
} // namespace wvcdm

View File

@@ -82,12 +82,12 @@ const size_t kOemCryptoApiVersionSupportsBigUsageTables = 13;
const int kExtensionOidSize = 64;
const char* const kWidevineSystemIdExtensionOid = "1.3.6.1.4.1.11129.4.1.1";
// Helpers for working with OpenSSL / BoringSSL
// Helpers for working with BoringSSL
template <typename T, void (*func)(T*)>
class openssl_ptr {
class boringssl_ptr {
public:
explicit openssl_ptr(T* p = NULL) : ptr_(p) {}
~openssl_ptr() {
explicit boringssl_ptr(T* p = NULL) : ptr_(p) {}
~boringssl_ptr() {
if (ptr_) func(ptr_);
}
T& operator*() const { return *ptr_; }
@@ -96,13 +96,13 @@ class openssl_ptr {
private:
T* ptr_;
CORE_DISALLOW_COPY_AND_ASSIGN(openssl_ptr);
CORE_DISALLOW_COPY_AND_ASSIGN(boringssl_ptr);
};
#ifdef OPENSSL_IS_BORINGSSL
void DeleteX509Stack(STACK_OF(X509)* stack) {
sk_X509_pop_free(stack, X509_free);
}
#endif
}
namespace wvcdm {
@@ -722,7 +722,7 @@ CryptoSession::CryptoSession(metrics::CryptoMetrics* metrics)
is_destination_buffer_type_valid_(false),
requested_security_level_(kLevelDefault),
is_usage_support_type_valid_(false),
usage_support_type_(kNonSecureUsageSupport),
usage_support_type_(kUnknownUsageSupport),
usage_table_header_(NULL),
request_id_base_(0),
cipher_mode_(kCipherModeCtr) {
@@ -811,6 +811,10 @@ void CryptoSession::Terminate() {
}
bool CryptoSession::GetTokenFromKeybox(std::string* token) {
if (token == NULL) {
LOGE("CryptoSession::GetTokenFromKeybox: token not provided");
return false;
}
std::string temp_buffer(KEYBOX_KEY_DATA_SIZE, '\0');
// lock is held by caller
size_t buf_size = temp_buffer.size();
@@ -974,6 +978,10 @@ bool CryptoSession::GetInternalDeviceUniqueId(std::string* device_id) {
}
bool CryptoSession::GetExternalDeviceUniqueId(std::string* device_id) {
if (device_id == NULL) {
LOGE("CryptoSession::GetExternalDeviceUniqueId: device_id not provided");
return false;
}
std::string temp;
if (!GetInternalDeviceUniqueId(&temp)) return false;
@@ -1066,9 +1074,8 @@ bool CryptoSession::GetSystemId(uint32_t* system_id) {
bool CryptoSession::ExtractSystemIdFromOemCert(const std::string& oem_cert,
uint32_t* system_id) {
// Load the certificate chain into an OpenSSL X509 Stack
#ifdef OPENSSL_IS_BORINGSSL
const openssl_ptr<STACK_OF(X509), DeleteX509Stack> x509_stack(
// Load the certificate chain into a BoringSSL X509 Stack
const boringssl_ptr<STACK_OF(X509), DeleteX509Stack> x509_stack(
sk_X509_new_null());
if (x509_stack.get() == NULL) {
LOGE("CryptoSession::GetSystemId: Unable to allocate X509 Stack.");
@@ -1084,27 +1091,6 @@ bool CryptoSession::ExtractSystemIdFromOemCert(const std::string& oem_cert,
}
STACK_OF(X509)* certs = x509_stack.get();
#else
openssl_ptr<BIO, BIO_vfree> bio(
// This const_cast is safe because BIO_new_mem_buf() creates a read-only
// buffer from the data given and does not mutate it. Its first parameter
// could be const, but it isn't.
BIO_new_mem_buf(
reinterpret_cast<uint8_t*>(const_cast<char*>(oem_cert.data())),
oem_cert.size()));
if (bio.get() == NULL) {
LOGE("CryptoSession::GetSystemId: Unable to allocate BIO buffer.");
return false;
}
openssl_ptr<PKCS7, PKCS7_free> cert(d2i_PKCS7_bio(bio.get(), NULL));
if (cert.get() == NULL) {
LOGE("CryptoSession::GetSystemId: Unable to allocate PKCS#7 buffer.");
return false;
}
STACK_OF(X509)* certs = cert->d.sign->cert;
#endif
// Get the Widevine intermediate cert from the stack
if (sk_X509_num(certs) != 2) {
@@ -2325,7 +2311,10 @@ CdmResponseType CryptoSession::GenericEncrypt(const std::string& in_buffer,
CdmEncryptionAlgorithm algorithm,
std::string* out_buffer) {
LOGV("GenericEncrypt: id=%ld", (uint32_t)oec_session_id_);
if (!out_buffer) return INVALID_PARAMETERS_ENG_9;
if (!out_buffer) {
LOGE("CryptoSession::GenericEncrypt: out_buffer not provided");
return PARAMETER_NULL;
}
OEMCrypto_Algorithm oec_algorithm = GenericEncryptionAlgorithm(algorithm);
if (iv.size() != GenericEncryptionBlockSize(algorithm) ||
@@ -2375,7 +2364,10 @@ CdmResponseType CryptoSession::GenericDecrypt(const std::string& in_buffer,
CdmEncryptionAlgorithm algorithm,
std::string* out_buffer) {
LOGV("GenericDecrypt: id=%ld", (uint32_t)oec_session_id_);
if (!out_buffer) return INVALID_PARAMETERS_ENG_10;
if (!out_buffer) {
LOGE("CryptoSession::GenericDecrypt: out_buffer not provided");
return PARAMETER_NULL;
}
OEMCrypto_Algorithm oec_algorithm = GenericEncryptionAlgorithm(algorithm);
if (iv.size() != GenericEncryptionBlockSize(algorithm) ||
@@ -2425,8 +2417,8 @@ CdmResponseType CryptoSession::GenericSign(const std::string& message,
std::string* signature) {
LOGV("GenericSign: id=%ld", (uint32_t)oec_session_id_);
if (!signature) {
LOGE("GenerateSign: null signature string");
return INVALID_PARAMETERS_ENG_11;
LOGE("CryptoSession::GenericSign: signature not provided");
return PARAMETER_NULL;
}
OEMCrypto_Algorithm oec_algorithm = GenericSigningAlgorithm(algorithm);

View File

@@ -8,6 +8,7 @@
#include "clock.h"
#include "cdm_session.h"
#include "client_identification.h"
#include "crypto_key.h"
#include "crypto_session.h"
#include "device_files.h"
@@ -20,17 +21,6 @@
#include "wv_cdm_constants.h"
namespace {
const std::string kCompanyNameKey = "company_name";
const std::string kModelNameKey = "model_name";
const std::string kArchitectureNameKey = "architecture_name";
const std::string kDeviceNameKey = "device_name";
const std::string kProductNameKey = "product_name";
const std::string kBuildInfoKey = "build_info";
const std::string kDeviceIdKey = "device_id";
const std::string kWVCdmVersionKey = "widevine_cdm_version";
const std::string kOemCryptoSecurityPatchLevelKey =
"oem_crypto_security_patch_level";
const uint32_t kFourCcCbc1 = 0x63626331;
const uint32_t kFourCcCbcs = 0x63626373;
const uint32_t kFourCcLittleEndianCbc1 = 0x31636263;
@@ -42,7 +32,6 @@ const uint32_t kFourCcCenc = 0x63656e63;
namespace wvcdm {
// Protobuf generated classes.
using video_widevine::ClientIdentification;
using video_widevine::ClientIdentification_ClientCapabilities;
using video_widevine::ClientIdentification_NameValue;
using video_widevine::DrmDeviceCertificate;
@@ -986,169 +975,17 @@ CdmResponseType CdmLicense::HandleKeyErrorResponse(
}
}
// Return the ClientIdentification message token type for license request.
// NOTE: an OEM Cert should never be presented to the provisioning server.
bool CdmLicense::GetClientTokenType(
ClientIdentification::TokenType* token_type) {
switch (client_token_type_) {
case kClientTokenKeybox:
*token_type = ClientIdentification::KEYBOX;
return true;
case kClientTokenDrmCert:
*token_type = ClientIdentification::DRM_DEVICE_CERTIFICATE;
return true;
case kClientTokenOemCert:
default:
// shouldn't happen
LOGE("GetClientTokenType: BAD TOKEN TYPE");
return false;
}
}
CdmResponseType CdmLicense::PrepareClientId(
const CdmAppParameterMap& app_parameters, LicenseRequest* license_request) {
ClientIdentification* client_id = license_request->mutable_client_id();
ClientIdentification::TokenType token_type;
if (!GetClientTokenType(&token_type)) {
return LICENSING_CLIENT_TOKEN_ERROR_1;
}
client_id->set_type(token_type);
client_id->set_token(client_token_);
wvcdm::ClientIdentification id;
CdmResponseType status = id.Init(client_token_, device_id_, crypto_session_);
if (status != NO_ERROR) return status;
ClientIdentification_NameValue* client_info;
CdmAppParameterMap::const_iterator iter;
for (iter = app_parameters.begin(); iter != app_parameters.end(); iter++) {
client_info = client_id->add_client_info();
client_info->set_name(iter->first);
client_info->set_value(iter->second);
}
std::string value;
if (Properties::GetCompanyName(&value)) {
client_info = client_id->add_client_info();
client_info->set_name(kCompanyNameKey);
client_info->set_value(value);
}
if (Properties::GetModelName(&value)) {
client_info = client_id->add_client_info();
client_info->set_name(kModelNameKey);
client_info->set_value(value);
}
if (Properties::GetArchitectureName(&value)) {
client_info = client_id->add_client_info();
client_info->set_name(kArchitectureNameKey);
client_info->set_value(value);
}
if (Properties::GetDeviceName(&value)) {
client_info = client_id->add_client_info();
client_info->set_name(kDeviceNameKey);
client_info->set_value(value);
}
if (Properties::GetProductName(&value)) {
client_info = client_id->add_client_info();
client_info->set_name(kProductNameKey);
client_info->set_value(value);
}
if (Properties::GetBuildInfo(&value)) {
client_info = client_id->add_client_info();
client_info->set_name(kBuildInfoKey);
client_info->set_value(value);
}
if (!device_id_.empty()) {
client_info = client_id->add_client_info();
client_info->set_name(kDeviceIdKey);
client_info->set_value(b2a_hex(device_id_));
} else if (crypto_session_->GetInternalDeviceUniqueId(&value)) {
client_info = client_id->add_client_info();
client_info->set_name(kDeviceIdKey);
client_info->set_value(value);
}
if (Properties::GetWVCdmVersion(&value)) {
client_info = client_id->add_client_info();
client_info->set_name(kWVCdmVersionKey);
client_info->set_value(value);
}
client_info = client_id->add_client_info();
client_info->set_name(kOemCryptoSecurityPatchLevelKey);
std::stringstream ss;
ss << (uint32_t)crypto_session_->GetSecurityPatchLevel();
client_info->set_value(ss.str());
ClientIdentification_ClientCapabilities* client_capabilities =
client_id->mutable_client_capabilities();
bool supports_usage_information;
if (crypto_session_->UsageInformationSupport(&supports_usage_information)) {
client_capabilities->set_session_token(supports_usage_information);
}
client_capabilities->set_anti_rollback_usage_table(
crypto_session_->IsAntiRollbackHwPresent());
uint32_t api_version = 0;
if (crypto_session_->GetApiVersion(&api_version)) {
client_capabilities->set_oem_crypto_api_version(api_version);
}
CryptoSession::HdcpCapability current_version, max_version;
if (crypto_session_->GetHdcpCapabilities(&current_version, &max_version)) {
switch (max_version) {
case HDCP_NONE:
client_capabilities->set_max_hdcp_version(
video_widevine::
ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_NONE);
break;
case HDCP_V1:
client_capabilities->set_max_hdcp_version(
video_widevine::
ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_V1);
break;
case HDCP_V2:
client_capabilities->set_max_hdcp_version(
video_widevine::
ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_V2);
break;
case HDCP_V2_1:
client_capabilities->set_max_hdcp_version(
video_widevine::
ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_V2_1);
break;
case HDCP_V2_2:
client_capabilities->set_max_hdcp_version(
video_widevine::
ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_V2_2);
break;
case HDCP_NO_DIGITAL_OUTPUT:
client_capabilities->set_max_hdcp_version(
video_widevine::
ClientIdentification_ClientCapabilities_HdcpVersion_HDCP_NO_DIGITAL_OUTPUT);
break;
default:
LOGW(
"CdmLicense::PrepareClientId: unexpected HDCP max capability "
"version %d",
max_version);
}
}
CryptoSession::SupportedCertificateTypes supported_certs;
if (crypto_session_->GetSupportedCertificateTypes(&supported_certs)) {
if (supported_certs.rsa_2048_bit) {
client_capabilities->add_supported_certificate_key_type(
video_widevine::
ClientIdentification_ClientCapabilities_CertificateKeyType_RSA_2048);
}
if (supported_certs.rsa_3072_bit) {
client_capabilities->add_supported_certificate_key_type(
video_widevine::
ClientIdentification_ClientCapabilities_CertificateKeyType_RSA_3072);
}
}
client_capabilities->set_can_update_srm(
crypto_session_->IsSrmUpdateSupported());
uint16_t srm_version;
if (crypto_session_->GetSrmVersion(&srm_version))
client_capabilities->set_srm_version(srm_version);
video_widevine::ClientIdentification* client_id =
license_request->mutable_client_id();
status = id.Prepare(app_parameters, client_id);
if (status != NO_ERROR) return status;
if (Properties::UsePrivacyMode(session_id_)) {
if (!service_certificate_.has_certificate()) {
@@ -1157,7 +994,6 @@ CdmResponseType CdmLicense::PrepareClientId(
}
EncryptedClientIdentification* encrypted_client_id =
license_request->mutable_encrypted_client_id();
CdmResponseType status;
status = service_certificate_.EncryptClientId(crypto_session_, client_id,
encrypted_client_id);
if (NO_ERROR == status) {

View File

@@ -16,11 +16,6 @@
#include <sys/mman.h>
#include <unistd.h>
#if __mips__
#include <sys/syscall.h>
#include <asm/cachectl.h>
#endif
#include <iostream>
#include <map>
#include <string>

View File

@@ -300,7 +300,8 @@ CdmResponseType PolicyEngine::Query(CdmQueryMap* query_response) {
CdmResponseType PolicyEngine::QueryKeyAllowedUsage(
const KeyId& key_id, CdmKeyAllowedUsage* key_usage) {
if (NULL == key_usage) {
return INVALID_PARAMETERS_ENG_12;
LOGE("PolicyEngine::QueryKeyAllowedUsage: no key_usage provided");
return PARAMETER_NULL;
}
if (license_keys_->GetAllowedUsage(key_id, key_usage)) {
return NO_ERROR;

View File

@@ -14,7 +14,6 @@ bool Properties::oem_crypto_use_fifo_;
bool Properties::oem_crypto_use_userspace_buffers_;
bool Properties::provisioning_messages_are_binary_;
bool Properties::allow_service_certificate_requests_;
bool Properties::security_level_path_backward_compatibility_support_;
scoped_ptr<CdmClientPropertySetMap> Properties::session_property_set_;
bool Properties::AddSessionPropertySet(

View File

@@ -24,6 +24,7 @@ UsageTableHeader::UsageTableHeader()
: security_level_(kSecurityLevelUninitialized),
requested_security_level_(kLevelDefault),
is_inited_(false) {
file_system_.reset(new FileSystem());
file_handle_.reset(new DeviceFiles(file_system_.get()));
}

View File

@@ -183,7 +183,7 @@ class WvCdmEnginePreProvTest : public testing::Test {
CdmCertificateType cert_type = kCertificateWidevine;
std::string cert_authority;
std::string cert, wrapped_key;
ASSERT_EQ(NO_ERROR, cdm_engine_.SetServiceCertificate(
ASSERT_EQ(NO_ERROR, cdm_engine_.SetProvisioningServiceCertificate(
g_provisioning_service_certificate));
CdmResponseType result = NO_ERROR;
for(int i = 0; i < 2; ++i) { // Retry once if there is a nonce problem.
@@ -217,9 +217,6 @@ class WvCdmEnginePreProvTest : public testing::Test {
ASSERT_EQ(NO_ERROR,
cdm_engine_.HandleProvisioningResponse(http_message,
&cert, &wrapped_key));
ASSERT_EQ(NO_ERROR,
cdm_engine_.SetServiceCertificate(g_license_service_certificate));
}
FileSystem file_system_;
@@ -287,7 +284,7 @@ class WvCdmEnginePreProvTestUatBinary : public WvCdmEnginePreProvTest {
CdmCertificateType cert_type = kCertificateWidevine;
std::string cert_authority;
std::string cert, wrapped_key;
ASSERT_EQ(NO_ERROR, cdm_engine_.SetServiceCertificate(
ASSERT_EQ(NO_ERROR, cdm_engine_.SetProvisioningServiceCertificate(
g_provisioning_service_certificate));
ASSERT_EQ(NO_ERROR, cdm_engine_.GetProvisioningRequest(
cert_type, cert_authority, &binary_prov_request,
@@ -333,9 +330,6 @@ class WvCdmEnginePreProvTestUatBinary : public WvCdmEnginePreProvTest {
ASSERT_EQ(NO_ERROR,
cdm_engine_.HandleProvisioningResponse(binary_protobuf_response,
&cert, &wrapped_key));
ASSERT_EQ(NO_ERROR,
cdm_engine_.SetServiceCertificate(g_license_service_certificate));
}
};
@@ -473,15 +467,17 @@ class WvCdmEngineTest : public WvCdmEnginePreProvTest {
};
// Test that service certificate is initially absent.
TEST_F(WvCdmEnginePreProvTestStaging, ServiceCertificateInitialNoneTest) {
ASSERT_FALSE(cdm_engine_.HasServiceCertificate());
TEST_F(WvCdmEnginePreProvTestStaging,
ProvisioningServiceCertificateInitialNoneTest) {
ASSERT_FALSE(cdm_engine_.HasProvisioningServiceCertificate());
};
// Test that service certificate can be properly installed.
TEST_F(WvCdmEnginePreProvTestStaging, ServiceCertificateGoodTest) {
ASSERT_EQ(cdm_engine_.SetServiceCertificate(g_license_service_certificate),
NO_ERROR);
ASSERT_TRUE(cdm_engine_.HasServiceCertificate());
TEST_F(WvCdmEnginePreProvTestStaging, ProvisioningServiceCertificateGoodTest) {
ASSERT_EQ(cdm_engine_.SetProvisioningServiceCertificate(
g_license_service_certificate),
NO_ERROR);
ASSERT_TRUE(cdm_engine_.HasProvisioningServiceCertificate());
};
// Test that provisioning works, even if device is already provisioned.

View File

@@ -48,7 +48,7 @@ SSL_CTX* InitSslContext() {
if (!ctx) LOGE("failed to create SSL context");
int ret = SSL_CTX_set_cipher_list(
ctx, "ALL:!RC4-MD5:!RC4-SHA:!ECDHE-ECDSA-RC4-SHA:!ECDHE-RSA-RC4-SHA");
if (0 != ret) LOGE("error disabling vulnerable ciphers");
if (0 == ret) LOGE("error disabling vulnerable ciphers");
return ctx;
}

View File

@@ -0,0 +1,128 @@
// Copyright 2017 Google Inc. All Rights Reserved.
#include <string>
#include <errno.h>
#include <getopt.h>
#include <gtest/gtest.h>
#include "shared_ptr.h"
#include "log.h"
namespace wvcdm {
class SharedPtrTest : public testing::Test {
public:
static void NoteDeletion() {
deletions++;
}
class Dummy {
public:
explicit Dummy(int v) : value_(v) { exists_ = true; }
~Dummy() {
NoteDeletion();
exists_ = false;
}
bool exists() { return exists_; }
int getValue() { return value_; }
void setValue(int v) { value_ = v; }
private:
bool exists_;
int value_;
};
static void ExpectedDeletions(int count) {
ASSERT_TRUE(deletions == count);
deletions = 0;
}
virtual void SetUpTest() {
deletions = 0;
}
virtual void TearDownTest() {
deletions = 0;
}
private:
static int deletions;
};
int SharedPtrTest::deletions = 0;
TEST_F(SharedPtrTest, NullSingletonCreate) {
shared_ptr<Dummy> sd1;
ASSERT_TRUE(sd1.unique());
ASSERT_TRUE(sd1.get() == NULL);
ExpectedDeletions(0);
}
TEST_F(SharedPtrTest, SingletonCreate) {
{
Dummy* d1 = new Dummy(42);
shared_ptr<Dummy> sd1(d1);
ASSERT_TRUE(sd1.unique());
ASSERT_TRUE(sd1.get() == d1);
ASSERT_TRUE(sd1->getValue() == 42);
}
ExpectedDeletions(1);
}
TEST_F(SharedPtrTest, ResetToNull) {
Dummy* d1 = new Dummy(42);
shared_ptr<Dummy> sd1(d1);
ASSERT_TRUE(sd1->getValue() == 42);
sd1.reset();
ExpectedDeletions(1);
ASSERT_TRUE(sd1.get() == NULL);
}
TEST_F(SharedPtrTest, SharedCreate) {
{
Dummy* d1 = new Dummy(42);
shared_ptr<Dummy> sd1(d1);
{
shared_ptr<Dummy> sd2(sd1);
ASSERT_FALSE(sd1.unique());
ASSERT_TRUE(sd1.get() == d1);
ASSERT_TRUE(sd2.get() == d1);
ASSERT_TRUE(sd1.use_count() == 2);
}
ExpectedDeletions(0);
ASSERT_TRUE(sd1.use_count() == 1);
}
ExpectedDeletions(1);
}
TEST_F(SharedPtrTest, SharedInstance) {
Dummy* d1 = new Dummy(42);
{
shared_ptr<Dummy> sd1(d1);
{
shared_ptr<Dummy> sd2(sd1);
ASSERT_FALSE(sd1.unique());
ASSERT_TRUE(sd1.get() == d1);
ASSERT_TRUE(sd2.get() == d1);
sd2->setValue(55);
ASSERT_TRUE(sd1.use_count() == 2);
}
ExpectedDeletions(0);
ASSERT_TRUE(sd1.use_count() == 1);
ASSERT_TRUE(sd1->getValue() == 55);
}
ExpectedDeletions(1);
}
TEST_F(SharedPtrTest, Reset) {
{
Dummy* d1 = new Dummy(42);
Dummy* d2 = new Dummy(96);
shared_ptr<Dummy> sd1(d1);
sd1.reset(d2);
ExpectedDeletions(1);
ASSERT_TRUE(sd1->getValue() == 96);
}
ExpectedDeletions(1);
}
} // namespace wvcdm

View File

@@ -75,16 +75,6 @@ void PrintTo(const enum CdmResponseType& value, ::std::ostream* os) {
case CERT_PROVISIONING_RESPONSE_ERROR_8:
*os << "CERT_PROVISIONING_RESPONSE_ERROR_8";
break;
case CRYPTO_SESSION_OPEN_ERROR_1: *os << "CRYPTO_SESSION_OPEN_ERROR_1";
break;
case CRYPTO_SESSION_OPEN_ERROR_2: *os << "CRYPTO_SESSION_OPEN_ERROR_2";
break;
case CRYPTO_SESSION_OPEN_ERROR_3: *os << "CRYPTO_SESSION_OPEN_ERROR_3";
break;
case CRYPTO_SESSION_OPEN_ERROR_4: *os << "CRYPTO_SESSION_OPEN_ERROR_4";
break;
case CRYPTO_SESSION_OPEN_ERROR_5: *os << "CRYPTO_SESSION_OPEN_ERROR_5";
break;
case DECRYPT_NOT_READY: *os << "DECRYPT_NOT_READY";
break;
case DEVICE_CERTIFICATE_ERROR_1: *os << "DEVICE_CERTIFICATE_ERROR_1";
@@ -143,16 +133,6 @@ void PrintTo(const enum CdmResponseType& value, ::std::ostream* os) {
break;
case INIT_DATA_NOT_FOUND: *os << "INIT_DATA_NOT_FOUND";
break;
case INVALID_CRYPTO_SESSION_1: *os << "INVALID_CRYPTO_SESSION_1";
break;
case INVALID_CRYPTO_SESSION_2: *os << "INVALID_CRYPTO_SESSION_2";
break;
case INVALID_CRYPTO_SESSION_3: *os << "INVALID_CRYPTO_SESSION_3";
break;
case INVALID_CRYPTO_SESSION_4: *os << "INVALID_CRYPTO_SESSION_4";
break;
case INVALID_CRYPTO_SESSION_5: *os << "INVALID_CRYPTO_SESSION_5";
break;
case INVALID_DECRYPT_PARAMETERS_ENG_1:
*os << "INVALID_DECRYPT_PARAMETERS_ENG_1";
break;
@@ -174,13 +154,11 @@ void PrintTo(const enum CdmResponseType& value, ::std::ostream* os) {
break;
case INVALID_LICENSE_TYPE: *os << "INVALID_LICENSE_TYPE";
break;
case INVALID_PARAMETERS_ENG_1: *os << "INVALID_PARAMETERS_ENG_1";
case PARAMETER_NULL: *os << "PARAMETER_NULL";
break;
case INVALID_PARAMETERS_ENG_2: *os << "INVALID_PARAMETERS_ENG_2";
case NOT_INITIALIZED_ERROR: *os << "NOT_INITIALIZED_ERROR";
break;
case INVALID_PARAMETERS_ENG_3: *os << "INVALID_PARAMETERS_ENG_3";
break;
case INVALID_PARAMETERS_ENG_4: *os << "INVALID_PARAMETERS_ENG_4";
case REINIT_ERROR: *os << "REINIT_ERROR";
break;
case INVALID_PARAMETERS_LIC_1: *os << "INVALID_PARAMETERS_LIC_1";
break;
@@ -280,10 +258,6 @@ void PrintTo(const enum CdmResponseType& value, ::std::ostream* os) {
case RESTORE_OFFLINE_LICENSE_ERROR_2:
*os << "RESTORE_OFFLINE_LICENSE_ERROR_2";
break;
case SESSION_INIT_ERROR_1: *os << "SESSION_INIT_ERROR_1";
break;
case SESSION_INIT_ERROR_2: *os << "SESSION_INIT_ERROR_2";
break;
case SESSION_NOT_FOUND_1: *os << "SESSION_NOT_FOUND_1";
break;
case SESSION_NOT_FOUND_2: *os << "SESSION_NOT_FOUND_2";
@@ -402,20 +376,6 @@ void PrintTo(const enum CdmResponseType& value, ::std::ostream* os) {
break;
case KEY_CONFLICT_1: *os << "KEY_CONFLICT_1";
break;
case INVALID_PARAMETERS_ENG_6: *os << "INVALID_PARAMETERS_ENG_6";
break;
case INVALID_PARAMETERS_ENG_7: *os << "INVALID_PARAMETERS_ENG_7";
break;
case INVALID_PARAMETERS_ENG_8: *os << "INVALID_PARAMETERS_ENG_8";
break;
case INVALID_PARAMETERS_ENG_9: *os << "INVALID_PARAMETERS_ENG_9";
break;
case INVALID_PARAMETERS_ENG_10: *os << "INVALID_PARAMETERS_ENG_10";
break;
case INVALID_PARAMETERS_ENG_11: *os << "INVALID_PARAMETERS_ENG_11";
break;
case INVALID_PARAMETERS_ENG_12: *os << "INVALID_PARAMETERS_ENG_12";
break;
case SESSION_NOT_FOUND_13: *os << "SESSION_NOT_FOUND_13";
break;
case SESSION_NOT_FOUND_14: *os << "SESSION_NOT_FOUND_14";
@@ -455,14 +415,11 @@ void PrintTo(const enum CdmResponseType& value, ::std::ostream* os) {
break;
case INVALID_PARAMETERS_ENG_19: *os << "INVALID_PARAMETERS_ENG_19";
break;
case CERT_PROVISIONING_CLIENT_TOKEN_ERROR_1:
*os << "CERT_PROVISIONING_CLIENT_TOKEN_ERROR_1";
case CLIENT_IDENTIFICATION_TOKEN_ERROR_1:
*os << "CLIENT_IDENTIFICATION_TOKEN_ERROR_1";
break;
case CERT_PROVISIONING_CLIENT_TOKEN_ERROR_2:
*os << "CERT_PROVISIONING_CLIENT_TOKEN_ERROR_2";
break;
case LICENSING_CLIENT_TOKEN_ERROR_1:
*os << "LICENSING_CLIENT_TOKEN_ERROR_1";
case CLIENT_IDENTIFICATION_TOKEN_ERROR_2:
*os << "CLIENT_IDENTIFICATION_TOKEN_ERROR_2";
break;
case ANALOG_OUTPUT_ERROR: *os << "ANALOG_OUTPUT_ERROR";
break;

View File

@@ -22,12 +22,6 @@ class FileUtils {
static bool IsRegularFile(const std::string& path);
static bool IsDirectory(const std::string& path);
static bool CreateDirectory(const std::string& path);
// Certificate and offline licenses are now stored in security
// level specific directories. In an earlier version they were
// stored in a common directory and need to be copied over.
static void SecurityLevelPathBackwardCompatibility(
CdmSecurityLevel security_level);
};
} // namespace wvcdm

View File

@@ -20,10 +20,6 @@ const bool kPropertyOemCryptoUseUserSpaceBuffers = false;
// string accepted by the CDM includes the JSON wrapper.
const bool kPropertyProvisioningMessagesAreBinary = false;
// If true, device files will be moved to the directory specified by
// Properties::GetDeviceFilesBasePath
const bool kSecurityLevelPathBackwardCompatibilitySupport = true;
// Controls behavior when privacy mode is enabled. If true
// and a service certificate is not provided, a service certificate
// request will be generated when requested to generate a license request.

View File

@@ -0,0 +1,445 @@
// Copyright 2017 Google Inc. All Rights Reserved.
//
// Unit tests for the metrics collections,
// EngineMetrics, SessionMetrics and CrytpoMetrics.
#include "metrics_collections.h"
#include <sstream>
#include "gmock/gmock.h"
#include "google/protobuf/text_format.h"
#include "gtest/gtest.h"
#include "log.h"
#include "metrics.pb.h"
#include "wv_cdm_types.h"
using drm_metrics::MetricsGroup;
using google::protobuf::TextFormat;
namespace wvcdm {
namespace metrics {
// TODO(blueeyes): Improve this implementation by supporting full message
// API In CDM. That allows us to use MessageDifferencer.
class EngineMetricsTest : public ::testing::Test {
};
TEST_F(EngineMetricsTest, AllEngineMetrics) {
EngineMetrics engine_metrics;
// Set some values in all of the engine metrics.
engine_metrics.cdm_engine_add_key_.Record(1.0, KEY_ADDED);
engine_metrics.cdm_engine_close_session_.Record(1.0, NO_ERROR);
engine_metrics.cdm_engine_decrypt_.Record(1.0, NO_ERROR);
engine_metrics.cdm_engine_find_session_for_key_.Record(1.0, false);
engine_metrics.cdm_engine_generate_key_request_.Record(1.0, NO_ERROR);
engine_metrics.cdm_engine_get_provisioning_request_.Record(1.0, NO_ERROR);
engine_metrics.cdm_engine_get_usage_info_.Record(1.0, NO_ERROR);
engine_metrics.cdm_engine_handle_provisioning_response_.Record(1.0, NO_ERROR);
engine_metrics.cdm_engine_life_span_.Record(1.0);
engine_metrics.cdm_engine_open_key_set_session_.Record(1.0, NO_ERROR);
engine_metrics.cdm_engine_open_session_.Record(1.0, NO_ERROR);
engine_metrics.cdm_engine_query_key_status_.Record(1.0, NO_ERROR);
engine_metrics.cdm_engine_release_all_usage_info_.Record(1.0, NO_ERROR);
engine_metrics.cdm_engine_release_usage_info_.Record(1.0, NO_ERROR);
engine_metrics.cdm_engine_remove_keys_.Record(1.0, NO_ERROR);
engine_metrics.cdm_engine_restore_key_.Record(1.0, NO_ERROR);
engine_metrics.cdm_engine_unprovision_.Record(1.0, NO_ERROR, kSecurityLevelL1);
drm_metrics::MetricsGroup actual_metrics;
engine_metrics.Serialize(&actual_metrics, true, false);
// For each EventMetric, 2 metrics get serialized since only one sample was
// taken. So, the total number of serialized metrics are 2*17.
ASSERT_EQ(2 * 17, actual_metrics.metric_size());
EXPECT_EQ(0, actual_metrics.metric_sub_group_size());
// Spot check some metrics.
EXPECT_EQ("/drm/widevine/cdm_engine/add_key/time/count{error:2}",
actual_metrics.metric(0).name());
EXPECT_EQ("/drm/widevine/cdm_engine/close_session/time/mean{error:0}",
actual_metrics.metric(3).name());
EXPECT_EQ("/drm/widevine/cdm_engine/decrypt/time/mean{error:0}",
actual_metrics.metric(5).name());
EXPECT_EQ(1.0, actual_metrics.metric(5).value().double_value());
}
TEST_F(EngineMetricsTest, EngineAndCryptoMetrics) {
EngineMetrics engine_metrics;
// Set some values in some of the engine metrics and some crypto metrics.
engine_metrics.cdm_engine_add_key_.Record(1.0, KEY_ADDED);
engine_metrics.cdm_engine_close_session_.Record(1.0, NO_ERROR);
CryptoMetrics* crypto_metrics = engine_metrics.GetCryptoMetrics();
crypto_metrics->crypto_session_generic_decrypt_
.Record(2.0, NO_ERROR, Pow2Bucket(1025), kEncryptionAlgorithmAesCbc128);
crypto_metrics->crypto_session_get_device_unique_id_
.Record(4.0, false);
drm_metrics::MetricsGroup actual_metrics;
engine_metrics.Serialize(&actual_metrics, true, false);
// For each EventMetric, 2 metrics get serialized since only one sample was
// taken. So, the total number of serialized metrics are 2*4 since we
// touched 4 metrics.
ASSERT_EQ(2 * 4, actual_metrics.metric_size());
EXPECT_EQ(0, actual_metrics.metric_sub_group_size());
// Spot check some metrics.
EXPECT_EQ("/drm/widevine/cdm_engine/add_key/time/count{error:2}",
actual_metrics.metric(0).name());
EXPECT_EQ(
"/drm/widevine/crypto_session/generic_decrypt/time/count"
"{error:0&length:1024&encryption_algorithm:1}",
actual_metrics.metric(4).name());
EXPECT_EQ(
"/drm/widevine/crypto_session/get_device_unique_id/time/mean{success:0}",
actual_metrics.metric(7).name());
EXPECT_EQ(4.0, actual_metrics.metric(7).value().double_value());
}
TEST_F(EngineMetricsTest, EmptyEngineMetrics) {
EngineMetrics engine_metrics;
drm_metrics::MetricsGroup actual_metrics;
engine_metrics.Serialize(&actual_metrics, true, false);
EXPECT_EQ(0, actual_metrics.metric_size());
EXPECT_EQ(0, actual_metrics.metric_sub_group_size());
}
TEST_F(EngineMetricsTest, EngineMetricsWithCompletedSessions) {
EngineMetrics engine_metrics;
// Set a values in an engine metric and in a crypto metric.
engine_metrics.cdm_engine_add_key_.Record(1.0, KEY_ADDED);
engine_metrics.GetCryptoMetrics()
->crypto_session_load_certificate_private_key_.Record(2.0, true);
// Create two sessions and record some metrics.
SessionMetrics* session_metrics_1 = engine_metrics.AddSession();
session_metrics_1->SetSessionId("session_id_1");
SessionMetrics* session_metrics_2 = engine_metrics.AddSession();
session_metrics_2->SetSessionId("session_id_2");
// Record a CryptoMetrics metric in the session.
session_metrics_2->GetCryptoMetrics()->crypto_session_generic_decrypt_
.Record(2.0, NO_ERROR, Pow2Bucket(1025), kEncryptionAlgorithmAesCbc128);
session_metrics_2->SetSessionId("session_id_2");
// Mark only session 2 as completed.
session_metrics_2->SetCompleted();
drm_metrics::MetricsGroup actual_metrics;
engine_metrics.Serialize(&actual_metrics, true, false);
// Validate metric counts.
// For each EventMetric, 2 metrics get serialized since only one sample was
// taken. So, the total number of serialized metrics are 2*2 since we
// touched 2 metrics.
ASSERT_EQ(2 * 2, actual_metrics.metric_size());
ASSERT_EQ(1, actual_metrics.metric_sub_group_size());
ASSERT_EQ(3, actual_metrics.metric_sub_group(0).metric_size());
// Spot check some metrics.
EXPECT_EQ("/drm/widevine/cdm_engine/add_key/time/count{error:2}",
actual_metrics.metric(0).name());
EXPECT_EQ("/drm/widevine/crypto_session/load_certificate_private_key"
"/time/count{success:1}",
actual_metrics.metric(2).name());
EXPECT_EQ("/drm/widevine/cdm_session/session_id",
actual_metrics.metric_sub_group(0).metric(0).name());
EXPECT_EQ(
"session_id_2",
actual_metrics.metric_sub_group(0).metric(0).value().string_value());
EXPECT_EQ(
"/drm/widevine/crypto_session/generic_decrypt/time/count"
"{error:0&length:1024&encryption_algorithm:1}",
actual_metrics.metric_sub_group(0).metric(1).name());
}
TEST_F(EngineMetricsTest, EngineMetricsSerializeAllSessions) {
EngineMetrics engine_metrics;
// Create two sessions and record some metrics.
SessionMetrics* session_metrics_1 = engine_metrics.AddSession();
session_metrics_1->SetSessionId("session_id_1");
SessionMetrics* session_metrics_2 = engine_metrics.AddSession();
session_metrics_2->SetSessionId("session_id_2");
// Mark only session 2 as completed.
session_metrics_2->SetCompleted();
drm_metrics::MetricsGroup actual_metrics;
engine_metrics.Serialize(&actual_metrics, false, false);
// Validate metric counts.
// No Engine-level metrics were recorded.
ASSERT_EQ(0, actual_metrics.metric_size());
// Two sub groups, 1 per session.
ASSERT_EQ(2, actual_metrics.metric_sub_group_size());
ASSERT_EQ(1, actual_metrics.metric_sub_group(0).metric_size());
// Spot check some metrics.
EXPECT_EQ("/drm/widevine/cdm_session/session_id",
actual_metrics.metric_sub_group(0).metric(0).name());
EXPECT_EQ(
"session_id_1",
actual_metrics.metric_sub_group(0).metric(0).value().string_value());
EXPECT_EQ("/drm/widevine/cdm_session/session_id",
actual_metrics.metric_sub_group(1).metric(0).name());
EXPECT_EQ(
"session_id_2",
actual_metrics.metric_sub_group(1).metric(0).value().string_value());
}
TEST_F(EngineMetricsTest, EngineMetricsRemoveSessions) {
EngineMetrics engine_metrics;
// Create two sessions and record some metrics.
SessionMetrics* session_metrics_1 = engine_metrics.AddSession();
session_metrics_1->SetSessionId("session_id_1");
SessionMetrics* session_metrics_2 = engine_metrics.AddSession();
session_metrics_2->SetSessionId("session_id_2");
// Mark only session 2 as completed.
session_metrics_2->SetCompleted();
// Serialize all metrics, don't remove any.
drm_metrics::MetricsGroup actual_metrics;
engine_metrics.Serialize(&actual_metrics, false, false);
// Validate metric counts.
// Two sub groups, 1 per session.
ASSERT_EQ(2, actual_metrics.metric_sub_group_size());
// Serialize completed metrics, remove them.
actual_metrics.Clear();
engine_metrics.Serialize(&actual_metrics, true, true);
// Validate metric counts.
// Only one, completed session should exist.
ASSERT_EQ(1, actual_metrics.metric_sub_group_size());
ASSERT_EQ(1, actual_metrics.metric_sub_group(0).metric_size());
EXPECT_EQ(
"session_id_2",
actual_metrics.metric_sub_group(0).metric(0).value().string_value());
// Serialize all metrics, remove them.
actual_metrics.Clear();
engine_metrics.Serialize(&actual_metrics, false, true);
// Validate metric counts.
// Only one, non-complete session should exist.
ASSERT_EQ(1, actual_metrics.metric_sub_group_size());
ASSERT_EQ(1, actual_metrics.metric_sub_group(0).metric_size());
EXPECT_EQ(
"session_id_1",
actual_metrics.metric_sub_group(0).metric(0).value().string_value());
// Serialize all metrics, don't remove any.
actual_metrics.Clear();
engine_metrics.Serialize(&actual_metrics, false, false);
// Validate metric counts.
// There should be no more metric subgroups left.
ASSERT_EQ(0, actual_metrics.metric_sub_group_size());
}
class SessionMetricsTest : public ::testing::Test {
};
TEST_F(SessionMetricsTest, AllSessionMetrics) {
SessionMetrics session_metrics;
session_metrics.SetSessionId("session_id 1");
session_metrics.cdm_session_life_span_.Record(1.0);
session_metrics.cdm_session_renew_key_.Record(1.0, NO_ERROR);
session_metrics.cdm_session_restore_offline_session_.Record(1.0, NO_ERROR);
session_metrics.cdm_session_restore_usage_session_.Record(1.0, NO_ERROR);
// Record a CryptoMetrics metric in the session.
session_metrics.GetCryptoMetrics()->crypto_session_generic_decrypt_
.Record(2.0, NO_ERROR, Pow2Bucket(1025), kEncryptionAlgorithmAesCbc128);
MetricsGroup actual_metrics;
session_metrics.Serialize(&actual_metrics);
ASSERT_EQ(11, actual_metrics.metric_size());
EXPECT_EQ(0, actual_metrics.metric_sub_group_size());
// Spot check some metrics.
EXPECT_EQ("/drm/widevine/cdm_session/session_id",
actual_metrics.metric(0).name());
EXPECT_EQ("/drm/widevine/cdm_session/life_span/time/count",
actual_metrics.metric(1).name());
EXPECT_EQ("/drm/widevine/cdm_session/renew_key/time/mean{error:0}",
actual_metrics.metric(4).name());
EXPECT_EQ(1.0, actual_metrics.metric(4).value().double_value());
EXPECT_EQ("/drm/widevine/crypto_session/generic_decrypt/time/count"
"{error:0&length:1024&encryption_algorithm:1}",
actual_metrics.metric(9).name());
}
TEST_F(SessionMetricsTest, EmptySessionMetrics) {
SessionMetrics session_metrics;
MetricsGroup actual_metrics;
session_metrics.Serialize(&actual_metrics);
// Session metric always has a session id.
ASSERT_EQ(1, actual_metrics.metric_size());
EXPECT_EQ("/drm/widevine/cdm_session/session_id",
actual_metrics.metric(0).name());
EXPECT_EQ("", actual_metrics.metric(0).value().string_value());
EXPECT_EQ(0, actual_metrics.metric_sub_group_size());
}
class CryptoMetricsTest : public ::testing::Test {
};
TEST_F(CryptoMetricsTest, AllCryptoMetrics) {
CryptoMetrics crypto_metrics;
// Crypto session metrics.
crypto_metrics.crypto_session_delete_all_usage_reports_
.Record(1.0, NO_ERROR);
crypto_metrics.crypto_session_delete_multiple_usage_information_
.Record(1.0, NO_ERROR);
crypto_metrics.crypto_session_generic_decrypt_
.Record(2.0, NO_ERROR, Pow2Bucket(1025), kEncryptionAlgorithmAesCbc128);
crypto_metrics.crypto_session_generic_encrypt_
.Record(2.0, NO_ERROR, Pow2Bucket(1025), kEncryptionAlgorithmAesCbc128);
crypto_metrics.crypto_session_generic_sign_
.Record(2.0, NO_ERROR, Pow2Bucket(1025), kSigningAlgorithmHmacSha256);
crypto_metrics.crypto_session_generic_verify_
.Record(2.0, NO_ERROR, Pow2Bucket(1025), kSigningAlgorithmHmacSha256);
crypto_metrics.crypto_session_get_device_unique_id_.Record(1.0, true);
crypto_metrics.crypto_session_get_security_level_
.Record(1.0, kSecurityLevelL1);
crypto_metrics.crypto_session_get_system_id_.Record(1.0, true, 1234);
crypto_metrics.crypto_session_get_token_.Record(1.0, true);
crypto_metrics.crypto_session_life_span_.Record(1.0);
crypto_metrics.crypto_session_load_certificate_private_key_
.Record(1.0, true);
crypto_metrics.crypto_session_open_.Record(1.0, NO_ERROR, kLevelDefault);
crypto_metrics.crypto_session_update_usage_information_
.Record(1.0, NO_ERROR);
crypto_metrics.crypto_session_usage_information_support_.Record(1.0, true);
// Oem crypto metrics.
crypto_metrics.oemcrypto_api_version_.Record(1.0, 123, kLevelDefault);
crypto_metrics.oemcrypto_close_session_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED);
crypto_metrics.oemcrypto_copy_buffer_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED,
kLevelDefault, Pow2Bucket(1025));
crypto_metrics.oemcrypto_deactivate_usage_entry_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED);
crypto_metrics.oemcrypto_decrypt_cenc_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED, Pow2Bucket(1025));
crypto_metrics.oemcrypto_delete_usage_entry_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED);
crypto_metrics.oemcrypto_delete_usage_table_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED);
crypto_metrics.oemcrypto_derive_keys_from_session_key_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED);
crypto_metrics.oemcrypto_force_delete_usage_entry_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED);
crypto_metrics.oemcrypto_generate_derived_keys_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED);
crypto_metrics.oemcrypto_generate_nonce_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED);
crypto_metrics.oemcrypto_generate_rsa_signature_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED, Pow2Bucket(1025));
crypto_metrics.oemcrypto_generate_signature_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED, Pow2Bucket(1025));
crypto_metrics.oemcrypto_generic_decrypt_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED, Pow2Bucket(1025));
crypto_metrics.oemcrypto_generic_encrypt_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED, Pow2Bucket(1025));
crypto_metrics.oemcrypto_generic_sign_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED, Pow2Bucket(1025));
crypto_metrics.oemcrypto_generic_verify_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED, Pow2Bucket(1025));
crypto_metrics.oemcrypto_get_device_id_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED, kLevelDefault);
crypto_metrics.oemcrypto_get_hdcp_capability_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED, kLevelDefault);
crypto_metrics.oemcrypto_get_key_data_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED,
Pow2Bucket(1025), kLevelDefault);
crypto_metrics.oemcrypto_get_max_number_of_sessions_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED, kLevelDefault);
crypto_metrics.oemcrypto_get_number_of_open_sessions_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED, kLevelDefault);
crypto_metrics.oemcrypto_get_oem_public_certificate_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED);
crypto_metrics.oemcrypto_get_provisioning_method_
.Record(1.0, OEMCrypto_Keybox, kLevelDefault);
crypto_metrics.oemcrypto_get_random_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED, Pow2Bucket(1025));
crypto_metrics.oemcrypto_initialize_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED);
crypto_metrics.oemcrypto_install_keybox_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED, kLevelDefault);
crypto_metrics.oemcrypto_is_anti_rollback_hw_present_
.Record(1.0, true, kLevelDefault);
crypto_metrics.oemcrypto_is_keybox_valid_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED, kLevelDefault);
crypto_metrics.oemcrypto_load_device_rsa_key_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED);
crypto_metrics.oemcrypto_load_keys_.Record(1.0, OEMCrypto_ERROR_INIT_FAILED);
crypto_metrics.oemcrypto_load_test_keybox_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED);
crypto_metrics.oemcrypto_load_test_rsa_key_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED);
crypto_metrics.oemcrypto_open_session_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED, kLevelDefault);
crypto_metrics.oemcrypto_refresh_keys_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED);
crypto_metrics.oemcrypto_report_usage_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED);
crypto_metrics.oemcrypto_rewrap_device_rsa_key_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED);
crypto_metrics.oemcrypto_rewrap_device_rsa_key_30_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED);
crypto_metrics.oemcrypto_security_level_
.Record(1.0, kSecurityLevelL2, kLevelDefault);
crypto_metrics.oemcrypto_security_patch_level_
.Record(1.0, 123, kLevelDefault);
crypto_metrics.oemcrypto_select_key_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED);
crypto_metrics.oemcrypto_supports_usage_table_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED, kLevelDefault);
crypto_metrics.oemcrypto_update_usage_table_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED);
crypto_metrics.oemcrypto_wrap_keybox_
.Record(1.0, OEMCrypto_ERROR_INIT_FAILED);
// Internal OEMCrypto Metrics
crypto_metrics.oemcrypto_initialization_mode_
.Record(1.0, OEMCrypto_INITIALIZED_FORCING_L3);
crypto_metrics.oemcrypto_l1_api_version_.Record(1.0, 12, 123);
MetricsGroup actual_metrics;
crypto_metrics.Serialize(&actual_metrics);
// 61 EventMetric instances, 2 values each.
ASSERT_EQ(122, actual_metrics.metric_size());
// Spot check some metrics.
EXPECT_EQ(
"/drm/widevine/crypto_session/delete_all_usage_reports/time/count"
"{error:0}",
actual_metrics.metric(0).name());
EXPECT_EQ(1, actual_metrics.metric(0).value().int_value());
EXPECT_EQ(
"/drm/widevine/oemcrypto/l1_api_version/mean{version:12&min_version:123}",
actual_metrics.metric(121).name());
EXPECT_EQ(1.0, actual_metrics.metric(121).value().double_value());
// No subgroups should exist.
EXPECT_EQ(0, actual_metrics.metric_sub_group_size());
}
} // namespace metrics
} // namespace wvcdm

View File

@@ -112,10 +112,7 @@ class FileSystem::Impl {};
FileSystem::FileSystem() : FileSystem(EMPTY_ORIGIN, NULL) {}
FileSystem::FileSystem(const std::string& origin, void* /* extra_data */)
: origin_(origin) {
FileUtils::SecurityLevelPathBackwardCompatibility(kSecurityLevelL1);
FileUtils::SecurityLevelPathBackwardCompatibility(kSecurityLevelL3);
}
: origin_(origin) {}
FileSystem::~FileSystem() {}

View File

@@ -210,56 +210,4 @@ bool FileUtils::CreateDirectory(const std::string& path_in) {
return true;
}
void FileUtils::SecurityLevelPathBackwardCompatibility(
CdmSecurityLevel security_level) {
std::string path;
if (!Properties::GetDeviceFilesBasePath(security_level, &path)) {
LOGW("SecurityLevelPathBackwardCompatibility: Unable to get base path");
return;
}
std::vector<std::string> security_dirs;
if (!Properties::GetSecurityLevelDirectories(&security_dirs)) {
LOGW("SecurityLevelPathBackwardCompatibility: Unable to get security "
"directories");
return;
}
size_t pos = std::string::npos;
for (size_t i = 0; i < security_dirs.size(); ++i) {
pos = path.find(security_dirs[i]);
if (pos != std::string::npos && pos > 0 &&
pos == path.size() - security_dirs[i].size() &&
path[pos - 1] == kDirectoryDelimiter) {
break;
}
}
if (pos == std::string::npos) {
LOGV("SecurityLevelPathBackwardCompatibility: Security level specific path "
"not found. Check properties?");
return;
}
std::string from_dir(path, 0, pos);
std::vector<std::string> files;
if (!FileUtils::List(from_dir, &files)) {
return;
}
for (size_t i = 0; i < files.size(); ++i) {
std::string from = from_dir + files[i];
if (!FileUtils::IsRegularFile(from)) continue;
for (size_t j = 0; j < security_dirs.size(); ++j) {
std::string to_dir = from_dir + security_dirs[j];
if (!FileUtils::Exists(to_dir)) FileUtils::CreateDirectory(to_dir);
std::string to = to_dir + files[i];
FileUtils::Copy(from, to);
}
FileUtils::Remove(from);
}
}
} // namespace wvcdm

View File

@@ -49,8 +49,6 @@ void Properties::Init() {
oem_crypto_use_userspace_buffers_ = kPropertyOemCryptoUseUserSpaceBuffers;
provisioning_messages_are_binary_ = kPropertyProvisioningMessagesAreBinary;
allow_service_certificate_requests_ = kAllowServiceCertificateRequests;
security_level_path_backward_compatibility_support_ =
kSecurityLevelPathBackwardCompatibilitySupport;
session_property_set_.reset(new CdmClientPropertySetMap());
}

View File

@@ -3083,144 +3083,6 @@ TEST_F(WvCdmRequestLicenseTest, QueryOemCryptoSessionId) {
decryptor_.CloseSession(session_id_);
}
TEST_F(WvCdmRequestLicenseTest, SecurityLevelPathBackwardCompatibility) {
Unprovision();
Provision(kLevelDefault);
// override default settings unless configured through the command line
std::string key_id;
std::string client_auth;
GetOfflineConfiguration(&key_id, &client_auth);
std::string level;
EXPECT_EQ(wvcdm::NO_ERROR,
decryptor_.QueryStatus(kLevelDefault,
wvcdm::QUERY_KEY_SECURITY_LEVEL,
&level));
EXPECT_TRUE(wvcdm::QUERY_VALUE_SECURITY_LEVEL_L3 == level ||
wvcdm::QUERY_VALUE_SECURITY_LEVEL_L1 == level);
CdmSecurityLevel security_level =
wvcdm::QUERY_VALUE_SECURITY_LEVEL_L1 == level
? kSecurityLevelL1
: kSecurityLevelL3;
std::string base_path;
EXPECT_TRUE(Properties::GetDeviceFilesBasePath(security_level, &base_path));
std::vector<std::string> security_dirs;
EXPECT_TRUE(Properties::GetSecurityLevelDirectories(&security_dirs));
size_t pos = std::string::npos;
for (size_t i = 0; i < security_dirs.size(); i++) {
pos = base_path.rfind(security_dirs[i]);
if (std::string::npos != pos) break;
}
// Delete any old files.
EXPECT_NE(std::string::npos, pos);
std::string old_base_path(base_path, 0, pos);
FileSystem file_system;
for (size_t i = 0; i < security_dirs.size(); i++) {
std::string path = old_base_path + kPathDelimiter + security_dirs[i];
file_system.Remove(path);
}
// Provision the device to create any required files.
decryptor_.OpenSession(g_key_system, NULL, kDefaultCdmIdentifier, NULL,
&session_id_);
std::string provisioning_server;
CdmCertificateType cert_type = kCertificateWidevine;
std::string cert_authority, cert, wrapped_key;
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.GetProvisioningRequest(
cert_type, cert_authority,
kDefaultCdmIdentifier, &key_msg_,
&provisioning_server));
EXPECT_EQ(provisioning_server, g_config->provisioning_server());
std::string response =
GetCertRequestResponse(g_config->provisioning_server());
EXPECT_NE(0, static_cast<int>(response.size()));
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.HandleProvisioningResponse(
kDefaultCdmIdentifier, response, &cert,
&wrapped_key));
decryptor_.CloseSession(session_id_);
std::vector<std::string> files;
EXPECT_TRUE(FileUtils::List(base_path, &files));
size_t number_of_files = files.size();
// Create an offline license to create license files.
decryptor_.OpenSession(g_key_system, NULL, kDefaultCdmIdentifier, NULL,
&session_id_);
GenerateKeyRequest(key_id, kLicenseTypeOffline);
VerifyKeyRequestResponse(g_license_server, client_auth);
CdmKeySetId key_set_id = key_set_id_;
EXPECT_FALSE(key_set_id_.empty());
decryptor_.CloseSession(session_id_);
EXPECT_TRUE(FileUtils::List(base_path, &files));
int number_of_new_files = files.size() - number_of_files;
// There should be a new license file, and maybe a new usage table
// file.
EXPECT_LE(1, number_of_new_files);
EXPECT_GE(2, number_of_new_files);
// Move files to the old location.
for (size_t i = 0; i < files.size(); ++i) {
std::string from = base_path + files[i];
if (FileUtils::IsRegularFile(from)) {
std::string to = old_base_path + files[i];
EXPECT_TRUE(FileUtils::Copy(from, to));
}
}
EXPECT_TRUE(file_system.Remove(base_path));
//// Setup complete to earlier version (non-security level based) path.
// Create a new file system. This will cause the files to be moved over.
// Normally this will happen when the plugin is created, but since we are
// reusing the same decryptor, we need it to update here.
FileSystem dummy_file_system;
// Restore persistent license, retrieve L1, L3 streaming licenses to verify
session_id_.clear();
decryptor_.OpenSession(g_key_system, NULL, kDefaultCdmIdentifier, NULL,
&session_id_);
EXPECT_EQ(wvcdm::KEY_ADDED, decryptor_.RestoreKey(session_id_, key_set_id));
decryptor_.CloseSession(session_id_);
decryptor_.OpenSession(g_key_system, NULL, kDefaultCdmIdentifier, NULL,
&session_id_);
GenerateKeyRequest(g_key_id, kLicenseTypeStreaming);
VerifyKeyRequestResponse(g_license_server, client_auth);
decryptor_.CloseSession(session_id_);
if (security_level != kSecurityLevelL1) return;
TestWvCdmClientPropertySet property_set;
property_set.set_security_level(QUERY_VALUE_SECURITY_LEVEL_L3);
EXPECT_EQ(wvcdm::NEED_PROVISIONING,
decryptor_.OpenSession(g_key_system, &property_set,
kDefaultCdmIdentifier, NULL, &session_id_));
EXPECT_EQ(NO_ERROR, decryptor_.GetProvisioningRequest(
cert_type, cert_authority, kDefaultCdmIdentifier,
&key_msg_, &provisioning_server));
EXPECT_EQ(provisioning_server, g_config->provisioning_server());
response = GetCertRequestResponse(g_config->provisioning_server());
EXPECT_NE(0, static_cast<int>(response.size()));
EXPECT_EQ(NO_ERROR, decryptor_.HandleProvisioningResponse(
kDefaultCdmIdentifier, response, &cert,
&wrapped_key));
EXPECT_EQ(NO_ERROR, decryptor_.OpenSession(g_key_system, &property_set,
kDefaultCdmIdentifier, NULL,
&session_id_));
GenerateKeyRequest(g_key_id, kLicenseTypeStreaming);
VerifyKeyRequestResponse(g_license_server, client_auth);
decryptor_.CloseSession(session_id_);
}
TEST_F(WvCdmRequestLicenseTest, DISABLED_OfflineLicenseDecryptionTest) {
decryptor_.OpenSession(g_key_system, NULL, kDefaultCdmIdentifier, NULL,
&session_id_);