Refactor oemcrypto mock into stand alone reference code

Merge from Widevine repo of http://go/wvgerrit/46204
Refactor utility code - split the mock, step 1

Merge from Widevine repo of http://go/wvgerrit/46205
Move some OEMCrypto types to common header - split the mock, step 2

Merge from Widevine repo of http://go/wvgerrit/46206
Split mock into two -- step 3

Merge from Widevine repo of http://go/wvgerrit/47460
Split the mock into two -- step 3.5

The CL moves several files used by oemcrypto and cdm into a common
subdirectory, so that it may more easily be shared with partners.

The CORE_DISALLOW_COPY_AND_ASSIGN macro was moved to its own header in
the util/include directory.

This CL removes some references to the mock from other code, and puts
some constants and types, such as the definition of the keybox, into a
header in oemcrypto.

Test: tested as part of http://go/ag/4674759
bug: 76393338
Change-Id: I75b4bde7062ed8ee572c97ebc2f4da018f4be0c9
This commit is contained in:
Fred Gylys-Colwell
2018-06-29 16:57:19 -07:00
parent b8091eaa7d
commit 947531a6a9
109 changed files with 806 additions and 1428 deletions

View File

@@ -91,6 +91,7 @@ LOCAL_STATIC_LIBRARIES := libcrypto
LOCAL_C_INCLUDES := \
vendor/widevine/libwvdrmengine/cdm/core/include \
vendor/widevine/libwvdrmengine/cdm/include \
vendor/widevine/libwvdrmengine/cdm/util/include \
vendor/widevine/libwvdrmengine/oemcrypto/include \
LOCAL_HEADER_LIBRARIES := \
@@ -100,15 +101,16 @@ LOCAL_SHARED_LIBRARIES := \
liblog
SRC_DIR := cdm/src
UTIL_SRC_DIR := cdm/util/src
CORE_SRC_DIR := cdm/core/src
LOCAL_SRC_FILES := \
$(CORE_SRC_DIR)/properties.cpp \
$(CORE_SRC_DIR)/string_conversions.cpp \
$(SRC_DIR)/clock.cpp \
$(SRC_DIR)/file_store.cpp \
$(SRC_DIR)/file_utils.cpp \
$(SRC_DIR)/lock.cpp \
$(SRC_DIR)/log.cpp \
$(UTIL_SRC_DIR)/string_conversions.cpp \
$(UTIL_SRC_DIR)/clock.cpp \
$(UTIL_SRC_DIR)/file_store.cpp \
$(UTIL_SRC_DIR)/file_utils.cpp \
$(UTIL_SRC_DIR)/lock.cpp \
$(UTIL_SRC_DIR)/log.cpp \
$(SRC_DIR)/properties_android.cpp \
$(SRC_DIR)/timer.cpp \
@@ -160,6 +162,7 @@ LOCAL_C_INCLUDES := \
frameworks/native/include \
vendor/widevine/libwvdrmengine/cdm/core/include \
vendor/widevine/libwvdrmengine/cdm/metrics/include \
vendor/widevine/libwvdrmengine/cdm/util/include \
vendor/widevine/libwvdrmengine/cdm/include \
vendor/widevine/libwvdrmengine/include \
vendor/widevine/libwvdrmengine/mediacrypto/include \
@@ -217,6 +220,7 @@ LOCAL_C_INCLUDES := \
frameworks/native/include \
vendor/widevine/libwvdrmengine/cdm/core/include \
vendor/widevine/libwvdrmengine/cdm/metrics/include \
vendor/widevine/libwvdrmengine/cdm/util/include \
vendor/widevine/libwvdrmengine/cdm/include \
vendor/widevine/libwvdrmengine/include_hidl \
vendor/widevine/libwvdrmengine/include \

View File

@@ -9,6 +9,7 @@ LOCAL_CFLAGS := -DDYNAMIC_ADAPTER
LOCAL_C_INCLUDES := \
vendor/widevine/libwvdrmengine/cdm/core/include \
vendor/widevine/libwvdrmengine/cdm/metrics/include \
vendor/widevine/libwvdrmengine/cdm/util/include \
vendor/widevine/libwvdrmengine/cdm/include \
vendor/widevine/libwvdrmengine/oemcrypto/include \

View File

@@ -9,7 +9,7 @@
#include <string>
#include <vector>
#include "wv_cdm_types.h"
#include "disallow_copy_and_assign.h"
namespace wvcdm {

View File

@@ -13,6 +13,7 @@
#include "certificate_provisioning.h"
#include "clock.h"
#include "crypto_session.h"
#include "disallow_copy_and_assign.h"
#include "file_store.h"
#include "initialization_data.h"
#include "lock.h"

View File

@@ -10,6 +10,7 @@
#include <vector>
#include "crypto_session.h"
#include "disallow_copy_and_assign.h"
#include "device_files.h"
#include "file_store.h"
#include "initialization_data.h"

View File

@@ -10,6 +10,8 @@
#include <string>
#include "cdm_session.h"
#include "disallow_copy_and_assign.h"
#include "lock.h"
#include "shared_ptr.h"
#include "wv_cdm_types.h"

View File

@@ -8,6 +8,7 @@
#include <string>
#include "crypto_session.h"
#include "disallow_copy_and_assign.h"
#include "license_protocol.pb.h"
#include "metrics_collections.h"
#include "oemcrypto_adapter.h"

View File

@@ -8,6 +8,7 @@
// ClientIdentification fills in the ClientIdentification portion
// of the License or Provisioning request messages.
#include "disallow_copy_and_assign.h"
#include "license_protocol.pb.h"
#include "wv_cdm_types.h"

View File

@@ -10,6 +10,7 @@
#include <vector>
#include "OEMCryptoCENC.h"
#include "disallow_copy_and_assign.h"
#include "key_session.h"
#include "lock.h"
#include "metrics_collections.h"

View File

@@ -12,6 +12,7 @@
#include <vector>
#include "device_files.pb.h"
#include "disallow_copy_and_assign.h"
#include "scoped_ptr.h"
#include "wv_cdm_types.h"

View File

@@ -31,4 +31,4 @@ class EntitlementKeySession : public ContentKeySession {
} // namespace wvcdm
#endif // WVCDM_CORE_ENTITLEMENT_KEY_SESSSION_H_
#endif // WVCDM_CORE_ENTITLEMENT_KEY_SESSSION_H_

View File

@@ -43,4 +43,4 @@ typedef std::map<std::string, CryptoSessionId> SubLicenseSessionMap;
} // namespace wvcdm
#endif // WVCDM_CORE_KEY_SESSSION_H_
#endif // WVCDM_CORE_KEY_SESSSION_H_

View File

@@ -7,6 +7,7 @@
#include <set>
#include "disallow_copy_and_assign.h"
#include "initialization_data.h"
#include "license_protocol.pb.h"
#include "scoped_ptr.h"

View File

@@ -8,6 +8,7 @@
#include <map>
#include "crypto_session.h"
#include "disallow_copy_and_assign.h"
#include "license_protocol.pb.h"
#include "wv_cdm_types.h"

View File

@@ -8,6 +8,7 @@
#include <map>
#include <string>
#include "disallow_copy_and_assign.h"
#include "license_key_status.h"
#include "license_protocol.pb.h"
#include "scoped_ptr.h"

View File

