Files
android/libwvdrmengine/cdm/core/include/crypto_session.h
Rahul Frias 5d690be108 Merges to android Pi release (part 11)
These are a set of CLs merged from the wv cdm repo to the android repo.

* Get System ID From OEM Cert

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

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

  (This is a merge of http://go/wvgerrit/30220 .  However, it has been
  significantly modified in the merge due to needing to support both
  OpenSSL and BoringSSL.)

  Previously, extracting the system ID was only supported on Keybox-based
  systems. This patch adds support for extracting the system ID from the
  OEM Certificate chain on Provisioning 3.0 devices. This is done by
  getting the Widevine intermediate cert from the chain, finding the
  Widevine System ID extension in that cert, and extracting the value.

  The code that does the extraction is separate from any code that calls
  OEMCrypto so that it can be unit-tested in isolation. This patch adds a
  crypto_session_unittest test to do this unit-testing.

  Bug: 34776194
  Test: crypto_session_unittest
  Test: widevine_ce_cdm_unittest

* Remove unique_ptr from oemcrypto mod mock

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

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

  Because we can't have C++11.

  Bug: 69935608

* Update CHANGELOG.md

  Author: Gene Morgan <gmorgan@google.com>

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

   - Add items about adapter support.
   - Add mention of SRM support.

  Merged from cdm_partner_3.5
  (Change-Id: I6d891e157edc3afb2797bf281ef3f06bdb8fe474)

* Add Adapter for OEMCrypto v13 to v12.

  Author: Gene Morgan <gmorgan@google.com>

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

  Also fix OEMCrypto_LoadKeys() definition broken by wvcl/38160
  (srm_requirement param).

* Allow certain warnings in protobuf build.

  Author: Gene Morgan <gmorgan@google.com>

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

  maybe-uninitialized is triggered in release build. Allow it.

* Enable -fPIC for jsmc.c build.

  Author: Gene Morgan <gmorgan@google.com>

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

  -fPIC was removed for common c/c++ build rules. Add it back.

* Missing OEMCrypto_LoadKeys param in static adapter.

  Author: Gene Morgan <gmorgan@google.com>

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

  srm_requirement param was omitted in v11 static adapter.

* Remove OEMCrypto v12 specification.

  Author: Gene Morgan <gmorgan@google.com>

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

* Update documentation for v3.5.

  Author: Gene Morgan <gmorgan@google.com>

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

* Added padded preprov key for 7880

  Author: Srujan Gaddam <srujzs@google.com>

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

  Bug: 68765915

* Change overrides in CE L3FileSystem

  Author: Srujan Gaddam <srujzs@google.com>

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

  The 'override's are changed to the macro defined in override.h to
  be gnu++98 compliant.

* Use source android level3 + add cache_flush call

  Author: Srujan Gaddam <srujzs@google.com>

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

  I put both changes in this CL since I have to generate Level3 libraries
  for both anyways. The first change involves shifting from using a
  prebuilt static library to using an obfuscated source library output
  from the Haystack tool on google3. The second change is from here:
  https://critique.corp.google.com/#review/176536782, and addresses
  b/69387416. Since the cache_flush function wasn't being used, the
  execution on Angler gave inconsistent segfaults, which this CL fixes.

  Verified on Angler, Sailfish, and Linux.

  11/27/17: Added mips and mips64 libraries.

* Make CDM result codes constexprs

  Author: Rahul Frias <rfrias@google.com>

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

  The values in the enumeration list of CdmResponseType error codes
  were earlier implicit. Comments were added to denote the actual
  values. This changes to make it fixed values, which makes it slightly
  more error prone, but cleaner when errors are retired.

* Change watchdog timer to 2 minutes

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

  This relaxes the watchdog timer around the level 3 oemcrypto
  initialization to 120 seconds.  There are also a couple of new log
  messages at the end of initialization and at termination.

  Library for arm updated:
  level3/arm/libwvlevel3.a       Level3 Library 4445 Oct  4 2017 17:06:25

  Bug: 65379279

  Merged from https://widevine-internal-review.googlesource.com/35480

