Merge "Clean comments, namespace, and variable names"
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
// Copyright 2012 Google Inc. All Rights Reserved.
|
// Copyright 2012 Google Inc. All Rights Reserved.
|
||||||
|
|
||||||
#ifndef CDM_BASE_BUFFER_READER_H_
|
#ifndef WVCDM_CORE_BUFFER_READER_H_
|
||||||
#define CDM_BASE_BUFFER_READER_H_
|
#define WVCDM_CORE_BUFFER_READER_H_
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -65,4 +65,4 @@ class BufferReader {
|
|||||||
|
|
||||||
} // namespace wvcdm
|
} // namespace wvcdm
|
||||||
|
|
||||||
#endif // CDM_BASE_BUFFER_READER_H_
|
#endif // WVCDM_CORE_BUFFER_READER_H_
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Copyright 2013 Google Inc. All Rights Reserved.
|
// Copyright 2013 Google Inc. All Rights Reserved.
|
||||||
|
|
||||||
#ifndef CDM_BASE_CDM_CLIENT_PROPERTY_SET_H_
|
#ifndef WVCDM_CORE_CDM_CLIENT_PROPERTY_SET_H_
|
||||||
#define CDM_BASE_CDM_CLIENT_PROPERTY_SET_H_
|
#define WVCDM_CORE_CDM_CLIENT_PROPERTY_SET_H_
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -23,4 +23,4 @@ class CdmClientPropertySet {
|
|||||||
|
|
||||||
} // namespace wvcdm
|
} // namespace wvcdm
|
||||||
|
|
||||||
#endif // CDM_BASE_CDM_CLIENT_PROPERTY_SET_H_
|
#endif // WVCDM_CORE_CDM_CLIENT_PROPERTY_SET_H_
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Copyright 2013 Google Inc. All Rights Reserved.
|
// Copyright 2013 Google Inc. All Rights Reserved.
|
||||||
|
|
||||||
#ifndef CDM_BASE_CDM_ENGINE_H_
|
#ifndef WVCDM_CORE_CDM_ENGINE_H_
|
||||||
#define CDM_BASE_CDM_ENGINE_H_
|
#define WVCDM_CORE_CDM_ENGINE_H_
|
||||||
|
|
||||||
#include "certificate_provisioning.h"
|
#include "certificate_provisioning.h"
|
||||||
#include "initialization_data.h"
|
#include "initialization_data.h"
|
||||||
@@ -132,4 +132,4 @@ class CdmEngine {
|
|||||||
|
|
||||||
} // namespace wvcdm
|
} // namespace wvcdm
|
||||||
|
|
||||||
#endif // CDM_BASE_CDM_ENGINE_H_
|
#endif // WVCDM_CORE_CDM_ENGINE_H_
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Copyright 2012 Google Inc. All Rights Reserved.
|
// Copyright 2012 Google Inc. All Rights Reserved.
|
||||||
|
|
||||||
#ifndef CDM_BASE_CDM_SESSION_H_
|
#ifndef WVCDM_CORE_CDM_SESSION_H_
|
||||||
#define CDM_BASE_CDM_SESSION_H_
|
#define WVCDM_CORE_CDM_SESSION_H_
|
||||||
|
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
@@ -131,4 +131,4 @@ class CdmSession {
|
|||||||
|
|
||||||
} // namespace wvcdm
|
} // namespace wvcdm
|
||||||
|
|
||||||
#endif // CDM_BASE_CDM_SESSION_H_
|
#endif // WVCDM_CORE_CDM_SESSION_H_
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Copyright 2013 Google Inc. All Rights Reserved.
|
// Copyright 2013 Google Inc. All Rights Reserved.
|
||||||
|
|
||||||
#ifndef CDM_BASE_CERTIFICATE_PROVISIONING_H_
|
#ifndef WVCDM_CORE_CERTIFICATE_PROVISIONING_H_
|
||||||
#define CDM_BASE_CERTIFICATE_PROVISIONING_H_
|
#define WVCDM_CORE_CERTIFICATE_PROVISIONING_H_
|
||||||
|
|
||||||
#include "crypto_session.h"
|
#include "crypto_session.h"
|
||||||
#include "oemcrypto_adapter.h"
|
#include "oemcrypto_adapter.h"
|
||||||
@@ -40,4 +40,4 @@ class CertificateProvisioning {
|
|||||||
};
|
};
|
||||||
} // namespace wvcdm
|
} // namespace wvcdm
|
||||||
|
|
||||||
#endif // CDM_BASE_CERTIFICATE_PROVISIONING_H_
|
#endif // WVCDM_CORE_CERTIFICATE_PROVISIONING_H_
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
//
|
//
|
||||||
// Clock - Platform independent interface for a time library
|
// Clock - Platform independent interface for a time library
|
||||||
//
|
//
|
||||||
#ifndef CDM_BASE_CLOCK_H_
|
#ifndef WVCDM_CORE_CLOCK_H_
|
||||||
#define CDM_BASE_CLOCK_H_
|
#define WVCDM_CORE_CLOCK_H_
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
@@ -22,4 +22,4 @@ class Clock {
|
|||||||
|
|
||||||
}; // namespace wvcdm
|
}; // namespace wvcdm
|
||||||
|
|
||||||
#endif // CDM_BASE_CLOCK_H_
|
#endif // WVCDM_CORE_CLOCK_H_
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
// Copyright 2012 Google Inc. All Rights Reserved.
|
// Copyright 2012 Google Inc. All Rights Reserved.
|
||||||
//
|
|
||||||
// OEMCrypto Client - wrapper class for C-style OEMCrypto interface
|
#ifndef WVCDM_CORE_CRYPTO_KEY_H_
|
||||||
//
|
#define WVCDM_CORE_CRYPTO_KEY_H_
|
||||||
#ifndef CDM_BASE_CRYPTO_KEY_H_
|
|
||||||
#define CDM_BASE_CRYPTO_KEY_H_
|
|
||||||
|
|
||||||
#include "wv_cdm_types.h"
|
#include "wv_cdm_types.h"
|
||||||
|
|
||||||
@@ -39,4 +37,4 @@ private:
|
|||||||
|
|
||||||
}; // namespace wvcdm
|
}; // namespace wvcdm
|
||||||
|
|
||||||
#endif // CDM_BASE_CRYPTO_KEY_H_
|
#endif // WVCDM_CORE_CRYPTO_KEY_H_
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
// Copyright 2012 Google Inc. All Rights Reserved.
|
// Copyright 2012 Google Inc. All Rights Reserved.
|
||||||
//
|
|
||||||
// OEMCrypto Client - wrapper class for C-style OEMCrypto interface
|
#ifndef WVCDM_CORE_CRYPTO_SESSSION_H_
|
||||||
//
|
#define WVCDM_CORE_CRYPTO_SESSSION_H_
|
||||||
#ifndef CDM_BASE_CRYPTO_SESSSION_H_
|
|
||||||
#define CDM_BASE_CRYPTO_SESSSION_H_
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
#include <map>
|
||||||
@@ -103,4 +101,4 @@ class CryptoSession {
|
|||||||
|
|
||||||
}; // namespace wvcdm
|
}; // namespace wvcdm
|
||||||
|
|
||||||
#endif // CDM_BASE_CRYPTO_SESSSION_H_
|
#endif // WVCDM_CORE_CRYPTO_SESSSION_H_
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Copyright 2013 Google Inc. All Rights Reserved.
|
// Copyright 2013 Google Inc. All Rights Reserved.
|
||||||
//
|
//
|
||||||
#ifndef CDM_BASE_DEVICE_FILES_H_
|
#ifndef WVCDM_CORE_DEVICE_FILES_H_
|
||||||
#define CDM_BASE_DEVICE_FILES_H_
|
#define WVCDM_CORE_DEVICE_FILES_H_
|
||||||
|
|
||||||
#include "wv_cdm_types.h"
|
#include "wv_cdm_types.h"
|
||||||
|
|
||||||
@@ -73,4 +73,4 @@ class DeviceFiles {
|
|||||||
|
|
||||||
} // namespace wvcdm
|
} // namespace wvcdm
|
||||||
|
|
||||||
#endif // CDM_BASE_DEVICE_FILES_H_
|
#endif // WVCDM_CORE_DEVICE_FILES_H_
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
//
|
//
|
||||||
// File - Platform independent interface for a File class
|
// File - Platform independent interface for a File class
|
||||||
//
|
//
|
||||||
#ifndef CDM_BASE_FILE_STORE_H_
|
#ifndef WVCDM_CORE_FILE_STORE_H_
|
||||||
#define CDM_BASE_FILE_STORE_H_
|
#define WVCDM_CORE_FILE_STORE_H_
|
||||||
|
|
||||||
#include "wv_cdm_types.h"
|
#include "wv_cdm_types.h"
|
||||||
|
|
||||||
@@ -48,4 +48,4 @@ class File {
|
|||||||
|
|
||||||
} // namespace wvcdm
|
} // namespace wvcdm
|
||||||
|
|
||||||
#endif // CDM_BASE_FILE_STORE_H_
|
#endif // WVCDM_CORE_FILE_STORE_H_
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Copyright 2012 Google Inc. All Rights Reserved.
|
// Copyright 2012 Google Inc. All Rights Reserved.
|
||||||
|
|
||||||
#ifndef CDM_BASE_LICENSE_H_
|
#ifndef WVCDM_CORE_LICENSE_H_
|
||||||
#define CDM_BASE_LICENSE_H_
|
#define WVCDM_CORE_LICENSE_H_
|
||||||
|
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
@@ -76,4 +76,4 @@ class CdmLicense {
|
|||||||
|
|
||||||
} // namespace wvcdm
|
} // namespace wvcdm
|
||||||
|
|
||||||
#endif // CDM_BASE_LICENSE_H_
|
#endif // WVCDM_CORE_LICENSE_H_
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
//
|
//
|
||||||
// Lock - Platform independent interface for a Mutex class
|
// Lock - Platform independent interface for a Mutex class
|
||||||
//
|
//
|
||||||
#ifndef CDM_BASE_LOCK_H_
|
#ifndef WVCDM_CORE_LOCK_H_
|
||||||
#define CDM_BASE_LOCK_H_
|
#define WVCDM_CORE_LOCK_H_
|
||||||
|
|
||||||
#include "wv_cdm_types.h"
|
#include "wv_cdm_types.h"
|
||||||
|
|
||||||
@@ -58,4 +58,4 @@ class AutoLock {
|
|||||||
|
|
||||||
}; // namespace wvcdm
|
}; // namespace wvcdm
|
||||||
|
|
||||||
#endif // CDM_BASE_LOCK_H_
|
#endif // WVCDM_CORE_LOCK_H_
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
//
|
//
|
||||||
// Log - Platform independent interface for a Logging class
|
// Log - Platform independent interface for a Logging class
|
||||||
//
|
//
|
||||||
#ifndef CDM_BASE_LOG_H_
|
#ifndef WVCDM_CORE_LOG_H_
|
||||||
#define CDM_BASE_LOG_H_
|
#define WVCDM_CORE_LOG_H_
|
||||||
|
|
||||||
namespace wvcdm {
|
namespace wvcdm {
|
||||||
|
|
||||||
@@ -17,13 +17,10 @@ typedef enum {
|
|||||||
LOG_VERBOSE
|
LOG_VERBOSE
|
||||||
} LogPriority;
|
} LogPriority;
|
||||||
|
|
||||||
// Required to enable/disable verbose logging (LOGV) in Chromium. In Chromium,
|
// Enable/disable verbose logging (LOGV).
|
||||||
// verbose logging level is controlled using command line switches --v (global)
|
// This function is supplied for cases where the system layer does not
|
||||||
// or --vmodule (per module). This function calls logging::InitLogging to
|
// initialize logging. This is also needed to initialize logging in
|
||||||
// initialize logging, which should have already been included in most Chromium
|
// unit tests.
|
||||||
// based binaries. However, it is typically not included by default in
|
|
||||||
// unittests, in particular, the unittests in CDM core need to call InitLogging
|
|
||||||
// to be able to control verbose logging in command line.
|
|
||||||
void InitLogging(int argc, const char* const* argv);
|
void InitLogging(int argc, const char* const* argv);
|
||||||
|
|
||||||
void Log(const char* file, int line, LogPriority level, const char* fmt, ...);
|
void Log(const char* file, int line, LogPriority level, const char* fmt, ...);
|
||||||
@@ -37,4 +34,4 @@ void Log(const char* file, int line, LogPriority level, const char* fmt, ...);
|
|||||||
|
|
||||||
}; // namespace wvcdm
|
}; // namespace wvcdm
|
||||||
|
|
||||||
#endif // CDM_BASE_LOG_H_
|
#endif // WVCDM_CORE_LOG_H_
|
||||||
|
|||||||
@@ -1,15 +1,11 @@
|
|||||||
/*********************************************************************
|
// Copyright 2013 Google Inc. All Rights Reserved.
|
||||||
* oemcrypto_adapter.h
|
//
|
||||||
*
|
// oemcrypto_adapter.h
|
||||||
* (c) Copyright 2013 Google, Inc.
|
// This interface allows CDM to open a Level 3 session instead of
|
||||||
*
|
// letting the wrapper function choose between level 1 or level 3.
|
||||||
* This interface allows CDM to open a Level 3 session instead of
|
//
|
||||||
* letting the wrapper function choose between level 1 or level 3.
|
#ifndef WVCDM_CORE_OEMCRYPTO_ADAPTER_H_
|
||||||
*
|
#define WVCDM_CORE_OEMCRYPTO_ADAPTER_H_
|
||||||
*********************************************************************/
|
|
||||||
|
|
||||||
#ifndef OEMCRYPTO_ADAPTER_H_
|
|
||||||
#define OEMCRYPTO_ADAPTER_H_
|
|
||||||
|
|
||||||
#include "OEMCryptoCENC.h"
|
#include "OEMCryptoCENC.h"
|
||||||
|
|
||||||
@@ -37,4 +33,4 @@ const char* OEMCrypto_SecurityLevel(SecurityLevel level);
|
|||||||
bool OEMCrypto_SupportsUsageTable(SecurityLevel level);
|
bool OEMCrypto_SupportsUsageTable(SecurityLevel level);
|
||||||
} // namespace wvcdm
|
} // namespace wvcdm
|
||||||
|
|
||||||
#endif // OEMCRYPTO_ADAPTER_H_
|
#endif // WVCDM_CORE_OEMCRYPTO_ADAPTER_H_
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Copyright 2013 Google Inc. All Rights Reserved.
|
// Copyright 2013 Google Inc. All Rights Reserved.
|
||||||
|
|
||||||
#ifndef CDM_BASE_POLICY_ENGINE_H_
|
#ifndef WVCDM_CORE_POLICY_ENGINE_H_
|
||||||
#define CDM_BASE_POLICY_ENGINE_H_
|
#define WVCDM_CORE_POLICY_ENGINE_H_
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@@ -118,5 +118,4 @@ class PolicyEngine {
|
|||||||
|
|
||||||
} // wvcdm
|
} // wvcdm
|
||||||
|
|
||||||
#endif // CDM_BASE_POLICY_ENGINE_H_
|
#endif // WVCDM_CORE_POLICY_ENGINE_H_
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
// Copyright 2013 Google Inc. All Rights Reserved.
|
// Copyright 2013 Google Inc. All Rights Reserved.
|
||||||
//
|
//
|
||||||
// RsaPublicKey based on //depot/google3/video/widevine/common/rsa_key.h by
|
|
||||||
// tinskip@google.com.
|
|
||||||
//
|
|
||||||
// Description:
|
// Description:
|
||||||
// Declaration of classes representing AES and RSA public keys used
|
// Declaration of classes representing AES and RSA public keys used
|
||||||
// for signature verification and encryption.
|
// for signature verification and encryption.
|
||||||
@@ -21,9 +18,9 @@
|
|||||||
// Algorithm: RSA-OAEP
|
// Algorithm: RSA-OAEP
|
||||||
// Mask generation function: mgf1SHA1
|
// Mask generation function: mgf1SHA1
|
||||||
// Label (encoding paramter): empty string
|
// Label (encoding paramter): empty string
|
||||||
|
//
|
||||||
#ifndef CDM_BASE_PRIVACY_CRYPTO_H_
|
#ifndef WVCDM_CORE_PRIVACY_CRYPTO_H_
|
||||||
#define CDM_BASE_PRIVACY_CRYPTO_H_
|
#define WVCDM_CORE_PRIVACY_CRYPTO_H_
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@@ -74,4 +71,4 @@ class RsaPublicKey {
|
|||||||
|
|
||||||
} // namespace wvcdm
|
} // namespace wvcdm
|
||||||
|
|
||||||
#endif // CDM_BASE_PRIVACY_CRYPTO_H_
|
#endif // WVCDM_CORE_PRIVACY_CRYPTO_H_
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Copyright 2013 Google Inc. All Rights Reserved.
|
// Copyright 2013 Google Inc. All Rights Reserved.
|
||||||
|
|
||||||
#ifndef CDM_BASE_PROPERTIES_H_
|
#ifndef WVCDM_CORE_PROPERTIES_H_
|
||||||
#define CDM_BASE_PROPERTIES_H_
|
#define WVCDM_CORE_PROPERTIES_H_
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -121,4 +121,4 @@ class Properties {
|
|||||||
|
|
||||||
} // namespace wvcdm
|
} // namespace wvcdm
|
||||||
|
|
||||||
#endif // CDM_BASE_PROPERTIES_H_
|
#endif // WVCDM_CORE_PROPERTIES_H_
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
// A simple and partial implementation of scoped_ptr class.
|
// A simple and partial implementation of scoped_ptr class.
|
||||||
// The implementation is copied from gtest/include/gtest/internal/gtest-port.h.
|
// The implementation is copied from gtest/include/gtest/internal/gtest-port.h.
|
||||||
//
|
//
|
||||||
#ifndef CDM_BASE_SCOPED_PTR_H_
|
#ifndef WVCDM_CORE_SCOPED_PTR_H_
|
||||||
#define CDM_BASE_SCOPED_PTR_H_
|
#define WVCDM_CORE_SCOPED_PTR_H_
|
||||||
|
|
||||||
#include "wv_cdm_types.h"
|
#include "wv_cdm_types.h"
|
||||||
|
|
||||||
@@ -61,4 +61,4 @@ class scoped_ptr {
|
|||||||
|
|
||||||
}; // namespace wvcdm
|
}; // namespace wvcdm
|
||||||
|
|
||||||
#endif // CDM_BASE_SCOPED_PTR_H_
|
#endif // WVCDM_CORE_SCOPED_PTR_H_
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Copyright 2013 Google Inc. All Rights Reserved.
|
// Copyright 2013 Google Inc. All Rights Reserved.
|
||||||
|
|
||||||
#ifndef CDM_BASE_STRING_CONVERSIONS_H_
|
#ifndef WVCDM_CORE_STRING_CONVERSIONS_H_
|
||||||
#define CDM_BASE_STRING_CONVERSIONS_H_
|
#define WVCDM_CORE_STRING_CONVERSIONS_H_
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@@ -25,4 +25,4 @@ int64_t htonll64(int64_t x);
|
|||||||
|
|
||||||
}; // namespace wvcdm
|
}; // namespace wvcdm
|
||||||
|
|
||||||
#endif // CDM_BASE_STRING_CONVERSIONS_H_
|
#endif // WVCDM_CORE_STRING_CONVERSIONS_H_
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
//
|
//
|
||||||
// Timer - Platform independent interface for a Timer class
|
// Timer - Platform independent interface for a Timer class
|
||||||
//
|
//
|
||||||
#ifndef CDM_BASE_TIMER_H_
|
#ifndef WVCDM_CORE_TIMER_H_
|
||||||
#define CDM_BASE_TIMER_H_
|
#define WVCDM_CORE_TIMER_H_
|
||||||
|
|
||||||
#include "wv_cdm_types.h"
|
#include "wv_cdm_types.h"
|
||||||
|
|
||||||
@@ -48,4 +48,4 @@ class Timer {
|
|||||||
|
|
||||||
}; // namespace wvcdm
|
}; // namespace wvcdm
|
||||||
|
|
||||||
#endif // CDM_BASE_TIMER_H_
|
#endif // WVCDM_CORE_TIMER_H_
|
||||||
|
|||||||
@@ -1,15 +1,12 @@
|
|||||||
// Copyright 2012 Google Inc. All Rights Reserved.
|
// Copyright 2012 Google Inc. All Rights Reserved.
|
||||||
|
|
||||||
#ifndef CDM_BASE_WV_CDM_CONSTANTS_H_
|
#ifndef WVCDM_CORE_WV_CDM_CONSTANTS_H_
|
||||||
#define CDM_BASE_WV_CDM_CONSTANTS_H_
|
#define WVCDM_CORE_WV_CDM_CONSTANTS_H_
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace wvcdm {
|
namespace wvcdm {
|
||||||
static const size_t KEY_CONTROL_SIZE = 16;
|
static const size_t KEY_CONTROL_SIZE = 16;
|
||||||
// TODO(kqyang): Key ID size is not fixed in spec, but conventionally we
|
|
||||||
// always use 16 bytes key id. We'll need to update oemcrypto to support
|
|
||||||
// variable size key id.
|
|
||||||
static const size_t KEY_ID_SIZE = 16;
|
static const size_t KEY_ID_SIZE = 16;
|
||||||
static const size_t KEY_IV_SIZE = 16;
|
static const size_t KEY_IV_SIZE = 16;
|
||||||
static const size_t KEY_PAD_SIZE = 16;
|
static const size_t KEY_PAD_SIZE = 16;
|
||||||
@@ -64,4 +61,4 @@ static const std::string CENC_INIT_DATA_FORMAT = "cenc";
|
|||||||
static const std::string WEBM_INIT_DATA_FORMAT = "webm";
|
static const std::string WEBM_INIT_DATA_FORMAT = "webm";
|
||||||
} // namespace wvcdm
|
} // namespace wvcdm
|
||||||
|
|
||||||
#endif // CDM_BASE_WV_CDM_CONSTANTS_H_
|
#endif // WVCDM_CORE_WV_CDM_CONSTANTS_H_
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Copyright 2012 Google Inc. All Rights Reserved.
|
// Copyright 2012 Google Inc. All Rights Reserved.
|
||||||
|
|
||||||
#ifndef CDM_BASE_WV_CDM_EVENT_LISTENER_H_
|
#ifndef WVCDM_CORE_WV_CDM_EVENT_LISTENER_H_
|
||||||
#define CDM_BASE_WV_CDM_EVENT_LISTENER_H_
|
#define WVCDM_CORE_WV_CDM_EVENT_LISTENER_H_
|
||||||
|
|
||||||
#include "wv_cdm_types.h"
|
#include "wv_cdm_types.h"
|
||||||
|
|
||||||
@@ -25,4 +25,4 @@ class WvCdmEventListener {
|
|||||||
|
|
||||||
} // namespace wvcdm
|
} // namespace wvcdm
|
||||||
|
|
||||||
#endif // CDM_BASE_WV_CDM_EVENT_LISTENER_H_
|
#endif // WVCDM_CORE_WV_CDM_EVENT_LISTENER_H_
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Copyright 2013 Google Inc. All Rights Reserved.
|
// Copyright 2013 Google Inc. All Rights Reserved.
|
||||||
|
|
||||||
#ifndef CDM_BASE_WV_CDM_TYPES_H_
|
#ifndef WVCDM_CORE_WV_CDM_TYPES_H_
|
||||||
#define CDM_BASE_WV_CDM_TYPES_H_
|
#define WVCDM_CORE_WV_CDM_TYPES_H_
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@@ -125,4 +125,4 @@ class Key;
|
|||||||
|
|
||||||
} // namespace wvcdm
|
} // namespace wvcdm
|
||||||
|
|
||||||
#endif // CDM_BASE_WV_CDM_TYPES_H_
|
#endif // WVCDM_CORE_WV_CDM_TYPES_H_
|
||||||
|
|||||||
@@ -19,7 +19,8 @@ bool BufferReader::Read1(uint8_t* v) {
|
|||||||
// Internal implementation of multi-byte reads
|
// Internal implementation of multi-byte reads
|
||||||
template<typename T> bool BufferReader::Read(T* v) {
|
template<typename T> bool BufferReader::Read(T* v) {
|
||||||
if (!HasBytes(sizeof(T))) {
|
if (!HasBytes(sizeof(T))) {
|
||||||
LOGE("BufferReader::Read<T> : Failure while parsing: Not enough bytes (%u)", sizeof(T));
|
LOGE("BufferReader::Read<T> : Failure during parse: Not enough bytes (%u)",
|
||||||
|
sizeof(T));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,7 +42,8 @@ bool BufferReader::Read8s(int64_t* v) { return Read(v); }
|
|||||||
|
|
||||||
bool BufferReader::ReadString(std::string* str, int count) {
|
bool BufferReader::ReadString(std::string* str, int count) {
|
||||||
if (!HasBytes(count)) {
|
if (!HasBytes(count)) {
|
||||||
LOGE("BufferReader::ReadString : Failure while parsing: Not enough bytes (%d)", count);
|
LOGE("BufferReader::ReadString : Parse Failure: Not enough bytes (%d)",
|
||||||
|
count);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,7 +54,7 @@ bool BufferReader::ReadString(std::string* str, int count) {
|
|||||||
|
|
||||||
bool BufferReader::ReadVec(std::vector<uint8_t>* vec, int count) {
|
bool BufferReader::ReadVec(std::vector<uint8_t>* vec, int count) {
|
||||||
if (!HasBytes(count)) {
|
if (!HasBytes(count)) {
|
||||||
LOGE("BufferReader::ReadVec : Failure while parsing: Not enough bytes (%d)", count);
|
LOGE("BufferReader::ReadVec : Parse Failure: Not enough bytes (%d)", count);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,7 +66,8 @@ bool BufferReader::ReadVec(std::vector<uint8_t>* vec, int count) {
|
|||||||
|
|
||||||
bool BufferReader::SkipBytes(int bytes) {
|
bool BufferReader::SkipBytes(int bytes) {
|
||||||
if (!HasBytes(bytes)) {
|
if (!HasBytes(bytes)) {
|
||||||
LOGE("BufferReader::SkipBytes : Failure while parsing: Not enough bytes (%d)", bytes);
|
LOGE("BufferReader::SkipBytes : Parse Failure: Not enough bytes (%d)",
|
||||||
|
bytes);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -57,8 +57,9 @@ CdmResponseType CdmEngine::OpenSession(
|
|||||||
if (sts == NEED_PROVISIONING) {
|
if (sts == NEED_PROVISIONING) {
|
||||||
cert_provisioning_requested_security_level_ =
|
cert_provisioning_requested_security_level_ =
|
||||||
new_session->GetRequestedSecurityLevel();
|
new_session->GetRequestedSecurityLevel();
|
||||||
}
|
} else {
|
||||||
LOGE("CdmEngine::OpenSession: bad session init: %u", sts);
|
LOGE("CdmEngine::OpenSession: bad session init: %u", sts);
|
||||||
|
}
|
||||||
return sts;
|
return sts;
|
||||||
}
|
}
|
||||||
*session_id = new_session->session_id();
|
*session_id = new_session->session_id();
|
||||||
@@ -278,7 +279,8 @@ CdmResponseType CdmEngine::CancelKeyRequest(const CdmSessionId& session_id) {
|
|||||||
|
|
||||||
CdmSessionMap::iterator iter = sessions_.find(session_id);
|
CdmSessionMap::iterator iter = sessions_.find(session_id);
|
||||||
if (iter == sessions_.end()) {
|
if (iter == sessions_.end()) {
|
||||||
LOGE("CdmEngine::CancelKeyRequest: session_id not found = %s", session_id.c_str());
|
LOGE("CdmEngine::CancelKeyRequest: session_id not found = %s",
|
||||||
|
session_id.c_str());
|
||||||
return KEY_ERROR;
|
return KEY_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -295,12 +297,13 @@ CdmResponseType CdmEngine::GenerateRenewalRequest(
|
|||||||
|
|
||||||
CdmSessionMap::iterator iter = sessions_.find(session_id);
|
CdmSessionMap::iterator iter = sessions_.find(session_id);
|
||||||
if (iter == sessions_.end()) {
|
if (iter == sessions_.end()) {
|
||||||
LOGE("CdmEngine::GenerateRenewalRequest: session_id not found = %s", session_id.c_str());
|
LOGE("CdmEngine::GenerateRenewalRequest: session_id not found = %s",
|
||||||
|
session_id.c_str());
|
||||||
return KEY_ERROR;
|
return KEY_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!key_request) {
|
if (!key_request) {
|
||||||
LOGE("CdmEngine::GenerateRenewalRequest: no key request destination provided");
|
LOGE("CdmEngine::GenerateRenewalRequest: no key request destination");
|
||||||
return KEY_ERROR;
|
return KEY_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -310,7 +313,7 @@ CdmResponseType CdmEngine::GenerateRenewalRequest(
|
|||||||
server_url);
|
server_url);
|
||||||
|
|
||||||
if (KEY_MESSAGE != sts) {
|
if (KEY_MESSAGE != sts) {
|
||||||
LOGE("CdmEngine::GenerateRenewalRequest: key request generation failed, sts=%d",
|
LOGE("CdmEngine::GenerateRenewalRequest: key request gen. failed, sts=%d",
|
||||||
(int)sts);
|
(int)sts);
|
||||||
return sts;
|
return sts;
|
||||||
}
|
}
|
||||||
@@ -406,7 +409,8 @@ CdmResponseType CdmEngine::QueryKeyStatus(
|
|||||||
LOGI("CdmEngine::QueryKeyStatus");
|
LOGI("CdmEngine::QueryKeyStatus");
|
||||||
CdmSessionMap::iterator iter = sessions_.find(session_id);
|
CdmSessionMap::iterator iter = sessions_.find(session_id);
|
||||||
if (iter == sessions_.end()) {
|
if (iter == sessions_.end()) {
|
||||||
LOGE("CdmEngine::QueryKeyStatus: session_id not found = %s", session_id.c_str());
|
LOGE("CdmEngine::QueryKeyStatus: session_id not found = %s",
|
||||||
|
session_id.c_str());
|
||||||
return KEY_ERROR;
|
return KEY_ERROR;
|
||||||
}
|
}
|
||||||
return iter->second->QueryKeyStatus(key_info);
|
return iter->second->QueryKeyStatus(key_info);
|
||||||
@@ -418,7 +422,8 @@ CdmResponseType CdmEngine::QueryKeyControlInfo(
|
|||||||
LOGI("CdmEngine::QueryKeyControlInfo");
|
LOGI("CdmEngine::QueryKeyControlInfo");
|
||||||
CdmSessionMap::iterator iter = sessions_.find(session_id);
|
CdmSessionMap::iterator iter = sessions_.find(session_id);
|
||||||
if (iter == sessions_.end()) {
|
if (iter == sessions_.end()) {
|
||||||
LOGE("CdmEngine::QueryKeyControlInfo: session_id not found = %s", session_id.c_str());
|
LOGE("CdmEngine::QueryKeyControlInfo: session_id not found = %s",
|
||||||
|
session_id.c_str());
|
||||||
return KEY_ERROR;
|
return KEY_ERROR;
|
||||||
}
|
}
|
||||||
return iter->second->QueryKeyControlInfo(key_info);
|
return iter->second->QueryKeyControlInfo(key_info);
|
||||||
|
|||||||
@@ -9,7 +9,11 @@
|
|||||||
#include "wv_cdm_constants.h"
|
#include "wv_cdm_constants.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
const std::string kDefaultProvisioningServerUrl =
|
|
||||||
|
// URL for Google Provisioning Server.
|
||||||
|
// This server supplies the certificate that is needed
|
||||||
|
// to communicate with the License Server.
|
||||||
|
const std::string kProvisioningServerUrl =
|
||||||
"https://www.googleapis.com/"
|
"https://www.googleapis.com/"
|
||||||
"certificateprovisioning/v1/devicecertificates/create"
|
"certificateprovisioning/v1/devicecertificates/create"
|
||||||
"?key=AIzaSyB-5OLKTx2iU5mko18DfdwK5611JIjbUhE";
|
"?key=AIzaSyB-5OLKTx2iU5mko18DfdwK5611JIjbUhE";
|
||||||
@@ -60,7 +64,12 @@ CdmResponseType CertificateProvisioning::GetProvisioningRequest(
|
|||||||
const std::string& cert_authority,
|
const std::string& cert_authority,
|
||||||
CdmProvisioningRequest* request,
|
CdmProvisioningRequest* request,
|
||||||
std::string* default_url) {
|
std::string* default_url) {
|
||||||
default_url->assign(kDefaultProvisioningServerUrl);
|
if (!default_url) {
|
||||||
|
LOGE("GetProvisioningRequest: pointer for returning URL is NULL");
|
||||||
|
return UNKNOWN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
default_url->assign(kProvisioningServerUrl);
|
||||||
|
|
||||||
CdmResponseType sts = crypto_session_.Open(requested_security_level);
|
CdmResponseType sts = crypto_session_.Open(requested_security_level);
|
||||||
if (NO_ERROR != sts) {
|
if (NO_ERROR != sts) {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
#include "crypto_session.h"
|
#include "crypto_session.h"
|
||||||
|
|
||||||
#include <arpa/inet.h> // TODO(fredgc): Add ntoh to wv_cdm_utilities.h
|
#include <arpa/inet.h> // needed for ntoh()
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include "crypto_key.h"
|
#include "crypto_key.h"
|
||||||
|
|||||||
@@ -202,7 +202,6 @@ bool CdmLicense::PrepareKeyRequest(const InitializationData& init_data,
|
|||||||
return PrepareServiceCertificateRequest(signed_request, server_url);
|
return PrepareServiceCertificateRequest(signed_request, server_url);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(gmorgan): Request ID owned by session?
|
|
||||||
std::string request_id;
|
std::string request_id;
|
||||||
session_->GenerateRequestId(request_id);
|
session_->GenerateRequestId(request_id);
|
||||||
|
|
||||||
|
|||||||
@@ -4,20 +4,8 @@
|
|||||||
// Copyright 2013 Google Inc. All Rights Reserved.
|
// Copyright 2013 Google Inc. All Rights Reserved.
|
||||||
//
|
//
|
||||||
// Description:
|
// Description:
|
||||||
// Merges certificate_provisioning.proto and client_identification.proto
|
|
||||||
// inline to avoid having to hardcode the import path. This is a temporary
|
|
||||||
// workaround for not getting proto_path to work in Android build envionment.
|
|
||||||
//
|
|
||||||
// Origin:
|
|
||||||
// This file is derived from the authoritative source file at
|
|
||||||
// https://cs.corp.google.com/#google3/video/widevine/server/sdk/
|
|
||||||
// license_protocol.proto
|
|
||||||
//
|
|
||||||
// Description:
|
|
||||||
// Definitions of the protocol buffer messages used in the Widevine license
|
// Definitions of the protocol buffer messages used in the Widevine license
|
||||||
// exchange protocol, which is described in the document
|
// exchange protocol.
|
||||||
// https://docs.google.com/a/google.com/document/d/
|
|
||||||
// 1cng6cDnchbDQDymLEd5MxMc_laS3EDv6IsoW3IzpgwQ
|
|
||||||
|
|
||||||
syntax = "proto2";
|
syntax = "proto2";
|
||||||
|
|
||||||
@@ -124,8 +112,6 @@ message License {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message KeyControl {
|
message KeyControl {
|
||||||
// |key_control| is documented here:
|
|
||||||
// https://docs.google.com/a/google.com/document/d/17eDxzzGpPc2qSm7zW68_5ensuxbHErYCvD3IxSKETRo/edit#
|
|
||||||
// If present, the key control must be communicated to the secure
|
// If present, the key control must be communicated to the secure
|
||||||
// environment prior to any usage. This message is automatically generated
|
// environment prior to any usage. This message is automatically generated
|
||||||
// by the Widevine License Server SDK.
|
// by the Widevine License Server SDK.
|
||||||
@@ -233,7 +219,6 @@ message LicenseRequest {
|
|||||||
optional EncryptedClientIdentification encrypted_client_id = 8;
|
optional EncryptedClientIdentification encrypted_client_id = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
message LicenseError {
|
message LicenseError {
|
||||||
enum Error {
|
enum Error {
|
||||||
// The device credentials are invalid. The device must re-provision.
|
// The device credentials are invalid. The device must re-provision.
|
||||||
@@ -286,17 +271,14 @@ message SessionState {
|
|||||||
// certificate_provisioning.proto
|
// certificate_provisioning.proto
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Copyright 2013 Google Inc. All Rights Reserved.
|
// Copyright 2013 Google Inc. All Rights Reserved.
|
||||||
// Author: tinskip@google.com (Thomas Inskip)
|
|
||||||
//
|
//
|
||||||
// Description:
|
// Description:
|
||||||
// Public protocol buffer definitions for Widevine Device Certificate
|
// Public protocol buffer definitions for Widevine Device Certificate
|
||||||
// Provisioning protocol.
|
// Provisioning protocol.
|
||||||
|
|
||||||
// PROPOSED message for customizing provisioning request.
|
// ProvisioningOptions specifies the type of certificate to specify and
|
||||||
// This could support requesting specificy types of certificates.
|
// in the case of X509 certificates, the certificate authority to use.
|
||||||
// E.g. Cast X.509 certs.
|
|
||||||
message ProvisioningOptions {
|
message ProvisioningOptions {
|
||||||
// PROPOSED enum identifying the certificate type.
|
|
||||||
enum CertificateType {
|
enum CertificateType {
|
||||||
RSA_WIDEVINE = 0; // Default. The original certificate type.
|
RSA_WIDEVINE = 0; // Default. The original certificate type.
|
||||||
X509 = 1; // X.509 certificate.
|
X509 = 1; // X.509 certificate.
|
||||||
@@ -304,8 +286,8 @@ message ProvisioningOptions {
|
|||||||
|
|
||||||
optional CertificateType certificate_type = 1;
|
optional CertificateType certificate_type = 1;
|
||||||
|
|
||||||
// OPEN QUESTION: How does the client specify the cert root authority?
|
// It is recommended that the certificate_authority specify the X.509
|
||||||
// Should this be the cert authority's domain? E.g. foo.com?
|
// Subject of the signing certificate.
|
||||||
optional string certificate_authority = 2;
|
optional string certificate_authority = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -320,10 +302,6 @@ message ProvisioningRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Provisioning response sent by the provisioning server to client devices.
|
// Provisioning response sent by the provisioning server to client devices.
|
||||||
//
|
|
||||||
// PROPOSAL: The contents of this message vary depending upon the value of
|
|
||||||
// CertificateType in options. TODO(blueeyes): Determine the right way to
|
|
||||||
// transfer X.509 certs.
|
|
||||||
message ProvisioningResponse {
|
message ProvisioningResponse {
|
||||||
// AES-128 encrypted device private RSA key. PKCS#1 ASN.1 DER-encoded.
|
// AES-128 encrypted device private RSA key. PKCS#1 ASN.1 DER-encoded.
|
||||||
// Required.
|
// Required.
|
||||||
@@ -349,12 +327,6 @@ message SignedProvisioningMessage {
|
|||||||
// client_identification.proto
|
// client_identification.proto
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Copyright 2013 Google Inc. All Rights Reserved.
|
// Copyright 2013 Google Inc. All Rights Reserved.
|
||||||
// Author: tinskip@google.com (Thomas Inskip)
|
|
||||||
//
|
|
||||||
// Origin:
|
|
||||||
// This file is derived from the authoritative source file at
|
|
||||||
// https://cs.corp.google.com/#google3/video/widevine/server/sdk/
|
|
||||||
// license_protocol.proto
|
|
||||||
//
|
//
|
||||||
// Description:
|
// Description:
|
||||||
// ClientIdentification messages used by provisioning and license protocols.
|
// ClientIdentification messages used by provisioning and license protocols.
|
||||||
@@ -388,8 +360,8 @@ message EncryptedClientIdentification {
|
|||||||
// Serial number for the service certificate for which ClientIdentification is
|
// Serial number for the service certificate for which ClientIdentification is
|
||||||
// encrypted.
|
// encrypted.
|
||||||
optional string service_certificate_serial_number = 2;
|
optional string service_certificate_serial_number = 2;
|
||||||
// Serialized ClientIdentification message, encrypted with the privacy key using
|
// Serialized ClientIdentification message, encrypted with the privacy key
|
||||||
// AES-128-CBC with PKCS#5 padding.
|
// using AES-128-CBC with PKCS#5 padding.
|
||||||
optional bytes encrypted_client_id = 3;
|
optional bytes encrypted_client_id = 3;
|
||||||
// Initialization vector needed to decrypt encrypted_client_id.
|
// Initialization vector needed to decrypt encrypted_client_id.
|
||||||
optional bytes encrypted_client_id_iv = 4;
|
optional bytes encrypted_client_id_iv = 4;
|
||||||
@@ -402,7 +374,6 @@ message EncryptedClientIdentification {
|
|||||||
// device_certificate.proto
|
// device_certificate.proto
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Copyright 2013 Google Inc. All Rights Reserved.
|
// Copyright 2013 Google Inc. All Rights Reserved.
|
||||||
// Author: tinskip@google.com (Thomas Inskip)
|
|
||||||
//
|
//
|
||||||
// Description:
|
// Description:
|
||||||
// Device certificate and certificate status list format definitions.
|
// Device certificate and certificate status list format definitions.
|
||||||
@@ -452,8 +423,8 @@ message SignedDeviceCertificate {
|
|||||||
// Contains device model information for a provisioned device.
|
// Contains device model information for a provisioned device.
|
||||||
message ProvisionedDeviceInfo {
|
message ProvisionedDeviceInfo {
|
||||||
enum WvSecurityLevel {
|
enum WvSecurityLevel {
|
||||||
// Defined in Widevine Security Integration Guide for DASH on Android:
|
// Defined in "WV Modular DRM Security Integration Guide for
|
||||||
// https://docs.google.com/a/google.com/document/d/1Zum-fcJeoIw6KG1kDP_KepIE5h9gAZg0PaMtemBvk9c/edit#heading=h.1t3h5sf
|
// Common Encryption (CENC)"
|
||||||
LEVEL_UNSPECIFIED = 0;
|
LEVEL_UNSPECIFIED = 0;
|
||||||
LEVEL_1 = 1;
|
LEVEL_1 = 1;
|
||||||
LEVEL_2 = 2;
|
LEVEL_2 = 2;
|
||||||
|
|||||||
@@ -1,14 +1,11 @@
|
|||||||
/*******************************************************************************
|
// Copyright 2013 Google Inc. All Rights Reserved.
|
||||||
*
|
//
|
||||||
* Copyright 2013 Google Inc. All Rights Reserved.
|
// Wrapper of OEMCrypto APIs for platforms that support both Levels 1 and 3.
|
||||||
*
|
// This should be used when liboemcrypto.so is dynamically loaded at run
|
||||||
* Wrapper of OEMCrypto APIs for platforms that support both Levels 1 and 3.
|
// time and not linked with the CDM code at compile time.
|
||||||
* This should be used when liboemcrypto.so is dynamically loaded at run
|
// An implementation should compile either oemcrypto_adapter_dynamic.cpp or
|
||||||
* time and not linked with the CDM code at compile time.
|
// oemcrypto_adapter_static.cpp, but not both.
|
||||||
* An implementation should compile either oemcrypto_adapter_dynamic.cpp or
|
//
|
||||||
* oemcrypto_adapter_static.cpp, but not both.
|
|
||||||
*
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
#include "oemcrypto_adapter.h"
|
#include "oemcrypto_adapter.h"
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,9 @@
|
|||||||
/*******************************************************************************
|
// Copyright 2013 Google Inc. All Rights Reserved.
|
||||||
*
|
//
|
||||||
* Copyright 2013 Google Inc. All Rights Reserved.
|
// Wrapper of OEMCrypto APIs for platforms that support Level 1 only.
|
||||||
*
|
// This should be used when liboemcrypto.so is linked with the CDM code at
|
||||||
* Wrapper of OEMCrypto APIs for platforms that support Level 1 only.
|
// compile time.
|
||||||
* This should be used when liboemcrypto.so is linked with the CDM code at
|
//
|
||||||
* compile time.
|
|
||||||
* An implementation should compile either oemcrypto_adapter_dynamic.cpp or
|
|
||||||
* oemcrypto_adapter_static.cpp, but not both.
|
|
||||||
*
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
#include "OEMCryptoCENC.h"
|
#include "OEMCryptoCENC.h"
|
||||||
#include "oemcrypto_adapter.h"
|
#include "oemcrypto_adapter.h"
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ extern "C" OEMCryptoResult OEMCrypto_LoadKeys(
|
|||||||
const uint8_t* enc_mac_key_iv, const uint8_t* enc_mac_key, size_t num_keys,
|
const uint8_t* enc_mac_key_iv, const uint8_t* enc_mac_key, size_t num_keys,
|
||||||
const OEMCrypto_KeyObject* key_array,
|
const OEMCrypto_KeyObject* key_array,
|
||||||
const uint8_t* pst, size_t pst_length) {
|
const uint8_t* pst, size_t pst_length) {
|
||||||
return LoadKeys_V8(pair.session, message, message_length, signature,
|
return OEMCrypto_LoadKeys_V8(session, message, message_length, signature,
|
||||||
signature_length, enc_mac_key_iv, enc_mac_key,
|
signature_length, enc_mac_key_iv, enc_mac_key,
|
||||||
num_keys, key_array);
|
num_keys, key_array);
|
||||||
}
|
}
|
||||||
@@ -84,7 +84,7 @@ extern "C" OEMCryptoResult OEMCrypto_LoadKeys(
|
|||||||
extern "C" OEMCryptoResult OEMCrypto_GenerateRSASignature(
|
extern "C" OEMCryptoResult OEMCrypto_GenerateRSASignature(
|
||||||
OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
|
OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
|
||||||
uint8_t* signature, size_t* signature_length, RSA_Padding_Scheme padding_scheme) {
|
uint8_t* signature, size_t* signature_length, RSA_Padding_Scheme padding_scheme) {
|
||||||
return GenerateRSASignature_V8(pair.session, message, message_length,
|
return OEMCrypto_GenerateRSASignature_V8(session, message, message_length,
|
||||||
signature, signature_length);
|
signature, signature_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -127,10 +127,6 @@ void PolicyEngine::UpdateLicense(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// TODO(edwingwong, rfrias): Check back with Thomas and see if
|
|
||||||
// we need to enforce that all duration windows are absent if
|
|
||||||
// license_start_time is not present. This is a TBD.
|
|
||||||
|
|
||||||
// if renewal, discard license if version has not been updated
|
// if renewal, discard license if version has not been updated
|
||||||
if (license.id().version() > license_id_.version())
|
if (license.id().version() > license_id_.version())
|
||||||
license_id_.CopyFrom(license.id());
|
license_id_.CopyFrom(license.id());
|
||||||
@@ -140,9 +136,6 @@ void PolicyEngine::UpdateLicense(
|
|||||||
|
|
||||||
// Update time information
|
// Update time information
|
||||||
int64_t current_time = clock_->GetCurrentTime();
|
int64_t current_time = clock_->GetCurrentTime();
|
||||||
// TODO(edwingwong, rfrias): Check back with Thomas and see if
|
|
||||||
// we need to enforce that all duration windows are absent if
|
|
||||||
// license_start_time is not present. This is a TBD.
|
|
||||||
if (license.has_license_start_time())
|
if (license.has_license_start_time())
|
||||||
license_start_time_ = license.license_start_time();
|
license_start_time_ = license.license_start_time();
|
||||||
license_received_time_ = current_time;
|
license_received_time_ = current_time;
|
||||||
@@ -276,10 +269,9 @@ bool PolicyEngine::IsRenewalDelayExpired(int64_t current_time) {
|
|||||||
current_time;
|
current_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(jfore, edwinwong, rfrias): This field is in flux and currently
|
|
||||||
// not implemented. Will address after possible updates from Thomas.
|
|
||||||
bool PolicyEngine::IsRenewalRecoveryDurationExpired(
|
bool PolicyEngine::IsRenewalRecoveryDurationExpired(
|
||||||
int64_t current_time) {
|
int64_t current_time) {
|
||||||
|
// NOTE: Renewal Recovery Duration is currently not used.
|
||||||
return (policy_.renewal_recovery_duration_seconds() > 0) &&
|
return (policy_.renewal_recovery_duration_seconds() > 0) &&
|
||||||
license_received_time_ + policy_.renewal_recovery_duration_seconds() <=
|
license_received_time_ + policy_.renewal_recovery_duration_seconds() <=
|
||||||
current_time;
|
current_time;
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
// Copyright 2013 Google Inc. All Rights Reserved.
|
// Copyright 2013 Google Inc. All Rights Reserved.
|
||||||
//
|
//
|
||||||
// Original code at //depot/google3/video/widevine/common/rsa_key.cc by
|
|
||||||
// tinskip@google.com. Modified for core CDM usage.
|
|
||||||
//
|
|
||||||
// Description:
|
// Description:
|
||||||
// Definition of classes representing RSA public keys used
|
// Definition of classes representing RSA public keys used
|
||||||
// for signature verification and encryption and decryption.
|
// for signature verification and encryption and decryption.
|
||||||
|
|||||||
@@ -75,10 +75,10 @@ std::string b2a_hex(const std::string& byte) {
|
|||||||
byte.length());
|
byte.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filename-friendly base64 encoding (RFC4648), commonly referred as
|
// Filename-friendly base64 encoding (RFC4648), commonly referred to
|
||||||
// Base64WebSafeEncode.
|
// as Base64WebSafeEncode.
|
||||||
// This is the encoding required by GooglePlay to interface with the
|
// This is the encoding required to interface with the provisioning
|
||||||
// provisioning server's Apiary interface as well as for certain license server
|
// server's Apiary interface as well as for certain license server
|
||||||
// transactions. It is also used for logging certain strings.
|
// transactions. It is also used for logging certain strings.
|
||||||
// The difference between web safe encoding vs regular encoding is that
|
// The difference between web safe encoding vs regular encoding is that
|
||||||
// the web safe version replaces '+' with '-' and '/' with '_'.
|
// the web safe version replaces '+' with '-' and '/' with '_'.
|
||||||
|
|||||||
@@ -1,861 +0,0 @@
|
|||||||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
|
||||||
// found in the LICENSE file.
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include <map>
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
#include "base/at_exit.h"
|
|
||||||
#include "base/basictypes.h"
|
|
||||||
#include "base/bind.h"
|
|
||||||
#include "base/message_loop.h"
|
|
||||||
#include "base/sys_byteorder.h"
|
|
||||||
#include "crypto/encryptor.h"
|
|
||||||
#include "crypto/hmac.h"
|
|
||||||
#include "crypto/symmetric_key.h"
|
|
||||||
#include "license_protocol.pb.h"
|
|
||||||
#include "testing/gtest/include/gtest/gtest.h"
|
|
||||||
#include "eureka/widevine_cdm/oemcrypto/client/oemcrypto_client.h"
|
|
||||||
#include "eureka/widevine_cdm/oemcrypto/mock/src/cmac.h"
|
|
||||||
#include "eureka/widevine_cdm/oemcrypto/mock/src/oemcrypto_keybox_mock.h"
|
|
||||||
#include "wv_cdm_types.h"
|
|
||||||
#include "wv_content_decryption_module.h"
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
namespace wv_license_protocol = video_widevine_server::sdk;
|
|
||||||
|
|
||||||
using wv_license_protocol::License;
|
|
||||||
using wv_license_protocol::LicenseIdentification;
|
|
||||||
using wv_license_protocol::LicenseRequest;
|
|
||||||
using wv_license_protocol::SessionState;
|
|
||||||
using wv_license_protocol::SignedMessage;
|
|
||||||
|
|
||||||
enum PolicyType {
|
|
||||||
kDefault = 0,
|
|
||||||
kNoPlay,
|
|
||||||
kShortDuration
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PolicyItem {
|
|
||||||
PolicyType type;
|
|
||||||
bool can_play;
|
|
||||||
bool can_renew;
|
|
||||||
int duration_seconds;
|
|
||||||
int renewal_delay_seconds;
|
|
||||||
int renewal_retry_interval_seconds;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PolicyItem PolicyItems[] = {
|
|
||||||
{
|
|
||||||
kDefault,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
1000,
|
|
||||||
100,
|
|
||||||
0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kShortDuration,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
12,
|
|
||||||
2,
|
|
||||||
2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kNoPlay,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO(jfore): Move this into the test class.
|
|
||||||
/*const*/ char kTestSigningKey[] = {
|
|
||||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
|
||||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
|
|
||||||
};
|
|
||||||
const int kTestSigningKeySize = arraysize(kTestSigningKey);
|
|
||||||
|
|
||||||
const char* kEncryptionKeyLabel = "ENCRYPTION";
|
|
||||||
const uint32_t kEncryptionKeySizeBits = 128;
|
|
||||||
const char* kSigningKeyLabel = "AUTHENTICATION";
|
|
||||||
const uint32_t kSigningKeySizeBits = 256;
|
|
||||||
|
|
||||||
// This is a container to hold the info for an encrypted frame.
|
|
||||||
struct WvCdmEncryptedFrameInfo {
|
|
||||||
char plain_text[32];
|
|
||||||
int plain_text_size;
|
|
||||||
uint8_t key_id[32];
|
|
||||||
int key_id_size;
|
|
||||||
uint8_t content_key[32];
|
|
||||||
int content_key_size;
|
|
||||||
uint8_t encrypted_data[64];
|
|
||||||
int encrypted_data_size;
|
|
||||||
PolicyType policy_type;
|
|
||||||
};
|
|
||||||
|
|
||||||
const WvCdmEncryptedFrameInfo kWvCdmEncryptedFrames[] = {
|
|
||||||
{
|
|
||||||
"Original data.", 14,
|
|
||||||
{ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
|
|
||||||
0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35
|
|
||||||
}, 16,
|
|
||||||
{ 0xeb, 0xdd, 0x62, 0xf1, 0x68, 0x14, 0xd2, 0x7b,
|
|
||||||
0x68, 0xef, 0x12, 0x2a, 0xfc, 0xe4, 0xae, 0x3c
|
|
||||||
}, 16,
|
|
||||||
{ 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0x82, 0x54, 0xab, 0x89, 0xa2, 0x75, 0xcd,
|
|
||||||
0x85, 0x83, 0x61, 0x3f, 0xfe, 0x13, 0x58
|
|
||||||
}, 23,
|
|
||||||
kShortDuration
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Original data.", 14,
|
|
||||||
{ 0x08, 0x01, 0x12, 0x10, 0x6f, 0x13, 0x33, 0xe7,
|
|
||||||
0x6e, 0x59, 0x5e, 0xb5, 0x8c, 0x04, 0x30, 0x72,
|
|
||||||
0xcb, 0xb2, 0x50, 0x68
|
|
||||||
}, 20,
|
|
||||||
{ 0xeb, 0xdd, 0x62, 0xf1, 0x68, 0x14, 0xd2, 0x7b,
|
|
||||||
0x68, 0xef, 0x12, 0x2a, 0xfc, 0xe4, 0xae, 0x3c
|
|
||||||
}, 16,
|
|
||||||
{ 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0x82, 0x54, 0xab, 0x89, 0xa2, 0x75, 0xcd,
|
|
||||||
0x85, 0x83, 0x61, 0x3f, 0xfe, 0x13, 0x58
|
|
||||||
}, 23,
|
|
||||||
kShortDuration
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Changed Original data.", 22,
|
|
||||||
{ 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02,
|
|
||||||
0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02
|
|
||||||
}, 16,
|
|
||||||
{ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
|
|
||||||
0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23
|
|
||||||
}, 16,
|
|
||||||
{ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x57, 0x66, 0xf4, 0x12, 0x1a, 0xed, 0xb5,
|
|
||||||
0x79, 0x1c, 0x8e, 0x25, 0xd7, 0x17, 0xe7, 0x5e,
|
|
||||||
0x16, 0xe3, 0x40, 0x08, 0x27, 0x11, 0xe9
|
|
||||||
}, 31,
|
|
||||||
kShortDuration
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Original data.", 14,
|
|
||||||
{ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
|
|
||||||
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f
|
|
||||||
}, 16,
|
|
||||||
{ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
|
|
||||||
0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40
|
|
||||||
}, 16,
|
|
||||||
{ 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x9c, 0x71, 0x26, 0x57, 0x3e, 0x25, 0x37,
|
|
||||||
0xf7, 0x31, 0x81, 0x19, 0x64, 0xce, 0xbc
|
|
||||||
}, 23,
|
|
||||||
kShortDuration
|
|
||||||
},
|
|
||||||
// For license renewal test. This has kNoPlay.
|
|
||||||
{
|
|
||||||
// Differnent key and key id.
|
|
||||||
"Original data.", 14,
|
|
||||||
{ 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
|
|
||||||
0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33
|
|
||||||
}, 16,
|
|
||||||
{ 0xeb, 0xdd, 0x62, 0xf1, 0x68, 0x14, 0xd2, 0x7b,
|
|
||||||
0x68, 0xef, 0x12, 0x2a, 0xfc, 0xe4, 0xae, 0x3c
|
|
||||||
}, 16,
|
|
||||||
{ 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0x82, 0x54, 0xab, 0x89, 0xa2, 0x75, 0xcd,
|
|
||||||
0x85, 0x83, 0x61, 0x3f, 0xfe, 0x13, 0x58
|
|
||||||
}, 23,
|
|
||||||
kNoPlay
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
bool GetPolicy(PolicyType policy_type, License::Policy* policy) {
|
|
||||||
DCHECK(policy);
|
|
||||||
PolicyItem policy_item;
|
|
||||||
switch (policy_type) {
|
|
||||||
case kDefault:
|
|
||||||
policy_item = PolicyItems[0];
|
|
||||||
DCHECK_EQ(policy_item.type, kDefault);
|
|
||||||
break;
|
|
||||||
case kShortDuration:
|
|
||||||
policy_item = PolicyItems[1];
|
|
||||||
DCHECK_EQ(policy_item.type, kShortDuration);
|
|
||||||
break;
|
|
||||||
case kNoPlay:
|
|
||||||
policy_item = PolicyItems[2];
|
|
||||||
DCHECK_EQ(policy_item.type, kNoPlay);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
NOTREACHED();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
policy->set_can_play(policy_item.can_play);
|
|
||||||
policy->set_can_renew(policy_item.can_renew);
|
|
||||||
policy->set_license_duration_seconds(policy_item.duration_seconds);
|
|
||||||
policy->set_renewal_delay_seconds(policy_item.renewal_delay_seconds);
|
|
||||||
policy->set_renewal_retry_interval_seconds(
|
|
||||||
policy_item.renewal_retry_interval_seconds);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
SessionState GetTestSessionState() {
|
|
||||||
static const std::string kTestSessionId = "SomeSessionId";
|
|
||||||
SessionState session_cache;
|
|
||||||
session_cache.mutable_license_id()->set_session_id(kTestSessionId);
|
|
||||||
session_cache.mutable_license_id()->set_version(0);
|
|
||||||
session_cache.set_signing_key(kTestSigningKey, kTestSigningKeySize);
|
|
||||||
return session_cache;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Since "GetTime" is used in this test where some functions cannot reach
|
|
||||||
// Host instance, this will be used as a universal clock for this test.
|
|
||||||
double GetCurrentTestTime() {
|
|
||||||
return base::Time::Now().ToDoubleT();
|
|
||||||
}
|
|
||||||
|
|
||||||
// This encrypts the content key using the device key in cdm/base/device_key.h.
|
|
||||||
std::string EncryptUsingKey(const std::string& input,
|
|
||||||
const std::string& iv,
|
|
||||||
const std::string& encryption_key) {
|
|
||||||
//static const int kAesBlockSize = 16;
|
|
||||||
crypto::Encryptor aes_ecryptor;
|
|
||||||
scoped_ptr<crypto::SymmetricKey> device_key(
|
|
||||||
crypto::SymmetricKey::Import(crypto::SymmetricKey::AES,
|
|
||||||
encryption_key));
|
|
||||||
if (!aes_ecryptor.Init(device_key.get(), crypto::Encryptor::CBC, iv))
|
|
||||||
return "";
|
|
||||||
|
|
||||||
std::string encrypted_data;
|
|
||||||
if (!aes_ecryptor.Encrypt(input, &encrypted_data))
|
|
||||||
return "";
|
|
||||||
|
|
||||||
return encrypted_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Takes the license and the session state and generates a SignedMessage. The
|
|
||||||
// return value is the serialized version of the SignedMessage object.
|
|
||||||
std::string GenerateSignedLicenseResponse(const License& license,
|
|
||||||
const std::string& signing_key) {
|
|
||||||
SignedMessage signed_message;
|
|
||||||
bool success = license.SerializeToString(
|
|
||||||
signed_message.mutable_msg());
|
|
||||||
DCHECK(success);
|
|
||||||
|
|
||||||
crypto::HMAC hmacer(crypto::HMAC::SHA256);
|
|
||||||
if (!hmacer.Init(signing_key))
|
|
||||||
return "";
|
|
||||||
|
|
||||||
static const int kDigestSize = 32;
|
|
||||||
uint8_t digest[kDigestSize] = { 0 };
|
|
||||||
if (!hmacer.Sign(signed_message.msg(), digest, kDigestSize))
|
|
||||||
return "";
|
|
||||||
|
|
||||||
signed_message.set_signature(digest, kDigestSize);
|
|
||||||
|
|
||||||
std::string signed_message_bytes;
|
|
||||||
success = signed_message.SerializeToString(&signed_message_bytes);
|
|
||||||
DCHECK(success);
|
|
||||||
|
|
||||||
return signed_message_bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note: We only use one session. So there aren't any list of sessions stored
|
|
||||||
// anywhere.
|
|
||||||
std::string GenerateNewSignedLicense(
|
|
||||||
const LicenseRequest& license_request,
|
|
||||||
const License::Policy& policies,
|
|
||||||
const License::KeyContainer& content_key,
|
|
||||||
const std::string& encryption_key,
|
|
||||||
const std::string& signing_key) {
|
|
||||||
DCHECK(license_request.content_id().has_cenc_id());
|
|
||||||
SessionState session_cache = GetTestSessionState();
|
|
||||||
DCHECK(session_cache.has_signing_key());
|
|
||||||
|
|
||||||
session_cache.mutable_license_id()->set_request_id(
|
|
||||||
license_request.content_id().webm_id().request_id());
|
|
||||||
session_cache.mutable_license_id()->set_type(
|
|
||||||
license_request.content_id().webm_id().license_type());
|
|
||||||
|
|
||||||
License license;
|
|
||||||
license.mutable_id()->CopyFrom(session_cache.license_id());
|
|
||||||
license.mutable_policy()->CopyFrom(policies);
|
|
||||||
license.set_license_start_time(GetCurrentTestTime());
|
|
||||||
|
|
||||||
License::KeyContainer* renewal_signing_key = license.add_key();
|
|
||||||
renewal_signing_key->set_key(session_cache.signing_key());
|
|
||||||
renewal_signing_key->set_type(License::KeyContainer::SIGNING);
|
|
||||||
|
|
||||||
license.add_key()->CopyFrom(content_key);
|
|
||||||
for (int i = 0; i < license.key_size(); ++i) {
|
|
||||||
license.mutable_key(i)->set_iv("0123456789012345");
|
|
||||||
license.mutable_key(i)->set_key(
|
|
||||||
EncryptUsingKey(license.key(i).key(),
|
|
||||||
license.key(i).iv(),
|
|
||||||
encryption_key));
|
|
||||||
if (license.key(i).key().empty())
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
return GenerateSignedLicenseResponse(license, signing_key);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GetContentKeyFromKeyId(const std::string& key_id,
|
|
||||||
std::string* content_key) {
|
|
||||||
DCHECK(content_key);
|
|
||||||
for (unsigned int i = 0; i < arraysize(kWvCdmEncryptedFrames); ++i) {
|
|
||||||
const WvCdmEncryptedFrameInfo& frame = kWvCdmEncryptedFrames[i];
|
|
||||||
if (frame.key_id_size != static_cast<int>(key_id.size()))
|
|
||||||
continue;
|
|
||||||
if (!memcmp(frame.key_id, key_id.data(), frame.key_id_size)) {
|
|
||||||
content_key->assign(frame.content_key,
|
|
||||||
frame.content_key + frame.content_key_size);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string DeriveKey(const std::string& key,
|
|
||||||
const std::string& purpose,
|
|
||||||
const std::string& context,
|
|
||||||
const uint32_t size_bits) {
|
|
||||||
if (key.size() != 16)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
// We only handle even multiples of 16 bytes (128 bits) right now.
|
|
||||||
if ((size_bits % 128) || (size_bits > (128 * 255))) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string result;
|
|
||||||
|
|
||||||
const EVP_CIPHER *cipher = EVP_aes_128_cbc();
|
|
||||||
CMAC_CTX* cmac_ctx = CMAC_CTX_new();
|
|
||||||
|
|
||||||
size_t reslen;
|
|
||||||
unsigned char res[128];
|
|
||||||
unsigned char counter;
|
|
||||||
for (counter = 1; counter <= (size_bits / 128); counter++) {
|
|
||||||
if (!CMAC_Init(cmac_ctx, key.data(), key.size(), cipher, 0))
|
|
||||||
break;
|
|
||||||
|
|
||||||
std::string message;
|
|
||||||
message.append(1, counter);
|
|
||||||
message.append(purpose);
|
|
||||||
message.append(1, '\0');
|
|
||||||
message.append(context);
|
|
||||||
uint32_t size_l = htonl(size_bits);
|
|
||||||
message.append(reinterpret_cast<char*>(&size_l), sizeof(size_l));
|
|
||||||
if (!CMAC_Update(cmac_ctx, message.data(), message.size()))
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (!CMAC_Final(cmac_ctx, res, &reslen))
|
|
||||||
break;
|
|
||||||
|
|
||||||
result.append((const char*)res, reslen);
|
|
||||||
}
|
|
||||||
|
|
||||||
CMAC_CTX_free(cmac_ctx);
|
|
||||||
|
|
||||||
if (counter <= (size_bits / 128))
|
|
||||||
return "";
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool VerifyTestSignature(const std::string& message,
|
|
||||||
const std::string& signature,
|
|
||||||
const std::string& key) {
|
|
||||||
crypto::HMAC hmacer(crypto::HMAC::SHA256);
|
|
||||||
if (!hmacer.Init(key))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!hmacer.Verify(message, signature))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string GenerateNewLicenseResponse(const LicenseRequest& license_request,
|
|
||||||
const PolicyType& policy_type) {
|
|
||||||
if (!license_request.content_id().has_cenc_id())
|
|
||||||
return "";
|
|
||||||
|
|
||||||
std::string content_key_id = license_request.content_id().cenc_id().pssh(0);
|
|
||||||
|
|
||||||
std::string content_key;
|
|
||||||
if (!GetContentKeyFromKeyId(content_key_id,
|
|
||||||
&content_key)) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (content_key_id.size() > 16)
|
|
||||||
content_key_id.resize(16);
|
|
||||||
|
|
||||||
License::Policy policies;
|
|
||||||
if (!GetPolicy(policy_type, &policies))
|
|
||||||
return "";
|
|
||||||
|
|
||||||
std::string context;
|
|
||||||
if (!license_request.SerializeToString(&context))
|
|
||||||
return "";
|
|
||||||
|
|
||||||
wvoec_mock::WvKeybox keybox;
|
|
||||||
|
|
||||||
// TODO(): Fix this to use a constant for key length.
|
|
||||||
std::string widevine_device_key(keybox.device_key().value());
|
|
||||||
std::string encryption_key = DeriveKey(widevine_device_key,
|
|
||||||
std::string(kEncryptionKeyLabel),
|
|
||||||
context,
|
|
||||||
kEncryptionKeySizeBits);
|
|
||||||
std::string signing_key = DeriveKey(widevine_device_key,
|
|
||||||
std::string(kSigningKeyLabel),
|
|
||||||
context,
|
|
||||||
kSigningKeySizeBits);
|
|
||||||
|
|
||||||
memcpy(kTestSigningKey, &signing_key[0], 32);
|
|
||||||
|
|
||||||
License::KeyContainer key_container;
|
|
||||||
key_container.set_id(content_key_id);
|
|
||||||
key_container.set_key(content_key);
|
|
||||||
key_container.set_type(License::KeyContainer::CONTENT);
|
|
||||||
return GenerateNewSignedLicense(license_request,
|
|
||||||
policies,
|
|
||||||
key_container,
|
|
||||||
encryption_key,
|
|
||||||
signing_key);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string GenerateLicenseRenewalResponse(
|
|
||||||
const SignedMessage& signed_message,
|
|
||||||
const PolicyType& policy_type) {
|
|
||||||
SessionState session_cache = GetTestSessionState();
|
|
||||||
|
|
||||||
LicenseRequest license_request;
|
|
||||||
if (!license_request.ParseFromString(signed_message.msg()))
|
|
||||||
return "";
|
|
||||||
|
|
||||||
std::string session_id = license_request.content_id().license().
|
|
||||||
license_id().session_id();
|
|
||||||
if (session_id.compare(session_cache.license_id().session_id()))
|
|
||||||
return "";
|
|
||||||
|
|
||||||
if (!VerifyTestSignature(signed_message.msg(),
|
|
||||||
signed_message.signature(),
|
|
||||||
session_cache.signing_key())) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
session_cache.mutable_license_id()->set_version(
|
|
||||||
session_cache.license_id().version() + 1);
|
|
||||||
|
|
||||||
License license;
|
|
||||||
license.mutable_id()->CopyFrom(session_cache.license_id());
|
|
||||||
|
|
||||||
// Always get Policy object with kDefault for renewal.
|
|
||||||
License::Policy policy;
|
|
||||||
GetPolicy(policy_type, &policy);
|
|
||||||
license.mutable_policy()->Swap(&policy);
|
|
||||||
license.set_license_start_time(GetCurrentTestTime());
|
|
||||||
|
|
||||||
return GenerateSignedLicenseResponse(license, session_cache.signing_key());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string GenerateLicenseResponse(const std::string& signed_request,
|
|
||||||
const PolicyType& policy) {
|
|
||||||
SignedMessage signed_message;
|
|
||||||
if (!signed_message.ParseFromString(signed_request))
|
|
||||||
return "";
|
|
||||||
|
|
||||||
LicenseRequest license_request;
|
|
||||||
if (!license_request.ParseFromString(signed_message.msg()))
|
|
||||||
return "";
|
|
||||||
|
|
||||||
if (license_request.type() == LicenseRequest::NEW) {
|
|
||||||
return GenerateNewLicenseResponse(license_request, policy);
|
|
||||||
} else if (license_request.type() == LicenseRequest::RENEWAL) {
|
|
||||||
return GenerateLicenseRenewalResponse(signed_message, policy);
|
|
||||||
}
|
|
||||||
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
struct WvCdmEncryptedData {
|
|
||||||
char plain_text[32];
|
|
||||||
int plain_text_size;
|
|
||||||
uint8_t key_id[32];
|
|
||||||
int key_id_size;
|
|
||||||
uint8_t content_key[32];
|
|
||||||
int content_key_size;
|
|
||||||
uint8_t encrypted_data[64];
|
|
||||||
int encrypted_data_size;
|
|
||||||
const char* license_response;
|
|
||||||
int license_response_size;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Container used to pass data from GenerateLicenseRequest to Decrypt.
|
|
||||||
// TODO(rkuroiwa): This class was made before KeyMessage existed; this
|
|
||||||
// should be removed.
|
|
||||||
class LicenseRequestParameter {
|
|
||||||
public:
|
|
||||||
explicit LicenseRequestParameter(const WvCdmEncryptedData& frame)
|
|
||||||
: init_data(new uint8_t[frame.key_id_size]),
|
|
||||||
init_data_size(frame.key_id_size),
|
|
||||||
session_id(NULL),
|
|
||||||
session_id_size(0),
|
|
||||||
key_request(NULL),
|
|
||||||
key_request_size(0),
|
|
||||||
default_url(NULL),
|
|
||||||
default_url_size(0) {
|
|
||||||
memcpy(init_data.get(), frame.key_id, frame.key_id_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
~LicenseRequestParameter() {
|
|
||||||
}
|
|
||||||
|
|
||||||
scoped_array<uint8_t> init_data;
|
|
||||||
int init_data_size;
|
|
||||||
scoped_array<char> session_id;
|
|
||||||
int session_id_size;
|
|
||||||
scoped_array<uint8_t> key_request;
|
|
||||||
int key_request_size;
|
|
||||||
scoped_array<char> default_url;
|
|
||||||
int default_url_size;
|
|
||||||
|
|
||||||
private:
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(LicenseRequestParameter);
|
|
||||||
};
|
|
||||||
|
|
||||||
// |encrypted_data| is encrypted from |plain_text| using |key|. |key_id| is
|
|
||||||
// used to distinguish |key|.
|
|
||||||
struct WebmEncryptedData {
|
|
||||||
uint8 plain_text[32];
|
|
||||||
int plain_text_size;
|
|
||||||
uint8 key_id[32];
|
|
||||||
int key_id_size;
|
|
||||||
uint8 key[32];
|
|
||||||
int key_size;
|
|
||||||
uint8 encrypted_data[64];
|
|
||||||
int encrypted_data_size;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Frames 0 & 1 are encrypted with the same key. Frame 2 is encrypted with a
|
|
||||||
// different key. Frame 3 is unencrypted.
|
|
||||||
const WebmEncryptedData kWebmEncryptedFrames[] = {
|
|
||||||
{
|
|
||||||
// plaintext
|
|
||||||
"Original data.", 14,
|
|
||||||
// key_id
|
|
||||||
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
|
||||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
|
||||||
0x10, 0x11, 0x12, 0x13
|
|
||||||
}, 20,
|
|
||||||
// key
|
|
||||||
{ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
|
|
||||||
0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23
|
|
||||||
}, 16,
|
|
||||||
// encrypted_data
|
|
||||||
{ 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xf0, 0xd1, 0x12, 0xd5, 0x24, 0x81, 0x96,
|
|
||||||
0x55, 0x1b, 0x68, 0x9f, 0x38, 0x91, 0x85
|
|
||||||
}, 23
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// plaintext
|
|
||||||
"Changed Original data.", 22,
|
|
||||||
// key_id
|
|
||||||
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
|
||||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
|
||||||
0x10, 0x11, 0x12, 0x13
|
|
||||||
}, 20,
|
|
||||||
// key
|
|
||||||
{ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
|
|
||||||
0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23
|
|
||||||
}, 16,
|
|
||||||
// encrypted_data
|
|
||||||
{ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x57, 0x66, 0xf4, 0x12, 0x1a, 0xed, 0xb5,
|
|
||||||
0x79, 0x1c, 0x8e, 0x25, 0xd7, 0x17, 0xe7, 0x5e,
|
|
||||||
0x16, 0xe3, 0x40, 0x08, 0x27, 0x11, 0xe9
|
|
||||||
}, 31
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// plaintext
|
|
||||||
"Original data.", 14,
|
|
||||||
// key_id
|
|
||||||
{ 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
|
|
||||||
0x2c, 0x2d, 0x2e, 0x2f, 0x30
|
|
||||||
}, 13,
|
|
||||||
// key
|
|
||||||
{ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
|
|
||||||
0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40
|
|
||||||
}, 16,
|
|
||||||
// encrypted_data
|
|
||||||
{ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x01, 0x9c, 0x71, 0x26, 0x57, 0x3e, 0x25, 0x37,
|
|
||||||
0xf7, 0x31, 0x81, 0x19, 0x64, 0xce, 0xbc
|
|
||||||
}, 23
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// plaintext
|
|
||||||
"Changed Original data.", 22,
|
|
||||||
// key_id
|
|
||||||
{ 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
|
|
||||||
0x2c, 0x2d, 0x2e, 0x2f, 0x30
|
|
||||||
}, 13,
|
|
||||||
// key
|
|
||||||
{ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
|
|
||||||
0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40
|
|
||||||
}, 16,
|
|
||||||
// encrypted_data
|
|
||||||
{ 0x00, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64,
|
|
||||||
0x20, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61,
|
|
||||||
0x6c, 0x20, 0x64, 0x61, 0x74, 0x61, 0x2e
|
|
||||||
}, 23
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint8 kWebmWrongSizedKey[] = { 0x20, 0x20 };
|
|
||||||
|
|
||||||
static const char kClearKeySystem[] = "org.w3.clearkey";
|
|
||||||
static const char *kWidevineKeySystem = "com.widevine.alpha";
|
|
||||||
static const char kKeyType[] = "any";
|
|
||||||
|
|
||||||
// All three ContentIdentification are supported but cenc_id only supports
|
|
||||||
// one key for now.
|
|
||||||
// Using key_id kCencTestRequest will return the content_key kCencTestRequest
|
|
||||||
//
|
|
||||||
static const char kCencTestRequest[] = "0123456789ABCDEF";
|
|
||||||
static const char kCencTestContentKey[] = {
|
|
||||||
0x16, 0x23, 0xa3, 0x16, 0x67, 0x6d, 0xb7, 0x70,
|
|
||||||
0xfe, 0x78, 0xf6, 0x58, 0x42, 0xb8, 0x16, 0x3c
|
|
||||||
};
|
|
||||||
|
|
||||||
// System Id of the Widevine DRM system for identification in pssh
|
|
||||||
static const uint8 kWidevineSystemId[] = {
|
|
||||||
0xED, 0xEF, 0x8B, 0xA9, 0x79, 0xD6, 0x4A, 0xCE,
|
|
||||||
0xA3, 0xC8, 0x27, 0xDC, 0xD5, 0x1D, 0x21, 0xED,
|
|
||||||
};
|
|
||||||
|
|
||||||
static std::string EncodeInt32(int i) {
|
|
||||||
std::string s;
|
|
||||||
s.resize(sizeof(int));
|
|
||||||
memcpy(&*s.begin(), &i, sizeof(int));
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate PSSH blob from init data
|
|
||||||
static std::string GeneratePSSHBlob(const uint8* init_data,
|
|
||||||
int init_data_length) {
|
|
||||||
std::string output;
|
|
||||||
|
|
||||||
// 4 byte size of the PSSH atom, inclusive
|
|
||||||
int size = 4 + 4 + 4 + sizeof(kWidevineSystemId) + 4 + init_data_length;
|
|
||||||
output.append(EncodeInt32(base::HostToNet32(size)));
|
|
||||||
|
|
||||||
// "pssh"
|
|
||||||
output.append("pssh");
|
|
||||||
|
|
||||||
// 4 byte flags, value 0
|
|
||||||
int flag = 0;
|
|
||||||
output.append(EncodeInt32(base::HostToNet32(flag)));
|
|
||||||
|
|
||||||
// 16 byte system id
|
|
||||||
output.append(reinterpret_cast<const char*>(kWidevineSystemId),
|
|
||||||
sizeof(kWidevineSystemId));
|
|
||||||
|
|
||||||
// 4 byte size of PSSH data, exclusive
|
|
||||||
output.append(EncodeInt32(base::HostToNet32(init_data_length)));
|
|
||||||
|
|
||||||
// pssh data
|
|
||||||
output.append(reinterpret_cast<const char*>(init_data),
|
|
||||||
init_data_length);
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
}; // anonymous
|
|
||||||
|
|
||||||
namespace wvcdm {
|
|
||||||
|
|
||||||
class WvCdmDecryptorTest : public testing::Test {
|
|
||||||
|
|
||||||
public:
|
|
||||||
WvCdmDecryptorTest() {}
|
|
||||||
|
|
||||||
~WvCdmDecryptorTest() {}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void GenerateKeyRequest(const uint8* key_id, int key_id_size,
|
|
||||||
std::string& message_buffer) {
|
|
||||||
std::string init_data = GeneratePSSHBlob(key_id, key_id_size);
|
|
||||||
wvcdm::CdmResponseType res = decryptor_.GenerateKeyRequest(
|
|
||||||
kWidevineKeySystem, init_data, &message_buffer, &session_id_string_);
|
|
||||||
EXPECT_TRUE(res == wvcdm::KEY_MESSAGE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PrepareForRenewalRequest(int i) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetRenewalMessage(std::string& message_buffer) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetFailedRenewalMessage(std::string& message_buffer) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
void AddKeyAndExpectToSucceed(const uint8* key_id, int key_id_size,
|
|
||||||
const uint8* key, int key_size) {
|
|
||||||
std::string cma_key((const char*)key, key_size);
|
|
||||||
std::string init_data = GeneratePSSHBlob(key_id, key_id_size);
|
|
||||||
wvcdm::CdmResponseType res = decryptor_.AddKey(
|
|
||||||
kWidevineKeySystem, init_data, cma_key, session_id_string_);
|
|
||||||
EXPECT_TRUE(res == wvcdm::KEY_ADDED);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AddKeyAndExpectToFail(const uint8* key_id, int key_id_size,
|
|
||||||
const uint8* key, int key_size) {
|
|
||||||
std::string cma_key((const char*)key, key_size);
|
|
||||||
std::string init_data = GeneratePSSHBlob(key_id, key_id_size);
|
|
||||||
wvcdm::CdmResponseType res = decryptor_.AddKey(
|
|
||||||
kWidevineKeySystem, init_data, cma_key, session_id_string_);
|
|
||||||
EXPECT_TRUE(res == wvcdm::KEY_ADDED);
|
|
||||||
}
|
|
||||||
protected:
|
|
||||||
|
|
||||||
wvcdm::WvContentDecryptionModule decryptor_;
|
|
||||||
std::string session_id_string_;
|
|
||||||
};
|
|
||||||
|
|
||||||
TEST_F(WvCdmDecryptorTest, RenewalTest) {
|
|
||||||
std::string response;
|
|
||||||
std::string message;
|
|
||||||
const WvCdmEncryptedFrameInfo& frame = kWvCdmEncryptedFrames[3];
|
|
||||||
License::Policy policies;
|
|
||||||
DCHECK(GetPolicy(frame.policy_type, &policies));
|
|
||||||
|
|
||||||
GenerateKeyRequest(frame.key_id, frame.key_id_size, message);
|
|
||||||
response = GenerateLicenseResponse(message, kShortDuration);
|
|
||||||
AddKeyAndExpectToSucceed(frame.key_id, frame.key_id_size,
|
|
||||||
reinterpret_cast<const uint8*>(response.data()),
|
|
||||||
response.size());
|
|
||||||
MessageLoop::current()->RunUntilIdle();
|
|
||||||
PrepareForRenewalRequest(1);
|
|
||||||
sleep(policies.renewal_delay_seconds());
|
|
||||||
MessageLoop::current()->RunUntilIdle();
|
|
||||||
GetRenewalMessage(message);
|
|
||||||
response = GenerateLicenseResponse(message, frame.policy_type);
|
|
||||||
AddKeyAndExpectToSucceed(frame.key_id, frame.key_id_size,
|
|
||||||
reinterpret_cast<const uint8*>(response.data()),
|
|
||||||
response.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(WvCdmDecryptorTest, MultiRenewalTest) {
|
|
||||||
std::string response;
|
|
||||||
std::string message;
|
|
||||||
const WvCdmEncryptedFrameInfo& frame = kWvCdmEncryptedFrames[3];
|
|
||||||
License::Policy policies;
|
|
||||||
DCHECK(GetPolicy(frame.policy_type, &policies));
|
|
||||||
|
|
||||||
GenerateKeyRequest(frame.key_id, frame.key_id_size, message);
|
|
||||||
response = GenerateLicenseResponse(message, kShortDuration);
|
|
||||||
AddKeyAndExpectToSucceed(frame.key_id, frame.key_id_size,
|
|
||||||
reinterpret_cast<const uint8*>(response.data()),
|
|
||||||
response.size());
|
|
||||||
MessageLoop::current()->RunUntilIdle();
|
|
||||||
PrepareForRenewalRequest(1);
|
|
||||||
sleep(policies.renewal_delay_seconds());
|
|
||||||
MessageLoop::current()->RunUntilIdle();
|
|
||||||
GetRenewalMessage(message);
|
|
||||||
response = GenerateLicenseResponse(message, frame.policy_type);
|
|
||||||
AddKeyAndExpectToSucceed(frame.key_id, frame.key_id_size,
|
|
||||||
reinterpret_cast<const uint8*>(response.data()),
|
|
||||||
response.size());
|
|
||||||
|
|
||||||
PrepareForRenewalRequest(2);
|
|
||||||
sleep(policies.renewal_delay_seconds());
|
|
||||||
MessageLoop::current()->RunUntilIdle();
|
|
||||||
GetRenewalMessage(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(WvCdmDecryptorTest, RenewalRetryTest_ExpectSuccess) {
|
|
||||||
std::string response;
|
|
||||||
std::string message;
|
|
||||||
const WvCdmEncryptedFrameInfo& frame = kWvCdmEncryptedFrames[3];
|
|
||||||
License::Policy policies;
|
|
||||||
DCHECK(GetPolicy(frame.policy_type, &policies));
|
|
||||||
|
|
||||||
GenerateKeyRequest(frame.key_id, frame.key_id_size, message);
|
|
||||||
response = GenerateLicenseResponse(message, kShortDuration);
|
|
||||||
AddKeyAndExpectToSucceed(frame.key_id, frame.key_id_size,
|
|
||||||
reinterpret_cast<const uint8*>(response.data()),
|
|
||||||
response.size());
|
|
||||||
MessageLoop::current()->RunUntilIdle();
|
|
||||||
|
|
||||||
int loop_seconds =
|
|
||||||
policies.license_duration_seconds() - policies.renewal_delay_seconds();
|
|
||||||
int loop_count = loop_seconds / policies.renewal_retry_interval_seconds();
|
|
||||||
if (loop_seconds % policies.renewal_retry_interval_seconds())
|
|
||||||
++loop_count;
|
|
||||||
for (int i = 1; i <= loop_count; ++i) {
|
|
||||||
PrepareForRenewalRequest(i);
|
|
||||||
sleep(policies.renewal_delay_seconds());
|
|
||||||
MessageLoop::current()->RunUntilIdle();
|
|
||||||
GetRenewalMessage(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
response = GenerateLicenseResponse(message, frame.policy_type);
|
|
||||||
AddKeyAndExpectToSucceed(frame.key_id, frame.key_id_size,
|
|
||||||
reinterpret_cast<const uint8*>(response.data()),
|
|
||||||
response.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(WvCdmDecryptorTest, RenewalRetryTest_ExpectLicenseExpiration) {
|
|
||||||
std::string response;
|
|
||||||
std::string message;
|
|
||||||
const WvCdmEncryptedFrameInfo& frame = kWvCdmEncryptedFrames[3];
|
|
||||||
License::Policy policies;
|
|
||||||
DCHECK(GetPolicy(frame.policy_type, &policies));
|
|
||||||
|
|
||||||
GenerateKeyRequest(frame.key_id, frame.key_id_size, message);
|
|
||||||
response = GenerateLicenseResponse(message, kShortDuration);
|
|
||||||
AddKeyAndExpectToSucceed(frame.key_id, frame.key_id_size,
|
|
||||||
reinterpret_cast<const uint8*>(response.data()),
|
|
||||||
response.size());
|
|
||||||
MessageLoop::current()->RunUntilIdle();
|
|
||||||
|
|
||||||
int loop_seconds =
|
|
||||||
policies.license_duration_seconds() - policies.renewal_delay_seconds();
|
|
||||||
int loop_count = loop_seconds / policies.renewal_retry_interval_seconds() + 1;
|
|
||||||
if (loop_seconds % policies.renewal_retry_interval_seconds())
|
|
||||||
++loop_count;
|
|
||||||
|
|
||||||
for (int i = 1; i <= loop_count; ++i) {
|
|
||||||
PrepareForRenewalRequest(i);
|
|
||||||
sleep(i > 1 ?
|
|
||||||
policies.renewal_retry_interval_seconds() :
|
|
||||||
policies.renewal_delay_seconds());
|
|
||||||
MessageLoop::current()->RunUntilIdle();
|
|
||||||
if (i < loop_count)
|
|
||||||
GetRenewalMessage(message);
|
|
||||||
}
|
|
||||||
GetFailedRenewalMessage(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace wvcdm
|
|
||||||
|
|
||||||
// TODO(rkuroiwa): Find where to put this main function just for Widevine CDM
|
|
||||||
// unit tests.
|
|
||||||
int main(int argc, char **argv) {
|
|
||||||
::testing::InitGoogleTest(&argc, argv);
|
|
||||||
base::AtExitManager exit;
|
|
||||||
MessageLoop ttr(MessageLoop::TYPE_IO);
|
|
||||||
return RUN_ALL_TESTS();
|
|
||||||
}
|
|
||||||
@@ -547,11 +547,9 @@ bool SessionContext::RefreshKey(const KeyId& key_id,
|
|||||||
// Decrypt encrypted key control block
|
// Decrypt encrypted key control block
|
||||||
std::vector<uint8_t> control;
|
std::vector<uint8_t> control;
|
||||||
if (key_control_iv.empty()) {
|
if (key_control_iv.empty()) {
|
||||||
// TODO(fredg): get confirmation from server team this is valid.
|
|
||||||
LOGD("Key control block is NOT encrypted.");
|
LOGD("Key control block is NOT encrypted.");
|
||||||
control = key_control;
|
control = key_control;
|
||||||
} else {
|
} else {
|
||||||
// TODO(fredg): get confirmation from server team this is valid, too.
|
|
||||||
LOGD("Key control block is encrypted.");
|
LOGD("Key control block is encrypted.");
|
||||||
if (!DecryptMessage(content_key_value, key_control_iv, key_control,
|
if (!DecryptMessage(content_key_value, key_control_iv, key_control,
|
||||||
&control)) {
|
&control)) {
|
||||||
@@ -1024,9 +1022,13 @@ OEMCryptoResult SessionContext::DecryptCTR(
|
|||||||
size_t cipher_data_length, bool is_encrypted, uint8_t* clear_data,
|
size_t cipher_data_length, bool is_encrypted, uint8_t* clear_data,
|
||||||
BufferType buffer_type) {
|
BufferType buffer_type) {
|
||||||
// If the data is clear, we do not need a current key selected.
|
// If the data is clear, we do not need a current key selected.
|
||||||
if (!is_encrypted && buffer_type != kBufferTypeDirect) {
|
if (!is_encrypted) {
|
||||||
memcpy(reinterpret_cast<uint8_t*>(clear_data),
|
if (buffer_type != kBufferTypeDirect) {
|
||||||
cipher_data, cipher_data_length);
|
memcpy(reinterpret_cast<uint8_t*>(clear_data), cipher_data,
|
||||||
|
cipher_data_length);
|
||||||
|
return OEMCrypto_SUCCESS;
|
||||||
|
}
|
||||||
|
// For reference implementation, we quietly drop the clear direct video.
|
||||||
return OEMCrypto_SUCCESS;
|
return OEMCrypto_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1083,7 +1085,7 @@ OEMCryptoResult SessionContext::DecryptCTR(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (buffer_type == kBufferTypeDirect) {
|
if (buffer_type == kBufferTypeDirect) {
|
||||||
// For reference implementation, we quietly drop direct video.
|
// For reference implementation, we quietly drop the decrypted direct video.
|
||||||
return OEMCrypto_SUCCESS;
|
return OEMCrypto_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ static void dump_hex(std::string name, const uint8_t* vector, size_t length) {
|
|||||||
printf("NULL;\n");
|
printf("NULL;\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// TODO(fredgc): replace with HEXEncode.
|
|
||||||
for (size_t i = 0; i < length; i++) {
|
for (size_t i = 0; i < length; i++) {
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
printf("\n wvcdm::a2b_hex(\"");
|
printf("\n wvcdm::a2b_hex(\"");
|
||||||
|
|||||||
Reference in New Issue
Block a user