@@ -26,6 +26,7 @@
#include <string>
#include "disallow_copy_and_assign.h"
#include "wv_cdm_types.h"
namespace wvcdm {

View File

@@ -9,6 +9,7 @@
#include <string>
#include "cdm_client_property_set.h"
#include "disallow_copy_and_assign.h"
#include "lock.h"
#include "scoped_ptr.h"
#include "wv_cdm_types.h"

View File

@@ -8,7 +8,7 @@
#ifndef WVCDM_CORE_SCOPED_PTR_H_
#define WVCDM_CORE_SCOPED_PTR_H_
#include "wv_cdm_types.h"
#include "disallow_copy_and_assign.h"
namespace wvcdm {

View File

@@ -15,6 +15,7 @@
#include <memory>
#include "disallow_copy_and_assign.h"
#include "license_protocol.pb.h"
#include "privacy_crypto.h"
#include "wv_cdm_types.h"

View File

@@ -10,6 +10,7 @@
#include "crypto_session.h"
#include "device_files.h"
#include "disallow_copy_and_assign.h"
#include "file_store.h"
#include "lock.h"
#include "metrics_collections.h"

View File

@@ -5,6 +5,7 @@
#ifndef WVCDM_CORE_WV_CDM_EVENT_LISTENER_H_
#define WVCDM_CORE_WV_CDM_EVENT_LISTENER_H_
#include "disallow_copy_and_assign.h"
#include "wv_cdm_types.h"
namespace wvcdm {

View File

@@ -155,7 +155,7 @@ enum CdmResponseType {
/* previously RESTORE_OFFLINE_LICENSE_ERROR_1 = 112 */
RESTORE_OFFLINE_LICENSE_ERROR_2 = 113,
NOT_INITIALIZED_ERROR = 114, /* prior to pi, SESSION_INIT_ERROR_1 = 114 */
REINIT_ERROR = 115, /* prior to pi, SESSION_INIT_ERROR_2 = 115 */
REINIT_ERROR = 115, /* prior to pi, SESSION_INIT_ERROR_2 = 115 */
/* previously SESSION_INIT_GET_KEYBOX_ERROR = 116 */
SESSION_NOT_FOUND_1 = 117,
SESSION_NOT_FOUND_2 = 118,
@@ -345,10 +345,6 @@ enum CdmKeyStatus {
};
typedef std::map<KeyId, CdmKeyStatus> CdmKeyStatusMap;
#define CORE_DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName&); \
void operator=(const TypeName&)
enum CdmLicenseType {
kLicenseTypeOffline,
kLicenseTypeStreaming,

View File

@@ -13,6 +13,7 @@
#include "cdm_engine.h"
#include "config_test_env.h"
#include "device_files.h"
#include "initialization_data.h"
#include "file_store.h"
#include "license_request.h"

View File

@@ -6,6 +6,7 @@
#define CDM_TEST_CONFIG_TEST_ENV_H_
#include <string>
#include "disallow_copy_and_assign.h"
#include "wv_cdm_types.h"
// Declare class ConfigTestEnv - holds the configuration settings needed

View File

@@ -17,8 +17,8 @@
#include "license_request.h"
#include "log.h"
#include "oec_session_util.h"
#include "../../oemcrypto/mock/src/oemcrypto_key_mock.h"
#include "oemcrypto_session_tests_helper.h"
#include "oemcrypto_types.h"
#include "properties.h"
#include "string_conversions.h"
#include "url_request.h"
@@ -113,13 +113,13 @@ class WvGenericOperationsTest : public testing::Test,
ASSERT_NO_FATAL_FAILURE(
oec_util_session_.FillSimpleMessage(duration, control, nonce, pst));
oec_util_session_.license().keys[kGenericEncrypt].control.control_bits |=
htonl(wvoec_mock::kControlAllowEncrypt);
htonl(wvoec::kControlAllowEncrypt);
oec_util_session_.license().keys[kGenericDecrypt].control.control_bits |=
htonl(wvoec_mock::kControlAllowDecrypt);
htonl(wvoec::kControlAllowDecrypt);
oec_util_session_.license().keys[kGenericSign].control.control_bits |=
htonl(wvoec_mock::kControlAllowSign);
htonl(wvoec::kControlAllowSign);
oec_util_session_.license().keys[kGenericVerify].control.control_bits |=
htonl(wvoec_mock::kControlAllowVerify);
htonl(wvoec::kControlAllowVerify);
oec_util_session_.license().keys[kGenericSign].key_data_length =
wvcdm::MAC_KEY_SIZE;
@@ -387,10 +387,10 @@ class WvGenericOperationsDataTest : public WvGenericOperationsTest {
ASSERT_NO_FATAL_FAILURE(
oec_util_session_.FillSimpleMessage(duration, control, nonce, pst));
oec_util_session_.license().keys[kGenericEncrypt].control.control_bits |=
htonl(wvoec_mock::kControlAllowEncrypt |
wvoec_mock::kControlAllowDecrypt);
htonl(wvoec::kControlAllowEncrypt |
wvoec::kControlAllowDecrypt);
oec_util_session_.license().keys[kGenericSign].control.control_bits |=
htonl(wvoec_mock::kControlAllowSign | wvoec_mock::kControlAllowVerify);
htonl(wvoec::kControlAllowSign | wvoec::kControlAllowVerify);
oec_util_session_.license().keys[kGenericSign].key_data_length =
wvcdm::MAC_KEY_SIZE;

View File

@@ -12,7 +12,7 @@
#include <gtest/gtest_prod.h>
#include <openssl/ssl.h>
#include "wv_cdm_types.h" // CORE_DISALLOW_COPY_AND_ASSIGN
#include "disallow_copy_and_assign.h"
namespace wvcdm {

View File

@@ -6,7 +6,7 @@
#define CDM_TEST_LICENSE_REQUEST_H_
#include <string>
#include "wv_cdm_types.h"
#include "disallow_copy_and_assign.h"
namespace wvcdm {

View File

@@ -6,8 +6,8 @@
#define CDM_TEST_URL_REQUEST_H_
#include <string>
#include "disallow_copy_and_assign.h"
#include "http_socket.h"
#include "wv_cdm_types.h"
namespace wvcdm {

View File

@@ -7,7 +7,9 @@
#ifndef CDM_BASE_TIMER_H_
#define CDM_BASE_TIMER_H_
#include "wv_cdm_types.h"
#include <stdint.h>
#include "disallow_copy_and_assign.h"
namespace wvcdm {

View File

@@ -11,6 +11,7 @@
#include <utils/RefBase.h>
#include "cdm_identifier.h"
#include "disallow_copy_and_assign.h"
#include "file_store.h"
#include "lock.h"
#include "metrics.pb.h"

View File

@@ -23,6 +23,7 @@ LOCAL_C_INCLUDES := \
vendor/widevine/libwvdrmengine/cdm/core/test \
vendor/widevine/libwvdrmengine/cdm/include \
vendor/widevine/libwvdrmengine/cdm/metrics/include \
vendor/widevine/libwvdrmengine/cdm/util/include \
vendor/widevine/libwvdrmengine/oemcrypto/include \
LOCAL_C_INCLUDES += external/protobuf/src

View File

@@ -1,11 +1,9 @@
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine Master
// License Agreement.
// Copyright 2013 Google Inc. All Rights Reserved.
//
// Clock - Platform independent interface for a time library
//
#ifndef WVCDM_CORE_CLOCK_H_
#define WVCDM_CORE_CLOCK_H_
#ifndef WVCDM_UTIL_CLOCK_H_
#define WVCDM_UTIL_CLOCK_H_
#include <stdint.h>
@@ -23,4 +21,4 @@ class Clock {
} // namespace wvcdm
#endif // WVCDM_CORE_CLOCK_H_
#endif // WVCDM_UTIL_CLOCK_H_

View File

@@ -0,0 +1,15 @@
// Copyright 2018 Google Inc. All Rights Reserved.
#ifndef WVCDM_UTIL_DISALLOW_COPY_AND_ASSIGN_H_
#define WVCDM_UTIL_DISALLOW_COPY_AND_ASSIGN_H_
namespace wvcdm {
#define CORE_DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName&); \
void operator=(const TypeName&)
} // namespace wvcdm
#endif // WVCDM_UTIL_DISALLOW_COPY_AND_ASSIGN_H_

View File

@@ -1,17 +1,15 @@
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine Master
// License Agreement.
// Copyright 2013 Google Inc. All Rights Reserved.
//
// File - Platform independent interface for a File class
//
#ifndef WVCDM_CORE_FILE_STORE_H_
#define WVCDM_CORE_FILE_STORE_H_
#ifndef WVCDM_UTIL_FILE_STORE_H_
#define WVCDM_UTIL_FILE_STORE_H_
#include <unistd.h>
#include <string>
#include <vector>
#include "wv_cdm_types.h"
#include "disallow_copy_and_assign.h"
namespace wvcdm {
@@ -79,4 +77,4 @@ class FileSystem {
} // namespace wvcdm
#endif // WVCDM_CORE_FILE_STORE_H_
#endif // WVCDM_UTIL_FILE_STORE_H_

View File

@@ -1,13 +1,11 @@
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine Master
// License Agreement.
// Copyright 2013 Google Inc. All Rights Reserved.
//
// Lock - Platform independent interface for a Mutex class
//
#ifndef WVCDM_CORE_LOCK_H_
#define WVCDM_CORE_LOCK_H_
#ifndef WVCDM_UTIL_LOCK_H_
#define WVCDM_UTIL_LOCK_H_
#include "wv_cdm_types.h"
#include "disallow_copy_and_assign.h"
namespace wvcdm {
@@ -50,4 +48,4 @@ class AutoLock {
} // namespace wvcdm
#endif // WVCDM_CORE_LOCK_H_
#endif // WVCDM_UTIL_LOCK_H_

View File

@@ -1,11 +1,9 @@
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine Master
// License Agreement.
// Copyright 2013 Google Inc. All Rights Reserved.
//
// Log - Platform independent interface for a Logging class
//
#ifndef WVCDM_CORE_LOG_H_
#define WVCDM_CORE_LOG_H_
#ifndef WVCDM_UTIL_LOG_H_
#define WVCDM_UTIL_LOG_H_
namespace wvcdm {
@@ -31,6 +29,7 @@ void Log(const char* file, const char* function, int line, LogPriority level,
const char* fmt, ...);
// Log APIs
#ifndef LOGE
#define LOGE(...) Log(__FILE__, __func__, __LINE__, \
wvcdm::LOG_ERROR, __VA_ARGS__)
#define LOGW(...) Log(__FILE__, __func__, __LINE__, \
@@ -41,6 +40,7 @@ void Log(const char* file, const char* function, int line, LogPriority level,
wvcdm::LOG_DEBUG, __VA_ARGS__)
#define LOGV(...) Log(__FILE__, __func__, __LINE__, \
wvcdm::LOG_VERBOSE, __VA_ARGS__)
#endif
} // namespace wvcdm
#endif // WVCDM_CORE_LOG_H_
#endif // WVCDM_UTIL_LOG_H_

View File

@@ -1,9 +1,7 @@
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine Master
// License Agreement.
// Copyright 2013 Google Inc. All Rights Reserved.
#ifndef WVCDM_CORE_STRING_CONVERSIONS_H_
#define WVCDM_CORE_STRING_CONVERSIONS_H_
#ifndef WVCDM_UTIL_STRING_CONVERSIONS_H_
#define WVCDM_UTIL_STRING_CONVERSIONS_H_
#include <stddef.h>
#include <stdint.h>
@@ -29,4 +27,4 @@ inline int64_t ntohll64(int64_t x) { return htonll64(x); }
} // namespace wvcdm
#endif // WVCDM_CORE_STRING_CONVERSIONS_H_
#endif // WVCDM_UTIL_STRING_CONVERSIONS_H_

View File

@@ -1,6 +1,4 @@
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine Master
// License Agreement.
// Copyright 2013 Google Inc. All Rights Reserved.
#include "string_conversions.h"

View File

@@ -7,6 +7,7 @@ LOCAL_CFLAGS := \
LOCAL_C_INCLUDES := \
system/core/include \
vendor/widevine/libwvdrmengine/cdm/core/include \
vendor/widevine/libwvdrmengine/cdm/util/include \
vendor/widevine/libwvdrmengine/level3/include \
vendor/widevine/libwvdrmengine/oemcrypto/include
LOCAL_MODULE := libwvlevel3

View File

@@ -7,6 +7,7 @@ LOCAL_CFLAGS := \
LOCAL_C_INCLUDES := \
system/core/include \
vendor/widevine/libwvdrmengine/cdm/core/include \
vendor/widevine/libwvdrmengine/cdm/util/include \
vendor/widevine/libwvdrmengine/level3/include \
vendor/widevine/libwvdrmengine/oemcrypto/include
LOCAL_MODULE := libwvlevel3

View File

@@ -7,6 +7,7 @@ LOCAL_CFLAGS := \
LOCAL_C_INCLUDES := \
system/core/include \
vendor/widevine/libwvdrmengine/cdm/core/include \
vendor/widevine/libwvdrmengine/cdm/util/include \
vendor/widevine/libwvdrmengine/level3/include \
vendor/widevine/libwvdrmengine/oemcrypto/include
LOCAL_MODULE := libwvlevel3

View File

@@ -7,6 +7,7 @@ LOCAL_CFLAGS := \
LOCAL_C_INCLUDES := \
system/core/include \
vendor/widevine/libwvdrmengine/cdm/core/include \
vendor/widevine/libwvdrmengine/cdm/util/include \
vendor/widevine/libwvdrmengine/level3/include \
vendor/widevine/libwvdrmengine/oemcrypto/include
LOCAL_MODULE := libwvlevel3

View File

@@ -7,6 +7,7 @@ LOCAL_CFLAGS := \
LOCAL_C_INCLUDES := \
system/core/include \
vendor/widevine/libwvdrmengine/cdm/core/include \
vendor/widevine/libwvdrmengine/cdm/util/include \
vendor/widevine/libwvdrmengine/level3/include \
vendor/widevine/libwvdrmengine/oemcrypto/include
LOCAL_MODULE := libwvlevel3

View File

@@ -7,6 +7,7 @@ LOCAL_CFLAGS := \
LOCAL_C_INCLUDES := \
system/core/include \
vendor/widevine/libwvdrmengine/cdm/core/include \
vendor/widevine/libwvdrmengine/cdm/util/include \
vendor/widevine/libwvdrmengine/level3/include \
vendor/widevine/libwvdrmengine/oemcrypto/include
LOCAL_MODULE := libwvlevel3

View File

@@ -14,6 +14,7 @@ LOCAL_C_INCLUDES := \
vendor/widevine/libwvdrmengine/cdm/core/include \
vendor/widevine/libwvdrmengine/cdm/include \
vendor/widevine/libwvdrmengine/cdm/metrics/include \
vendor/widevine/libwvdrmengine/cdm/util/include \
vendor/widevine/libwvdrmengine/include \
vendor/widevine/libwvdrmengine/mediacrypto/include \
vendor/widevine/libwvdrmengine/oemcrypto/include \
@@ -49,6 +50,7 @@ LOCAL_C_INCLUDES := \
vendor/widevine/libwvdrmengine/cdm/core/include \
vendor/widevine/libwvdrmengine/cdm/include \
vendor/widevine/libwvdrmengine/cdm/metrics/include \
vendor/widevine/libwvdrmengine/cdm/util/include \
vendor/widevine/libwvdrmengine/include_hidl \
vendor/widevine/libwvdrmengine/include \
vendor/widevine/libwvdrmengine/mediacrypto/include_hidl \

View File

@@ -14,6 +14,7 @@ LOCAL_C_INCLUDES := \
vendor/widevine/libwvdrmengine/cdm/core/include \
vendor/widevine/libwvdrmengine/cdm/include \
vendor/widevine/libwvdrmengine/cdm/metrics/include \
vendor/widevine/libwvdrmengine/cdm/util/include \
vendor/widevine/libwvdrmengine/mediacrypto/include \
vendor/widevine/libwvdrmengine/oemcrypto/include \
@@ -70,6 +71,7 @@ LOCAL_C_INCLUDES := \
vendor/widevine/libwvdrmengine/cdm/core/include \
vendor/widevine/libwvdrmengine/cdm/include \
vendor/widevine/libwvdrmengine/cdm/metrics/include \
vendor/widevine/libwvdrmengine/cdm/util/include \
vendor/widevine/libwvdrmengine/include_hidl \
vendor/widevine/libwvdrmengine/mediacrypto/include_hidl \
vendor/widevine/libwvdrmengine/mediacrypto/include \

View File

@@ -15,6 +15,7 @@ LOCAL_C_INCLUDES := \
vendor/widevine/libwvdrmengine/cdm/core/include \
vendor/widevine/libwvdrmengine/cdm/include \
vendor/widevine/libwvdrmengine/cdm/metrics/include \
vendor/widevine/libwvdrmengine/cdm/util/include \
vendor/widevine/libwvdrmengine/include \
vendor/widevine/libwvdrmengine/mediadrm/include \
vendor/widevine/libwvdrmengine/oemcrypto/include \
@@ -51,6 +52,7 @@ LOCAL_C_INCLUDES := \
vendor/widevine/libwvdrmengine/cdm/core/include \
vendor/widevine/libwvdrmengine/cdm/include \
vendor/widevine/libwvdrmengine/cdm/metrics/include \
vendor/widevine/libwvdrmengine/cdm/util/include \
vendor/widevine/libwvdrmengine/include_hidl \
vendor/widevine/libwvdrmengine/include \
vendor/widevine/libwvdrmengine/mediadrm/include_hidl \

View File

@@ -14,6 +14,7 @@ LOCAL_C_INCLUDES := \
vendor/widevine/libwvdrmengine/cdm/core/include \
vendor/widevine/libwvdrmengine/cdm/include \
vendor/widevine/libwvdrmengine/cdm/metrics/include \
vendor/widevine/libwvdrmengine/cdm/util/include \
vendor/widevine/libwvdrmengine/include \
vendor/widevine/libwvdrmengine/mediadrm/include \
vendor/widevine/libwvdrmengine/oemcrypto/include \
@@ -70,6 +71,7 @@ LOCAL_C_INCLUDES := \
vendor/widevine/libwvdrmengine/cdm/core/include \
vendor/widevine/libwvdrmengine/cdm/include \
vendor/widevine/libwvdrmengine/cdm/metrics/include \
vendor/widevine/libwvdrmengine/cdm/util/include \
vendor/widevine/libwvdrmengine/include_hidl \
vendor/widevine/libwvdrmengine/include \
vendor/widevine/libwvdrmengine/mediadrm/include_hidl \
@@ -133,6 +135,7 @@ LOCAL_C_INCLUDES := \
vendor/widevine/libwvdrmengine/cdm/core/include \
vendor/widevine/libwvdrmengine/cdm/include \
vendor/widevine/libwvdrmengine/cdm/metrics/include \
vendor/widevine/libwvdrmengine/cdm/util/include \
vendor/widevine/libwvdrmengine/include_hidl \
vendor/widevine/libwvdrmengine/include \
vendor/widevine/libwvdrmengine/mediadrm/include_hidl \

View File

@@ -0,0 +1,67 @@
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine Master
// License Agreement.
#ifndef WV_OEMCRYPTO_TYPES_H_
#define WV_OEMCRYPTO_TYPES_H_
#include <stdint.h>
namespace wvoec {
// This is the format of a Widevine keybox.
typedef struct WidevineKeybox { // 128 bytes total.
// C character string identifying the device. Null terminated.
uint8_t device_id_[32];
// 128 bit AES key assigned to device. Generated by Widevine.
uint8_t device_key_[16];
// Key Data. Encrypted data.
uint8_t data_[72];
// Constant code used to recognize a valid keybox "kbox" = 0x6b626f78.
uint8_t magic_[4];
// The CRC checksum of the first 124 bytes of the keybox.
uint8_t crc_[4];
} WidevineKeybox;
// Key Control Block Bit Masks:
const uint32_t kControlObserveDataPath = (1<<31);
const uint32_t kControlObserveHDCP = (1<<30);
const uint32_t kControlObserveCGMS = (1<<29);
const uint32_t kControlRequireAntiRollbackHardware = (1<<28);
const uint32_t kSharedLicense = (1<<23);
const uint32_t kControlSRMVersionRequired = (1<<22);
const uint32_t kControlDisableAnalogOutput = (1<<21);
const uint32_t kControlSecurityPatchLevelShift = 15;
const uint32_t kControlSecurityPatchLevelMask =
(0x3F<<kControlSecurityPatchLevelShift);
const uint32_t kControlReplayMask = (0x03<<13);
const uint32_t kControlNonceRequired = (0x01<<13);
const uint32_t kControlNonceOrEntry = (0x02<<13);
const uint32_t kControlHDCPVersionShift = 9;
const uint32_t kControlHDCPVersionMask = (0x0F<<kControlHDCPVersionShift);
const uint32_t kControlAllowEncrypt = (1<<8);
const uint32_t kControlAllowDecrypt = (1<<7);
const uint32_t kControlAllowSign = (1<<6);
const uint32_t kControlAllowVerify = (1<<5);
const uint32_t kControlDataPathSecure = (1<<4);
const uint32_t kControlNonceEnabled = (1<<3);
const uint32_t kControlHDCPRequired = (1<<2);
const uint32_t kControlCGMSMask = (0x03);
const uint32_t kControlCGMSCopyFreely = (0x00);
const uint32_t kControlCGMSCopyOnce = (0x02);
const uint32_t kControlCGMSCopyNever = (0x03);
// Various constants and sizes:
static const size_t KEY_CONTROL_SIZE = 16;
static const size_t KEY_ID_SIZE = 16;
static const size_t KEY_IV_SIZE = 16;
static const size_t KEY_PAD_SIZE = 16;
static const size_t KEY_SIZE = 16;
static const size_t MAC_KEY_SIZE = 32;
static const size_t KEYBOX_KEY_DATA_SIZE = 72;
static const size_t SRM_REQUIREMENT_SIZE = 12;
} // namespace wvoec
#endif // WV_OEMCRYPTO_TYPES_H_

View File

@@ -84,12 +84,12 @@ class Unpacked_PST_Report {
int64_t time;
memcpy(&time, buffer_ + kseconds_since_license_received_offset,
sizeof(int64_t));
return wvcdm::ntohll64(time);
return ntohll64(time);
}
// Parameter time is in host byte order.
void set_seconds_since_license_received(int64_t time) const {
time = wvcdm::ntohll64(time);
time = ntohll64(time);
memcpy(buffer_ + kseconds_since_license_received_offset, &time,
sizeof(int64_t));
}
@@ -99,12 +99,12 @@ class Unpacked_PST_Report {
int64_t time;
memcpy(&time, buffer_ + kseconds_since_first_decrypt_offset,
sizeof(int64_t));
return wvcdm::ntohll64(time);
return ntohll64(time);
}
// Parameter time is in host byte order.
void set_seconds_since_first_decrypt(int64_t time) const {
time = wvcdm::ntohll64(time);
time = ntohll64(time);
memcpy(buffer_ + kseconds_since_first_decrypt_offset, &time,
sizeof(int64_t));
}
@@ -114,12 +114,12 @@ class Unpacked_PST_Report {
int64_t time;
memcpy(&time, buffer_ + kseconds_since_last_decrypt_offset,
sizeof(int64_t));
return wvcdm::ntohll64(time);
return ntohll64(time);
}
// Parameter time is in host byte order.
void set_seconds_since_last_decrypt(int64_t time) const {
time = wvcdm::ntohll64(time);
time = ntohll64(time);
memcpy(buffer_ + kseconds_since_last_decrypt_offset, &time,
sizeof(int64_t));
}

View File

@@ -1,599 +0,0 @@
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// Mock implementation of OEMCrypto APIs
//
// This file contains oemcrypto engine properties that reads data from a file
// to decide what it's current status is. It is used for testing cdm code.
// The following properties are read from the file:
// log_level: logging level to use.
// 0 = LOG_ERROR,
// 1 = LOG_WARN,
// 2 = LOG_INFO,
// 3 = LOG_DEBUG,
// 4 = LOG_VERBOSE
// kLogging*: All logging flags found in oemcrypto/include/oemcrypto_logging.h
// can be turned on (1) or off (0).
// security_level: returned by OEMCrypto_SecurityLevel.
// secure_lib: If set, then this will be used as a path to
// the L1 liboemcrypto.so that we can use secure buffers.
// current_hdcp: returned by OEMCrypto_GetHDCPCapability and
// used to verify the key control block in methods like DecryptCENC.
// HDCP_NONE = 0, // No HDCP supported, no secure data path.
// HDCP_V1 = 1, // HDCP version 1.0
// HDCP_V2 = 2, // HDCP version 2.0 Type 1.
// HDCP_V2_1 = 3, // HDCP version 2.1 Type 1.
// HDCP_V2_2 = 4, // HDCP version 2.2 Type 1.
// HDCP_NO_DIGITAL_OUTPUT = 0xff // No digital output.
// max_hdcp: returned by OEMCrypto_GetHDCPCapability. Same values as above.
// srm_update_supported: If "1", then srm update is supported.
// srm_initial_version: Initial value for srm version.
// This will be ignored after a reset. If this is not set, CurrentSRM will
// return NOT_IMPLEMENTED.
// srm_load_fail: If set to a nonzero number, then load_srm will
// fail and the version will not be updated. The number is converted to
// an OEMCryptoResult and returned.
// srm_load_version: If this is set, then it will be used as the
// new srm version after loading an SRM -- ignoring the contents of the SRM.
// If srm_load_version is -1, then the buffer passed into LoadSRM will be
// parsed.
// srm_blacklisted_device_attached: If set to "1", then a
// oemcrypto will act as if a blacklisted device is attached -- i.e.
// playback will be restricted to the local display only.
// srm_attached_device_id: If nonzero, the id of a blacklisted device.
// If this id is in the revocation list of an SRM file when it is loaded,
// playback will be restricted to the local display only.
// security_patch_level: This is the value returned by
// OEMCrypto_Security_Patch_Level. If the key control block requires a
// higher level, then OEMCrypto_LoadKeys will fail.
// max_buffer_size: maximum size of a buffer accepted by DecryptCENC and
// friends. If this is 0, there is no restriction. If it is 1, the
// minimum allowed value is used.
// use_keybox: If this is 1, then the test keybox is used. If this is zero,
// then the test OEM certificate is used.
// use_fallback: If this is nonzero, then the installed Level 1 library will
// be used to play content to a secure buffer. Decryption and key
// verification are done by the mock, but then the data is copied to the
// secure buffer using OEMCrypto_CopyBuffer. The filename of the fallback
// library is hardcoded to "level1_backup_liboemcrypto.so". It is
// recommended you use the install script to ensure you have the right
// filename.
//
#include <arpa/inet.h>
#include <dlfcn.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include <string>
#include <map>
#include "log.h"
#include "oem_cert.h"
#include "oemcrypto_engine_mock.h"
#include "oemcrypto_logging.h"
#include "properties.h"
#include "string_conversions.h"
namespace wvoec_mock {
namespace {
typedef OEMCryptoResult (*L1_Initialize_t)(void);
typedef OEMCryptoResult (*L1_Terminate_t)(void);
typedef OEMCryptoResult (*L1_CopyBuffer_t)(const uint8_t* data_addr,
size_t data_length,
OEMCrypto_DestBufferDesc* out_buffer,
uint8_t subsample_flags);
const std::string kDefaultOptionsFile = "/data/mediadrm/oemcrypto/options.txt";
} // namespace
class AndroidModifiableCryptoEngine : public CryptoEngine {
public:
AndroidModifiableCryptoEngine(std::auto_ptr<wvcdm::FileSystem> file_system)
: CryptoEngine(file_system),
options_file_(kDefaultOptionsFile),
srm_loaded_(false),
srm_version_(0),
level1_valid_(false),
level1_library_(NULL) {
std::string path;
if (wvcdm::Properties::GetDeviceFilesBasePath(wvcdm::kSecurityLevelL3,
&path)) {
options_file_ = path + "options.txt";
}
}
void MaybeReadOptionsFile() {
static time_t last_check = 0;
static time_t last_changed = 0;
time_t now = time(NULL);
if (now > last_check + 5) { // Check every five seconds.
last_check = now;
struct stat file_stat;
if (stat(options_file_.c_str(), &file_stat)) {
LOGE("Could not stat %s: %s", options_file_.c_str(), strerror(errno));
return;
}
if (file_stat.st_mtime > last_changed) {
last_changed = file_stat.st_mtime;
ReadOptionsFile();
}
}
}
void ReadOptionsFile() {
FILE *file = fopen(options_file_.c_str(), "r");
if (!file) {
LOGE("Could not read %s %s", options_file_.c_str(), strerror(errno));
return;
}
while (!feof(file)) {
char name[80 + 1];
int64_t value;
if (fscanf(file, "%80s %lld", name, &value)) {
LOGD("Option %s = %lld", name, value);
options_[std::string(name)] = value;
}
}
fclose(file);
InitializeLogging();
}
int64_t GetOption(const std::string &key, int64_t default_value) {
MaybeReadOptionsFile();
if (options_.find(key) == options_.end() ) {
LOGW("Option %s not set. Using default %lld", key.c_str(), default_value);
return default_value;
}
return options_[key];
}
void InitializeLogging() {
int log_level = GetOption("log_level", wvcdm::LOG_DEBUG);
int categories = 0;
if (GetOption("kLoggingTraceOEMCryptoCalls", 0) > 0)
categories |= kLoggingTraceOEMCryptoCalls;
if (GetOption("kLoggingDumpContentKeys", 0) > 0)
categories |= kLoggingDumpContentKeys;
if (GetOption("kLoggingDumpKeyControlBlocks", 0) > 0)
categories |= kLoggingDumpKeyControlBlocks;
if (GetOption("kLoggingDumpDerivedKeys", 0) > 0)
categories |= kLoggingDumpDerivedKeys;
if (GetOption("kLoggingTraceNonce", 0) > 0)
categories |= kLoggingTraceNonce;
if (GetOption("kLoggingTraceDecryption", 0) > 0)
categories |= kLoggingTraceDecryption;
if (GetOption("kLoggingTraceUsageTable", 0) > 0)
categories |= kLoggingTraceUsageTable;
if (GetOption("kLoggingTraceDecryptCalls", 0) > 0)
categories |= kLoggingTraceDecryptCalls;
if (GetOption("kLoggingDumpTraceAll", 0) > 0)
categories |= kLoggingDumpTraceAll;
SetLoggingSettings(log_level, categories);
}
#define QUOTE_DEFINE(A) #A
#define QUOTE(A) QUOTE_DEFINE(A)
#define LOOKUP(Name, Function) \
Name = (L1_##Name##t)dlsym(level1_library_, QUOTE(Function)); \
if (!Name) { \
LOGW("Could not load L1 %s.", \
QUOTE(Function)); \
Terminate(); \
return false; \
}
virtual bool Initialize() {
LOGD("OEMCrypto Mock With Options " " " __DATE__ " " __TIME__);
MaybeReadOptionsFile();
if (!GetOption("use_fallback", 1)) {
LOGD("Level 1 fallback ignored.");
return true;
}
level1_library_ = dlopen("level1_backup_liboemcrypto.so", RTLD_NOW);
if (level1_library_ == NULL) {
LOGE("Could not load backup: %s", dlerror());
return false;
}
LOOKUP(Initialize_, OEMCrypto_Initialize);
LOOKUP(Terminate_, OEMCrypto_Terminate);
LOOKUP(CopyBuffer_, OEMCrypto_CopyBuffer);
level1_valid_ = true;
OEMCryptoResult sts = Initialize_();
LOGD("L1 fall back initialized. status = %d.", sts);
if (sts != OEMCrypto_SUCCESS) {
LOGW("Terminating L1 because init failed.");
Terminate();
LOGW("Continuing Mock without L1 fallback.");
}
return true;
}
virtual void Terminate() {
if (level1_valid_) Terminate_();
if (level1_library_ != NULL) {
LOGD("Closing L1 fall back.\n");
dlclose(level1_library_);
level1_valid_ = false;
level1_library_ = NULL;
CopyBuffer_ = NULL;
Initialize_ = NULL;
Terminate_ = NULL;
} else {
LOGD("Terminate mock.\n");
}
}
const char *HDCPCapabilityAsString(OEMCrypto_HDCP_Capability value) {
switch (value) {
case HDCP_NONE:
return "No HDCP supported, no secure data path";
case HDCP_V1:
return "HDCP version 1.0";
case HDCP_V2:
return "HDCP version 2.0";
case HDCP_V2_1:
return "HDCP version 2.1";
case HDCP_V2_2:
return "HDCP version 2.2";
case HDCP_NO_DIGITAL_OUTPUT:
return "No HDCP device attached/using local display with secure path";
default:
return "<INVALID VALUE>";
}
}
OEMCrypto_ProvisioningMethod config_provisioning_method() {
if (GetOption("use_keybox", 1)) {
return OEMCrypto_Keybox;
} else {
return OEMCrypto_OEMCertificate;
}
}
OEMCryptoResult get_oem_certificate(SessionContext* session,
uint8_t* public_cert,
size_t* public_cert_length) {
if (GetOption("use_keybox", 1)) {
LOGD("OEM Cert asked for when use_keybox = 1.");
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
}
if (kOEMPublicCertSize == 0) {
LOGD("OEM Cert Size is 0.");
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
}
if (public_cert_length == NULL) {
LOGD("OEM Cert length is 0.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
if (*public_cert_length < kOEMPublicCertSize) {
*public_cert_length = kOEMPublicCertSize;
return OEMCrypto_ERROR_SHORT_BUFFER;
}
*public_cert_length = kOEMPublicCertSize;
if (public_cert == NULL) {
return OEMCrypto_ERROR_SHORT_BUFFER;
}
memcpy(public_cert, kOEMPublicCert, kOEMPublicCertSize);
if (!session->LoadRSAKey(kOEMPrivateKey, kOEMPrivateKeySize)) {
LOGE("Private RSA Key did not load correctly.");
return OEMCrypto_ERROR_INVALID_RSA_KEY;
}
return OEMCrypto_SUCCESS;
}
// Returns "L3" for a software only library. L1 is for hardware protected
// data paths.
const char *config_security_level() {
switch (GetOption("security_level", 0)) {
default:
LOGW("Option security_level not set. Default is L3.");
case 3:
return "L3";
case 2:
return "L2";
case 1:
return "L1";
}
}
// Returns the HDCP version currently in use.
OEMCrypto_HDCP_Capability config_current_hdcp_capability() {
static OEMCrypto_HDCP_Capability current_hdcp = HDCP_NONE;
OEMCrypto_HDCP_Capability new_current_hdcp =
static_cast<OEMCrypto_HDCP_Capability>(GetOption("current_hdcp", 0));
if (current_hdcp != new_current_hdcp) {
LOGI("OEMCrypto current HDCP changed from %d (%s) to %d (%s)", current_hdcp,
HDCPCapabilityAsString(current_hdcp), new_current_hdcp,
HDCPCapabilityAsString(new_current_hdcp));
current_hdcp = new_current_hdcp;
}
return current_hdcp;
}
// Returns the max HDCP version supported.
OEMCrypto_HDCP_Capability config_maximum_hdcp_capability() {
static OEMCrypto_HDCP_Capability max_hdcp = HDCP_NONE;
MaybeReadOptionsFile();
OEMCrypto_HDCP_Capability new_max_hdcp =
static_cast<OEMCrypto_HDCP_Capability>(GetOption("max_hdcp", 0));
if (max_hdcp != new_max_hdcp) {
LOGI("OEMCrypto max HDCP changed from %d (%s) to %d (%s)", max_hdcp,
HDCPCapabilityAsString(max_hdcp), new_max_hdcp,
HDCPCapabilityAsString(new_max_hdcp));
max_hdcp = new_max_hdcp;
}
return max_hdcp;
}
// This should start at 0, and be incremented only when a security patch has
// been applied to the device that fixes a security bug.
uint8_t config_security_patch_level() {
return GetOption("security_patch_level", 0);
}
size_t max_buffer_size() {
int max = GetOption("max_buffer_size", 0);
// If max is 1, just use default max buffer.
if (max == 1) return CryptoEngine::max_buffer_size();
return max; // If 0, no restriction. If something else, use that restriction.
}
bool srm_update_supported() {
int supported = GetOption("srm_update_supported", 0);
LOGI("OEMCrypto mock %s supporting SRM update.",
supported ? "is" : "is not");
return supported != 0;
}
OEMCryptoResult current_srm_version(uint16_t *version) {
if (srm_loaded_) {
LOGV("SRM loaded. version used is %d.", srm_version_);
*version = srm_version_;
return OEMCrypto_SUCCESS;
}
int value = GetOption("srm_initial_version", -1);
if (value > 0) {
LOGV("SRM version from get option: %d.", value);
srm_version_ = value;
*version = value;
return OEMCrypto_SUCCESS;
} else {
LOGI("SRM initial version is %d -- reporting not implemented.", value);
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
}
}
// Convert uint24 or uint40 into a uint64.
int64_t unpack_odd_bytes(const uint8_t *buffer, size_t length) {
uint8_t small_buffer[8];
memset(small_buffer, 0, 8);
if (length > 8) {
LOGE("OEMCrypto Mock: programmer error. unpack %d bytes.", length);
length = 8;
}
size_t offset = 8 - length;
memcpy(small_buffer + offset, buffer, length);
return wvcdm::htonll64(*reinterpret_cast<const int64_t*>(small_buffer));
}
OEMCryptoResult load_srm(const uint8_t *buffer, size_t buffer_length) {
if (!srm_update_supported()) {
LOGE("OEMCrypto mock update not supported, but load_srm called.");
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
}
int result = GetOption("srm_load_fail", 0);
if (result > 0) {
LOGE("OEMCrypto mock load_srm returning error %d.", result);
return static_cast<OEMCryptoResult>(result);
}
int new_version = GetOption("srm_load_version", -1);
if (new_version >= 0) {
if (new_version < srm_version_) {
LOGE("New SRM version is lower than existing SRM version: %d < %d",
new_version, srm_version_);
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
srm_version_ = new_version;
LOGI("OEMCrypto mock told to change SRM version to %d.", srm_version_);
srm_loaded_ = true;
return OEMCrypto_SUCCESS;
}
if (buffer_length < 395) {
LOGE("OEMCrypto mock bad buffer size: %ld < 395.", buffer_length);
return OEMCrypto_ERROR_SHORT_BUFFER;
}
uint8_t srm_id = buffer[0] >> 4;
uint8_t hdcp2_indicator = buffer[0] & 0x0F;
uint8_t reserved = buffer[1];
uint16_t version = htons(*reinterpret_cast<const uint16_t *>(&buffer[2]));
if (reserved) {
LOGE("OEMCrypto mock. SRM's second byte nonzero: %02X.", reserved);
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
uint8_t generation = buffer[4];
if (generation > 1) {
LOGW("OEMCrypto mock. SRM Generation number is %d, but only first gen is parsed.",
generation);
LOGW("If the revoked device is in a a later generation, it will not be recognized.");
}
int64_t length = unpack_odd_bytes(buffer + 5, 3); // 24 bits.
if (length + 5 != buffer_length) {
LOGW("OEMCrypto mock. SRM length is %lld = 0x%llx, but I expected %zd = 0x%zx.",
length, length, buffer_length - 5, buffer_length - 5);
}
int64_t count = 0;
const uint8_t *ids;
if (srm_id == 8 && hdcp2_indicator == 0) {
// https://www.digital-cp.com/sites/default/files/specifications/HDCP%20Specification%20Rev1_4_Secure.pdf
count = buffer[8];
LOGI("OEMCrypto mock loading HDCP1 SRM. version = %d. count=%lld.",
version, count);
ids = buffer + 9;
if (buffer_length < 9 + count*5) {
LOGE("OEMCrypto mock bad buffer size for count = %lld: %d < %lld.",
count, buffer_length, 12 + count*5);
return OEMCrypto_ERROR_SHORT_BUFFER;
}
} else if (srm_id == 9 && hdcp2_indicator == 1) {
// https://www.digital-cp.com/sites/default/files/specifications/HDCP%20on%20HDMI%20Specification%20Rev2_2_Final1.pdf
count = unpack_odd_bytes(buffer + 8, 2) >> 6; // 10 bits = 2 bytes - 6.
LOGI("OEMCrypto mock loading HDCP2 SRM. version = %d. count=%lld.",
version, count);
ids = buffer + 12;
if (buffer_length < 12 + count*5) {
LOGE("OEMCrypto mock bad buffer size for count: %d < %ld.",
buffer_length, 12 + count*5);
return OEMCrypto_ERROR_SHORT_BUFFER;
}
} else {
LOGE("OEMCrypto mock bad buffer start: %02X%02X%02X%02X...", buffer[0],
buffer[1], buffer[2], buffer[3]);
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
for(size_t i = 0; i < count; i++) {
int64_t id = unpack_odd_bytes(ids + 5*i, 5);
srm_revocation_list_.push_back(id);
LOGI("OEMCrypto mock SRM revokes device %lld = 0x%llx", id, id);
}
srm_loaded_ = true;
srm_version_ = version;
return OEMCrypto_SUCCESS;
}
OEMCryptoResult remove_srm() {
if (!srm_update_supported()) {
LOGE("OEMCrypto mock update not supported, bug load_srm called.");
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
}
srm_version_ = 0;
srm_loaded_ = false;
return OEMCrypto_SUCCESS;
}
bool srm_blacklisted_device_attached() {
if (GetOption("srm_load_version", -1) < 0) {
return scan_revoked_list();
}
static int blacklisted = 0;
int new_value = GetOption("srm_blacklisted_device_attached", 0);
if (new_value != blacklisted) {
LOGI("SRM blacklisted device changed from %d to %d", blacklisted,
new_value);
blacklisted = new_value;
}
return blacklisted > 0;
}
bool scan_revoked_list() {
static int64_t old_attached_id = 0;
int64_t attached_id = GetOption("srm_attached_device_id", 0);
bool print_all_ids = false;
if (attached_id != old_attached_id) {
LOGD("OEMCrypto mock -- ID of attached device is %lld = 0x%lld",
attached_id, attached_id);
old_attached_id = attached_id;
print_all_ids = true;
}
for (size_t i = 0; i < srm_revocation_list_.size(); i++) {
if (print_all_ids) {
LOGD("OEMCrypto mock: %d) revoked id %lld = 0x%lld.", i,
srm_revocation_list_[i], srm_revocation_list_[i]);
}
if (srm_revocation_list_[i] == attached_id) {
LOGD("OEMCrypto mock: attached device %lld = 0x%lld is revoked.",
attached_id, attached_id);
return true;
}
}
LOGD("OEMCrypto mock: attached device %lld is not revoked.", attached_id);
return false;
}
virtual int nonce_flood_count() { GetOption("nonce_flood_count", 20); }
virtual void adjust_destination(OEMCrypto_DestBufferDesc *out_description,
size_t data_length, uint8_t subsample_flags) {
if (out_description->type != OEMCrypto_BufferType_Secure) return;
if (!level1_valid_) {
static bool warned_once = false;
if (!warned_once) {
warned_once = true;
LOGW("OEMCrypto Mock: given secure buffer with no level1 fallback.");
}
return;
}
if (subsample_flags & OEMCrypto_FirstSubsample) {
final_destination_.type = OEMCrypto_BufferType_Secure;
final_destination_.buffer.secure.handle =
out_description->buffer.secure.handle;
final_destination_.buffer.secure.max_length =
out_description->buffer.secure.max_length;
final_destination_.buffer.secure.offset =
out_description->buffer.secure.offset;
temp_buffer_.resize(final_destination_.buffer.secure.max_length);
temp_buffer_length_ = 0;
}
if (temp_buffer_length_ != out_description->buffer.secure.offset) {
LOGW("OEMCrypto: offset into secure buffer is not correct %zd != %zd.",
temp_buffer_length_, out_description->buffer.secure.offset);
}
size_t new_length = temp_buffer_length_ + data_length;
if (new_length > temp_buffer_.size()) {
LOGW("Temp buffer was not big enough. %zd > %zd.", new_length,
temp_buffer_.size());
temp_buffer_.resize(new_length);
}
destination_ = &temp_buffer_[temp_buffer_length_];
temp_buffer_length_ = new_length;
}
// Push destination buffer to L1 output.
virtual OEMCryptoResult PushDestination(
OEMCrypto_DestBufferDesc *out_description, uint8_t subsample_flags) {
if (level1_valid_ &&
(out_description->type == OEMCrypto_BufferType_Secure)) {
if (subsample_flags & OEMCrypto_LastSubsample) {
return CopyBuffer_(&temp_buffer_[0], temp_buffer_length_,
&final_destination_,
OEMCrypto_FirstSubsample | OEMCrypto_LastSubsample);
}
}
return OEMCrypto_SUCCESS;
}
private:
// If the SRM version has been loaded or not. If not, we use the system
// property to find the current SRM version.
bool srm_loaded_;
// Current srm version. Before an SRM has been loaded, this will be set from
// the system property.
int srm_version_;
// List of forbidden/revoked devices.
std::vector<int64_t> srm_revocation_list_;
std::map<std::string, int64_t> options_;
std::string options_file_;
bool level1_valid_;
void* level1_library_;
L1_CopyBuffer_t CopyBuffer_;
L1_Initialize_t Initialize_;
L1_Terminate_t Terminate_;
OEMCrypto_DestBufferDesc final_destination_;
std::vector<uint8_t> temp_buffer_;
size_t temp_buffer_length_; // Length of temp buffer currently in use.
};
CryptoEngine* CryptoEngine::MakeCryptoEngine(
std::auto_ptr<wvcdm::FileSystem> file_system) {
return new AndroidModifiableCryptoEngine(file_system);
}
} // namespace wvoec_mock

View File

@@ -1,28 +0,0 @@
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine Master
// License Agreement.
#ifndef WV_KEYBOX_H_
#define WV_KEYBOX_H_
#include <stdint.h>
namespace wvoec_mock {
// This is the format of a Widevine keybox.
typedef struct { // 128 bytes total.
// C character string identifying the device. Null terminated.
uint8_t device_id_[32];
// 128 bit AES key assigned to device. Generated by Widevine.
uint8_t device_key_[16];
// Key Data. Encrypted data.
uint8_t data_[72];
// Constant code used to recognize a valid keybox "kbox" = 0x6b626f78.
uint8_t magic_[4];
// The CRC checksum of the first 124 bytes of the keybox.
uint8_t crc_[4];
} WidevineKeybox;
} // namespace wvoec_mock
#endif // WV_KEYBOX_H_

View File

@@ -1,121 +0,0 @@
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine Master
// License Agreement.
#include "OEMCryptoCENC.h"
#include <string>
#include <gtest/gtest.h>
#include "log.h"
#include "oemcrypto_logging.h"
#include "oemcrypto_mock.cpp"
class OEMCryptoLoggingTest : public ::testing::Test {
protected:
OEMCryptoLoggingTest() {}
void SetUp() {
::testing::Test::SetUp();
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_Initialize());
}
void TearDown() {
OEMCrypto_Terminate();
::testing::Test::TearDown();
}
};
TEST_F(OEMCryptoLoggingTest, TestDumpHexFunctions) {
uint8_t vector[] = {0xFA, 0x11, 0x28, 0x33};
std::string buffer;
wvoec_mock::dump_hex_helper(buffer, "name", vector, 4u);
ASSERT_EQ("name = \n wvcdm::a2b_hex(\"FA112833\");\n", buffer);
uint8_t vector2[] = {
0xFA, 0x11, 0x28, 0x33, 0xFA, 0x11, 0x28, 0x33, 0xFA, 0x11,
0x28, 0x33, 0xFA, 0x11, 0x28, 0x33, 0xFA, 0x11, 0x28, 0x33,
0xFA, 0x11, 0x28, 0x33, 0x01, 0x14, 0x28, 0xAB, 0xFA, 0xCD,
0xEF, 0x67, 0x01, 0x14, 0x28, 0xAB, 0xFA, 0xCD, 0xEF, 0x67,
};
buffer.clear(); // dump_hex_helper appends to buffer
wvoec_mock::dump_hex_helper(buffer, "name", vector2, 40u);
ASSERT_EQ(
"name = \n "
"wvcdm::a2b_hex("
"\"FA112833FA112833FA112833FA112833FA112833FA112833011428ABFACDEF67\"\n "
" \"011428ABFACDEF67\");\n",
buffer);
buffer.clear(); // dump_hex_helper appends to buffer
wvoec_mock::dump_array_part_helper(buffer, "array", 5u, "name", vector2, 40u);
ASSERT_EQ(
"std::string s5_name = \n "
"wvcdm::a2b_hex("
"\"FA112833FA112833FA112833FA112833FA112833FA112833011428ABFACDEF67\"\n "
" \"011428ABFACDEF67\");\narray[5].name = message_ptr + "
"message.find(s5_name.data());\n",
buffer);
buffer.clear(); // dump_hex_helper appends to buffer
wvoec_mock::dump_array_part_helper(buffer, "array", 5u, "name", NULL, 40u);
ASSERT_EQ("array[5].name = NULL;\n", buffer);
}
TEST_F(OEMCryptoLoggingTest, TestChangeLoggingLevel) {
wvoec_mock::SetLoggingLevel(wvcdm::LOG_WARN);
ASSERT_EQ(wvcdm::LOG_WARN, wvcdm::g_cutoff);
wvoec_mock::SetLoggingLevel(wvcdm::LOG_INFO);
ASSERT_EQ(wvcdm::LOG_INFO, wvcdm::g_cutoff);
wvoec_mock::SetLoggingSettings(wvcdm::LOG_WARN,
wvoec_mock::kLoggingDumpTraceAll);
ASSERT_EQ(wvcdm::LOG_WARN, wvcdm::g_cutoff);
ASSERT_TRUE(wvoec_mock::LogCategoryEnabled(wvoec_mock::kLoggingDumpTraceAll));
wvoec_mock::TurnOffLoggingForAllCategories();
wvoec_mock::SetLoggingLevel(wvcdm::LOG_VERBOSE);
ASSERT_EQ(wvcdm::LOG_VERBOSE, wvcdm::g_cutoff);
wvoec_mock::SetLoggingLevel(wvcdm::LOG_WARN);
}
TEST_F(OEMCryptoLoggingTest, TestChangeLoggingCategories) {
using namespace wvoec_mock;
TurnOffLoggingForAllCategories();
ASSERT_FALSE(LogCategoryEnabled(kLoggingTraceDecryption |
kLoggingTraceOEMCryptoCalls));
AddLoggingForCategories(kLoggingDumpKeyControlBlocks |
kLoggingDumpDerivedKeys);
ASSERT_TRUE(LogCategoryEnabled(kLoggingDumpKeyControlBlocks));
ASSERT_FALSE(LogCategoryEnabled(kLoggingTraceUsageTable));
ASSERT_TRUE(LogCategoryEnabled(kLoggingDumpTraceAll));
RemoveLoggingForCategories(kLoggingDumpKeyControlBlocks |
kLoggingTraceUsageTable);
ASSERT_FALSE(LogCategoryEnabled(kLoggingDumpKeyControlBlocks));
ASSERT_TRUE(LogCategoryEnabled(kLoggingDumpDerivedKeys));
ASSERT_FALSE(LogCategoryEnabled(kLoggingTraceUsageTable));
TurnOffLoggingForAllCategories();
ASSERT_FALSE(LogCategoryEnabled(kLoggingTraceUsageTable));
AddLoggingForCategories(kLoggingDumpTraceAll);
ASSERT_TRUE(LogCategoryEnabled(kLoggingDumpKeyControlBlocks));
ASSERT_TRUE(LogCategoryEnabled(kLoggingTraceOEMCryptoCalls));
ASSERT_TRUE(LogCategoryEnabled(kLoggingDumpContentKeys));
ASSERT_TRUE(LogCategoryEnabled(kLoggingDumpKeyControlBlocks));
ASSERT_TRUE(LogCategoryEnabled(kLoggingDumpDerivedKeys));
ASSERT_TRUE(LogCategoryEnabled(kLoggingTraceNonce));
ASSERT_TRUE(LogCategoryEnabled(kLoggingTraceDecryption));
ASSERT_TRUE(LogCategoryEnabled(kLoggingTraceUsageTable));
ASSERT_TRUE(LogCategoryEnabled(kLoggingTraceDecryptCalls));
ASSERT_TRUE(LogCategoryEnabled(kLoggingDumpTraceAll));
RemoveLoggingForCategories(kLoggingDumpKeyControlBlocks);
ASSERT_FALSE(LogCategoryEnabled(kLoggingDumpKeyControlBlocks));
}

View File

@@ -4,20 +4,20 @@ include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
src/keys.cpp \
src/oemcrypto_auth_mock.cpp \
src/oemcrypto_auth_ref.cpp \
src/oemcrypto_engine_device_properties.cpp \
src/oemcrypto_engine_mock.cpp \
src/oemcrypto_key_mock.cpp \
src/oemcrypto_keybox_mock.cpp \
src/oemcrypto_engine_ref.cpp \
src/oemcrypto_key_ref.cpp \
src/oemcrypto_keybox_ref.cpp \
src/oemcrypto_keybox_testkey.cpp \
src/oemcrypto_logging.cpp \
src/oemcrypto_mock.cpp \
src/oemcrypto_ref.cpp \
src/oemcrypto_nonce_table.cpp \
src/oemcrypto_old_usage_table_mock.cpp \
src/oemcrypto_old_usage_table_ref.cpp \
src/oemcrypto_rsa_key_shared.cpp \
src/oemcrypto_session.cpp \
src/oemcrypto_session_key_table.cpp \
src/oemcrypto_usage_table_mock.cpp \
src/oemcrypto_usage_table_ref.cpp \
src/wvcrc.cpp \
LOCAL_MODULE_TAGS := tests
@@ -25,7 +25,7 @@ LOCAL_MODULE_TAGS := tests
LOCAL_C_INCLUDES += \
$(LOCAL_PATH)/../include \
$(LOCAL_PATH)/src \
vendor/widevine/libwvdrmengine/cdm/core/include \
vendor/widevine/libwvdrmengine/cdm/util/include \
LOCAL_SHARED_LIBRARIES := \
libcutils \

View File

@@ -0,0 +1,5 @@
# Reference OEMCrypto
This directory contains a testing-only implementation of OEMCrypto. **This
implementation is *NOT* suitable for production use and should *NOT* be released
on devices.**

View File

@@ -2,7 +2,7 @@
#include "oem_cert.h"
namespace wvoec_mock {
namespace wvoec_ref {
extern const uint32_t kOEMSystemId_Prod = 7346;
@@ -389,4 +389,4 @@ const uint8_t* kOEMPublicCert = kOEMPublicCert_Prod;
const size_t kOEMPrivateKeySize = kOEMPrivateKeySize_Prod;
const size_t kOEMPublicCertSize = kOEMPublicCertSize_Prod;
} // namespace wvoec_mock
} // namespace wvoec_ref

View File

@@ -5,7 +5,7 @@
#include <stddef.h>
#include <stdint.h>
namespace wvoec_mock {
namespace wvoec_ref {
// Refer to the following in main modules
extern const uint32_t kOEMSystemId;
@@ -16,6 +16,6 @@ extern const uint8_t* kOEMPublicCert;
extern const size_t kOEMPrivateKeySize;
extern const size_t kOEMPublicCertSize;
} // namespace wvoec_mock
} // namespace wvoec_ref
#endif // OEM_CERT_H_

View File

@@ -2,23 +2,23 @@
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// Mock implementation of OEMCrypto APIs
// Ref implementation of OEMCrypto APIs
//
#include "oemcrypto_auth_mock.h"
#include "oemcrypto_auth_ref.h"
#include <vector>
#include "keys.h"
#include "log.h"
#include "oemcrypto_key_mock.h"
#include "oemcrypto_key_ref.h"
#include "oemcrypto_logging.h"
#include "oemcrypto_rsa_key_shared.h"
#include "wv_cdm_constants.h"
namespace {
// A 2048 bit RSA key in PKCS#8 PrivateKeyInfo format
// This is the RSA Test Key.
// This is the RSA Test Key. This key is not derived
// from any Widevine authentication root.
static const uint8_t kTestRSAPKCS8PrivateKeyInfo2_2048[] = {
0x30, 0x82, 0x04, 0xbc, 0x02, 0x01, 0x00, 0x30,
0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
@@ -176,7 +176,7 @@ static const uint8_t kTestRSAPKCS8PrivateKeyInfo2_2048[] = {
} // namespace
namespace wvoec_mock {
namespace wvoec_ref {
AuthenticationRoot::AuthenticationRoot(OEMCrypto_ProvisioningMethod method) :
provisioning_method_(method),
@@ -202,4 +202,4 @@ bool AuthenticationRoot::Validate() {
return NO_ERROR == ValidateKeybox();
}
} // namespace wvoec_mock
} // namespace wvoec_ref

View File

@@ -2,10 +2,10 @@
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// Mock implementation of OEMCrypto APIs
// Ref implementation of OEMCrypto APIs
//
#ifndef OEMCRYPTO_AUTH_MOCK_H_
#define OEMCRYPTO_AUTH_MOCK_H_
#ifndef OEMCRYPTO_AUTH_REF_H_
#define OEMCRYPTO_AUTH_REF_H_
#include <stdint.h>
#include <vector>
@@ -13,12 +13,14 @@
#include <openssl/rsa.h>
#include "OEMCryptoCENC.h" // Needed for enums only.
#include "oemcrypto_key_mock.h"
#include "oemcrypto_keybox_mock.h"
#include "disallow_copy_and_assign.h"
#include "oemcrypto_key_ref.h"
#include "oemcrypto_keybox_ref.h"
#include "oemcrypto_rsa_key_shared.h"
#include "wv_cdm_types.h"
#include "oemcrypto_scoped_ptr.h"
#include "oemcrypto_types.h"
namespace wvoec_mock {
namespace wvoec_ref {
class AuthenticationRoot {
public:
@@ -73,6 +75,6 @@ class AuthenticationRoot {
CORE_DISALLOW_COPY_AND_ASSIGN(AuthenticationRoot);
};
} // namespace wvoec_mock
} // namespace wvoec_ref
#endif // OEMCRYPTO_AUTH_MOCK_H_
#endif // OEMCRYPTO_AUTH_REF_H_

View File

@@ -2,16 +2,16 @@
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// Mock implementation of OEMCrypto APIs
// Ref implementation of OEMCrypto APIs
//
#include "oemcrypto_engine_mock.h"
#include "oemcrypto_engine_ref.h"
namespace wvoec_mock {
namespace wvoec_ref {
CryptoEngine* CryptoEngine::MakeCryptoEngine(
std::auto_ptr<wvcdm::FileSystem> file_system) {
scoped_ptr<wvcdm::FileSystem> file_system) {
return new CryptoEngine(file_system);
}
} // namespace wvoec_mock
} // namespace wvoec_ref

View File

@@ -2,17 +2,17 @@
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// Mock implementation of OEMCrypto APIs
// Ref implementation of OEMCrypto APIs
//
// This file contains oemcrypto engine properties that would be for a
// level 1 device.
#include "oemcrypto_engine_mock.h"
#include "oemcrypto_engine_ref.h"
namespace wvoec_mock {
namespace wvoec_ref {
class L1CryptoEngine : public CryptoEngine {
public:
explicit L1CryptoEngine(std::auto_ptr<wvcdm::FileSystem> file_system)
explicit L1CryptoEngine(scoped_ptr<wvcdm::FileSystem> file_system)
: CryptoEngine(file_system) {}
bool config_local_display_only() { return true; }
@@ -31,8 +31,8 @@ class L1CryptoEngine : public CryptoEngine {
};
CryptoEngine* CryptoEngine::MakeCryptoEngine(
std::auto_ptr<wvcdm::FileSystem> file_system) {
scoped_ptr<wvcdm::FileSystem> file_system) {
return new L1CryptoEngine(file_system);
}
} // namespace wvoec_mock
} // namespace wvoec_ref

View File

@@ -2,20 +2,20 @@
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// Mock implementation of OEMCrypto APIs
// Ref implementation of OEMCrypto APIs
//
// This file contains oemcrypto engine properties that would be for a device
// that does not have persistant storage or a keybox.
//
// Note: We also define it to be L2 for illustration only. Production devices
// are rarely level 2.
#include "oemcrypto_engine_mock.h"
#include "oemcrypto_engine_ref.h"
namespace wvoec_mock {
namespace wvoec_ref {
class CertOnlyCryptoEngine : public CryptoEngine {
public:
explicit CertOnlyCryptoEngine(std::auto_ptr<wvcdm::FileSystem> file_system)
explicit CertOnlyCryptoEngine(scoped_ptr<wvcdm::FileSystem> file_system)
: CryptoEngine(file_system) {}
bool config_local_display_only() { return true; }
@@ -30,8 +30,8 @@ class CertOnlyCryptoEngine : public CryptoEngine {
};
CryptoEngine* CryptoEngine::MakeCryptoEngine(
std::auto_ptr<wvcdm::FileSystem> file_system) {
scoped_ptr<wvcdm::FileSystem> file_system) {
return new CertOnlyCryptoEngine(file_system);
}
} // namespace wvoec_mock
} // namespace wvoec_ref

View File

@@ -2,24 +2,24 @@
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// Mock implementation of OEMCrypto APIs
// Ref implementation of OEMCrypto APIs
//
// This file contains oemcrypto engine properties that would be for a
// level 2 device that does not have persistant storage or a keybox.
// Note: this is for illustration only. Production devices are rarely level 2.
#include "oemcrypto_engine_mock.h"
#include "oemcrypto_engine_ref.h"
#include <string.h>
#include "log.h"
#include "oem_cert.h"
namespace wvoec_mock {
namespace wvoec_ref {
class Prov30CryptoEngine : public CryptoEngine {
public:
explicit Prov30CryptoEngine(std::auto_ptr<wvcdm::FileSystem> file_system)
explicit Prov30CryptoEngine(scoped_ptr<wvcdm::FileSystem> file_system)
: CryptoEngine(file_system) {}
bool config_local_display_only() { return true; }
@@ -77,8 +77,8 @@ class Prov30CryptoEngine : public CryptoEngine {
};
CryptoEngine* CryptoEngine::MakeCryptoEngine(
std::auto_ptr<wvcdm::FileSystem> file_system) {
scoped_ptr<wvcdm::FileSystem> file_system) {
return new Prov30CryptoEngine(file_system);
}
} // namespace wvoec_mock
} // namespace wvoec_ref

View File

@@ -2,9 +2,9 @@
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// Mock implementation of OEMCrypto APIs
// Ref implementation of OEMCrypto APIs
//
#include "oemcrypto_engine_mock.h"
#include "oemcrypto_engine_ref.h"
#include <arpa/inet.h>
#include <assert.h>
@@ -17,19 +17,17 @@
#include "keys.h"
#include "log.h"
#include "oemcrypto_key_mock.h"
#include "oemcrypto_key_ref.h"
#include "oemcrypto_rsa_key_shared.h"
#include "string_conversions.h"
#include "wv_cdm_constants.h"
namespace wvoec_mock {
namespace wvoec_ref {
// Note: The class CryptoEngine is configured at compile time by compiling in
// different device property files. The methods in this file are generic to
// all configurations. See the files oemcrypto_engine_device_properties*.cpp
// for methods that are configured for specific configurations.
CryptoEngine::CryptoEngine(std::auto_ptr<wvcdm::FileSystem> file_system)
CryptoEngine::CryptoEngine(scoped_ptr<wvcdm::FileSystem> file_system)
: root_of_trust_(config_provisioning_method()),
file_system_(file_system),
usage_table_(this) {
@@ -123,4 +121,4 @@ OEMCryptoResult CryptoEngine::SetDestination(
return OEMCrypto_SUCCESS;
}
} // namespace wvoec_mock
} // namespace wvoec_ref

View File

@@ -2,10 +2,10 @@
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// Mock implementation of OEMCrypto APIs
// Ref implementation of OEMCrypto APIs
//
#ifndef MOCK_OEMCRYPTO_ENGINE_MOCK_H_
#define MOCK_OEMCRYPTO_ENGINE_MOCK_H_
#ifndef REF_OEMCRYPTO_ENGINE_REF_H_
#define REF_OEMCRYPTO_ENGINE_REF_H_
#include <stdint.h>
#include <time.h>
@@ -18,14 +18,15 @@
#include "OEMCryptoCENC.h" // Needed for enums only.
#include "file_store.h"
#include "lock.h"
#include "oemcrypto_auth_mock.h"
#include "oemcrypto_key_mock.h"
#include "oemcrypto_auth_ref.h"
#include "oemcrypto_key_ref.h"
#include "oemcrypto_rsa_key_shared.h"
#include "oemcrypto_scoped_ptr.h"
#include "oemcrypto_session.h"
#include "oemcrypto_usage_table_mock.h"
#include "wv_cdm_types.h"
#include "oemcrypto_usage_table_ref.h"
#include "oemcrypto_types.h"
namespace wvoec_mock {
namespace wvoec_ref {
typedef std::map<SessionId, SessionContext*> ActiveSessions;
@@ -37,7 +38,7 @@ class CryptoEngine {
// NOTE: The caller must instantiate a FileSystem object - ownership
// will be transferred to the new CryptoEngine object.
static CryptoEngine* MakeCryptoEngine(
std::auto_ptr<wvcdm::FileSystem> file_system);
scoped_ptr<wvcdm::FileSystem> file_system);
virtual ~CryptoEngine();
@@ -82,7 +83,7 @@ class CryptoEngine {
size_t GetNumberOfOpenSessions() { return sessions_.size(); }
size_t GetMaxNumberOfSessions() {
// An arbitrary limit for mock implementation.
// An arbitrary limit for ref implementation.
static const size_t kMaxSupportedOEMCryptoSessions = 64;
return kMaxSupportedOEMCryptoSessions;
}
@@ -170,19 +171,19 @@ class CryptoEngine {
}
protected:
explicit CryptoEngine(std::auto_ptr<wvcdm::FileSystem> file_system);
explicit CryptoEngine(scoped_ptr<wvcdm::FileSystem> file_system);
uint8_t* destination_;
private:
ActiveSessions sessions_;
AuthenticationRoot root_of_trust_;
wvcdm::Lock session_table_lock_;
std::auto_ptr<wvcdm::FileSystem> file_system_;
scoped_ptr<wvcdm::FileSystem> file_system_;
UsageTable usage_table_;
CORE_DISALLOW_COPY_AND_ASSIGN(CryptoEngine);
};
} // namespace wvoec_mock
} // namespace wvoec_ref
#endif // MOCK_OEMCRYPTO_ENGINE_MOCK_H_
#endif // REF_OEMCRYPTO_ENGINE_REF_H_

View File

@@ -2,18 +2,18 @@
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// Mock implementation of OEMCrypto APIs
// Ref implementation of OEMCrypto APIs
//
#include "oemcrypto_key_mock.h"
#include "oemcrypto_key_ref.h"
#include "oemcrypto_types.h"
#include <string.h>
#include <vector>
#include "log.h"
#include "oemcrypto_logging.h"
#include "wv_cdm_constants.h"
namespace wvoec_mock {
namespace wvoec_ref {
bool KeyControlBlock::Validate() {
if (memcmp(verification_, "kctl", 4) && // original verification
@@ -45,15 +45,15 @@ uint32_t KeyControlBlock::ExtractField(const std::vector<uint8_t>& str,
KeyControlBlock::KeyControlBlock(
const std::vector<uint8_t>& key_control_string) {
if (key_control_string.size() < wvcdm::KEY_CONTROL_SIZE) {
if (key_control_string.size() < wvoec::KEY_CONTROL_SIZE) {
LOGE("KCB: BAD Size: %d (not %d)", key_control_string.size(),
wvcdm::KEY_CONTROL_SIZE);
wvoec::KEY_CONTROL_SIZE);
return;
}
memcpy(verification_, &key_control_string[0], 4);
duration_ = ExtractField(key_control_string, 1);
nonce_ = ExtractField(key_control_string, 2);
duration_ = ExtractField(key_control_string, 1);
nonce_ = ExtractField(key_control_string, 2);
control_bits_ = ExtractField(key_control_string, 3);
if (LogCategoryEnabled(kLoggingDumpKeyControlBlocks)) {
LOGD("KCB:");
@@ -63,19 +63,20 @@ KeyControlBlock::KeyControlBlock(
LOGD(" magic: %08X", verification());
LOGD(" bits: %08X", control_bits());
LOGD(" bit kSharedLicense %s.",
(control_bits() & kSharedLicense) ? "set" : "unset");
(control_bits() & wvoec::kSharedLicense) ? "set" : "unset");
LOGD(" bit kControlSRMVersionRequired %s.",
(control_bits() & kControlSRMVersionRequired) ? "set" : "unset");
(control_bits() & wvoec::kControlSRMVersionRequired) ? "set" : "unset");
LOGD(" bit kControlDisableAnalogOutput %s.",
(control_bits() & kControlDisableAnalogOutput) ? "set" : "unset");
(control_bits() & wvoec::kControlDisableAnalogOutput) ? "set"
: "unset");
LOGD(" bits kControlSecurityPatchLevel 0x%02x.",
(control_bits() & kControlSecurityPatchLevelMask)
>> kControlSecurityPatchLevelShift);
switch (control_bits() & kControlReplayMask) {
case kControlNonceRequired:
(control_bits() & wvoec::kControlSecurityPatchLevelMask) >>
wvoec::kControlSecurityPatchLevelShift);
switch (control_bits() & wvoec::kControlReplayMask) {
case wvoec::kControlNonceRequired:
LOGD(" bits kControlReplay kControlNonceRequired.");
break;
case kControlNonceOrEntry:
case wvoec::kControlNonceOrEntry:
LOGD(" bits kControlReplay kControlNonceOrEntry.");
break;
default:
@@ -83,28 +84,28 @@ KeyControlBlock::KeyControlBlock(
break;
}
LOGD(" bits kControlHDCPVersion 0x%02x.",
(control_bits() & kControlHDCPVersionMask)
>> kControlHDCPVersionShift);
(control_bits() & wvoec::kControlHDCPVersionMask) >>
wvoec::kControlHDCPVersionShift);
LOGD(" bit kControlAllowEncrypt %s.",
(control_bits() & kControlAllowEncrypt) ? "set" : "unset");
(control_bits() & wvoec::kControlAllowEncrypt) ? "set" : "unset");
LOGD(" bit kControlAllowDecrypt %s.",
(control_bits() & kControlAllowDecrypt) ? "set" : "unset");
(control_bits() & wvoec::kControlAllowDecrypt) ? "set" : "unset");
LOGD(" bit kControlAllowSign %s.",
(control_bits() & kControlAllowSign) ? "set" : "unset");
(control_bits() & wvoec::kControlAllowSign) ? "set" : "unset");
LOGD(" bit kControlAllowVerify %s.",
(control_bits() & kControlAllowVerify) ? "set" : "unset");
(control_bits() & wvoec::kControlAllowVerify) ? "set" : "unset");
LOGD(" bit kControlObserveDataPath %s.",
(control_bits() & kControlObserveDataPath) ? "set" : "unset");
(control_bits() & wvoec::kControlObserveDataPath) ? "set" : "unset");
LOGD(" bit kControlObserveHDCP %s.",
(control_bits() & kControlObserveHDCP) ? "set" : "unset");
(control_bits() & wvoec::kControlObserveHDCP) ? "set" : "unset");
LOGD(" bit kControlObserveCGMS %s.",
(control_bits() & kControlObserveCGMS) ? "set" : "unset");
(control_bits() & wvoec::kControlObserveCGMS) ? "set" : "unset");
LOGD(" bit kControlDataPathSecure %s.",
(control_bits() & kControlDataPathSecure) ? "set" : "unset");
(control_bits() & wvoec::kControlDataPathSecure) ? "set" : "unset");
LOGD(" bit kControlNonceEnabled %s.",
(control_bits() & kControlNonceEnabled) ? "set" : "unset");
(control_bits() & wvoec::kControlNonceEnabled) ? "set" : "unset");
LOGD(" bit kControlHDCPRequired %s.",
(control_bits() & kControlHDCPRequired) ? "set" : "unset");
(control_bits() & wvoec::kControlHDCPRequired) ? "set" : "unset");
uint32_t cgms_bits = control_bits() & 0x3;
const char* cgms_values[4] = {"free", "BAD", "once", "never"};
LOGD(" CGMS = %s", cgms_values[cgms_bits]);
@@ -118,7 +119,7 @@ void Key::UpdateDuration(const KeyControlBlock& control) {
void KeyControlBlock::RequireLocalDisplay() {
// Set all bits to require HDCP Local Display Only.
control_bits_ |= kControlHDCPVersionMask;
control_bits_ |= wvoec::kControlHDCPVersionMask;
}
} // namespace wvoec_mock
} // namespace wvoec_ref

View File

@@ -2,43 +2,16 @@
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// Mock implementation of OEMCrypto APIs
// Ref implementation of OEMCrypto APIs
//
#ifndef OEMCRYPTO_KEY_MOCK_H_
#define OEMCRYPTO_KEY_MOCK_H_
#ifndef OEMCRYPTO_KEY_REF_H_
#define OEMCRYPTO_KEY_REF_H_
#include <stdint.h>
#include <string>
#include <vector>
namespace wvoec_mock {
const uint32_t kControlObserveDataPath = (1<<31);
const uint32_t kControlObserveHDCP = (1<<30);
const uint32_t kControlObserveCGMS = (1<<29);
const uint32_t kControlRequireAntiRollbackHardware = (1<<28);
const uint32_t kSharedLicense = (1<<23);
const uint32_t kControlSRMVersionRequired = (1<<22);
const uint32_t kControlDisableAnalogOutput = (1<<21);
const uint32_t kControlSecurityPatchLevelShift = 15;
const uint32_t kControlSecurityPatchLevelMask =
(0x3F<<kControlSecurityPatchLevelShift);
const uint32_t kControlReplayMask = (0x03<<13);
const uint32_t kControlNonceRequired = (0x01<<13);
const uint32_t kControlNonceOrEntry = (0x02<<13);
const uint32_t kControlHDCPVersionShift = 9;
const uint32_t kControlHDCPVersionMask = (0x0F<<kControlHDCPVersionShift);
const uint32_t kControlAllowEncrypt = (1<<8);
const uint32_t kControlAllowDecrypt = (1<<7);
const uint32_t kControlAllowSign = (1<<6);
const uint32_t kControlAllowVerify = (1<<5);
const uint32_t kControlDataPathSecure = (1<<4);
const uint32_t kControlNonceEnabled = (1<<3);
const uint32_t kControlHDCPRequired = (1<<2);
const uint32_t kControlCGMSMask = (0x03);
const uint32_t kControlCGMSCopyFreely = (0x00);
const uint32_t kControlCGMSCopyOnce = (0x02);
const uint32_t kControlCGMSCopyNever = (0x03);
namespace wvoec_ref {
class KeyControlBlock {
public:
@@ -109,6 +82,6 @@ class EntitlementKey : public Key {
std::vector<uint8_t> content_key_id_;
};
} // namespace wvoec_mock
} // namespace wvoec_ref
#endif // OEMCRYPTO_KEY_MOCK_H_
#endif // OEMCRYPTO_KEY_REF_H_

View File

@@ -2,23 +2,24 @@
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// Mock implementation of OEMCrypto APIs
// Ref implementation of OEMCrypto APIs
//
#include "oemcrypto_keybox_mock.h"
#include "oemcrypto_keybox_ref.h"
#include <arpa/inet.h> // needed for ntoh()
#include <string.h>
#include <sys/types.h>
#include <string>
#include "log.h"
#include "wv_keybox.h"
#include "oemcrypto_types.h"
#include "wvcrc32.h"
namespace wvoec_mock {
namespace wvoec_ref {
namespace {
const WidevineKeybox kTestKeybox = {
const wvoec::WidevineKeybox kTestKeybox = {
// Sample keybox used for test vectors
{
// deviceID
@@ -69,7 +70,7 @@ KeyboxError WvKeybox::Validate() {
uint32_t crc_stored;
uint8_t* crc_stored_bytes = (uint8_t*) &crc_stored;
memcpy(crc_stored_bytes, crc_, sizeof(crc_));
WidevineKeybox keybox;
wvoec::WidevineKeybox keybox;
memset(&keybox, 0, sizeof(keybox));
memcpy(keybox.device_id_, &device_id_[0], device_id_.size());
memcpy(keybox.device_key_, &device_key_[0], sizeof(keybox.device_key_));
@@ -91,8 +92,8 @@ bool WvKeybox::InstallKeybox(const uint8_t* buffer, size_t keyBoxLength) {
return false;
}
const WidevineKeybox* keybox
= reinterpret_cast<const WidevineKeybox*>(buffer);
const wvoec::WidevineKeybox* keybox
= reinterpret_cast<const wvoec::WidevineKeybox*>(buffer);
size_t device_id_length
= strnlen(reinterpret_cast<const char*>(keybox->device_id_), 32);
device_id_.assign(keybox->device_id_,
@@ -111,4 +112,4 @@ WvTestKeybox::WvTestKeybox() {
sizeof(kTestKeybox));
}
} // namespace wvoec_mock
} // namespace wvoec_ref

View File

@@ -2,14 +2,14 @@
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// Mock implementation of OEMCrypto APIs
// Ref implementation of OEMCrypto APIs
//
#ifndef OEMCRYPTO_KEYBOX_MOCK_H_
#define OEMCRYPTO_KEYBOX_MOCK_H_
#ifndef OEMCRYPTO_KEYBOX_REF_H_
#define OEMCRYPTO_KEYBOX_REF_H_
#include "oemcrypto_key_mock.h"
#include "oemcrypto_key_ref.h"
namespace wvoec_mock {
namespace wvoec_ref {
const int DEVICE_KEY_LENGTH = 16;
typedef uint8_t WvKeyboxKey[DEVICE_KEY_LENGTH];
@@ -48,6 +48,6 @@ class WvTestKeybox : public WvKeybox {
WvTestKeybox();
};
} // namespace wvoec_mock
} // namespace wvoec_ref
#endif // OEMCRYPTO_KEYBOX_MOCK_H_
#endif // OEMCRYPTO_KEYBOX_REF_H_

View File

@@ -4,16 +4,16 @@
//
// Test keybox.
#include "oemcrypto_keybox_mock.h"
#include "wv_keybox.h"
#include "oemcrypto_keybox_ref.h"
#include "oemcrypto_types.h"
namespace wvoec_mock {
namespace wvoec_ref {
namespace {
// Note: this is a valid keybox, but it is not accepted by production servers.
// However, it is different from the one used for most of the unit tests.
const WidevineKeybox kKeybox = {
const wvoec::WidevineKeybox kKeybox = {
// Sample keybox used for test vectors
{
// deviceID
@@ -53,4 +53,4 @@ bool WvKeybox::Prepare() {
return true;
}
} // namespace wvoec_mock
} // namespace wvoec_ref

View File

@@ -6,7 +6,7 @@
#include <stdio.h>
namespace wvoec_mock {
namespace wvoec_ref {
int logging_category_setting = 0x00;
@@ -49,7 +49,7 @@ void dump_hex_helper(std::string& buffer, std::string name,
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
for (size_t i = 0; i < length; i++) {
if (i == 0) {
buffer += "\n wvcdm::a2b_hex(\"";
buffer += "\n a2b_hex(\"";
} else if (i % 32 == 0) {
buffer += "\"\n \"";
}
@@ -103,4 +103,4 @@ void dump_array_part(std::string array, size_t index, std::string name,
LOGV(buffer.c_str());
}
} // namespace wvoec_mock
} // namespace wvoec_ref

View File

@@ -11,7 +11,7 @@
#include "OEMCryptoCENC.h"
#include "log.h"
namespace wvoec_mock {
namespace wvoec_ref {
// The constants below represent integers with a single "on" bit that
// represents categories of logging This allows users to specify with
@@ -62,6 +62,6 @@ void dump_array_part_helper(std::string& buffer, std::string array,
void dump_array_part(std::string array, size_t index, std::string name,
const uint8_t* vector, size_t length);
} // namespace wvoec_mock
} // namespace wvoec_ref
#endif
#endif // WVOEC_OEMCRYPTO_LOGGING_H_

View File

@@ -2,11 +2,11 @@
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// Mock implementation of OEMCrypto APIs
// Ref implementation of OEMCrypto APIs
//
#include "oemcrypto_nonce_table.h"
namespace wvoec_mock {
namespace wvoec_ref {
void NonceTable::AddNonce(uint32_t nonce) {
int new_slot = -1;
@@ -66,4 +66,4 @@ void NonceTable::Flush() {
}
}
} // namespace wvoec_mock
} // namespace wvoec_ref

View File

@@ -2,14 +2,14 @@
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// Mock implementation of OEMCrypto APIs
// Ref implementation of OEMCrypto APIs
//
#ifndef MOCK_OEMCRYPTO_NONCE_TABLE_H_
#define MOCK_OEMCRYPTO_NONCE_TABLE_H_
#ifndef REF_OEMCRYPTO_NONCE_TABLE_H_
#define REF_OEMCRYPTO_NONCE_TABLE_H_
#include <stdint.h>
namespace wvoec_mock {
namespace wvoec_ref {
class NonceTable {
public:
@@ -35,6 +35,6 @@ class NonceTable {
uint32_t nonces_[kTableSize];
};
} // namespace wvoec_mock
} // namespace wvoec_ref
#endif // MOCK_OEMCRYPTO_NONCE_TABLE_H_
#endif // REF_OEMCRYPTO_NONCE_TABLE_H_

View File

@@ -2,12 +2,12 @@
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// Mock implementation of OEMCrypto APIs
// Ref implementation of OEMCrypto APIs
//
// This is from the v12 version of oemcrypto usage tables. It is used for
// devices that upgrade from v12 to v13 in the field, and need to convert from
// the old type of usage table to the new.
#include "oemcrypto_old_usage_table_mock.h"
#include "oemcrypto_old_usage_table_ref.h"
#include <string.h>
#include <time.h>
@@ -22,14 +22,15 @@
#include "file_store.h"
#include "log.h"
#include "oemcrypto_engine_mock.h"
#include "oemcrypto_engine_ref.h"
#include "oemcrypto_logging.h"
#include "properties.h"
// TODO(fredgc): Setting the device files base bath is currently broken as
// wvcdm::Properties is no longer used by the reference code.
//#include "properties.h"
#include "pst_report.h"
#include "string_conversions.h"
#include "wv_cdm_constants.h"
namespace wvoec_mock {
namespace wvoec_ref {
OldUsageTableEntry::OldUsageTableEntry(const std::vector<uint8_t> &pst_hash)
: pst_hash_(pst_hash),
@@ -47,9 +48,9 @@ OldUsageTableEntry::OldUsageTableEntry(const OldStoredUsageEntry *buffer) {
time_of_last_decrypt_ = buffer->time_of_last_decrypt;
status_ = buffer->status;
mac_key_server_.assign(buffer->mac_key_server,
buffer->mac_key_server + wvcdm::MAC_KEY_SIZE);
buffer->mac_key_server + wvoec::MAC_KEY_SIZE);
mac_key_client_.assign(buffer->mac_key_client,
buffer->mac_key_client + wvcdm::MAC_KEY_SIZE);
buffer->mac_key_client + wvoec::MAC_KEY_SIZE);
}
OldUsageTable::OldUsageTable(CryptoEngine *ce) {
@@ -58,16 +59,17 @@ OldUsageTable::OldUsageTable(CryptoEngine *ce) {
table_.clear();
// Load saved table.
wvcdm::FileSystem* file_system = ce->file_system();
wvcdm::FileSystem *file_system = ce->file_system();
wvcdm::File *file;
std::string path;
// Note: this path is OK for a real implementation, but using security level 1
// would be better.
if (!wvcdm::Properties::GetDeviceFilesBasePath(wvcdm::kSecurityLevelL3,
&path)) {
// TODO(fredgc, jfore): Address how this property is presented to the ref.
// For now, the path is empty.
/*if (!Properties::GetDeviceFilesBasePath(kSecurityLevelL3, &path)) {
LOGE("OldUsageTable: Unable to get base path");
return;
}
}*/
std::string filename = path + "UsageTable.dat";
if (!file_system->Exists(filename)) {
if (LogCategoryEnabled(kLoggingTraceUsageTable)) {
@@ -119,14 +121,14 @@ OldUsageTable::OldUsageTable(CryptoEngine *ce) {
}
// Next, decrypt the table.
uint8_t iv_buffer[wvcdm::KEY_IV_SIZE];
memcpy(iv_buffer, encrypted_table->iv, wvcdm::KEY_IV_SIZE);
uint8_t iv_buffer[wvoec::KEY_IV_SIZE];
memcpy(iv_buffer, encrypted_table->iv, wvoec::KEY_IV_SIZE);
AES_KEY aes_key;
AES_set_decrypt_key(&key[0], 128, &aes_key);
AES_cbc_encrypt(&encrypted_buffer[SHA256_DIGEST_LENGTH + wvcdm::KEY_IV_SIZE],
&buffer[SHA256_DIGEST_LENGTH + wvcdm::KEY_IV_SIZE],
file_size - SHA256_DIGEST_LENGTH - wvcdm::KEY_IV_SIZE,
&aes_key, iv_buffer, AES_DECRYPT);
AES_cbc_encrypt(&encrypted_buffer[SHA256_DIGEST_LENGTH + wvoec::KEY_IV_SIZE],
&buffer[SHA256_DIGEST_LENGTH + wvoec::KEY_IV_SIZE],
file_size - SHA256_DIGEST_LENGTH - wvoec::KEY_IV_SIZE, &aes_key,
iv_buffer, AES_DECRYPT);
// Next, read the generation number from a different location.
// On a real implementation, you should NOT put the generation number in
@@ -176,7 +178,8 @@ OldUsageTableEntry *OldUsageTable::FindEntry(const std::vector<uint8_t> &pst) {
return FindEntryLocked(pst);
}
OldUsageTableEntry *OldUsageTable::FindEntryLocked(const std::vector<uint8_t> &pst) {
OldUsageTableEntry *OldUsageTable::FindEntryLocked(
const std::vector<uint8_t> &pst) {
std::vector<uint8_t> pst_hash;
if (!ComputeHash(pst, pst_hash)) {
LOGE("OldUsageTable: Could not compute hash of pst.");
@@ -189,7 +192,8 @@ OldUsageTableEntry *OldUsageTable::FindEntryLocked(const std::vector<uint8_t> &p
return it->second;
}
OldUsageTableEntry *OldUsageTable::CreateEntry(const std::vector<uint8_t> &pst) {
OldUsageTableEntry *OldUsageTable::CreateEntry(
const std::vector<uint8_t> &pst) {
std::vector<uint8_t> pst_hash;
if (!ComputeHash(pst, pst_hash)) {
LOGE("OldUsageTable: Could not compute hash of pst.");
@@ -210,15 +214,16 @@ void OldUsageTable::Clear() {
}
void OldUsageTable::DeleteFile(CryptoEngine *ce) {
wvcdm::FileSystem* file_system = ce->file_system();
wvcdm::FileSystem *file_system = ce->file_system();
std::string path;
// Note: this path is OK for a real implementation, but using security level 1
// would be better.
if (!wvcdm::Properties::GetDeviceFilesBasePath(wvcdm::kSecurityLevelL3,
&path)) {
// TODO(jfore): Address how this property is presented to the ref. For now,
// the path is empty.
/*if (!Properties::GetDeviceFilesBasePath(kSecurityLevelL3, &path)) {
LOGE("OldUsageTable: Unable to get base path");
return;
}
}*/
std::string filename = path + "UsageTable.dat";
if (file_system->Exists(filename)) {
if (!file_system->Remove(filename)) {
@@ -228,7 +233,7 @@ void OldUsageTable::DeleteFile(CryptoEngine *ce) {
}
bool OldUsageTable::ComputeHash(const std::vector<uint8_t> &pst,
std::vector<uint8_t> &pst_hash) {
std::vector<uint8_t> &pst_hash) {
// The PST is not fixed size, and we have no promises that it is reasonbly
// sized, so we compute a hash of it, and store that instead.
pst_hash.resize(SHA256_DIGEST_LENGTH);
@@ -239,4 +244,4 @@ bool OldUsageTable::ComputeHash(const std::vector<uint8_t> &pst,
return true;
}
} // namespace wvoec_mock
} // namespace wvoec_ref

View File

@@ -1,26 +1,26 @@
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine Master
// License Agreement.
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// Mock implementation of OEMCrypto APIs
// Ref implementation of OEMCrypto APIs
//
// This is from the v12 version of oemcrypto usage tables. It is used for
// devices that upgrade from v12 to v13 in the field, and need to convert from
// the old type of usage table to the new.
#ifndef OEMCRYPTO_OLD_USAGE_TABLE_MOCK_H_
#define OEMCRYPTO_OLD_USAGE_TABLE_MOCK_H_
#ifndef OEMCRYPTO_OLD_USAGE_TABLE_REF_H_
#define OEMCRYPTO_OLD_USAGE_TABLE_REF_H_
#include <stdint.h>
#include <map>
#include <string>
#include <vector>
#include "lock.h"
#include "OEMCryptoCENC.h"
#include "lock.h"
#include "oemcrypto_types.h"
#include "openssl/sha.h"
#include "wv_cdm_constants.h"
namespace wvoec_mock {
namespace wvoec_ref {
class CryptoEngine;
class UsagetTableEntry;
@@ -32,8 +32,8 @@ struct OldStoredUsageEntry {
int64_t time_of_first_decrypt;
int64_t time_of_last_decrypt;
enum OEMCrypto_Usage_Entry_Status status;
uint8_t mac_key_server[wvcdm::MAC_KEY_SIZE];
uint8_t mac_key_client[wvcdm::MAC_KEY_SIZE];
uint8_t mac_key_server[wvoec::MAC_KEY_SIZE];
uint8_t mac_key_client[wvoec::MAC_KEY_SIZE];
};
typedef union {
@@ -43,7 +43,7 @@ typedef union {
struct OldStoredUsageTable {
uint8_t signature[SHA256_DIGEST_LENGTH];
uint8_t iv[wvcdm::KEY_IV_SIZE];
uint8_t iv[wvoec::KEY_IV_SIZE];
int64_t generation;
uint64_t count;
AlignedOldStoredUsageEntry entries[];
@@ -90,6 +90,6 @@ class OldUsageTable {
CryptoEngine *ce_;
};
} // namespace wvoec_mock
} // namespace wvoec_ref
#endif // OEMCRYPTO_OLD_USAGE_TABLE_MOCK_H_
#endif // OEMCRYPTO_OLD_USAGE_TABLE_REF_H_

View File

@@ -22,12 +22,11 @@
#include <vector>
#include "file_store.h"
#include "log.h"
#include "oemcrypto_engine_mock.h"
#include "oemcrypto_engine_ref.h"
#include "oemcrypto_logging.h"
#include "oemcrypto_session.h"
#include "oemcrypto_usage_table_mock.h"
#include "oemcrypto_usage_table_ref.h"
#include "string_conversions.h"
#include "wv_cdm_constants.h"
namespace {
const uint8_t kBakedInCertificateMagicBytes[] = {0xDE, 0xAD, 0xBE, 0xEF};
@@ -39,7 +38,7 @@ uint32_t unaligned_dereference_uint32(const void* unaligned_ptr) {
uint32_t value;
const uint8_t* src = reinterpret_cast<const uint8_t*>(unaligned_ptr);
uint8_t* dest = reinterpret_cast<uint8_t*>(&value);
for (unsigned long i=0; i < sizeof(value); i++) {
for (unsigned long i = 0; i < sizeof(value); i++) {
dest[i] = src[i];
}
return value;
@@ -47,14 +46,14 @@ uint32_t unaligned_dereference_uint32(const void* unaligned_ptr) {
} // namespace
namespace wvoec_mock {
namespace wvoec_ref {
static CryptoEngine* crypto_engine = NULL;
typedef struct {
uint8_t signature[wvcdm::MAC_KEY_SIZE];
uint8_t context[wvcdm::MAC_KEY_SIZE];
uint8_t iv[wvcdm::KEY_IV_SIZE];
uint8_t signature[wvoec::MAC_KEY_SIZE];
uint8_t context[wvoec::MAC_KEY_SIZE];
uint8_t iv[wvoec::KEY_IV_SIZE];
uint8_t enc_rsa_key[];
} WrappedRSAKey;
@@ -69,7 +68,7 @@ extern "C" OEMCryptoResult OEMCrypto_Initialize(void) {
}
// NOTE: This requires a compatible Filesystem implementation.
// NOTE: Ownership of the FileSystem object is transferred to CryptoEngine
std::auto_ptr<wvcdm::FileSystem> fs(new wvcdm::FileSystem());
scoped_ptr<wvcdm::FileSystem> fs(new wvcdm::FileSystem());
crypto_engine = CryptoEngine::MakeCryptoEngine(fs);
if (!crypto_engine || !crypto_engine->Initialize()) {
@@ -103,8 +102,9 @@ extern "C" OEMCryptoResult OEMCrypto_Terminate(void) {
extern "C" OEMCryptoResult OEMCrypto_OpenSession(OEMCrypto_SESSION* session) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_OpenSession"
"(OEMCrypto_SESSION *session)\n");
LOGI(
"-- OEMCryptoResult OEMCrypto_OpenSession"
"(OEMCrypto_SESSION *session)\n");
}
if (!crypto_engine) {
LOGE("OEMCrypto_OpenSession: OEMCrypto not initialized.");
@@ -118,15 +118,16 @@ extern "C" OEMCryptoResult OEMCrypto_OpenSession(OEMCrypto_SESSION* session) {
SessionId sid = crypto_engine->CreateSession();
*session = (OEMCrypto_SESSION)sid;
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGD("[OEMCrypto_OpenSession(): SID=%08X]", sid);
LOGD("[OEMCrypto_OpenSession(): SID=%08x]", sid);
}
return OEMCrypto_SUCCESS;
}
extern "C" OEMCryptoResult OEMCrypto_CloseSession(OEMCrypto_SESSION session) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_CloseSession"
"(OEMCrypto_SESSION session)\n");
LOGI(
"-- OEMCryptoResult OEMCrypto_CloseSession"
"(OEMCrypto_SESSION session)\n");
}
if (!crypto_engine) {
LOGE("OEMCrypto_CloseSession: OEMCrypto not initialized.");
@@ -209,8 +210,9 @@ static uint64_t TimeStamp(void) {
extern "C" OEMCryptoResult OEMCrypto_GenerateNonce(OEMCrypto_SESSION session,
uint32_t* nonce) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_GenerateNonce"
"(OEMCrypto_SESSION session,\n");
LOGI(
"-- OEMCryptoResult OEMCrypto_GenerateNonce"
"(OEMCrypto_SESSION session,\n");
}
if (!crypto_engine) {
LOGE("OEMCrypto_GenerateNonce: OEMCrypto not initialized.");
@@ -251,7 +253,7 @@ extern "C" OEMCryptoResult OEMCrypto_GenerateNonce(OEMCrypto_SESSION session,
session_ctx->AddNonce(nonce_value);
*nonce = nonce_value;
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("nonce = %08X\n", nonce_value);
LOGI("nonce = %08x\n", nonce_value);
}
return OEMCrypto_SUCCESS;
}
@@ -322,23 +324,23 @@ extern "C" OEMCryptoResult OEMCrypto_LoadKeys(
if (wvcdm::g_cutoff >= wvcdm::LOG_VERBOSE) {
dump_hex("message", message, message_length);
dump_hex("signature", signature, signature_length);
dump_hex("enc_mac_key_iv", enc_mac_key_iv, wvcdm::KEY_IV_SIZE);
dump_hex("enc_mac_keys", enc_mac_keys, 2 * wvcdm::MAC_KEY_SIZE);
dump_hex("enc_mac_key_iv", enc_mac_key_iv, wvoec::KEY_IV_SIZE);
dump_hex("enc_mac_keys", enc_mac_keys, 2 * wvoec::MAC_KEY_SIZE);
dump_hex("pst", pst, pst_length);
dump_hex("srm_requirement", srm_requirement, wvcdm::KEY_CONTROL_SIZE);
dump_hex("srm_requirement", srm_requirement, wvoec::KEY_CONTROL_SIZE);
for (size_t i = 0; i < num_keys; i++) {
LOGV("key_array[%zu].key_id_length=%zu;\n", i,
key_array[i].key_id_length);
dump_array_part("key_array", i, "key_id", key_array[i].key_id,
key_array[i].key_id_length);
dump_array_part("key_array", i, "key_data_iv", key_array[i].key_data_iv,
wvcdm::KEY_IV_SIZE);
wvoec::KEY_IV_SIZE);
dump_array_part("key_array", i, "key_data", key_array[i].key_data,
key_array[i].key_data_length);
dump_array_part("key_array", i, "key_control_iv",
key_array[i].key_control_iv, wvcdm::KEY_IV_SIZE);
key_array[i].key_control_iv, wvoec::KEY_IV_SIZE);
dump_array_part("key_array", i, "key_control", key_array[i].key_control,
wvcdm::KEY_IV_SIZE);
wvoec::KEY_IV_SIZE);
}
}
}
@@ -368,15 +370,15 @@ extern "C" OEMCryptoResult OEMCrypto_LoadKeys(
}
// Range check
if (!RangeCheck(message, message_length, enc_mac_keys,
2 * wvcdm::MAC_KEY_SIZE, true) ||
!RangeCheck(message, message_length, enc_mac_key_iv, wvcdm::KEY_IV_SIZE,
if (!RangeCheck(message, message_length, enc_mac_keys, 2 * wvoec::MAC_KEY_SIZE,
true) ||
!RangeCheck(message, message_length, enc_mac_key_iv, wvoec::KEY_IV_SIZE, true) ||
!RangeCheck(message, message_length, pst, pst_length, true) ||
!RangeCheck(message, message_length, srm_requirement,
wvcdm::SRM_REQUIREMENT_SIZE, true)) {
LOGE("[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_INVALID_CONTEXT - range "
"check.]");
wvoec::SRM_REQUIREMENT_SIZE, true)) {
LOGE(
"[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_INVALID_CONTEXT - range "
"check.]");
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
@@ -386,13 +388,15 @@ extern "C" OEMCryptoResult OEMCrypto_LoadKeys(
!RangeCheck(message, message_length, key_array[i].key_data,
key_array[i].key_data_length, false) ||
!RangeCheck(message, message_length, key_array[i].key_data_iv,
wvcdm::KEY_IV_SIZE, false) ||
wvoec::KEY_IV_SIZE, false) ||
!RangeCheck(message, message_length, key_array[i].key_control,
wvcdm::KEY_CONTROL_SIZE, false) ||
wvoec::KEY_CONTROL_SIZE, false) ||
!RangeCheck(message, message_length, key_array[i].key_control_iv,
wvcdm::KEY_IV_SIZE, false)) {
LOGE("[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_INVALID_CONTEXT -range "
"check %d]", i);
wvoec::KEY_IV_SIZE, false)) {
LOGE(
"[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_INVALID_CONTEXT -range "
"check %d]",
i);
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
}
@@ -403,8 +407,7 @@ extern "C" OEMCryptoResult OEMCrypto_LoadKeys(
}
extern "C" OEMCryptoResult OEMCrypto_LoadEntitledContentKeys(
OEMCrypto_SESSION session,
size_t num_keys,
OEMCrypto_SESSION session, size_t num_keys,
const OEMCrypto_EntitledContentKeyObject* key_array) {
if (num_keys == 0) {
LOGE("[OEMCrypto_LoadEntitledContentKeys(): key_array is empty.");
@@ -461,9 +464,9 @@ extern "C" OEMCryptoResult OEMCrypto_RefreshKeys(
if (!RangeCheck(message, message_length, key_array[i].key_id,
key_array[i].key_id_length, true) ||
!RangeCheck(message, message_length, key_array[i].key_control,
wvcdm::KEY_CONTROL_SIZE, false) ||
wvoec::KEY_CONTROL_SIZE, false) ||
!RangeCheck(message, message_length, key_array[i].key_control_iv,
wvcdm::KEY_IV_SIZE, true)) {
wvoec::KEY_IV_SIZE, true)) {
LOGE("[OEMCrypto_RefreshKeys(): Range Check %d]", i);
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
@@ -486,12 +489,12 @@ extern "C" OEMCryptoResult OEMCrypto_RefreshKeys(
key_id.assign(key_array[i].key_id,
key_array[i].key_id + key_array[i].key_id_length);
key_control.assign(key_array[i].key_control,
key_array[i].key_control + wvcdm::KEY_CONTROL_SIZE);
key_array[i].key_control + wvoec::KEY_CONTROL_SIZE);
if (key_array[i].key_control_iv == NULL) {
key_control_iv.clear();
} else {
key_control_iv.assign(key_array[i].key_control_iv,
key_array[i].key_control_iv + wvcdm::KEY_IV_SIZE);
key_array[i].key_control_iv + wvoec::KEY_IV_SIZE);
}
} else {
// key_id could be null if special control key type
@@ -499,7 +502,7 @@ extern "C" OEMCryptoResult OEMCrypto_RefreshKeys(
key_id.clear();
key_control_iv.clear();
key_control.assign(key_array[i].key_control,
key_array[i].key_control + wvcdm::KEY_CONTROL_SIZE);
key_array[i].key_control + wvoec::KEY_CONTROL_SIZE);
}
status = session_ctx->RefreshKey(key_id, key_control, key_control_iv);
@@ -531,14 +534,15 @@ extern "C" OEMCryptoResult OEMCrypto_QueryKeyControl(
}
uint32_t* block = reinterpret_cast<uint32_t*>(key_control_block);
if ((key_control_block_length == NULL) ||
(*key_control_block_length < wvcdm::KEY_CONTROL_SIZE)) {
(*key_control_block_length < wvoec::KEY_CONTROL_SIZE)) {
LOGE("[OEMCrypto_QueryKeyControl(): OEMCrypto_ERROR_SHORT_BUFFER]");
return OEMCrypto_ERROR_SHORT_BUFFER;
}
*key_control_block_length = wvcdm::KEY_CONTROL_SIZE;
*key_control_block_length = wvoec::KEY_CONTROL_SIZE;
if (key_id == NULL) {
LOGE("[OEMCrypto_QueryKeyControl(): key_id null. "
"OEMCrypto_ERROR_UNKNOWN_FAILURE]");
LOGE(
"[OEMCrypto_QueryKeyControl(): key_id null. "
"OEMCrypto_ERROR_UNKNOWN_FAILURE]");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
@@ -656,7 +660,7 @@ extern "C" OEMCryptoResult OEMCrypto_CopyBuffer(
crypto_engine->SetDestination(out_buffer, data_length, subsample_flags);
if (status != OEMCrypto_SUCCESS) return status;
if (crypto_engine->destination() != NULL) {
memcpy(crypto_engine->destination(), data_addr, data_length);
memmove(crypto_engine->destination(), data_addr, data_length);
}
return crypto_engine->PushDestination(out_buffer, subsample_flags);
}
@@ -701,8 +705,8 @@ extern "C" OEMCryptoResult OEMCrypto_InstallKeybox(const uint8_t* keybox,
return OEMCrypto_ERROR_WRITE_KEYBOX;
}
extern "C" OEMCryptoResult OEMCrypto_LoadTestKeybox(
const uint8_t* buffer, size_t length) {
extern "C" OEMCryptoResult OEMCrypto_LoadTestKeybox(const uint8_t* buffer,
size_t length) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_LoadTestKeybox()\n");
}
@@ -880,7 +884,7 @@ extern "C" OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey30(
dump_hex("encrypted_message_key", encrypted_message_key,
encrypted_message_key_length);
dump_hex("enc_rsa_key", enc_rsa_key, enc_rsa_key_length);
dump_hex("enc_rsa_key_iv", enc_rsa_key_iv, wvcdm::KEY_IV_SIZE);
dump_hex("enc_rsa_key_iv", enc_rsa_key_iv, wvoec::KEY_IV_SIZE);
}
}
if (!crypto_engine) {
@@ -929,8 +933,9 @@ extern "C" OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey30(
if (!session_ctx->InstallRSAEncryptedKey(encrypted_message_key,
encrypted_message_key_length)) {
LOGE("OEMCrypto_RewrapDeviceRSAKey30: "
"Error loading encrypted_message_key.");
LOGE(
"OEMCrypto_RewrapDeviceRSAKey30: "
"Error loading encrypted_message_key.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
@@ -942,9 +947,10 @@ extern "C" OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey30(
}
size_t padding = pkcs8_rsa_key[enc_rsa_key_length - 1];
if (padding > 16) {
LOGE("[OEMCrypto_RewrapDeviceRSAKey30(): "
"Encrypted RSA has bad padding: %d]",
padding);
LOGE(
"[OEMCrypto_RewrapDeviceRSAKey30(): "
"Encrypted RSA has bad padding: %d]",
padding);
return OEMCrypto_ERROR_INVALID_RSA_KEY;
}
size_t rsa_key_length = enc_rsa_key_length - padding;
@@ -984,7 +990,8 @@ extern "C" OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey30(
unsigned int sig_length = sizeof(wrapped->signature);
if (LogCategoryEnabled(kLoggingDumpDerivedKeys)) {
LOGI(("message verified with HMAC and mac_key_server, key = " +
wvcdm::b2a_hex(session_ctx->mac_key_server())).c_str());
wvcdm::b2a_hex(session_ctx->mac_key_server()))
.c_str());
}
if (!HMAC(EVP_sha256(), &session_ctx->mac_key_server()[0],
session_ctx->mac_key_server().size(), wrapped->context,
@@ -1007,7 +1014,7 @@ extern "C" OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey(
const uint8_t* signature, size_t signature_length,
const uint32_t* unaligned_nonce, const uint8_t* enc_rsa_key,
size_t enc_rsa_key_length, const uint8_t* enc_rsa_key_iv,
uint8_t* wrapped_rsa_key, size_t* wrapped_rsa_key_length) {
uint8_t* wrapped_rsa_key, size_t* wrapped_rsa_key_length) {
uint32_t nonce = unaligned_dereference_uint32(unaligned_nonce);
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls | kLoggingTraceNonce)) {
LOGI("-- OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey(%d)\n", session);
@@ -1023,7 +1030,7 @@ extern "C" OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey(
}
if (wvcdm::g_cutoff >= wvcdm::LOG_VERBOSE) {
dump_hex("enc_rsa_key", enc_rsa_key, enc_rsa_key_length);
dump_hex("enc_rsa_key_iv", enc_rsa_key_iv, wvcdm::KEY_IV_SIZE);
dump_hex("enc_rsa_key_iv", enc_rsa_key_iv, wvoec::KEY_IV_SIZE);
}
}
if (!crypto_engine) {
@@ -1072,8 +1079,7 @@ extern "C" OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey(
sizeof(uint32_t), true) ||
!RangeCheck(message, message_length, enc_rsa_key, enc_rsa_key_length,
true) ||
!RangeCheck(message, message_length, enc_rsa_key_iv, wvcdm::KEY_IV_SIZE,
true)) {
!RangeCheck(message, message_length, enc_rsa_key_iv, wvoec::KEY_IV_SIZE, true)) {
LOGE("[OEMCrypto_RewrapDeviceRSAKey(): - range check.]");
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
@@ -1133,7 +1139,8 @@ extern "C" OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey(
unsigned int sig_length = sizeof(wrapped->signature);
if (LogCategoryEnabled(kLoggingDumpDerivedKeys)) {
LOGI(("message verified with HMAC and mac_key_server, key = " +
wvcdm::b2a_hex(session_ctx->mac_key_server())).c_str());
wvcdm::b2a_hex(session_ctx->mac_key_server()))
.c_str());
}
if (!HMAC(EVP_sha256(), &session_ctx->mac_key_server()[0],
session_ctx->mac_key_server().size(), wrapped->context,
@@ -1393,7 +1400,7 @@ extern "C" OEMCryptoResult OEMCrypto_GetHDCPCapability(
}
extern "C" uint32_t OEMCrypto_GetAnalogOutputFlags() {
// TODO(b/69867568, fredgc): parameterize this.
// TODO(b/69867568, fredgc): parameterize this.
return 0;
}
@@ -1463,7 +1470,7 @@ extern "C" OEMCryptoResult OEMCrypto_Generic_Encrypt(
algorithm);
if (wvcdm::g_cutoff >= wvcdm::LOG_VERBOSE) {
dump_hex("in_buffer", in_buffer, buffer_length);
dump_hex("iv", iv, wvcdm::KEY_IV_SIZE);
dump_hex("iv", iv, wvoec::KEY_IV_SIZE);
}
}
if (!crypto_engine) {
@@ -1502,7 +1509,7 @@ extern "C" OEMCryptoResult OEMCrypto_Generic_Decrypt(
algorithm);
if (wvcdm::g_cutoff >= wvcdm::LOG_VERBOSE) {
dump_hex("in_buffer", in_buffer, buffer_length);
dump_hex("iv", iv, wvcdm::KEY_IV_SIZE);
dump_hex("iv", iv, wvoec::KEY_IV_SIZE);
}
}
if (!crypto_engine) {
@@ -1681,9 +1688,10 @@ extern "C" OEMCryptoResult OEMCrypto_ReportUsage(OEMCrypto_SESSION session,
return sts;
}
extern "C" OEMCryptoResult OEMCrypto_DeleteUsageEntry(
OEMCrypto_SESSION, const uint8_t*, size_t, const uint8_t*, size_t,
const uint8_t*, size_t) {
extern "C" OEMCryptoResult OEMCrypto_DeleteUsageEntry(OEMCrypto_SESSION,
const uint8_t*, size_t,
const uint8_t*, size_t,
const uint8_t*, size_t) {
// TODO(fredgc): delete this.
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
}
@@ -1768,8 +1776,7 @@ extern "C" OEMCryptoResult OEMCrypto_RemoveSRM() {
}
extern "C" OEMCryptoResult OEMCrypto_CreateUsageTableHeader(
uint8_t* header_buffer,
size_t* header_buffer_length) {
uint8_t* header_buffer, size_t* header_buffer_length) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_CreateUsageTableHeader()\n");
}
@@ -1781,8 +1788,8 @@ extern "C" OEMCryptoResult OEMCrypto_CreateUsageTableHeader(
LOGE("OEMCrypto_CreateUsageTableHeader: Configured without Usage Tables.");
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
}
return crypto_engine->usage_table()
.CreateUsageTableHeader(header_buffer, header_buffer_length);
return crypto_engine->usage_table().CreateUsageTableHeader(
header_buffer, header_buffer_length);
}
extern "C" OEMCryptoResult OEMCrypto_LoadUsageTableHeader(
@@ -1943,15 +1950,11 @@ extern "C" OEMCryptoResult OEMCrypto_CopyOldUsageEntry(
return session_ctx->CopyOldUsageEntry(pstv);
}
extern "C"
OEMCryptoResult OEMCrypto_CreateOldUsageEntry(uint64_t time_since_license_received,
uint64_t time_since_first_decrypt,
uint64_t time_since_last_decrypt,
OEMCrypto_Usage_Entry_Status status,
uint8_t *server_mac_key,
uint8_t *client_mac_key,
const uint8_t* pst,
size_t pst_length) {
extern "C" OEMCryptoResult OEMCrypto_CreateOldUsageEntry(
uint64_t time_since_license_received, uint64_t time_since_first_decrypt,
uint64_t time_since_last_decrypt, OEMCrypto_Usage_Entry_Status status,
uint8_t* server_mac_key, uint8_t* client_mac_key, const uint8_t* pst,
size_t pst_length) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_CreateOldUsageEntry()\n");
}
@@ -1968,4 +1971,4 @@ OEMCryptoResult OEMCrypto_CreateOldUsageEntry(uint64_t time_since_license_receiv
pst_length);
}
} // namespace wvoec_mock
} // namespace wvoec_ref

View File

@@ -2,7 +2,7 @@
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// Mock implementation of OEMCrypto APIs
// Ref implementation of OEMCrypto APIs
//
#include "oemcrypto_rsa_key_shared.h"
@@ -16,7 +16,7 @@
#include "oemcrypto_logging.h"
namespace wvoec_mock {
namespace wvoec_ref {
void dump_boringssl_error() {
int count = 0;
@@ -98,4 +98,4 @@ bool RSA_shared_ptr::LoadPkcs8RsaKey(const uint8_t* buffer, size_t length) {
}
}
} // namespace wvoec_mock
} // namespace wvoec_ref

View File

@@ -2,7 +2,7 @@
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// Mock implementation of OEMCrypto APIs
// Ref implementation of OEMCrypto APIs
//
#ifndef OEMCRYPTO_RSA_KEY_SHARED_H_
#define OEMCRYPTO_RSA_KEY_SHARED_H_
@@ -11,7 +11,7 @@
#include <openssl/rsa.h>
namespace wvoec_mock {
namespace wvoec_ref {
// Shared pointer with specialized destructor. This pointer is only shared
// from a CryptoEngine to a Session -- so we don't have to use full reference
@@ -37,6 +37,6 @@ class RSA_shared_ptr {
// Log errors from BoringSSL.
void dump_boringssl_error();
} // namespace wvoec_mock
} // namespace wvoec_ref
#endif // OEMCRYPTO_RSA_KEY_SHARED_H_

View File

@@ -0,0 +1,44 @@
#ifndef OEMCRYPTO_SCOPED_PTR_H_
#define OEMCRYPTO_SCOPED_PTR_H_
#include <stddef.h>
#include <memory>
#include <arpa/inet.h>
namespace wvoec_ref {
// TODO(fredgc, jfore): scoped_ptr may not be the best name for this smart
// pointer type. It basically works like auto_ptr which is deprecated.
#if __cplusplus < 201103L
template <typename T>
class scoped_ptr {
public:
explicit scoped_ptr(T* p = NULL) : ptr_(p) {}
T* get() const { return ptr_.get(); }
private:
std::auto_ptr<T> ptr_;
};
#else
template <typename T>
class scoped_ptr {
public:
explicit scoped_ptr(T* p = nullptr) : ptr_(p) {}
scoped_ptr(scoped_ptr& r) { ptr_ = std::move(r.ptr_); }
T& operator*() const { return *ptr_; }
T* operator->() const { return ptr_.get(); }
T* get() const { return ptr_.get(); }
void reset(T* p = NULL) { ptr_.reset(); }
private:
std::unique_ptr<T> ptr_;
};
#endif
} // namespace wvoec_ref
#endif // OEMCRYPTO_SCOPED_PTR_H_

View File

@@ -2,7 +2,7 @@
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// Mock implementation of OEMCrypto APIs
// Ref implementation of OEMCrypto APIs
//
#include "oemcrypto_session.h"
@@ -26,12 +26,13 @@
#include "keys.h"
#include "log.h"
#include "oemcrypto_engine_mock.h"
#include "oemcrypto_key_mock.h"
#include "oemcrypto_engine_ref.h"
#include "oemcrypto_key_ref.h"
#include "oemcrypto_logging.h"
#include "oemcrypto_rsa_key_shared.h"
#include "oemcrypto_types.h"
#include "disallow_copy_and_assign.h"
#include "string_conversions.h"
#include "wv_cdm_constants.h"
static const int kPssSaltLength = 20;
@@ -47,7 +48,7 @@ void ctr128_inc64(uint8_t* counter) {
}
} // namespace
namespace wvoec_mock {
namespace wvoec_ref {
/***************************************/
@@ -285,7 +286,7 @@ bool SessionContext::RSADeriveKeys(
return false;
}
session_key_.resize(decrypted_size);
if (decrypted_size != static_cast<int>(wvcdm::KEY_SIZE)) {
if (decrypted_size != static_cast<int>(wvoec::KEY_SIZE)) {
LOGE("[RSADeriveKeys(): error. Session key is wrong size: %d.]",
decrypted_size);
dump_boringssl_error();
@@ -306,7 +307,7 @@ bool SessionContext::GenerateSignature(const uint8_t* message,
return false;
}
if (mac_key_client_.size() != wvcdm::MAC_KEY_SIZE) {
if (mac_key_client_.size() != wvoec::MAC_KEY_SIZE) {
return false;
}
@@ -320,7 +321,7 @@ bool SessionContext::GenerateSignature(const uint8_t* message,
if (usage_entry_status_ == kUsageEntryLoaded) {
usage_entry_mac_key_client.assign(
usage_entry_->mac_key_client(),
usage_entry_->mac_key_client() + wvcdm::MAC_KEY_SIZE * sizeof(uint8_t));
usage_entry_->mac_key_client() + wvoec::MAC_KEY_SIZE * sizeof(uint8_t));
using_usage_entry_mac_key_client =
mac_key_client_ == usage_entry_mac_key_client;
}
@@ -335,7 +336,7 @@ bool SessionContext::GenerateSignature(const uint8_t* message,
}
unsigned int md_len = *signature_length;
if (HMAC(EVP_sha256(), &mac_key_client_[0], wvcdm::MAC_KEY_SIZE, message,
if (HMAC(EVP_sha256(), &mac_key_client_[0], wvoec::MAC_KEY_SIZE, message,
message_length, signature, &md_len)) {
*signature_length = md_len;
return true;
@@ -452,7 +453,7 @@ bool SessionContext::ValidateMessage(const uint8_t* given_message,
OEMCryptoResult SessionContext::CheckStatusOnline(uint32_t nonce,
uint32_t control) {
if (!(control & kControlNonceEnabled)) {
if (!(control & wvoec::kControlNonceEnabled)) {
LOGE("LoadKeys: Server provided Nonce_Required but Nonce_Enabled = 0.");
// Server error. Continue, and assume nonce required.
}
@@ -473,7 +474,7 @@ OEMCryptoResult SessionContext::CheckStatusOnline(uint32_t nonce,
OEMCryptoResult SessionContext::CheckStatusOffline(uint32_t nonce,
uint32_t control) {
if (control & kControlNonceEnabled) {
if (control & wvoec::kControlNonceEnabled) {
LOGE("KCB: Server provided NonceOrEntry but Nonce_Enabled = 1.");
// Server error. Continue, and assume nonce required.
}
@@ -495,17 +496,17 @@ OEMCryptoResult SessionContext::CheckStatusOffline(uint32_t nonce,
OEMCryptoResult SessionContext::CheckNonceOrEntry(
const KeyControlBlock& key_control_block) {
switch (key_control_block.control_bits() & kControlReplayMask) {
case kControlNonceRequired: // Online license. Nonce always required.
switch (key_control_block.control_bits() & wvoec::kControlReplayMask) {
case wvoec::kControlNonceRequired: // Online license. Nonce always required.
return CheckStatusOnline(key_control_block.nonce(),
key_control_block.control_bits());
break;
case kControlNonceOrEntry: // Offline license. Nonce required on first use.
case wvoec::kControlNonceOrEntry: // Offline license. Nonce required on first use.
return CheckStatusOffline(key_control_block.nonce(),
key_control_block.control_bits());
break;
default:
if ((key_control_block.control_bits() & kControlNonceEnabled) &&
if ((key_control_block.control_bits() & wvoec::kControlNonceEnabled) &&
(!CheckNonce(key_control_block.nonce()))) {
LOGE("LoadKeys: BAD Nonce");
return OEMCrypto_ERROR_INVALID_NONCE;
@@ -599,15 +600,15 @@ OEMCryptoResult SessionContext::LoadKeys(
enc_key_data.assign(key_array[i].key_data,
key_array[i].key_data + key_array[i].key_data_length);
key_data_iv.assign(key_array[i].key_data_iv,
key_array[i].key_data_iv + wvcdm::KEY_IV_SIZE);
key_array[i].key_data_iv + wvoec::KEY_IV_SIZE);
if (key_array[i].key_control == NULL) {
status = OEMCrypto_ERROR_UNKNOWN_FAILURE;
break;
}
key_control.assign(key_array[i].key_control,
key_array[i].key_control + wvcdm::KEY_CONTROL_SIZE);
key_array[i].key_control + wvoec::KEY_CONTROL_SIZE);
key_control_iv.assign(key_array[i].key_control_iv,
key_array[i].key_control_iv + wvcdm::KEY_IV_SIZE);
key_array[i].key_control_iv + wvoec::KEY_IV_SIZE);
OEMCryptoResult result =
InstallKey(key_id, enc_key_data, key_data_iv, key_control,
@@ -624,9 +625,9 @@ OEMCryptoResult SessionContext::LoadKeys(
if (enc_mac_keys != NULL) {
// V2.1 license protocol: update mac keys after processing license response
const std::vector<uint8_t> enc_mac_keys_str = std::vector<uint8_t>(
enc_mac_keys, enc_mac_keys + 2 * wvcdm::MAC_KEY_SIZE);
enc_mac_keys, enc_mac_keys + 2 * wvoec::MAC_KEY_SIZE);
const std::vector<uint8_t> enc_mac_key_iv_str = std::vector<uint8_t>(
enc_mac_key_iv, enc_mac_key_iv + wvcdm::KEY_IV_SIZE);
enc_mac_key_iv, enc_mac_key_iv + wvoec::KEY_IV_SIZE);
if (!UpdateMacKeys(enc_mac_keys_str, enc_mac_key_iv_str)) {
LOGE("Failed to update mac keys.\n");
@@ -763,14 +764,14 @@ OEMCryptoResult SessionContext::InstallKey(
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
if ((key_control_block.control_bits() &
kControlRequireAntiRollbackHardware) &&
wvoec::kControlRequireAntiRollbackHardware) &&
!ce_->config_is_anti_rollback_hw_present()) {
LOGE("Anti-rollback hardware is required but hardware not present.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
uint8_t minimum_patch_level =
(key_control_block.control_bits() & kControlSecurityPatchLevelMask) >>
kControlSecurityPatchLevelShift;
(key_control_block.control_bits() & wvoec::kControlSecurityPatchLevelMask) >>
wvoec::kControlSecurityPatchLevelShift;
if (minimum_patch_level > OEMCrypto_Security_Patch_Level()) {
LOGE("[InstallKey(): security patch level: %d. Minimum:%d]",
OEMCrypto_Security_Patch_Level(), minimum_patch_level);
@@ -781,13 +782,13 @@ OEMCryptoResult SessionContext::InstallKey(
LOGE("LoadKeys: Failed Nonce/PST check.");
return result;
}
if (key_control_block.control_bits() & kSharedLicense) {
if (key_control_block.control_bits() & wvoec::kSharedLicense) {
if (!second_license) {
LOGE("LoadKeys: Shared License, but no keys previously loaded.");
return OEMCrypto_ERROR_MISSING_MASTER;
}
}
if (key_control_block.control_bits() & kControlSRMVersionRequired) {
if (key_control_block.control_bits() & wvoec::kControlSRMVersionRequired) {
if (srm_requirements_status_ == NoSRMVersion) {
LOGE("[LoadKeys: control bit says SRM version required]");
return OEMCrypto_ERROR_INVALID_CONTEXT;
@@ -818,7 +819,7 @@ bool SessionContext::InstallRSAEncryptedKey(
return false;
}
encryption_key_.resize(decrypted_size);
if (decrypted_size != static_cast<int>(wvcdm::KEY_SIZE)) {
if (decrypted_size != static_cast<int>(wvoec::KEY_SIZE)) {
LOGE("[RSADeriveKeys(): error. Session key is wrong size: %d.]",
decrypted_size);
dump_boringssl_error();
@@ -841,7 +842,7 @@ OEMCryptoResult SessionContext::RefreshKey(
LOGE("Parse key control error.");
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
if ((key_control_block.control_bits() & kControlNonceEnabled) &&
if ((key_control_block.control_bits() & wvoec::kControlNonceEnabled) &&
(!CheckNonce(key_control_block.nonce()))) {
LOGE("KCB: BAD Nonce");
return OEMCrypto_ERROR_INVALID_NONCE;
@@ -896,7 +897,7 @@ OEMCryptoResult SessionContext::RefreshKey(
}
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
if ((key_control_block.control_bits() & kControlNonceEnabled) &&
if ((key_control_block.control_bits() & wvoec::kControlNonceEnabled) &&
(!CheckNonce(key_control_block.nonce()))) {
LOGE("KCB: BAD Nonce");
return OEMCrypto_ERROR_INVALID_NONCE;
@@ -910,8 +911,8 @@ bool SessionContext::DecryptRSAKey(const uint8_t* enc_rsa_key,
const uint8_t* enc_rsa_key_iv,
uint8_t* pkcs8_rsa_key) {
// Decrypt rsa key with keybox.
uint8_t iv_buffer[wvcdm::KEY_IV_SIZE];
memcpy(iv_buffer, enc_rsa_key_iv, wvcdm::KEY_IV_SIZE);
uint8_t iv_buffer[wvoec::KEY_IV_SIZE];
memcpy(iv_buffer, enc_rsa_key_iv, wvoec::KEY_IV_SIZE);
AES_KEY aes_key;
AES_set_decrypt_key(&encryption_key_[0], 128, &aes_key);
AES_cbc_encrypt(enc_rsa_key, pkcs8_rsa_key, enc_rsa_key_length, &aes_key,
@@ -924,8 +925,8 @@ bool SessionContext::EncryptRSAKey(const uint8_t* pkcs8_rsa_key,
const uint8_t* enc_rsa_key_iv,
uint8_t* enc_rsa_key) {
// Encrypt rsa key with keybox.
uint8_t iv_buffer[wvcdm::KEY_IV_SIZE];
memcpy(iv_buffer, enc_rsa_key_iv, wvcdm::KEY_IV_SIZE);
uint8_t iv_buffer[wvoec::KEY_IV_SIZE];
memcpy(iv_buffer, enc_rsa_key_iv, wvoec::KEY_IV_SIZE);
AES_KEY aes_key;
AES_set_encrypt_key(&encryption_key_[0], 128, &aes_key);
AES_cbc_encrypt(pkcs8_rsa_key, enc_rsa_key, enc_rsa_key_length, &aes_key,
@@ -960,14 +961,14 @@ OEMCryptoResult SessionContext::CheckKeyUse(const std::string& log_string,
LOGE("[%s(): control bit says not allowed.", log_string.c_str());
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
if (control.control_bits() & kControlDataPathSecure) {
if (control.control_bits() & wvoec::kControlDataPathSecure) {
if (!ce_->config_closed_platform() &&
buffer_type == OEMCrypto_BufferType_Clear) {
LOGE("[%s(): Secure key with insecure buffer]", log_string.c_str());
return OEMCrypto_ERROR_DECRYPT_FAILED;
}
}
if (control.control_bits() & kControlReplayMask) {
if (control.control_bits() & wvoec::kControlReplayMask) {
if (!CheckUsageEntry()) {
LOGE("[%s(): usage entry not valid]", log_string.c_str());
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -982,10 +983,10 @@ OEMCryptoResult SessionContext::CheckKeyUse(const std::string& log_string,
if (!ce_->config_local_display_only()) {
// Only look at HDCP and Analog restrictions if the display can be
// non-local.
if (control.control_bits() & kControlHDCPRequired) {
if (control.control_bits() & wvoec::kControlHDCPRequired) {
uint8_t required_hdcp =
(control.control_bits() & kControlHDCPVersionMask) >>
kControlHDCPVersionShift;
(control.control_bits() & wvoec::kControlHDCPVersionMask) >>
wvoec::kControlHDCPVersionShift;
if (ce_->srm_blacklisted_device_attached()) {
required_hdcp = HDCP_NO_DIGITAL_OUTPUT;
}
@@ -999,7 +1000,7 @@ OEMCryptoResult SessionContext::CheckKeyUse(const std::string& log_string,
}
if (!ce_->config_local_display_only() ||
buffer_type == OEMCrypto_BufferType_Clear) {
if (control.control_bits() & kControlDisableAnalogOutput) {
if (control.control_bits() & wvoec::kControlDisableAnalogOutput) {
LOGE("[%s(): control bit says disable analog.", log_string.c_str());
return OEMCrypto_ERROR_ANALOG_OUTPUT;
}
@@ -1023,7 +1024,7 @@ OEMCryptoResult SessionContext::Generic_Encrypt(const uint8_t* in_buffer,
LOGE("[Generic_Encrypt(): CONTENT_KEY has wrong size: %d", key.size());
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
OEMCryptoResult result = CheckKeyUse("Generic_Encrypt", kControlAllowEncrypt,
OEMCryptoResult result = CheckKeyUse("Generic_Encrypt", wvoec::kControlAllowEncrypt,
OEMCrypto_BufferType_Clear);
if (result != OEMCrypto_SUCCESS) return result;
if (algorithm != OEMCrypto_AES_CBC_128_NO_PADDING) {
@@ -1040,8 +1041,8 @@ OEMCryptoResult SessionContext::Generic_Encrypt(const uint8_t* in_buffer,
LOGE("[Generic_Encrypt(): FAILURE]");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
uint8_t iv_buffer[wvcdm::KEY_IV_SIZE];
memcpy(iv_buffer, iv, wvcdm::KEY_IV_SIZE);
uint8_t iv_buffer[wvoec::KEY_IV_SIZE];
memcpy(iv_buffer, iv, wvoec::KEY_IV_SIZE);
AES_cbc_encrypt(in_buffer, out_buffer, buffer_length, &aes_key, iv_buffer,
AES_ENCRYPT);
return OEMCrypto_SUCCESS;
@@ -1063,7 +1064,7 @@ OEMCryptoResult SessionContext::Generic_Decrypt(const uint8_t* in_buffer,
LOGE("[Generic_Decrypt(): CONTENT_KEY has wrong size.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
OEMCryptoResult result = CheckKeyUse("Generic_Decrypt", kControlAllowDecrypt,
OEMCryptoResult result = CheckKeyUse("Generic_Decrypt", wvoec::kControlAllowDecrypt,
OEMCrypto_BufferType_Clear);
if (result != OEMCrypto_SUCCESS) return result;
@@ -1081,8 +1082,8 @@ OEMCryptoResult SessionContext::Generic_Decrypt(const uint8_t* in_buffer,
LOGE("[Generic_Decrypt(): FAILURE]");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
uint8_t iv_buffer[wvcdm::KEY_IV_SIZE];
memcpy(iv_buffer, iv, wvcdm::KEY_IV_SIZE);
uint8_t iv_buffer[wvoec::KEY_IV_SIZE];
memcpy(iv_buffer, iv, wvoec::KEY_IV_SIZE);
AES_cbc_encrypt(in_buffer, out_buffer, buffer_length, &aes_key, iv_buffer,
AES_DECRYPT);
return OEMCrypto_SUCCESS;
@@ -1108,7 +1109,7 @@ OEMCryptoResult SessionContext::Generic_Sign(const uint8_t* in_buffer,
LOGE("[Generic_Sign(): CONTENT_KEY has wrong size; %d", key.size());
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
OEMCryptoResult result = CheckKeyUse("Generic_Sign", kControlAllowSign,
OEMCryptoResult result = CheckKeyUse("Generic_Sign", wvoec::kControlAllowSign,
OEMCrypto_BufferType_Clear);
if (result != OEMCrypto_SUCCESS) return result;
if (algorithm != OEMCrypto_HMAC_SHA256) {
@@ -1144,7 +1145,7 @@ OEMCryptoResult SessionContext::Generic_Verify(const uint8_t* in_buffer,
LOGE("[Generic_Verify(): CONTENT_KEY has wrong size: %d", key.size());
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
OEMCryptoResult result = CheckKeyUse("Generic_Verify", kControlAllowVerify,
OEMCryptoResult result = CheckKeyUse("Generic_Verify", wvoec::kControlAllowVerify,
OEMCrypto_BufferType_Clear);
if (result != OEMCrypto_SUCCESS) return result;
if (algorithm != OEMCrypto_HMAC_SHA256) {
@@ -1175,8 +1176,8 @@ bool SessionContext::UpdateMacKeys(const std::vector<uint8_t>& enc_mac_keys,
return false;
}
mac_key_server_ = std::vector<uint8_t>(
mac_keys.begin(), mac_keys.begin() + wvcdm::MAC_KEY_SIZE);
mac_key_client_ = std::vector<uint8_t>(mac_keys.begin() + wvcdm::MAC_KEY_SIZE,
mac_keys.begin(), mac_keys.begin() + wvoec::MAC_KEY_SIZE);
mac_key_client_ = std::vector<uint8_t>(mac_keys.begin() + wvoec::MAC_KEY_SIZE,
mac_keys.end());
if (LogCategoryEnabled(kLoggingDumpDerivedKeys)) {
LOGI(("mac_key_client_ has been updated to = " +
@@ -1276,10 +1277,10 @@ OEMCryptoResult SessionContext::LoadUsageEntry(
// Copy the mac keys to the current session.
mac_key_server_ = std::vector<uint8_t>(
usage_entry_->mac_key_server(),
usage_entry_->mac_key_server() + wvcdm::MAC_KEY_SIZE);
usage_entry_->mac_key_server() + wvoec::MAC_KEY_SIZE);
mac_key_client_ = std::vector<uint8_t>(
usage_entry_->mac_key_client(),
usage_entry_->mac_key_client() + wvcdm::MAC_KEY_SIZE);
usage_entry_->mac_key_client() + wvoec::MAC_KEY_SIZE);
if (LogCategoryEnabled(kLoggingDumpDerivedKeys)) {
LOGI(("mac_key_client_ has been updated to = " +
wvcdm::b2a_hex(mac_key_client_)).c_str());
@@ -1354,8 +1355,8 @@ OEMCryptoResult SessionContext::DecryptCENC(
// If the data is clear, we do not need a current key selected.
if (!is_encrypted) {
if (buffer_type != OEMCrypto_BufferType_Direct) {
memcpy(reinterpret_cast<uint8_t*>(clear_data), cipher_data,
cipher_data_length);
memmove(reinterpret_cast<uint8_t*>(clear_data), cipher_data,
cipher_data_length);
return OEMCrypto_SUCCESS;
}
// For reference implementation, we quietly drop the clear direct video.
@@ -1420,7 +1421,7 @@ OEMCryptoResult SessionContext::DecryptCBC(
pattern_offset = (pattern_offset + 1) % pattern_length;
}
if (skip_block || (size < AES_BLOCK_SIZE)) {
memcpy(&clear_data[l], &cipher_data[l], size);
memmove(&clear_data[l], &cipher_data[l], size);
} else {
uint8_t aes_output[AES_BLOCK_SIZE];
// Save the iv for the next block, in case cipher_data is in the same
@@ -1458,7 +1459,7 @@ OEMCryptoResult SessionContext::PatternDecryptCTR(
pattern_offset = (pattern_offset + 1) % pattern_length;
}
if (skip_block) {
memcpy(&clear_data[l], &cipher_data[l], size);
memmove(&clear_data[l], &cipher_data[l], size);
} else {
uint8_t aes_output[AES_BLOCK_SIZE];
AES_encrypt(iv, aes_output, &aes_key);
@@ -1518,22 +1519,12 @@ OEMCryptoResult SessionContext::DecryptCTR(const uint8_t* key_u8,
int out_len = 0;
while (remaining) {
#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
EVP_CIPHER_CTX ctx_struct;
EVP_CIPHER_CTX* evp_cipher_ctx = &ctx_struct;
EVP_CIPHER_CTX_init(evp_cipher_ctx);
#else
EVP_CIPHER_CTX* evp_cipher_ctx = EVP_CIPHER_CTX_new();
#endif
EVP_CIPHER_CTX_set_padding(evp_cipher_ctx, 0);
if (!EVP_DecryptInit_ex(evp_cipher_ctx, EVP_aes_128_ctr(), NULL, key_u8,
aes_iv_u8)) {
LOGE("[DecryptCTR(): EVP_INIT ERROR]");
#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
EVP_CIPHER_CTX_cleanup(evp_cipher_ctx);
#else
EVP_CIPHER_CTX_free(evp_cipher_ctx);
#endif
return OEMCrypto_ERROR_DECRYPT_FAILED;
}
@@ -1553,11 +1544,7 @@ OEMCryptoResult SessionContext::DecryptCTR(const uint8_t* key_u8,
if (!EVP_DecryptUpdate(evp_cipher_ctx, &clear_data[l], &out_len,
&cipher_data[l], decrypt_length)) {
LOGE("[DecryptCTR(): EVP_UPDATE_ERROR]");
#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
EVP_CIPHER_CTX_cleanup(evp_cipher_ctx);
#else
EVP_CIPHER_CTX_free(evp_cipher_ctx);
#endif
return OEMCrypto_ERROR_DECRYPT_FAILED;
}
l += decrypt_length;
@@ -1568,18 +1555,10 @@ OEMCryptoResult SessionContext::DecryptCTR(const uint8_t* key_u8,
&clear_data[cipher_data_length - remaining],
&final)) {
LOGE("[DecryptCTR(): EVP_FINAL_ERROR]");
#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
EVP_CIPHER_CTX_cleanup(evp_cipher_ctx);
#else
EVP_CIPHER_CTX_free(evp_cipher_ctx);
#endif
return OEMCrypto_ERROR_DECRYPT_FAILED;
}
#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
EVP_CIPHER_CTX_cleanup(evp_cipher_ctx);
#else
EVP_CIPHER_CTX_free(evp_cipher_ctx);
#endif
// If remaining is not zero, reset the iv before the second pass.
if (remaining) {
@@ -1590,4 +1569,4 @@ OEMCryptoResult SessionContext::DecryptCTR(const uint8_t* key_u8,
return OEMCrypto_SUCCESS;
}
} // namespace wvoec_mock
} // namespace wvoec_ref

View File

@@ -2,10 +2,10 @@
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// Mock implementation of OEMCrypto APIs
// Ref implementation of OEMCrypto APIs
//
#ifndef MOCK_OEMCRYPTO_SESSION_H_
#define MOCK_OEMCRYPTO_SESSION_H_
#ifndef REF_OEMCRYPTO_SESSION_H_
#define REF_OEMCRYPTO_SESSION_H_
#include <stdint.h>
#include <time.h>
@@ -15,17 +15,15 @@
#include <openssl/rsa.h>
#include "OEMCryptoCENC.h" // Needed for enums only.
#include "file_store.h"
#include "lock.h"
#include "oemcrypto_auth_mock.h"
#include "oemcrypto_key_mock.h"
#include "oemcrypto_auth_ref.h"
#include "oemcrypto_key_ref.h"
#include "oemcrypto_nonce_table.h"
#include "oemcrypto_rsa_key_shared.h"
#include "oemcrypto_session_key_table.h"
#include "oemcrypto_usage_table_mock.h"
#include "wv_cdm_types.h"
#include "oemcrypto_usage_table_ref.h"
#include "oemcrypto_types.h"
namespace wvoec_mock {
namespace wvoec_ref {
class CryptoEngine;
typedef uint32_t SessionId;
@@ -245,6 +243,6 @@ class SessionContext {
CORE_DISALLOW_COPY_AND_ASSIGN(SessionContext);
};
} // namespace wvoec_mock
} // namespace wvoec_ref
#endif // MOCK_OEMCRYPTO_SESSION_H_
#endif // REF_OEMCRYPTO_SESSION_H_

View File

@@ -2,14 +2,14 @@
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// Mock implementation of OEMCrypto APIs
// Ref implementation of OEMCrypto APIs
//
#include "oemcrypto_session_key_table.h"
#include "keys.h"
#include "log.h"
namespace wvoec_mock {
namespace wvoec_ref {
SessionKeyTable::~SessionKeyTable() {
for (KeyMap::iterator i = keys_.begin(); i != keys_.end(); ++i) {
@@ -116,4 +116,4 @@ bool EntitlementKeyTable::GetEntitlementKey(
return true;
}
} // namespace wvoec_mock
} // namespace wvoec_ref

View File

@@ -2,19 +2,20 @@
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// Mock implementation of OEMCrypto APIs
// Ref implementation of OEMCrypto APIs
//
#ifndef MOCK_OEMCRYPTO_SESSION_KEY_TABLE_H_
#define MOCK_OEMCRYPTO_SESSION_KEY_TABLE_H_
#ifndef REF_OEMCRYPTO_SESSION_KEY_TABLE_H_
#define REF_OEMCRYPTO_SESSION_KEY_TABLE_H_
#include <stdint.h>
#include <map>
#include <vector>
#include "oemcrypto_key_mock.h"
#include "wv_cdm_types.h"
#include "disallow_copy_and_assign.h"
#include "oemcrypto_key_ref.h"
#include "oemcrypto_types.h"
namespace wvoec_mock {
namespace wvoec_ref {
class SessionContext;
class CryptoEngine;
@@ -65,6 +66,6 @@ class EntitlementKeyTable {
CORE_DISALLOW_COPY_AND_ASSIGN(EntitlementKeyTable);
};
} // namespace wvoec_mock
} // namespace wvoec_ref
#endif // MOCK_OEMCRYPTO_SESSION_KEY_TABLE_H_
#endif // REF_OEMCRYPTO_SESSION_KEY_TABLE_H_

View File

@@ -2,9 +2,9 @@
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// Mock implementation of OEMCrypto APIs
// Ref implementation of OEMCrypto APIs
//
#include "oemcrypto_usage_table_mock.h"
#include "oemcrypto_usage_table_ref.h"
#include <string.h>
#include <time.h>
@@ -19,15 +19,16 @@
#include "file_store.h"
#include "log.h"
#include "oemcrypto_engine_mock.h"
#include "oemcrypto_engine_ref.h"
#include "oemcrypto_logging.h"
#include "oemcrypto_old_usage_table_mock.h"
#include "properties.h"
#include "oemcrypto_old_usage_table_ref.h"
// TODO(fredgc): Setting the device files base bath is currently broken as
// wvcdm::Properties is no longer used by the reference code.
//#include "properties.h"
#include "pst_report.h"
#include "string_conversions.h"
#include "wv_cdm_constants.h"
namespace wvoec_mock {
namespace wvoec_ref {
namespace {
const size_t kMagicLength = 8;
const char* kEntryVerification = "USEENTRY";
@@ -84,19 +85,19 @@ bool UsageTableEntry::VerifyPST(const uint8_t* pst, size_t pst_length) {
bool UsageTableEntry::VerifyMacKeys(const std::vector<uint8_t>& server,
const std::vector<uint8_t>& client) {
return (server.size() == wvcdm::MAC_KEY_SIZE) &&
(client.size() == wvcdm::MAC_KEY_SIZE) &&
(0 == memcmp(&server[0], data_.mac_key_server, wvcdm::MAC_KEY_SIZE)) &&
(0 == memcmp(&client[0], data_.mac_key_client, wvcdm::MAC_KEY_SIZE));
return (server.size() == wvoec::MAC_KEY_SIZE) &&
(client.size() == wvoec::MAC_KEY_SIZE) &&
(0 == memcmp(&server[0], data_.mac_key_server, wvoec::MAC_KEY_SIZE)) &&
(0 == memcmp(&client[0], data_.mac_key_client, wvoec::MAC_KEY_SIZE));
}
bool UsageTableEntry::SetMacKeys(const std::vector<uint8_t>& server,
const std::vector<uint8_t>& client) {
if ((server.size() != wvcdm::MAC_KEY_SIZE) ||
(client.size() != wvcdm::MAC_KEY_SIZE))
if ((server.size() != wvoec::MAC_KEY_SIZE) ||
(client.size() != wvoec::MAC_KEY_SIZE))
return false;
memcpy(data_.mac_key_server, &server[0], wvcdm::MAC_KEY_SIZE);
memcpy(data_.mac_key_client, &client[0], wvcdm::MAC_KEY_SIZE);
memcpy(data_.mac_key_server, &server[0], wvoec::MAC_KEY_SIZE);
memcpy(data_.mac_key_client, &client[0], wvoec::MAC_KEY_SIZE);
return true;
}
@@ -130,13 +131,12 @@ OEMCryptoResult UsageTableEntry::ReportUsage(const std::vector<uint8_t>& pst,
if (recent_decrypt_) return OEMCrypto_ERROR_ENTRY_NEEDS_UPDATE;
if (pst.size() == 0 || pst.size() > kMaxPSTLength ||
pst.size() != data_.pst_length) {
LOGE("ReportUsage: bad pst length = %d, should be %d.",
pst.size(), data_.pst_length);
LOGE("ReportUsage: bad pst length = %d, should be %d.", pst.size(),
data_.pst_length);
return OEMCrypto_ERROR_WRONG_PST;
}
if (memcmp(&pst[0], data_.pst, data_.pst_length)) {
LOGE("ReportUsage: wrong pst %s, should be %s.",
wvcdm::b2a_hex(pst).c_str(),
LOGE("ReportUsage: wrong pst %s, should be %s.", wvcdm::b2a_hex(pst).c_str(),
wvcdm::HexEncode(data_.pst, data_.pst_length).c_str());
return OEMCrypto_ERROR_WRONG_PST;
}
@@ -163,12 +163,13 @@ OEMCryptoResult UsageTableEntry::ReportUsage(const std::vector<uint8_t>& pst,
if (LogCategoryEnabled(kLoggingDumpDerivedKeys)) {
std::vector<uint8_t> mac_key_client(
data_.mac_key_client,
data_.mac_key_client + wvcdm::MAC_KEY_SIZE * sizeof(uint8_t));
data_.mac_key_client + wvoec::MAC_KEY_SIZE * sizeof(uint8_t));
LOGI(("message signed with HMAC and data_.mac_key_client, "
"mac_key_client = " +
wvcdm::b2a_hex(mac_key_client)).c_str());
wvcdm::b2a_hex(mac_key_client))
.c_str());
}
if (!HMAC(EVP_sha1(), data_.mac_key_client, wvcdm::MAC_KEY_SIZE,
if (!HMAC(EVP_sha1(), data_.mac_key_client, wvoec::MAC_KEY_SIZE,
buffer + SHA_DIGEST_LENGTH, length_needed - SHA_DIGEST_LENGTH,
pst_report.signature(), &md_len)) {
LOGE("ReportUsage: could not compute signature.");
@@ -209,9 +210,9 @@ OEMCryptoResult UsageTableEntry::SaveData(CryptoEngine* ce,
const std::vector<uint8_t>& key = ce->DeviceRootKey(override_to_real);
// Encrypt the entry.
RAND_bytes(encrypted->iv, wvcdm::KEY_IV_SIZE);
uint8_t iv_buffer[wvcdm::KEY_IV_SIZE]; // working iv buffer.
memcpy(iv_buffer, encrypted->iv, wvcdm::KEY_IV_SIZE);
RAND_bytes(encrypted->iv, wvoec::KEY_IV_SIZE);
uint8_t iv_buffer[wvoec::KEY_IV_SIZE]; // working iv buffer.
memcpy(iv_buffer, encrypted->iv, wvoec::KEY_IV_SIZE);
AES_KEY aes_key;
AES_set_encrypt_key(&key[0], 128, &aes_key);
AES_cbc_encrypt(
@@ -265,8 +266,8 @@ OEMCryptoResult UsageTableEntry::LoadData(CryptoEngine* ce, uint32_t index,
}
// Next, decrypt the entry.
uint8_t iv_buffer[wvcdm::KEY_IV_SIZE];
memcpy(iv_buffer, encrypted->iv, wvcdm::KEY_IV_SIZE);
uint8_t iv_buffer[wvoec::KEY_IV_SIZE];
memcpy(iv_buffer, encrypted->iv, wvoec::KEY_IV_SIZE);
AES_KEY aes_key;
AES_set_decrypt_key(&key[0], 128, &aes_key);
AES_cbc_encrypt(&buffer[kEncryptionOffset], &clear_buffer[kEncryptionOffset],
@@ -279,7 +280,8 @@ OEMCryptoResult UsageTableEntry::LoadData(CryptoEngine* ce, uint32_t index,
wvcdm::HexEncode(clear->verification, kMagicLength).c_str(),
clear->verification,
wvcdm::HexEncode(reinterpret_cast<const uint8_t*>(kEntryVerification),
kMagicLength).c_str(),
kMagicLength)
.c_str(),
reinterpret_cast<const uint8_t*>(kEntryVerification));
return OEMCrypto_ERROR_BAD_MAGIC;
}
@@ -306,23 +308,23 @@ OEMCryptoResult UsageTableEntry::CopyOldUsageEntry(
data_.time_of_first_decrypt = old_entry->time_of_first_decrypt_;
data_.time_of_last_decrypt = old_entry->time_of_last_decrypt_;
data_.status = old_entry->status_;
if (old_entry->mac_key_server_.size() != wvcdm::MAC_KEY_SIZE) {
if (old_entry->mac_key_server_.size() != wvoec::MAC_KEY_SIZE) {
LOGE("CopyOldEntry: Old entry has bad server mac key.");
} else {
memcpy(data_.mac_key_server, &(old_entry->mac_key_server_[0]),
wvcdm::MAC_KEY_SIZE);
wvoec::MAC_KEY_SIZE);
}
if (old_entry->mac_key_client_.size() != wvcdm::MAC_KEY_SIZE) {
if (old_entry->mac_key_client_.size() != wvoec::MAC_KEY_SIZE) {
LOGE("CopyOldEntry: Old entry has bad client mac key.");
} else {
memcpy(data_.mac_key_client, &(old_entry->mac_key_client_[0]),
wvcdm::MAC_KEY_SIZE);
wvoec::MAC_KEY_SIZE);
if (LogCategoryEnabled(kLoggingDumpDerivedKeys)) {
std::vector<uint8_t> mac_key_client(
data_.mac_key_client,
data_.mac_key_client + wvcdm::MAC_KEY_SIZE * sizeof(uint8_t));
LOGI(("data_.mac_key_client has changed to = " +
wvcdm::b2a_hex(mac_key_client)).c_str());
data_.mac_key_client + wvoec::MAC_KEY_SIZE * sizeof(uint8_t));
LOGI(("data_.mac_key_client has changed to = " +
wvcdm::b2a_hex(mac_key_client)).c_str());
}
}
if (pst.size() > kMaxPSTLength) {
@@ -336,12 +338,11 @@ OEMCryptoResult UsageTableEntry::CopyOldUsageEntry(
return OEMCrypto_SUCCESS;
}
size_t UsageTableEntry::SignedEntrySize() {
size_t base = sizeof(SignedEntryBlock);
// round up to make even number of blocks:
size_t blocks = (base - 1) / wvcdm::KEY_IV_SIZE + 1;
return blocks * wvcdm::KEY_IV_SIZE;
size_t blocks = (base - 1) / wvoec::KEY_IV_SIZE + 1;
return blocks * wvoec::KEY_IV_SIZE;
}
UsageTable::~UsageTable() {
@@ -354,8 +355,8 @@ UsageTable::~UsageTable() {
size_t UsageTable::SignedHeaderSize(size_t count) {
size_t base = sizeof(SignedHeaderBlock) + count * sizeof(int64_t);
// round up to make even number of blocks:
size_t blocks = (base - 1) / wvcdm::KEY_IV_SIZE + 1;
return blocks * wvcdm::KEY_IV_SIZE;
size_t blocks = (base - 1) / wvoec::KEY_IV_SIZE + 1;
return blocks * wvoec::KEY_IV_SIZE;
}
OEMCryptoResult UsageTable::UpdateUsageEntry(SessionContext* session,
@@ -503,9 +504,9 @@ OEMCryptoResult UsageTable::SaveUsageTableHeader(uint8_t* signed_buffer,
const std::vector<uint8_t>& key = ce_->DeviceRootKey(override_to_real);
// Encrypt the entry.
RAND_bytes(encrypted->iv, wvcdm::KEY_IV_SIZE);
uint8_t iv_buffer[wvcdm::KEY_IV_SIZE]; // working iv buffer.
memcpy(iv_buffer, encrypted->iv, wvcdm::KEY_IV_SIZE);
RAND_bytes(encrypted->iv, wvoec::KEY_IV_SIZE);
uint8_t iv_buffer[wvoec::KEY_IV_SIZE]; // working iv buffer.
memcpy(iv_buffer, encrypted->iv, wvoec::KEY_IV_SIZE);
AES_KEY aes_key;
AES_set_encrypt_key(&key[0], 128, &aes_key);
AES_cbc_encrypt(
@@ -558,8 +559,8 @@ OEMCryptoResult UsageTable::LoadUsageTableHeader(
}
// Next, decrypt the entry.
uint8_t iv_buffer[wvcdm::KEY_IV_SIZE];
memcpy(iv_buffer, encrypted->iv, wvcdm::KEY_IV_SIZE);
uint8_t iv_buffer[wvoec::KEY_IV_SIZE];
memcpy(iv_buffer, encrypted->iv, wvoec::KEY_IV_SIZE);
AES_KEY aes_key;
AES_set_decrypt_key(&key[0], 128, &aes_key);
AES_cbc_encrypt(&buffer[kEncryptionOffset], &clear_buffer[kEncryptionOffset],
@@ -572,7 +573,8 @@ OEMCryptoResult UsageTable::LoadUsageTableHeader(
wvcdm::HexEncode(clear->verification, kMagicLength).c_str(),
clear->verification,
wvcdm::HexEncode(reinterpret_cast<const uint8_t*>(kHeaderVerification),
kMagicLength).c_str(),
kMagicLength)
.c_str(),
reinterpret_cast<const uint8_t*>(kHeaderVerification));
return OEMCrypto_ERROR_BAD_MAGIC;
}
@@ -641,11 +643,13 @@ bool UsageTable::SaveGenerationNumber() {
std::string path;
// Note: this path is OK for a real implementation, but using security level 1
// would be better.
if (!wvcdm::Properties::GetDeviceFilesBasePath(wvcdm::kSecurityLevelL3,
// TODO(jfore, rfrias): Address how this property is presented to the ref.
// For now, the path is empty.
/*if (!Properties::GetDeviceFilesBasePath(kSecurityLevelL3,
&path)) {
LOGE("UsageTable: Unable to get base path");
return false;
}
}*/
// On a real implementation, you should NOT put the generation number in
// a file in user space. It should be stored in secure memory.
std::string filename = path + "GenerationNumber.dat";
@@ -666,16 +670,17 @@ bool UsageTable::LoadGenerationNumber(bool or_make_new_one) {
std::string path;
// Note: this path is OK for a real implementation, but using security level 1
// would be better.
if (!wvcdm::Properties::GetDeviceFilesBasePath(wvcdm::kSecurityLevelL3,
// TODO(jfore, rfrias): Address how this property is presented to the ref.
// For now, the path is empty.
/*if (!Properties::GetDeviceFilesBasePath(kSecurityLevelL3,
&path)) {
LOGE("UsageTable: Unable to get base path");
return false;
}
}*/
// On a real implementation, you should NOT put the generation number in
// a file in user space. It should be stored in secure memory.
std::string filename = path + "GenerationNumber.dat";
wvcdm::File* file = file_system->Open(filename,
wvcdm::FileSystem::kReadOnly);
wvcdm::File* file = file_system->Open(filename, wvcdm::FileSystem::kReadOnly);
if (!file) {
if (or_make_new_one) {
RAND_bytes(reinterpret_cast<uint8_t*>(&master_generation_number_),
@@ -702,7 +707,7 @@ OEMCryptoResult UsageTable::CreateUsageTableHeader(
*header_buffer_length = signed_header_size;
if (!LoadGenerationNumber(true)) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
// Make sure there are no entries that are currently tied to an open session.
for (size_t i=0; i < sessions_.size(); ++i) {
for (size_t i = 0; i < sessions_.size(); ++i) {
if (sessions_[i] != NULL) {
LOGE("CreateUsageTableHeader: index %d used by session.", i);
return OEMCrypto_ERROR_INVALID_SESSION;
@@ -736,8 +741,8 @@ OEMCryptoResult UsageTable::CreateOldUsageEntry(
uint8_t* server_mac_key, uint8_t* client_mac_key, const uint8_t* pst,
size_t pst_length) {
if (!old_table_) old_table_ = new OldUsageTable(ce_);
std::vector<uint8_t> pstv(pst, pst+pst_length);
OldUsageTableEntry *old_entry = old_table_->CreateEntry(pstv);
std::vector<uint8_t> pstv(pst, pst + pst_length);
OldUsageTableEntry* old_entry = old_table_->CreateEntry(pstv);
int64_t now = time(NULL);
old_entry->time_of_license_received_ = now - time_since_license_received;
@@ -745,10 +750,10 @@ OEMCryptoResult UsageTable::CreateOldUsageEntry(
old_entry->time_of_last_decrypt_ = now - time_since_last_decrypt;
old_entry->status_ = status;
old_entry->mac_key_server_.assign(server_mac_key,
server_mac_key + wvcdm::MAC_KEY_SIZE);
server_mac_key + wvoec::MAC_KEY_SIZE);
old_entry->mac_key_client_.assign(client_mac_key,
client_mac_key + wvcdm::MAC_KEY_SIZE);
client_mac_key + wvoec::MAC_KEY_SIZE);
return OEMCrypto_SUCCESS;
}
} // namespace wvoec_mock
} // namespace wvoec_ref

View File

@@ -2,10 +2,10 @@
// source code may only be used and distributed under the Widevine Master
// License Agreement.
//
// Mock implementation of OEMCrypto APIs
// Ref implementation of OEMCrypto APIs
//
#ifndef OEMCRYPTO_USAGE_TABLE_MOCK_H_
#define OEMCRYPTO_USAGE_TABLE_MOCK_H_
#ifndef OEMCRYPTO_USAGE_TABLE_REF_H_
#define OEMCRYPTO_USAGE_TABLE_REF_H_
#include <stdint.h>
#include <map>
@@ -13,12 +13,10 @@
#include <vector>
#include "OEMCryptoCENC.h"
#include "file_store.h"
#include "lock.h"
#include "openssl/sha.h"
#include "wv_cdm_constants.h"
#include "oemcrypto_types.h"
namespace wvoec_mock {
namespace wvoec_ref {
class SessionContext;
class CryptoEngine;
@@ -34,8 +32,8 @@ struct StoredUsageEntry {
int64_t time_of_first_decrypt;
int64_t time_of_last_decrypt;
enum OEMCrypto_Usage_Entry_Status status;
uint8_t mac_key_server[wvcdm::MAC_KEY_SIZE];
uint8_t mac_key_client[wvcdm::MAC_KEY_SIZE];
uint8_t mac_key_server[wvoec::MAC_KEY_SIZE];
uint8_t mac_key_client[wvoec::MAC_KEY_SIZE];
uint32_t index;
uint8_t pst[kMaxPSTLength+1]; // add 1 for padding.
uint8_t pst_length;
@@ -134,6 +132,6 @@ class UsageTable {
OldUsageTable *old_table_;
};
} // namespace wvoec_mock
} // namespace wvoec_ref
#endif // OEMCRYPTO_USAGE_TABLE_MOCK_H_
#endif // OEMCRYPTO_USAGE_TABLE_REF_H_

View File

@@ -2,6 +2,9 @@ LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_C_INCLUDES := \
vendor/widevine/libwvdrmengine/cdm/util/include \
LOCAL_MODULE:=oemcrypto_test
LOCAL_MODULE_TAGS := tests

View File

@@ -17,6 +17,7 @@ LOCAL_C_INCLUDES += \
$(LOCAL_PATH)/../include \
$(LOCAL_PATH)/../mock/src \
vendor/widevine/libwvdrmengine/cdm/core/include \
vendor/widevine/libwvdrmengine/cdm/util/include \
LOCAL_STATIC_LIBRARIES := \
libcdm \

View File

@@ -4,7 +4,7 @@
#include <string>
#include "OEMCryptoCENC.h"
#include "wv_keybox.h"
#include "oemcrypto_types.h"
namespace wvoec {

View File

@@ -26,14 +26,12 @@
#include <vector>
#include "OEMCryptoCENC.h"
#include "disallow_copy_and_assign.h"
#include "log.h"
#include "oec_device_features.h"
#include "oec_test_data.h"
#include "oemcrypto_key_mock.h"
#include "oemcrypto_types.h"
#include "string_conversions.h"
#include "wv_cdm_constants.h"
#include "wv_cdm_types.h"
#include "wv_keybox.h"
using namespace std;
@@ -102,9 +100,9 @@ Session::Session()
: open_(false),
forced_session_id_(false),
session_id_(0),
mac_key_server_(wvcdm::MAC_KEY_SIZE),
mac_key_client_(wvcdm::MAC_KEY_SIZE),
enc_key_(wvcdm::KEY_SIZE),
mac_key_server_(MAC_KEY_SIZE),
mac_key_client_(MAC_KEY_SIZE),
enc_key_(KEY_SIZE),
public_rsa_(0),
message_size_(sizeof(MessageData)),
// Most tests only use 4 keys. Other tests will explicitly call
@@ -187,7 +185,7 @@ void Session::DeriveKey(const uint8_t* key, const vector<uint8_t>& context,
CMAC_CTX* cmac_ctx = CMAC_CTX_new();
ASSERT_NE(static_cast<void*>(NULL), cmac_ctx);
ASSERT_EQ(1, CMAC_Init(cmac_ctx, key, wvcdm::KEY_SIZE, cipher, 0));
ASSERT_EQ(1, CMAC_Init(cmac_ctx, key, KEY_SIZE, cipher, 0));
std::vector<uint8_t> message;
message.push_back(counter);
@@ -223,7 +221,7 @@ void Session::DeriveKeys(const uint8_t* master_key,
}
void Session::GenerateDerivedKeysFromKeybox(
const wvoec_mock::WidevineKeybox& keybox) {
const wvoec::WidevineKeybox& keybox) {
GenerateNonce();
vector<uint8_t> mac_context;
vector<uint8_t> enc_context;
@@ -269,9 +267,9 @@ void Session::LoadTestKeys(const std::string& pst, bool new_mac_keys) {
key_array_, pst_ptr, pst.length(), NULL,
OEMCrypto_ContentLicense));
// Update new generated keys.
memcpy(&mac_key_server_[0], license_.mac_keys, wvcdm::MAC_KEY_SIZE);
memcpy(&mac_key_client_[0], license_.mac_keys + wvcdm::MAC_KEY_SIZE,
wvcdm::MAC_KEY_SIZE);
memcpy(&mac_key_server_[0], license_.mac_keys, MAC_KEY_SIZE);
memcpy(&mac_key_client_[0], license_.mac_keys + MAC_KEY_SIZE,
MAC_KEY_SIZE);
} else {
ASSERT_EQ(
OEMCrypto_SUCCESS,
@@ -299,9 +297,9 @@ void Session::LoadEnitlementTestKeys(const std::string& pst,
key_array_, pst_ptr, pst.length(), NULL,
OEMCrypto_EntitlementLicense));
// Update new generated keys.
memcpy(&mac_key_server_[0], license_.mac_keys, wvcdm::MAC_KEY_SIZE);
memcpy(&mac_key_client_[0], license_.mac_keys + wvcdm::MAC_KEY_SIZE,
wvcdm::MAC_KEY_SIZE);
memcpy(&mac_key_server_[0], license_.mac_keys, MAC_KEY_SIZE);
memcpy(&mac_key_client_[0], license_.mac_keys + MAC_KEY_SIZE,
MAC_KEY_SIZE);
} else {
ASSERT_EQ(
expected_sts,
@@ -479,7 +477,7 @@ void Session::FillSimpleMessage(uint32_t duration, uint32_t control,
memset(license_.keys[i].key_id, i, license_.keys[i].key_id_length);
EXPECT_EQ(1, GetRandBytes(license_.keys[i].key_data,
sizeof(license_.keys[i].key_data)));
license_.keys[i].key_data_length = wvcdm::KEY_SIZE;
license_.keys[i].key_data_length = KEY_SIZE;
EXPECT_EQ(1, GetRandBytes(license_.keys[i].key_iv,
sizeof(license_.keys[i].key_iv)));
EXPECT_EQ(1, GetRandBytes(license_.keys[i].control_iv,
@@ -493,14 +491,14 @@ void Session::FillSimpleMessage(uint32_t duration, uint32_t control,
} else if (global_features.api_version == 12) {
// For version 12, we require OEMCrypto to handle kc12 for all licenses.
memcpy(license_.keys[i].control.verification, "kc12", 4);
} else if (control & wvoec_mock::kControlSecurityPatchLevelMask) {
} else if (control & wvoec::kControlSecurityPatchLevelMask) {
// For versions before 12, we require the special key control block only
// when there are newer features present.
memcpy(license_.keys[i].control.verification, "kc11", 4);
} else if (control & wvoec_mock::kControlRequireAntiRollbackHardware) {
} else if (control & wvoec::kControlRequireAntiRollbackHardware) {
memcpy(license_.keys[i].control.verification, "kc10", 4);
} else if (control & (wvoec_mock::kControlHDCPVersionMask |
wvoec_mock::kControlReplayMask)) {
} else if (control & (wvoec::kControlHDCPVersionMask |
wvoec::kControlReplayMask)) {
memcpy(license_.keys[i].control.verification, "kc09", 4);
} else {
memcpy(license_.keys[i].control.verification, "kctl", 4);
@@ -526,7 +524,7 @@ void Session::FillSimpleEntitlementMessage(
memset(license_.keys[i].key_id, i, license_.keys[i].key_id_length);
EXPECT_EQ(1, GetRandBytes(license_.keys[i].key_data,
sizeof(license_.keys[i].key_data)));
license_.keys[i].key_data_length = wvcdm::KEY_SIZE * 2; // AES-256 keys
license_.keys[i].key_data_length = KEY_SIZE * 2; // AES-256 keys
EXPECT_EQ(1, GetRandBytes(license_.keys[i].key_iv,
sizeof(license_.keys[i].key_iv)));
EXPECT_EQ(1, GetRandBytes(license_.keys[i].control_iv,
@@ -540,14 +538,14 @@ void Session::FillSimpleEntitlementMessage(
} else if (global_features.api_version == 12) {
// For version 12, we require OEMCrypto to handle kc12 for all licenses.
memcpy(license_.keys[i].control.verification, "kc12", 4);
} else if (control & wvoec_mock::kControlSecurityPatchLevelMask) {
} else if (control & wvoec::kControlSecurityPatchLevelMask) {
// For versions before 12, we require the special key control block only
// when there are newer features present.
memcpy(license_.keys[i].control.verification, "kc11", 4);
} else if (control & wvoec_mock::kControlRequireAntiRollbackHardware) {
} else if (control & wvoec::kControlRequireAntiRollbackHardware) {
memcpy(license_.keys[i].control.verification, "kc10", 4);
} else if (control & (wvoec_mock::kControlHDCPVersionMask |
wvoec_mock::kControlReplayMask)) {
} else if (control & (wvoec::kControlHDCPVersionMask |
wvoec::kControlReplayMask)) {
memcpy(license_.keys[i].control.verification, "kc09", 4);
} else {
memcpy(license_.keys[i].control.verification, "kctl", 4);
@@ -591,21 +589,21 @@ void Session::EncryptAndSign() {
encrypted_license() = license_;
uint8_t iv_buffer[16];
memcpy(iv_buffer, &license_.mac_key_iv[0], wvcdm::KEY_IV_SIZE);
memcpy(iv_buffer, &license_.mac_key_iv[0], KEY_IV_SIZE);
AES_KEY aes_key;
AES_set_encrypt_key(&enc_key_[0], 128, &aes_key);
AES_cbc_encrypt(&license_.mac_keys[0], &encrypted_license().mac_keys[0],
2 * wvcdm::MAC_KEY_SIZE, &aes_key, iv_buffer, AES_ENCRYPT);
2 * MAC_KEY_SIZE, &aes_key, iv_buffer, AES_ENCRYPT);
for (unsigned int i = 0; i < num_keys_; i++) {
memcpy(iv_buffer, &license_.keys[i].control_iv[0], wvcdm::KEY_IV_SIZE);
memcpy(iv_buffer, &license_.keys[i].control_iv[0], KEY_IV_SIZE);
AES_set_encrypt_key(&license_.keys[i].key_data[0], 128, &aes_key);
AES_cbc_encrypt(
reinterpret_cast<const uint8_t*>(&license_.keys[i].control),
reinterpret_cast<uint8_t*>(&encrypted_license().keys[i].control),
wvcdm::KEY_SIZE, &aes_key, iv_buffer, AES_ENCRYPT);
KEY_SIZE, &aes_key, iv_buffer, AES_ENCRYPT);
memcpy(iv_buffer, &license_.keys[i].key_iv[0], wvcdm::KEY_IV_SIZE);
memcpy(iv_buffer, &license_.keys[i].key_iv[0], KEY_IV_SIZE);
AES_set_encrypt_key(&enc_key_[0], 128, &aes_key);
AES_cbc_encrypt(
&license_.keys[i].key_data[0], &encrypted_license().keys[i].key_data[0],
@@ -620,14 +618,14 @@ void Session::EncryptAndSign() {
void Session::EncryptProvisioningMessage(
RSAPrivateKeyMessage* data, RSAPrivateKeyMessage* encrypted,
const vector<uint8_t>& encryption_key) {
ASSERT_EQ(encryption_key.size(), wvcdm::KEY_SIZE);
ASSERT_EQ(encryption_key.size(), KEY_SIZE);
*encrypted = *data;
size_t padding = wvcdm::KEY_SIZE - (data->rsa_key_length % wvcdm::KEY_SIZE);
size_t padding = KEY_SIZE - (data->rsa_key_length % KEY_SIZE);
memset(data->rsa_key + data->rsa_key_length, static_cast<uint8_t>(padding),
padding);
encrypted->rsa_key_length = data->rsa_key_length + padding;
uint8_t iv_buffer[16];
memcpy(iv_buffer, &data->rsa_key_iv[0], wvcdm::KEY_IV_SIZE);
memcpy(iv_buffer, &data->rsa_key_iv[0], KEY_IV_SIZE);
AES_KEY aes_key;
AES_set_encrypt_key(&encryption_key[0], 128, &aes_key);
AES_cbc_encrypt(&data->rsa_key[0], &encrypted->rsa_key[0],
@@ -740,8 +738,8 @@ void Session::TestDecryptCTR(bool select_key_first,
for (size_t i = 0; i < unencryptedData.size(); i++)
unencryptedData[i] = i % 256;
EXPECT_EQ(1, GetRandBytes(&unencryptedData[0], unencryptedData.size()));
vector<uint8_t> encryptionIv(wvcdm::KEY_IV_SIZE);
EXPECT_EQ(1, GetRandBytes(&encryptionIv[0], wvcdm::KEY_IV_SIZE));
vector<uint8_t> encryptionIv(KEY_IV_SIZE);
EXPECT_EQ(1, GetRandBytes(&encryptionIv[0], KEY_IV_SIZE));
vector<uint8_t> encryptedData(unencryptedData.size());
EncryptCTR(unencryptedData, license_.keys[key_index].key_data,
&encryptionIv[0], &encryptedData);
@@ -893,7 +891,7 @@ void Session::MakeRSACertificate(struct RSAPrivateKeyMessage* encrypted,
memcpy(message.rsa_key, rsa_key.data(), rsa_key.size());
message.rsa_key_length = rsa_key.size();
}
EXPECT_EQ(1, GetRandBytes(message.rsa_key_iv, wvcdm::KEY_IV_SIZE));
EXPECT_EQ(1, GetRandBytes(message.rsa_key_iv, KEY_IV_SIZE));
message.nonce = nonce_;
EncryptProvisioningMessage(&message, encrypted, *encryption_key);

Some files were not shown because too many files have changed in this diff Show More