* Add test to get service certificate from server.

  Author: Gene Morgan <gmorgan@google.com>

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

  This was extracted from Ic38dd27d06dc7528ae4cd995da4261fe6c34ad55

* Add watch dog timer to OEMCrypto L3

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

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

  This code adds a watchdog timer to the level 3 initialization.  If
  initialization does not finish within 5 seconds, the process
  will abort, printing a small amount of debugging information.

  arm/libwvlevel3.a Level3 Library 4445 Sep 11 2017 14:05:15

  Test: unit tests on bullhead. Video on Play Movies.
  GTS tests run on loop overnight.

  Bug: 65379279
  Merged from https://widevine-internal-review.googlesource.com/33540

* Remove libwidevinehidl_utils dependency

  Author: Rahul Frias <rfrias@google.com>

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

  libwvdrmcryptoplugin_hidl has a dependency on libwidevinehidl_utils
  which was introduced due to an out of order merge from oc-mr1-dev
  to master.

  Bug: 69573113

* Automatically generate log location information

  Author: Rahul Frias <rfrias@google.com>

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

  Currently class and method names are manually added to each log message
  in the CDM on android and some other platforms. This change prepends
  log messages with file name, line number and function name automatically.

  The code is platform specific so it can be enabled and the precise
  format configured on a per-platform basis.

  As an example, here is a log on android before the change,

  11-01 02:48:48.658 D/WVCdm   (32198): CryptoSession::Open:
  Lock: requested_security_level: Default

  and after,

  11-01 02:48:48.658 D/WVCdm   (32198): [crypto_session.cpp(1108):Open]
  Lock: requested_security_level: Default

  A follow on CL will remove the manually added class/method information.

  Bug: 9261010

* Fix BoringSSL Compatibility of oec_session_util.cpp

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

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

  A previous change inadvertantly used APIs from OpenSSL that do not exist
  in BoringSSL in oec_session_util.cpp. As a temporary fix until we can
  move all targets to BoringSSL, this patch switches that file to use
  conditional compilation to choose the correct API depending on the
  library in use. It does not otherwise change the behavior of the file.

  Bug: 67908123
  Test: wv_ce_cdm_unittest on x86-64
  Test: linux_unit_tests

* Create local shared_ptr implementation

  Author: Gene Morgan <gmorgan@google.com>

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

  Derived from protobuf version, which came from google3.
  Removed locking (not thread-safe) and removed weak pointers (not
  needed for usages in CDM).

  Locking can easily be added if needed.

* Revert C++11 usage - back to gnu++98

  Author: Gene Morgan <gmorgan@google.com>

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

  These changes roll back C++11-specific constructs:
    std::unique_ptr -> std::auto_ptr
    container initializers
    nullptr -> NULL
    std::shared_ptr to local shared_ptr
    compiler flags (-std=c++11 -> -sdt=gnu++98)

  NOTE: the "local" shared_ptr implementation is temporarily
  a direct reference to the shared_ptr implementation in
  third_party/protobuf. This has been fixed (implementation
  extracted and moved to core/include) in CL 37600.

BUG: 71650075
Test: Not currently passing. Will be addressed in a subsequent
  commit in the chain.

Change-Id: Ie09ecb970aa06fe9301ac255375ca7d8e7ead8bc
2018-01-16 19:33:36 -08:00

308 lines
13 KiB
C++

// Copyright 2012 Google Inc. All Rights Reserved.
#ifndef WVCDM_CORE_CRYPTO_SESSSION_H_
#define WVCDM_CORE_CRYPTO_SESSSION_H_
#include <map>
#include <string>
#include <vector>
#include "OEMCryptoCENC.h"
#include "lock.h"
#include "metrics_collections.h"
#include "oemcrypto_adapter.h"
#include "OEMCryptoCENC.h"
#include "scoped_ptr.h"
#include "timer_metric.h"
#include "wv_cdm_types.h"
namespace wvcdm {
class CryptoKey;
class UsageTableHeader;
typedef std::map<std::string, CryptoKey*> CryptoKeyMap;
typedef std::map<std::string, CryptoSessionId> SubLicenseSessionMap;
class KeySession {
protected:
KeySession(metrics::CryptoMetrics* metrics) : metrics_(metrics) {}
public:
typedef enum { kDefault, kSubLicense } KeySessionType;
virtual ~KeySession() {}
virtual KeySessionType Type() = 0;
virtual bool GenerateDerivedKeys(const std::string& message) = 0;
virtual bool GenerateDerivedKeys(const std::string& message,
const std::string& session_key) = 0;
virtual OEMCryptoResult LoadKeys(const std::string& message,
const std::string& signature,
const std::string& mac_key_iv,
const std::string& mac_key,
const std::vector<CryptoKey>& keys,
const std::string& provider_session_token,
CdmCipherMode* cipher_mode,
const std::string& srm_requirement) = 0;
virtual OEMCryptoResult SelectKey(const std::string& key_id) = 0;
virtual OEMCryptoResult Decrypt(
const CdmDecryptionParameters& params,
OEMCrypto_DestBufferDesc& buffer_descriptor,
OEMCrypto_CENCEncryptPatternDesc& pattern_descriptor) = 0;
protected:
metrics::CryptoMetrics* metrics_;
};
class CryptoSession {
public:
typedef OEMCrypto_HDCP_Capability HdcpCapability;
typedef enum {
kUsageDurationsInvalid = 0,
kUsageDurationPlaybackNotBegun = 1,
kUsageDurationsValid = 2,
} UsageDurationStatus;
struct SupportedCertificateTypes {
bool rsa_2048_bit;
bool rsa_3072_bit;
bool rsa_cast;
};
// Creates an instance of CryptoSession with the given |crypto_metrics|.
// |crypto_metrics| is owned by the caller, must NOT be null, and must
// exist as long as the new CryptoSession exists.
explicit CryptoSession(metrics::CryptoMetrics* crypto_metrics);
virtual ~CryptoSession();
virtual bool GetClientToken(std::string* client_token);
virtual bool GetProvisioningToken(std::string* client_token);
virtual CdmClientTokenType GetPreProvisionTokenType() {
return pre_provision_token_type_;
}
virtual CdmSecurityLevel GetSecurityLevel();
virtual bool GetInternalDeviceUniqueId(std::string* device_id);
virtual bool GetExternalDeviceUniqueId(std::string* device_id);
virtual bool GetApiVersion(uint32_t* version);
virtual bool GetSystemId(uint32_t* system_id);
virtual bool GetProvisioningId(std::string* provisioning_id);
virtual uint8_t GetSecurityPatchLevel();
virtual CdmResponseType Open() { return Open(kLevelDefault); }
virtual CdmResponseType Open(SecurityLevel requested_security_level);
virtual void Close();
virtual bool IsOpen() { return open_; }
virtual CryptoSessionId oec_session_id() { return oec_session_id_; }
// Key request/response
virtual bool GenerateRequestId(std::string* req_id_str);
virtual bool PrepareRequest(const std::string& key_deriv_message,
bool is_provisioning, std::string* signature);
virtual bool PrepareRenewalRequest(const std::string& message,
std::string* signature);
virtual CdmResponseType LoadKeys(const std::string& message,
const std::string& signature,
const std::string& mac_key_iv,
const std::string& mac_key,
const std::vector<CryptoKey>& key_array,
const std::string& provider_session_token,
const std::string& srm_requirement);
virtual bool LoadCertificatePrivateKey(std::string& wrapped_key);
virtual bool RefreshKeys(const std::string& message,
const std::string& signature, int num_keys,
const CryptoKey* key_array);
virtual bool GenerateNonce(uint32_t* nonce);
virtual bool GenerateDerivedKeys(const std::string& message);
virtual bool GenerateDerivedKeys(const std::string& message,
const std::string& session_key);
virtual bool RewrapCertificate(const std::string& signed_message,
const std::string& signature,
const std::string& nonce,
const std::string& private_key,
const std::string& iv,
const std::string& wrapping_key,
std::string* wrapped_private_key);
// Media data path
virtual CdmResponseType Decrypt(const CdmDecryptionParameters& params);
// Usage related methods
virtual bool UsageInformationSupport(bool* has_support);
virtual CdmResponseType UpdateUsageInformation(); // only for OEMCrypto v9-12
virtual CdmResponseType DeactivateUsageInformation(
const std::string& provider_session_token);
virtual CdmResponseType GenerateUsageReport(
const std::string& provider_session_token, std::string* usage_report,
UsageDurationStatus* usage_duration_status,
int64_t* seconds_since_started, int64_t* seconds_since_last_played);
virtual CdmResponseType ReleaseUsageInformation(
const std::string& message, const std::string& signature,
const std::string& provider_session_token);
// Delete a usage information for a single token. This does not require
// a signed message from the server.
virtual CdmResponseType DeleteUsageInformation(
const std::string& provider_session_token);
// Delete usage information for a list of tokens. This does not require
// a signed message from the server.
virtual CdmResponseType DeleteMultipleUsageInformation(
const std::vector<std::string>& provider_session_tokens);
virtual CdmResponseType DeleteAllUsageReports();
virtual bool IsAntiRollbackHwPresent();
virtual bool GetHdcpCapabilities(HdcpCapability* current,
HdcpCapability* max);
virtual bool GetSupportedCertificateTypes(SupportedCertificateTypes* support);
virtual bool GetRandom(size_t data_length, uint8_t* random_data);
virtual bool GetNumberOfOpenSessions(size_t* count);
virtual bool GetMaxNumberOfSessions(size_t* max);
virtual bool GetSrmVersion(uint16_t* srm_version);
virtual bool IsSrmUpdateSupported();
virtual bool LoadSrm(const std::string& srm);
virtual CdmResponseType GenericEncrypt(const std::string& in_buffer,
const std::string& key_id,
const std::string& iv,
CdmEncryptionAlgorithm algorithm,
std::string* out_buffer);
virtual CdmResponseType GenericDecrypt(const std::string& in_buffer,
const std::string& key_id,
const std::string& iv,
CdmEncryptionAlgorithm algorithm,
std::string* out_buffer);
virtual CdmResponseType GenericSign(const std::string& message,
const std::string& key_id,
CdmSigningAlgorithm algorithm,
std::string* signature);
virtual CdmResponseType GenericVerify(const std::string& message,
const std::string& key_id,
CdmSigningAlgorithm algorithm,
const std::string& signature);
// Usage table header and usage entry related methods
virtual UsageTableHeader* GetUsageTableHeader() {
return usage_table_header_;
}
virtual CdmResponseType GetUsageSupportType(CdmUsageSupportType* type);
virtual CdmResponseType CreateUsageTableHeader(
CdmUsageTableHeader* usage_table_header);
virtual CdmResponseType LoadUsageTableHeader(
const CdmUsageTableHeader& usage_table_header);
virtual CdmResponseType CreateUsageEntry(uint32_t* entry_number);
virtual CdmResponseType LoadUsageEntry(uint32_t entry_number,
const CdmUsageEntry& usage_entry);
virtual CdmResponseType UpdateUsageEntry(
CdmUsageTableHeader* usage_table_header,
CdmUsageEntry* usage_entry);
virtual CdmResponseType ShrinkUsageTableHeader(
uint32_t new_entry_count, CdmUsageTableHeader* usage_table_header);
virtual CdmResponseType MoveUsageEntry(uint32_t new_entry_number);
virtual bool CreateOldUsageEntry(
uint64_t time_since_license_received,
uint64_t time_since_first_decrypt,
uint64_t time_since_last_decrypt,
UsageDurationStatus status,
const std::string& server_mac_key,
const std::string& client_mac_key,
const std::string& provider_session_token);
virtual CdmResponseType CopyOldUsageEntry(
const std::string& provider_session_token);
virtual metrics::CryptoMetrics* GetCryptoMetrics() { return metrics_; }
virtual CdmResponseType AddSubSession(const std::string& sub_session_key_id,
const std::string& group_master_key_id);
// TODO(jfore): exists is set based on whether a sub session exists. For now,
// that is not assumed to be an error.
virtual bool GenerateSubSessionNonce(const std::string& sub_session_key_id,
bool* exists, uint32_t* nonce);
private:
friend class CryptoSessionForTest;
bool GetProvisioningMethod(CdmClientTokenType* token_type);
void Init();
void Terminate();
bool GetTokenFromKeybox(std::string* token);
bool GetTokenFromOemCert(std::string* token);
static bool ExtractSystemIdFromOemCert(const std::string& oem_cert,
uint32_t* system_id);
bool GenerateSignature(const std::string& message, std::string* signature);
bool GenerateRsaSignature(const std::string& message, std::string* signature);
bool SetDestinationBufferType();
bool RewrapDeviceRSAKey(
const std::string& message, const std::string& signature,
const std::string& nonce, const std::string& enc_rsa_key,
const std::string& rsa_key_iv, std::string* wrapped_rsa_key);
bool RewrapDeviceRSAKey30(
const std::string& message, const std::string& nonce,
const std::string& private_key, const std::string& iv,
const std::string& wrapping_key, std::string* wrapped_private_key);
CdmResponseType SelectKey(const std::string& key_id);
static const OEMCrypto_Algorithm kInvalidAlgorithm =
static_cast<OEMCrypto_Algorithm>(-1);
OEMCrypto_Algorithm GenericSigningAlgorithm(CdmSigningAlgorithm algorithm);
OEMCrypto_Algorithm GenericEncryptionAlgorithm(
CdmEncryptionAlgorithm algorithm);
size_t GenericEncryptionBlockSize(CdmEncryptionAlgorithm algorithm);
// These methods are used when a subsample exceeds the maximum buffer size
// that the device can handle.
OEMCryptoResult CopyBufferInChunks(
const CdmDecryptionParameters& params,
OEMCrypto_DestBufferDesc buffer_descriptor);
OEMCryptoResult DecryptInChunks(
const CdmDecryptionParameters& params,
const OEMCrypto_DestBufferDesc& full_buffer_descriptor,
const OEMCrypto_CENCEncryptPatternDesc& pattern_descriptor,
size_t max_chunk_size);
static void IncrementIV(uint64_t increase_by, std::vector<uint8_t>* iv_out);
static const size_t kAes128BlockSize = 16; // Block size for AES_CBC_128
static const size_t kSignatureSize = 32; // size for HMAC-SHA256 signature
static Lock crypto_lock_;
static bool initialized_;
static int session_count_;
metrics::CryptoMetrics* metrics_;
metrics::TimerMetric life_span_;
bool open_;
CdmClientTokenType pre_provision_token_type_;
std::string oem_token_; // Cached OEMCrypto Public Key
bool update_usage_table_after_close_session_;
CryptoSessionId oec_session_id_;
SubLicenseSessionMap sub_license_oec_sessions_;
// Used for sub license sessions.
std::string wrapped_key_;
scoped_ptr<KeySession> key_session_;
OEMCryptoBufferType destination_buffer_type_;
bool is_destination_buffer_type_valid_;
SecurityLevel requested_security_level_;
KeyId cached_key_id_;
bool is_usage_support_type_valid_;
CdmUsageSupportType usage_support_type_;
UsageTableHeader* usage_table_header_;
static UsageTableHeader* usage_table_header_l1_;
static UsageTableHeader* usage_table_header_l3_;
uint64_t request_id_base_;
static uint64_t request_id_index_;
CdmCipherMode cipher_mode_;
CORE_DISALLOW_COPY_AND_ASSIGN(CryptoSession);
};
} // namespace wvcdm
#endif // WVCDM_CORE_CRYPTO_SESSSION_H_