├── .gitignore ├── LICENSE ├── README.md ├── cdm ├── LICENSE ├── base │ ├── base_export.h │ ├── basictypes.h │ ├── compiler_specific.h │ ├── macros.h │ ├── native_library.cc │ ├── native_library.h │ ├── native_library_ios.mm │ ├── native_library_mac.mm │ └── native_library_win.cc ├── build │ └── build_config.h └── media │ ├── base │ ├── cdm_config.h │ └── limits.h │ └── cdm │ ├── api │ ├── content_decryption_module.h │ ├── content_decryption_module_export.h │ └── content_decryption_module_proxy.h │ ├── cdm_adapter.cc │ └── cdm_adapter.h ├── wvadapter.cpp ├── wvadapter.h └── wvadapter.vcxproj /.gitignore: -------------------------------------------------------------------------------- 1 | .vs/ 2 | .vscode/ 3 | x64/ 4 | vc140.pdb 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 athrowaway2021 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # wvadapter1610 2 | Tool to perform modular exponentiation with the private key in a WidevineCDM library on arbitrary data provided by the user. The data must be exactly 256 bytes/2048 bits but can be padded with zeroes. Only works with the 1610 version of the library. 3 | 4 | Usage: 5 | ``` 6 | > wvadapter [hex-formatted data] [path to cdm library] 7 | ``` 8 | ``` 9 | > wvadapter 48ce88d1f8f4dcc348b160595142c84e2f2ad3fae20f009222ba58e4a40f6c09209f1b16d1ed9d2aca346051c2abccca946af11f16d23159cfc585dd78a5d45a385844124a7744a1d62af19b2468e903338dfbbbd702c30d864e5a2bdf474c96bd13a94de6d0603c940f0830b25f8da936ef5dd32d7c7f0ff4c99842c2199d16ccf23796c27bd1d15816b4644e517ccb98d40c329fafa499fa39b5d27775a2c636f72abb1de03b2b39ca0dbf7c56992c0c605b6e23a59536f1fb073894966feec44e0bbfb990ee190c1302962f04c0f785dd73c8cf68039d7185b23a97d678ed4f94030d752011a279e7c72db8ed70a241dbdd47f46a9ac70a23029daebf3bc6 ../widevinecdm.dll 10 | 19ded36a30b83dfdec210a1f39c9f4ea08ee0f611bcb8fa057ccf8dd741124eca3c415d125d66df2c73bf5e12fb63b7e7346788ca0fd54852e849a3b0dc7105ff6040d7404155a52774b977e399bcfe6eb6bed11c6d2cb5cb0d1586ba327c69488c0fa5f19cbd79a8fa4327d0f874c8f99769d9e3c058e04b1ae91108c9135753d11acf9b4056c62ba2c4e557317826435f4181e05d3c1070d4689ebc882f068190305f58f731a12ba4c80c98d82c446dcdec3a4cd725ea263e212f8815de54049c6ed312b3d2d409188714e649045b6c71f9b1fc62b9eb2102dd40c75065068b0e4be7d9fe7d7ec74638b01c76727dbee24574d003fb2c2e5fa86f2f025bbd1 11 | ``` 12 | 13 | Works by replacing code at a fixed address in the library to load our data instead of a hash during the license request signing process, resulting in the signature field being replaced with our data exponentiated by the private key. This gives us a primitive that can be then extended for signing or decrypting by wrapping it with PSS or OAEP scheme respectively. I would love to do a writeup for this but it's been more than a year since I wrote this D: 14 | 15 | Releasing since the key is now revoked and this was a rather fun project. This method is universal, is practically much easier than extracting the private key itself, and could be replicated for any previous or future version of the library if you have the time to find out where the whiteboxed signing procedure is in the library, although it's not difficult with a modicum of reverse engineering experience. 16 | -------------------------------------------------------------------------------- /cdm/LICENSE: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Chromium Authors. All rights reserved. 2 | // 3 | // Redistribution and use in source and binary forms, with or without 4 | // modification, are permitted provided that the following conditions are 5 | // met: 6 | // 7 | // * Redistributions of source code must retain the above copyright 8 | // notice, this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above 10 | // copyright notice, this list of conditions and the following disclaimer 11 | // in the documentation and/or other materials provided with the 12 | // distribution. 13 | // * Neither the name of Google Inc. nor the names of its 14 | // contributors may be used to endorse or promote products derived from 15 | // this software without specific prior written permission. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /cdm/base/base_export.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | #ifndef BASE_BASE_EXPORT_H_ 6 | #define BASE_BASE_EXPORT_H_ 7 | 8 | #if defined(COMPONENT_BUILD) 9 | #if defined(WIN32) 10 | 11 | #if defined(BASE_IMPLEMENTATION) 12 | #define BASE_EXPORT __declspec(dllexport) 13 | #else 14 | #define BASE_EXPORT __declspec(dllimport) 15 | #endif // defined(BASE_IMPLEMENTATION) 16 | 17 | #else // defined(WIN32) 18 | #if defined(BASE_IMPLEMENTATION) 19 | #define BASE_EXPORT __attribute__((visibility("default"))) 20 | #else 21 | #define BASE_EXPORT 22 | #endif // defined(BASE_IMPLEMENTATION) 23 | #endif 24 | 25 | #else // defined(COMPONENT_BUILD) 26 | #define BASE_EXPORT 27 | #endif 28 | 29 | #endif // BASE_BASE_EXPORT_H_ 30 | -------------------------------------------------------------------------------- /cdm/base/basictypes.h: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | #ifndef BASE_BASICTYPES_H_ 6 | #define BASE_BASICTYPES_H_ 7 | 8 | #include // So we can set the bounds of our types. 9 | #include // For size_t. 10 | #include // For intptr_t. 11 | 12 | #include "macros.h" 13 | #include "../build/build_config.h" 14 | 15 | // DEPRECATED: Use (u)int{8,16,32,64}_t instead (and include ). 16 | // http://crbug.com/138542 17 | typedef int8_t int8; 18 | typedef uint8_t uint8; 19 | typedef int16_t int16; 20 | typedef uint16_t uint16; 21 | typedef int32_t int32; 22 | typedef uint32_t uint32; 23 | typedef int64_t int64; 24 | typedef uint64_t uint64; 25 | 26 | // DEPRECATED: Use std::numeric_limits (from ) or 27 | // (U)INT{8,16,32,64}_{MIN,MAX} in case of globals (and include ). 28 | // http://crbug.com/138542 29 | const uint64 kuint64max = 0xFFFFFFFFFFFFFFFFULL; 30 | const int32 kint32max = 0x7FFFFFFF; 31 | const int64 kint64max = 0x7FFFFFFFFFFFFFFFLL; 32 | 33 | #endif // BASE_BASICTYPES_H_ 34 | -------------------------------------------------------------------------------- /cdm/base/compiler_specific.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | #ifndef BASE_COMPILER_SPECIFIC_H_ 6 | #define BASE_COMPILER_SPECIFIC_H_ 7 | 8 | #include "../build/build_config.h" 9 | 10 | #if defined(COMPILER_MSVC) 11 | 12 | // For _Printf_format_string_. 13 | #include 14 | 15 | // Macros for suppressing and disabling warnings on MSVC. 16 | // 17 | // Warning numbers are enumerated at: 18 | // http://msdn.microsoft.com/en-us/library/8x5x43k7(VS.80).aspx 19 | // 20 | // The warning pragma: 21 | // http://msdn.microsoft.com/en-us/library/2c8f766e(VS.80).aspx 22 | // 23 | // Using __pragma instead of #pragma inside macros: 24 | // http://msdn.microsoft.com/en-us/library/d9x1s805.aspx 25 | 26 | // MSVC_SUPPRESS_WARNING disables warning |n| for the remainder of the line and 27 | // for the next line of the source file. 28 | #define MSVC_SUPPRESS_WARNING(n) __pragma(warning(suppress:n)) 29 | 30 | // MSVC_PUSH_DISABLE_WARNING pushes |n| onto a stack of warnings to be disabled. 31 | // The warning remains disabled until popped by MSVC_POP_WARNING. 32 | #define MSVC_PUSH_DISABLE_WARNING(n) __pragma(warning(push)) \ 33 | __pragma(warning(disable:n)) 34 | 35 | // MSVC_PUSH_WARNING_LEVEL pushes |n| as the global warning level. The level 36 | // remains in effect until popped by MSVC_POP_WARNING(). Use 0 to disable all 37 | // warnings. 38 | #define MSVC_PUSH_WARNING_LEVEL(n) __pragma(warning(push, n)) 39 | 40 | // Pop effects of innermost MSVC_PUSH_* macro. 41 | #define MSVC_POP_WARNING() __pragma(warning(pop)) 42 | 43 | #define MSVC_DISABLE_OPTIMIZE() __pragma(optimize("", off)) 44 | #define MSVC_ENABLE_OPTIMIZE() __pragma(optimize("", on)) 45 | 46 | // Allows exporting a class that inherits from a non-exported base class. 47 | // This uses suppress instead of push/pop because the delimiter after the 48 | // declaration (either "," or "{") has to be placed before the pop macro. 49 | // 50 | // Example usage: 51 | // class EXPORT_API Foo : NON_EXPORTED_BASE(public Bar) { 52 | // 53 | // MSVC Compiler warning C4275: 54 | // non dll-interface class 'Bar' used as base for dll-interface class 'Foo'. 55 | // Note that this is intended to be used only when no access to the base class' 56 | // static data is done through derived classes or inline methods. For more info, 57 | // see http://msdn.microsoft.com/en-us/library/3tdb471s(VS.80).aspx 58 | #define NON_EXPORTED_BASE(code) MSVC_SUPPRESS_WARNING(4275) \ 59 | code 60 | 61 | #else // Not MSVC 62 | 63 | #define _Printf_format_string_ 64 | #define MSVC_SUPPRESS_WARNING(n) 65 | #define MSVC_PUSH_DISABLE_WARNING(n) 66 | #define MSVC_PUSH_WARNING_LEVEL(n) 67 | #define MSVC_POP_WARNING() 68 | #define MSVC_DISABLE_OPTIMIZE() 69 | #define MSVC_ENABLE_OPTIMIZE() 70 | #define NON_EXPORTED_BASE(code) code 71 | 72 | #endif // COMPILER_MSVC 73 | 74 | 75 | // Annotate a variable indicating it's ok if the variable is not used. 76 | // (Typically used to silence a compiler warning when the assignment 77 | // is important for some other reason.) 78 | // Use like: 79 | // int x = ...; 80 | // ALLOW_UNUSED_LOCAL(x); 81 | #define ALLOW_UNUSED_LOCAL(x) false ? (void)x : (void)0 82 | 83 | // Annotate a typedef or function indicating it's ok if it's not used. 84 | // Use like: 85 | // typedef Foo Bar ALLOW_UNUSED_TYPE; 86 | #if defined(COMPILER_GCC) || defined(__clang__) 87 | #define ALLOW_UNUSED_TYPE __attribute__((unused)) 88 | #else 89 | #define ALLOW_UNUSED_TYPE 90 | #endif 91 | 92 | // Annotate a function indicating it should not be inlined. 93 | // Use like: 94 | // NOINLINE void DoStuff() { ... } 95 | #if defined(COMPILER_GCC) 96 | #define NOINLINE __attribute__((noinline)) 97 | #elif defined(COMPILER_MSVC) 98 | #define NOINLINE __declspec(noinline) 99 | #else 100 | #define NOINLINE 101 | #endif 102 | 103 | // Specify memory alignment for structs, classes, etc. 104 | // Use like: 105 | // class ALIGNAS(16) MyClass { ... } 106 | // ALIGNAS(16) int array[4]; 107 | #if defined(COMPILER_MSVC) 108 | #define ALIGNAS(byte_alignment) __declspec(align(byte_alignment)) 109 | #elif defined(COMPILER_GCC) 110 | #define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment))) 111 | #endif 112 | 113 | // Return the byte alignment of the given type (available at compile time). 114 | // Use like: 115 | // ALIGNOF(int32) // this would be 4 116 | #if defined(COMPILER_MSVC) 117 | #define ALIGNOF(type) __alignof(type) 118 | #elif defined(COMPILER_GCC) 119 | #define ALIGNOF(type) __alignof__(type) 120 | #endif 121 | 122 | // Annotate a function indicating the caller must examine the return value. 123 | // Use like: 124 | // int foo() WARN_UNUSED_RESULT; 125 | // To explicitly ignore a result, see |ignore_result()| in base/macros.h. 126 | // TODO(dcheng): Update //third_party/webrtc's macro definition to match. 127 | #undef WARN_UNUSED_RESULT 128 | #if defined(COMPILER_GCC) || defined(__clang__) 129 | #define WARN_UNUSED_RESULT __attribute__((warn_unused_result)) 130 | #else 131 | #define WARN_UNUSED_RESULT 132 | #endif 133 | 134 | // Tell the compiler a function is using a printf-style format string. 135 | // |format_param| is the one-based index of the format string parameter; 136 | // |dots_param| is the one-based index of the "..." parameter. 137 | // For v*printf functions (which take a va_list), pass 0 for dots_param. 138 | // (This is undocumented but matches what the system C headers do.) 139 | #if defined(COMPILER_GCC) 140 | #define PRINTF_FORMAT(format_param, dots_param) \ 141 | __attribute__((format(printf, format_param, dots_param))) 142 | #else 143 | #define PRINTF_FORMAT(format_param, dots_param) 144 | #endif 145 | 146 | // WPRINTF_FORMAT is the same, but for wide format strings. 147 | // This doesn't appear to yet be implemented in any compiler. 148 | // See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38308 . 149 | #define WPRINTF_FORMAT(format_param, dots_param) 150 | // If available, it would look like: 151 | // __attribute__((format(wprintf, format_param, dots_param))) 152 | 153 | // MemorySanitizer annotations. 154 | #if defined(MEMORY_SANITIZER) && !defined(OS_NACL) 155 | #include 156 | 157 | // Mark a memory region fully initialized. 158 | // Use this to annotate code that deliberately reads uninitialized data, for 159 | // example a GC scavenging root set pointers from the stack. 160 | #define MSAN_UNPOISON(p, size) __msan_unpoison(p, size) 161 | 162 | // Check a memory region for initializedness, as if it was being used here. 163 | // If any bits are uninitialized, crash with an MSan report. 164 | // Use this to sanitize data which MSan won't be able to track, e.g. before 165 | // passing data to another process via shared memory. 166 | #define MSAN_CHECK_MEM_IS_INITIALIZED(p, size) \ 167 | __msan_check_mem_is_initialized(p, size) 168 | #else // MEMORY_SANITIZER 169 | #define MSAN_UNPOISON(p, size) 170 | #define MSAN_CHECK_MEM_IS_INITIALIZED(p, size) 171 | #endif // MEMORY_SANITIZER 172 | 173 | // Macro useful for writing cross-platform function pointers. 174 | #if !defined(CDECL) 175 | #if defined(OS_WIN) 176 | #define CDECL __cdecl 177 | #else // defined(OS_WIN) 178 | #define CDECL 179 | #endif // defined(OS_WIN) 180 | #endif // !defined(CDECL) 181 | 182 | // Macro for hinting that an expression is likely to be false. 183 | #if !defined(UNLIKELY) 184 | #if defined(COMPILER_GCC) 185 | #define UNLIKELY(x) __builtin_expect(!!(x), 0) 186 | #else 187 | #define UNLIKELY(x) (x) 188 | #endif // defined(COMPILER_GCC) 189 | #endif // !defined(UNLIKELY) 190 | 191 | #endif // BASE_COMPILER_SPECIFIC_H_ 192 | -------------------------------------------------------------------------------- /cdm/base/macros.h: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | // This file contains macros and macro-like constructs (e.g., templates) that 6 | // are commonly used throughout Chromium source. (It may also contain things 7 | // that are closely related to things that are commonly used that belong in this 8 | // file.) 9 | 10 | #ifndef BASE_MACROS_H_ 11 | #define BASE_MACROS_H_ 12 | 13 | #include // For size_t. 14 | #include // For memcpy. 15 | 16 | // INITIALIZE_CDM_MODULE is a macro in api/content_decryption_module.h. 17 | // However, we need to pass it as a string to GetFunctionPointer() once it 18 | // is expanded. 19 | #define STRINGIFY(X) #X 20 | #define MAKE_STRING(X) STRINGIFY(X) 21 | 22 | // Put this in the declarations for a class to be uncopyable. 23 | #define DISALLOW_COPY(TypeName) \ 24 | TypeName(const TypeName&) = delete 25 | 26 | // Put this in the declarations for a class to be unassignable. 27 | #define DISALLOW_ASSIGN(TypeName) \ 28 | void operator=(const TypeName&) = delete 29 | 30 | // A macro to disallow the copy constructor and operator= functions 31 | // This should be used in the private: declarations for a class 32 | #define DISALLOW_COPY_AND_ASSIGN(TypeName) \ 33 | TypeName(const TypeName&); \ 34 | void operator=(const TypeName&) 35 | 36 | // A macro to disallow all the implicit constructors, namely the 37 | // default constructor, copy constructor and operator= functions. 38 | // 39 | // This should be used in the private: declarations for a class 40 | // that wants to prevent anyone from instantiating it. This is 41 | // especially useful for classes containing only static methods. 42 | #define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \ 43 | TypeName() = delete; \ 44 | DISALLOW_COPY_AND_ASSIGN(TypeName) 45 | 46 | // The arraysize(arr) macro returns the # of elements in an array arr. 47 | // The expression is a compile-time constant, and therefore can be 48 | // used in defining new arrays, for example. If you use arraysize on 49 | // a pointer by mistake, you will get a compile-time error. 50 | 51 | // This template function declaration is used in defining arraysize. 52 | // Note that the function doesn't need an implementation, as we only 53 | // use its type. 54 | template char (&ArraySizeHelper(T (&array)[N]))[N]; 55 | #define arraysize(array) (sizeof(ArraySizeHelper(array))) 56 | 57 | // bit_cast is a template function that implements the 58 | // equivalent of "*reinterpret_cast(&source)". We need this in 59 | // very low-level functions like the protobuf library and fast math 60 | // support. 61 | // 62 | // float f = 3.14159265358979; 63 | // int i = bit_cast(f); 64 | // // i = 0x40490fdb 65 | // 66 | // The classical address-casting method is: 67 | // 68 | // // WRONG 69 | // float f = 3.14159265358979; // WRONG 70 | // int i = * reinterpret_cast(&f); // WRONG 71 | // 72 | // The address-casting method actually produces undefined behavior 73 | // according to ISO C++ specification section 3.10 -15 -. Roughly, this 74 | // section says: if an object in memory has one type, and a program 75 | // accesses it with a different type, then the result is undefined 76 | // behavior for most values of "different type". 77 | // 78 | // This is true for any cast syntax, either *(int*)&f or 79 | // *reinterpret_cast(&f). And it is particularly true for 80 | // conversions between integral lvalues and floating-point lvalues. 81 | // 82 | // The purpose of 3.10 -15- is to allow optimizing compilers to assume 83 | // that expressions with different types refer to different memory. gcc 84 | // 4.0.1 has an optimizer that takes advantage of this. So a 85 | // non-conforming program quietly produces wildly incorrect output. 86 | // 87 | // The problem is not the use of reinterpret_cast. The problem is type 88 | // punning: holding an object in memory of one type and reading its bits 89 | // back using a different type. 90 | // 91 | // The C++ standard is more subtle and complex than this, but that 92 | // is the basic idea. 93 | // 94 | // Anyways ... 95 | // 96 | // bit_cast<> calls memcpy() which is blessed by the standard, 97 | // especially by the example in section 3.9 . Also, of course, 98 | // bit_cast<> wraps up the nasty logic in one place. 99 | // 100 | // Fortunately memcpy() is very fast. In optimized mode, with a 101 | // constant size, gcc 2.95.3, gcc 4.0.1, and msvc 7.1 produce inline 102 | // code with the minimal amount of data movement. On a 32-bit system, 103 | // memcpy(d,s,4) compiles to one load and one store, and memcpy(d,s,8) 104 | // compiles to two loads and two stores. 105 | // 106 | // I tested this code with gcc 2.95.3, gcc 4.0.1, icc 8.1, and msvc 7.1. 107 | // 108 | // WARNING: if Dest or Source is a non-POD type, the result of the memcpy 109 | // is likely to surprise you. 110 | 111 | template 112 | inline Dest bit_cast(const Source& source) { 113 | static_assert(sizeof(Dest) == sizeof(Source), 114 | "bit_cast requires source and destination to be the same size"); 115 | 116 | Dest dest; 117 | memcpy(&dest, &source, sizeof(dest)); 118 | return dest; 119 | } 120 | 121 | // Used to explicitly mark the return value of a function as unused. If you are 122 | // really sure you don't want to do anything with the return value of a function 123 | // that has been marked WARN_UNUSED_RESULT, wrap it with this. Example: 124 | // 125 | // scoped_ptr my_var = ...; 126 | // if (TakeOwnership(my_var.get()) == SUCCESS) 127 | // ignore_result(my_var.release()); 128 | // 129 | template 130 | inline void ignore_result(const T&) { 131 | } 132 | 133 | // The following enum should be used only as a constructor argument to indicate 134 | // that the variable has static storage class, and that the constructor should 135 | // do nothing to its state. It indicates to the reader that it is legal to 136 | // declare a static instance of the class, provided the constructor is given 137 | // the base::LINKER_INITIALIZED argument. Normally, it is unsafe to declare a 138 | // static variable that has a constructor or a destructor because invocation 139 | // order is undefined. However, IF the type can be initialized by filling with 140 | // zeroes (which the loader does for static variables), AND the destructor also 141 | // does nothing to the storage, AND there are no virtual methods, then a 142 | // constructor declared as 143 | // explicit MyClass(base::LinkerInitialized x) {} 144 | // and invoked as 145 | // static MyClass my_variable_name(base::LINKER_INITIALIZED); 146 | namespace base { 147 | enum LinkerInitialized { LINKER_INITIALIZED }; 148 | 149 | // Use these to declare and define a static local variable (static T;) so that 150 | // it is leaked so that its destructors are not called at exit. If you need 151 | // thread-safe initialization, use base/lazy_instance.h instead. 152 | #define CR_DEFINE_STATIC_LOCAL(type, name, arguments) \ 153 | static type& name = *new type arguments 154 | 155 | } // base 156 | 157 | #endif // BASE_MACROS_H_ 158 | -------------------------------------------------------------------------------- /cdm/base/native_library.cc: -------------------------------------------------------------------------------- 1 | #include "native_library.h" 2 | 3 | namespace base { 4 | 5 | const char *int2char(int value, char* buffer) 6 | { 7 | const char *result = buffer; 8 | unsigned int buffer_pos = 0; 9 | 10 | if (value < 0) { 11 | buffer[buffer_pos++] = '-'; 12 | value = -value; 13 | } 14 | 15 | int number_of_digits = 0; 16 | int t = value; 17 | do { 18 | ++number_of_digits; 19 | } while (t /= 10); 20 | 21 | buffer_pos += number_of_digits; 22 | 23 | do { 24 | int last_digit = value % 10; 25 | buffer[--buffer_pos] = '0' + last_digit; 26 | value /= 10; 27 | } while (value); 28 | return result; 29 | } 30 | } //namespace 31 | -------------------------------------------------------------------------------- /cdm/base/native_library.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | #ifndef BASE_NATIVE_LIBRARY_H_ 6 | #define BASE_NATIVE_LIBRARY_H_ 7 | 8 | // This file defines a cross-platform "NativeLibrary" type which represents 9 | // a loadable module. 10 | 11 | #include 12 | 13 | #include "../base/base_export.h" 14 | #include "../base/compiler_specific.h" 15 | //#include "base/strings/string16.h" 16 | #include "../build/build_config.h" 17 | 18 | #if defined(OS_WIN) 19 | #include 20 | #elif defined(OS_MACOSX) 21 | #import 22 | #endif // OS_* 23 | 24 | namespace base { 25 | 26 | const char *int2char(int value, char* buffer); 27 | 28 | //class FilePath; 29 | 30 | #if defined(OS_WIN) 31 | typedef HMODULE NativeLibrary; 32 | #elif defined(OS_MACOSX) 33 | enum NativeLibraryType { 34 | BUNDLE, 35 | DYNAMIC_LIB 36 | }; 37 | enum NativeLibraryObjCStatus { 38 | OBJC_UNKNOWN, 39 | OBJC_PRESENT, 40 | OBJC_NOT_PRESENT, 41 | }; 42 | struct NativeLibraryStruct { 43 | NativeLibraryType type; 44 | CFBundleRefNum bundle_resource_ref; 45 | NativeLibraryObjCStatus objc_status; 46 | union { 47 | CFBundleRef bundle; 48 | void* dylib; 49 | }; 50 | }; 51 | typedef NativeLibraryStruct* NativeLibrary; 52 | #elif defined(OS_POSIX) 53 | typedef void* NativeLibrary; 54 | #endif // OS_* 55 | 56 | struct BASE_EXPORT NativeLibraryLoadError { 57 | #if defined(OS_WIN) 58 | NativeLibraryLoadError() : code(0) {} 59 | #endif // OS_WIN 60 | 61 | // Returns a string representation of the load error. 62 | std::string ToString() const; 63 | 64 | #if defined(OS_WIN) 65 | DWORD code; 66 | #else 67 | std::string message; 68 | #endif // OS_WIN 69 | }; 70 | 71 | // Loads a native library from disk. Release it with UnloadNativeLibrary when 72 | // you're done. Returns NULL on failure. 73 | // If |error| is not NULL, it may be filled in on load error. 74 | BASE_EXPORT NativeLibrary LoadNativeLibrary(const std::string& library_path, 75 | NativeLibraryLoadError* error); 76 | 77 | #if defined(OS_WIN) 78 | // Loads a native library from disk. Release it with UnloadNativeLibrary when 79 | // you're done. 80 | // This function retrieves the LoadLibrary function exported from kernel32.dll 81 | // and calls it instead of directly calling the LoadLibrary function via the 82 | // import table. 83 | BASE_EXPORT NativeLibrary LoadNativeLibraryDynamically( 84 | const std::string& library_path); 85 | #endif // OS_WIN 86 | 87 | // Unloads a native library. 88 | BASE_EXPORT void UnloadNativeLibrary(NativeLibrary library); 89 | 90 | // Gets a function pointer from a native library. 91 | BASE_EXPORT void* GetFunctionPointerFromNativeLibrary(NativeLibrary library, 92 | const char* name); 93 | 94 | // Returns the full platform specific name for a native library. 95 | // For example: 96 | // "mylib" returns "mylib.dll" on Windows, "libmylib.so" on Linux, 97 | // "mylib.dylib" on Mac. 98 | //BASE_EXPORT string16 GetNativeLibraryName(const string16& name); 99 | 100 | } // namespace base 101 | 102 | #endif // BASE_NATIVE_LIBRARY_H_ 103 | -------------------------------------------------------------------------------- /cdm/base/native_library_ios.mm: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | #include "base/native_library.h" 6 | 7 | #include "base/logging.h" 8 | 9 | namespace base { 10 | 11 | std::string NativeLibraryLoadError::ToString() const { 12 | return message; 13 | } 14 | 15 | // static 16 | NativeLibrary LoadNativeLibrary(const base::FilePath& library_path, 17 | NativeLibraryLoadError* error) { 18 | NOTIMPLEMENTED(); 19 | if (error) 20 | error->message = "Not implemented."; 21 | return nullptr; 22 | } 23 | 24 | // static 25 | void UnloadNativeLibrary(NativeLibrary library) { 26 | NOTIMPLEMENTED(); 27 | DCHECK(!library); 28 | } 29 | 30 | // static 31 | void* GetFunctionPointerFromNativeLibrary(NativeLibrary library, 32 | const char* name) { 33 | NOTIMPLEMENTED(); 34 | return nullptr; 35 | } 36 | 37 | // static 38 | string16 GetNativeLibraryName(const string16& name) { 39 | return name; 40 | } 41 | 42 | } // namespace base 43 | -------------------------------------------------------------------------------- /cdm/base/native_library_mac.mm: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | #include "native_library.h" 6 | 7 | #include 8 | #include 9 | 10 | namespace base { 11 | 12 | static NativeLibraryObjCStatus GetObjCStatusForImage( 13 | const void* function_pointer) { 14 | Dl_info info; 15 | if (!dladdr(function_pointer, &info)) 16 | return OBJC_UNKNOWN; 17 | 18 | // See if the the image contains an "ObjC image info" segment. This method 19 | // of testing is used in _CFBundleGrokObjcImageInfoFromFile in 20 | // CF-744/CFBundle.c, around lines 2447-2474. 21 | // 22 | // In 32-bit images, ObjC can be recognized in __OBJC,__image_info, whereas 23 | // in 64-bit, the data is in __DATA,__objc_imageinfo. 24 | #if __LP64__ 25 | const section_64* section = getsectbynamefromheader_64( 26 | reinterpret_cast(info.dli_fbase), 27 | SEG_DATA, "__objc_imageinfo"); 28 | #else 29 | const section* section = getsectbynamefromheader( 30 | reinterpret_cast(info.dli_fbase), 31 | SEG_OBJC, "__image_info"); 32 | #endif 33 | return section == NULL ? OBJC_NOT_PRESENT : OBJC_PRESENT; 34 | } 35 | 36 | std::string NativeLibraryLoadError::ToString() const { 37 | return message; 38 | } 39 | 40 | // static 41 | NativeLibrary LoadNativeLibrary(const std::string& library_path, 42 | NativeLibraryLoadError* error) { 43 | // dlopen() etc. open the file off disk. 44 | std::string::size_type delim(library_path.find_last_of('.', library_path.length())); 45 | if ((delim != std::string::npos && library_path.substr(delim+1) == "dylib")) { 46 | void* dylib = dlopen(library_path.c_str(), RTLD_LAZY); 47 | if (!dylib) { 48 | if (error) 49 | error->message = dlerror(); 50 | return NULL; 51 | } 52 | NativeLibrary native_lib = new NativeLibraryStruct(); 53 | native_lib->type = DYNAMIC_LIB; 54 | native_lib->dylib = dylib; 55 | native_lib->objc_status = OBJC_UNKNOWN; 56 | return native_lib; 57 | } 58 | 59 | CFURLRef url = CFURLCreateFromFileSystemRepresentation( 60 | kCFAllocatorDefault, 61 | (const UInt8*)library_path.c_str(), 62 | library_path.length(), 63 | true); 64 | if (!url) 65 | return NULL; 66 | CFBundleRef bundle = CFBundleCreate(kCFAllocatorDefault, url); 67 | if (!bundle) 68 | return NULL; 69 | 70 | NativeLibrary native_lib = new NativeLibraryStruct(); 71 | native_lib->type = BUNDLE; 72 | native_lib->bundle = bundle; 73 | native_lib->bundle_resource_ref = CFBundleOpenBundleResourceMap(bundle); 74 | native_lib->objc_status = OBJC_UNKNOWN; 75 | return native_lib; 76 | } 77 | 78 | // static 79 | void UnloadNativeLibrary(NativeLibrary library) { 80 | if (!library) 81 | return; 82 | if (library->objc_status == OBJC_NOT_PRESENT) { 83 | if (library->type == BUNDLE) { 84 | CFBundleCloseBundleResourceMap(library->bundle, 85 | library->bundle_resource_ref); 86 | CFRelease(library->bundle); 87 | } else { 88 | dlclose(library->dylib); 89 | } 90 | } 91 | delete library; 92 | } 93 | 94 | // static 95 | void* GetFunctionPointerFromNativeLibrary(NativeLibrary library, 96 | const char* name) { 97 | void* function_pointer = NULL; 98 | 99 | // Get the function pointer using the right API for the type. 100 | if (library->type == BUNDLE) { 101 | CFStringRef symbol_name = CFStringCreateWithCString( 102 | kCFAllocatorDefault, name, kCFStringEncodingUTF8); 103 | function_pointer = CFBundleGetFunctionPointerForName(library->bundle, 104 | symbol_name); 105 | } else { 106 | function_pointer = dlsym(library->dylib, name); 107 | } 108 | 109 | // If this library hasn't been tested for having ObjC, use the function 110 | // pointer to look up the section information for the library. 111 | if (function_pointer && library->objc_status == OBJC_UNKNOWN) 112 | library->objc_status = GetObjCStatusForImage(function_pointer); 113 | 114 | return function_pointer; 115 | } 116 | 117 | // static 118 | //string16 GetNativeLibraryName(const string16& name) { 119 | // return name + ASCIIToUTF16(".dylib"); 120 | //} 121 | 122 | } // namespace base 123 | -------------------------------------------------------------------------------- /cdm/base/native_library_win.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | #include "native_library.h" 6 | 7 | #include 8 | 9 | //#include "base/files/file_util.h" 10 | //#include "base/strings/stringprintf.h" 11 | //#include "base/strings/utf_string_conversions.h" 12 | //#include "base/threading/thread_restrictions.h" 13 | 14 | namespace base { 15 | 16 | #if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) 17 | typedef HMODULE (WINAPI* LoadLibraryFunction)(const wchar_t* file_name, unsigned long res); 18 | #else 19 | typedef HMODULE (WINAPI* LoadLibraryFunction)(const wchar_t* file_name); 20 | #endif 21 | 22 | namespace { 23 | 24 | NativeLibrary LoadNativeLibraryHelper(const std::string& library_path, 25 | LoadLibraryFunction load_library_api, 26 | NativeLibraryLoadError* error) { 27 | // LoadLibrary() opens the file off disk. 28 | //ThreadRestrictions::AssertIOAllowed(); 29 | 30 | // Switch the current directory to the library directory as the library 31 | // may have dependencies on DLLs in this directory. 32 | bool restore_directory = false; 33 | wchar_t current_directory[MAX_PATH]; 34 | std::wstring lp; 35 | std::wstring plugin_path, plugin_value; 36 | 37 | int len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, library_path.c_str(), (int)library_path.length(), NULL, 0); 38 | if (len) 39 | { 40 | lp.resize(len); 41 | len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, library_path.c_str(), (int)library_path.length(), &lp[0], len); 42 | } 43 | if (!len) 44 | lp.assign(library_path.begin(), library_path.end()); 45 | 46 | if (GetCurrentDirectoryW(MAX_PATH,current_directory)) 47 | { 48 | const wchar_t *res = wcsrchr(lp.c_str(), '\\'); 49 | if (res) 50 | { 51 | plugin_path.assign(lp.c_str(),res); 52 | plugin_value.assign(++res, wcsrchr(res,0)); 53 | } 54 | else 55 | plugin_value = lp; 56 | 57 | if (!plugin_path.empty()) 58 | { 59 | SetCurrentDirectoryW((wchar_t*)plugin_path.c_str()); 60 | restore_directory = true; 61 | } 62 | } 63 | 64 | #if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) 65 | HMODULE module = (*load_library_api)((wchar_t*)plugin_value.c_str(), 0); 66 | #else 67 | HMODULE module = (*load_library_api)((wchar_t*)plugin_value.c_str()); 68 | #endif 69 | if (!module && error) { 70 | // GetLastError() needs to be called immediately after |load_library_api|. 71 | error->code = GetLastError(); 72 | } 73 | 74 | if (restore_directory) 75 | SetCurrentDirectoryW(current_directory); 76 | 77 | return module; 78 | } 79 | 80 | } // namespace 81 | 82 | std::string NativeLibraryLoadError::ToString() const 83 | { 84 | char buf[32]; 85 | return int2char(code, buf); 86 | } 87 | 88 | // static 89 | NativeLibrary LoadNativeLibrary(const std::string& library_path, 90 | NativeLibraryLoadError* error) { 91 | #if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) 92 | return LoadNativeLibraryHelper(library_path, LoadPackagedLibrary, error); 93 | #else 94 | return LoadNativeLibraryHelper(library_path, LoadLibraryW, error); 95 | #endif 96 | } 97 | 98 | NativeLibrary LoadNativeLibraryDynamically(const std::string& library_path) { 99 | typedef HMODULE (WINAPI* LoadLibraryFunction)(const wchar_t* file_name); 100 | 101 | #if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) 102 | return LoadNativeLibraryHelper(library_path, LoadPackagedLibrary, NULL); 103 | #else 104 | LoadLibraryFunction load_library; 105 | load_library = reinterpret_cast( 106 | GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "LoadLibraryW")); 107 | 108 | return LoadNativeLibraryHelper(library_path, load_library, NULL); 109 | #endif 110 | } 111 | 112 | // static 113 | void UnloadNativeLibrary(NativeLibrary library) { 114 | FreeLibrary(library); 115 | } 116 | 117 | // static 118 | void* GetFunctionPointerFromNativeLibrary(NativeLibrary library, 119 | const char* name) { 120 | return GetProcAddress(library, name); 121 | } 122 | 123 | // static 124 | //string16 GetNativeLibraryName(const string16& name) { 125 | // return name + ASCIIToUTF16(".dll"); 126 | //} 127 | 128 | } // namespace base 129 | -------------------------------------------------------------------------------- /cdm/build/build_config.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | // This file adds defines about the platform we're currently building on. 6 | // Operating System: 7 | // OS_WIN / OS_MACOSX / OS_LINUX / OS_POSIX (MACOSX or LINUX) / 8 | // OS_NACL (NACL_SFI or NACL_NONSFI) / OS_NACL_SFI / OS_NACL_NONSFI 9 | // Compiler: 10 | // COMPILER_MSVC / COMPILER_GCC 11 | // Processor: 12 | // ARCH_CPU_X86 / ARCH_CPU_X86_64 / ARCH_CPU_X86_FAMILY (X86 or X86_64) 13 | // ARCH_CPU_32_BITS / ARCH_CPU_64_BITS 14 | 15 | #ifndef BUILD_BUILD_CONFIG_H_ 16 | #define BUILD_BUILD_CONFIG_H_ 17 | 18 | // A set of macros to use for platform detection. 19 | #if defined(__native_client__) 20 | // __native_client__ must be first, so that other OS_ defines are not set. 21 | #define OS_NACL 1 22 | // OS_NACL comes in two sandboxing technology flavors, SFI or Non-SFI. 23 | // PNaCl toolchain defines __native_client_nonsfi__ macro in Non-SFI build 24 | // mode, while it does not in SFI build mode. 25 | #if defined(__native_client_nonsfi__) 26 | #define OS_NACL_NONSFI 27 | #else 28 | #define OS_NACL_SFI 29 | #endif 30 | #elif defined(ANDROID) 31 | #define OS_ANDROID 1 32 | #elif defined(__APPLE__) 33 | // only include TargetConditions after testing ANDROID as some android builds 34 | // on mac don't have this header available and it's not needed unless the target 35 | // is really mac/ios. 36 | #include 37 | #define OS_MACOSX 1 38 | #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE 39 | #define OS_IOS 1 40 | #endif // defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE 41 | #elif defined(__linux__) 42 | #define OS_LINUX 1 43 | // include a system header to pull in features.h for glibc/uclibc macros. 44 | #include 45 | #if defined(__GLIBC__) && !defined(__UCLIBC__) 46 | // we really are using glibc, not uClibc pretending to be glibc 47 | #define LIBC_GLIBC 1 48 | #endif 49 | #elif defined(_WIN32) 50 | #define OS_WIN 1 51 | #define TOOLKIT_VIEWS 1 52 | #elif defined(__FreeBSD__) 53 | #define OS_FREEBSD 1 54 | #elif defined(__OpenBSD__) 55 | #define OS_OPENBSD 1 56 | #elif defined(__sun) 57 | #define OS_SOLARIS 1 58 | #elif defined(__QNXNTO__) 59 | #define OS_QNX 1 60 | #else 61 | #error Please add support for your platform in build/build_config.h 62 | #endif 63 | 64 | #if defined(USE_OPENSSL_CERTS) && defined(USE_NSS_CERTS) 65 | #error Cannot use both OpenSSL and NSS for certificates 66 | #endif 67 | 68 | // For access to standard BSD features, use OS_BSD instead of a 69 | // more specific macro. 70 | #if defined(OS_FREEBSD) || defined(OS_OPENBSD) 71 | #define OS_BSD 1 72 | #endif 73 | 74 | // For access to standard POSIXish features, use OS_POSIX instead of a 75 | // more specific macro. 76 | #if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_FREEBSD) || \ 77 | defined(OS_OPENBSD) || defined(OS_SOLARIS) || defined(OS_ANDROID) || \ 78 | defined(OS_NACL) || defined(OS_QNX) 79 | #define OS_POSIX 1 80 | #endif 81 | 82 | // Use tcmalloc 83 | #if (defined(OS_WIN) || defined(OS_LINUX) || defined(OS_ANDROID)) && \ 84 | !defined(NO_TCMALLOC) 85 | #define USE_TCMALLOC 1 86 | #endif 87 | 88 | // Compiler detection. 89 | #if defined(__GNUC__) 90 | #define COMPILER_GCC 1 91 | #elif defined(_MSC_VER) 92 | #define COMPILER_MSVC 1 93 | #else 94 | #error Please add support for your compiler in build/build_config.h 95 | #endif 96 | 97 | // Processor architecture detection. For more info on what's defined, see: 98 | // http://msdn.microsoft.com/en-us/library/b0084kay.aspx 99 | // http://www.agner.org/optimize/calling_conventions.pdf 100 | // or with gcc, run: "echo | gcc -E -dM -" 101 | #if defined(_M_ARM) 102 | #define ARCH_CPU_ARM_FAMILY 1 103 | #define ARCH_CPU_ARMEL 1 104 | #define ARCH_CPU_32_BITS 1 105 | #define ARCH_CPU_LITTLE_ENDIAN 1 106 | #elif defined(_M_X64) || defined(__x86_64__) 107 | #define ARCH_CPU_X86_FAMILY 1 108 | #define ARCH_CPU_X86_64 1 109 | #define ARCH_CPU_64_BITS 1 110 | #define ARCH_CPU_LITTLE_ENDIAN 1 111 | #elif defined(_M_IX86) || defined(__i386__) 112 | #define ARCH_CPU_X86_FAMILY 1 113 | #define ARCH_CPU_X86 1 114 | #define ARCH_CPU_32_BITS 1 115 | #define ARCH_CPU_LITTLE_ENDIAN 1 116 | #elif defined(__ARMEL__) 117 | #define ARCH_CPU_ARM_FAMILY 1 118 | #define ARCH_CPU_ARMEL 1 119 | #define ARCH_CPU_32_BITS 1 120 | #define ARCH_CPU_LITTLE_ENDIAN 1 121 | #elif defined(__aarch64__) 122 | #define ARCH_CPU_ARM_FAMILY 1 123 | #define ARCH_CPU_ARM64 1 124 | #define ARCH_CPU_64_BITS 1 125 | #define ARCH_CPU_LITTLE_ENDIAN 1 126 | #elif defined(__pnacl__) 127 | #define ARCH_CPU_32_BITS 1 128 | #define ARCH_CPU_LITTLE_ENDIAN 1 129 | #elif defined(__MIPSEL__) 130 | #if defined(__LP64__) 131 | #define ARCH_CPU_MIPS64_FAMILY 1 132 | #define ARCH_CPU_MIPS64EL 1 133 | #define ARCH_CPU_64_BITS 1 134 | #define ARCH_CPU_LITTLE_ENDIAN 1 135 | #else 136 | #define ARCH_CPU_MIPS_FAMILY 1 137 | #define ARCH_CPU_MIPSEL 1 138 | #define ARCH_CPU_32_BITS 1 139 | #define ARCH_CPU_LITTLE_ENDIAN 1 140 | #endif 141 | #else 142 | #error Please add support for your architecture in build/build_config.h 143 | #endif 144 | 145 | // Type detection for wchar_t. 146 | #if defined(OS_WIN) 147 | #define WCHAR_T_IS_UTF16 148 | #elif defined(OS_POSIX) && defined(COMPILER_GCC) && \ 149 | defined(__WCHAR_MAX__) && \ 150 | (__WCHAR_MAX__ == 0x7fffffff || __WCHAR_MAX__ == 0xffffffff) 151 | #define WCHAR_T_IS_UTF32 152 | #elif defined(OS_POSIX) && defined(COMPILER_GCC) && \ 153 | defined(__WCHAR_MAX__) && \ 154 | (__WCHAR_MAX__ == 0x7fff || __WCHAR_MAX__ == 0xffff) 155 | // On Posix, we'll detect short wchar_t, but projects aren't guaranteed to 156 | // compile in this mode (in particular, Chrome doesn't). This is intended for 157 | // other projects using base who manage their own dependencies and make sure 158 | // short wchar works for them. 159 | #define WCHAR_T_IS_UTF16 160 | #else 161 | #error Please add support for your compiler in build/build_config.h 162 | #endif 163 | 164 | #if defined(OS_ANDROID) 165 | // The compiler thinks std::string::const_iterator and "const char*" are 166 | // equivalent types. 167 | #define STD_STRING_ITERATOR_IS_CHAR_POINTER 168 | // The compiler thinks base::string16::const_iterator and "char16*" are 169 | // equivalent types. 170 | #define BASE_STRING16_ITERATOR_IS_CHAR16_POINTER 171 | #endif 172 | 173 | #endif // BUILD_BUILD_CONFIG_H_ 174 | -------------------------------------------------------------------------------- /cdm/media/base/cdm_config.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | #ifndef MEDIA_BASE_CDM_CONFIG_H_ 6 | #define MEDIA_BASE_CDM_CONFIG_H_ 7 | 8 | namespace media { 9 | 10 | // The runtime configuration for new CDM instances as computed by 11 | // |requestMediaKeySystemAccess|. This is in some sense the Chromium-side 12 | // counterpart of Blink's WebMediaKeySystemConfiguration. 13 | struct CdmConfig { 14 | CdmConfig(bool distinctive_identifier=false, bool persistent_state=false) 15 | :allow_distinctive_identifier(distinctive_identifier) 16 | , allow_persistent_state(persistent_state) 17 | , use_hw_secure_codecs(false){}; 18 | 19 | // Allow access to a distinctive identifier. 20 | bool allow_distinctive_identifier; 21 | 22 | // Allow access to persistent state. 23 | bool allow_persistent_state; 24 | 25 | // Use hardware-secure codecs. This flag is only used on Android, it should 26 | // always be false on other platforms. 27 | bool use_hw_secure_codecs; 28 | }; 29 | 30 | } // namespace media 31 | 32 | #endif // MEDIA_BASE_CDM_CONFIG_H_ 33 | -------------------------------------------------------------------------------- /cdm/media/base/limits.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | // Contains limit definition constants for the media subsystem. 6 | 7 | #ifndef MEDIA_BASE_LIMITS_H_ 8 | #define MEDIA_BASE_LIMITS_H_ 9 | 10 | #include "../../base/basictypes.h" 11 | 12 | namespace media { 13 | 14 | namespace limits { 15 | 16 | enum { 17 | // Maximum possible dimension (width or height) for any video. 18 | kMaxDimension = (1 << 15) - 1, // 32767 19 | 20 | // Maximum possible canvas size (width multiplied by height) for any video. 21 | kMaxCanvas = (1 << (14 * 2)), // 16384 x 16384 22 | 23 | // Total number of video frames which are populating in the pipeline. 24 | kMaxVideoFrames = 4, 25 | 26 | // The following limits are used by AudioParameters::IsValid(). 27 | // 28 | // A few notes on sample rates of common formats: 29 | // - AAC files are limited to 96 kHz. 30 | // - MP3 files are limited to 48 kHz. 31 | // - Vorbis used to be limited to 96 KHz, but no longer has that 32 | // restriction. 33 | // - Most PC audio hardware is limited to 192 KHz. 34 | kMaxSampleRate = 192000, 35 | kMinSampleRate = 3000, 36 | kMaxChannels = 32, 37 | kMaxBytesPerSample = 4, 38 | kMaxBitsPerSample = kMaxBytesPerSample * 8, 39 | kMaxSamplesPerPacket = kMaxSampleRate, 40 | kMaxPacketSizeInBytes = 41 | kMaxBytesPerSample * kMaxChannels * kMaxSamplesPerPacket, 42 | 43 | // This limit is used by ParamTraits. 44 | kMaxFramesPerSecond = 1000, 45 | 46 | // Maximum lengths for various EME API parameters. These are checks to 47 | // prevent unnecessarily large parameters from being passed around, and the 48 | // lengths are somewhat arbitrary as the EME spec doesn't specify any limits. 49 | kMinCertificateLength = 128, 50 | kMaxCertificateLength = 16 * 1024, 51 | kMaxSessionIdLength = 512, 52 | kMinKeyIdLength = 1, 53 | kMaxKeyIdLength = 512, 54 | kMaxKeyIds = 128, 55 | kMaxInitDataLength = 64 * 1024, // 64 KB 56 | kMaxSessionResponseLength = 64 * 1024, // 64 KB 57 | kMaxKeySystemLength = 256, 58 | }; 59 | 60 | } // namespace limits 61 | 62 | } // namespace media 63 | 64 | #endif // MEDIA_BASE_LIMITS_H_ 65 | -------------------------------------------------------------------------------- /cdm/media/cdm/api/content_decryption_module.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | #ifndef CDM_CONTENT_DECRYPTION_MODULE_H_ 6 | #define CDM_CONTENT_DECRYPTION_MODULE_H_ 7 | 8 | #include 9 | 10 | #include "content_decryption_module_export.h" 11 | #include "content_decryption_module_proxy.h" 12 | 13 | #if defined(_MSC_VER) 14 | typedef unsigned char uint8_t; 15 | typedef unsigned int uint32_t; 16 | typedef int int32_t; 17 | typedef __int64 int64_t; 18 | #else 19 | #include 20 | #endif 21 | 22 | // The version number must be rolled when the exported functions are updated! 23 | // If the CDM and the adapter use different versions of these functions, the 24 | // adapter will fail to load or crash! 25 | #define CDM_MODULE_VERSION 4 26 | 27 | // Build the versioned entrypoint name. 28 | // The extra macros are necessary to expand version to an actual value. 29 | #define INITIALIZE_CDM_MODULE \ 30 | BUILD_ENTRYPOINT(InitializeCdmModule, CDM_MODULE_VERSION) 31 | #define BUILD_ENTRYPOINT(name, version) \ 32 | BUILD_ENTRYPOINT_NO_EXPANSION(name, version) 33 | #define BUILD_ENTRYPOINT_NO_EXPANSION(name, version) name##_##version 34 | 35 | // Macro to check that |type| does the following: 36 | // 1. is a standard layout. 37 | // 2. is trivial. 38 | // 3. sizeof(type) matches the expected size in bytes. As some types contain 39 | // pointers, the size is specified for both 32 and 64 bit. 40 | #define CHECK_TYPE(type, size_32, size_64) \ 41 | static_assert(std::is_standard_layout(), \ 42 | #type " not standard_layout"); \ 43 | static_assert(std::is_trivial(), #type " not trivial"); \ 44 | static_assert((sizeof(void*) == 4 && sizeof(type) == size_32) || \ 45 | (sizeof(void*) == 8 && sizeof(type) == size_64), \ 46 | #type " size mismatch") 47 | 48 | extern "C" { 49 | 50 | CDM_API void INITIALIZE_CDM_MODULE(); 51 | 52 | CDM_API void DeinitializeCdmModule(); 53 | 54 | // Returns a pointer to the requested CDM Host interface upon success. 55 | // Returns NULL if the requested CDM Host interface is not supported. 56 | // The caller should cast the returned pointer to the type matching 57 | // |host_interface_version|. 58 | typedef void* (*GetCdmHostFunc)(int host_interface_version, void* user_data); 59 | 60 | // Returns a pointer to the requested CDM upon success. 61 | // Returns NULL if an error occurs or the requested |cdm_interface_version| or 62 | // |key_system| is not supported or another error occurs. 63 | // The caller should cast the returned pointer to the type matching 64 | // |cdm_interface_version|. 65 | // Caller retains ownership of arguments and must call Destroy() on the returned 66 | // object. 67 | CDM_API void* CreateCdmInstance(int cdm_interface_version, 68 | const char* key_system, 69 | uint32_t key_system_size, 70 | GetCdmHostFunc get_cdm_host_func, 71 | void* user_data); 72 | 73 | CDM_API const char* GetCdmVersion(); 74 | 75 | } // extern "C" 76 | 77 | namespace cdm { 78 | 79 | enum Status : uint32_t { 80 | kSuccess = 0, 81 | kNeedMoreData, // Decoder needs more data to produce a decoded frame/sample. 82 | kNoKey, // The required decryption key is not available. 83 | kInitializationError, // Initialization error. 84 | kDecryptError, // Decryption failed. 85 | kDecodeError, // Error decoding audio or video. 86 | kDeferredInitialization // Decoder is not ready for initialization. 87 | }; 88 | CHECK_TYPE(Status, 4, 4); 89 | 90 | // Exceptions used by the CDM to reject promises. 91 | // https://w3c.github.io/encrypted-media/#exceptions 92 | enum Exception : uint32_t { 93 | kExceptionTypeError, 94 | kExceptionNotSupportedError, 95 | kExceptionInvalidStateError, 96 | kExceptionQuotaExceededError 97 | }; 98 | CHECK_TYPE(Exception, 4, 4); 99 | 100 | // The encryption scheme. The definitions are from ISO/IEC 23001-7:2016. 101 | enum class EncryptionScheme : uint32_t { 102 | kUnencrypted = 0, 103 | kCenc, // 'cenc' subsample encryption using AES-CTR mode. 104 | kCbcs // 'cbcs' pattern encryption using AES-CBC mode. 105 | }; 106 | CHECK_TYPE(EncryptionScheme, 4, 4); 107 | 108 | // The pattern used for pattern encryption. Note that ISO/IEC 23001-7:2016 109 | // defines each block to be 16-bytes. 110 | struct Pattern { 111 | uint32_t crypt_byte_block; // Count of the encrypted blocks. 112 | uint32_t skip_byte_block; // Count of the unencrypted blocks. 113 | }; 114 | CHECK_TYPE(Pattern, 8, 8); 115 | 116 | enum class ColorRange : uint8_t { 117 | kInvalid, 118 | kLimited, // 709 color range with RGB values ranging from 16 to 235. 119 | kFull, // Full RGB color range with RGB values from 0 to 255. 120 | kDerived // Range is defined by |transfer_id| and |matrix_id|. 121 | }; 122 | CHECK_TYPE(ColorRange, 1, 1); 123 | 124 | // Described in ISO 23001-8:2016, section 7. All the IDs are in the range 125 | // [0, 255] so 8-bit integer is sufficient. An unspecified ColorSpace should be 126 | // {2, 2, 2, ColorRange::kInvalid}, where value 2 means "Unspecified" for all 127 | // the IDs, as defined by the spec. 128 | struct ColorSpace { 129 | uint8_t primary_id; // 7.1 colour primaries, table 2 130 | uint8_t transfer_id; // 7.2 transfer characteristics, table 3 131 | uint8_t matrix_id; // 7.3 matrix coefficients, table 4 132 | ColorRange range; 133 | }; 134 | CHECK_TYPE(ColorSpace, 4, 4); 135 | 136 | // Time is defined as the number of seconds since the Epoch 137 | // (00:00:00 UTC, January 1, 1970), not including any added leap second. 138 | // Also see Time definition in spec: https://w3c.github.io/encrypted-media/#time 139 | // Note that Time is defined in millisecond accuracy in the spec but in second 140 | // accuracy here. 141 | typedef double Time; 142 | 143 | // An input buffer can be split into several continuous subsamples. 144 | // A SubsampleEntry specifies the number of clear and cipher bytes in each 145 | // subsample. For example, the following buffer has three subsamples: 146 | // 147 | // |<----- subsample1 ----->|<----- subsample2 ----->|<----- subsample3 ----->| 148 | // | clear1 | cipher1 | clear2 | cipher2 | clear3 | cipher3 | 149 | // 150 | // For decryption, all of the cipher bytes in a buffer should be concatenated 151 | // (in the subsample order) into a single logical stream. The clear bytes should 152 | // not be considered as part of decryption. 153 | // 154 | // Stream to decrypt: | cipher1 | cipher2 | cipher3 | 155 | // Decrypted stream: | decrypted1| decrypted2 | decrypted3 | 156 | // 157 | // After decryption, the decrypted bytes should be copied over the position 158 | // of the corresponding cipher bytes in the original buffer to form the output 159 | // buffer. Following the above example, the decrypted buffer should be: 160 | // 161 | // |<----- subsample1 ----->|<----- subsample2 ----->|<----- subsample3 ----->| 162 | // | clear1 | decrypted1| clear2 | decrypted2 | clear3 | decrypted3 | 163 | // 164 | struct SubsampleEntry { 165 | uint32_t clear_bytes; 166 | uint32_t cipher_bytes; 167 | }; 168 | CHECK_TYPE(SubsampleEntry, 8, 8); 169 | 170 | // Represents an input buffer to be decrypted (and possibly decoded). It does 171 | // not own any pointers in this struct. If |iv_size| = 0, the data is 172 | // unencrypted. 173 | // Deprecated: New CDM implementations should use InputBuffer_2. 174 | struct InputBuffer_1 { 175 | const uint8_t* data; // Pointer to the beginning of the input data. 176 | uint32_t data_size; // Size (in bytes) of |data|. 177 | 178 | const uint8_t* key_id; // Key ID to identify the decryption key. 179 | uint32_t key_id_size; // Size (in bytes) of |key_id|. 180 | 181 | const uint8_t* iv; // Initialization vector. 182 | uint32_t iv_size; // Size (in bytes) of |iv|. 183 | 184 | const struct SubsampleEntry* subsamples; 185 | uint32_t num_subsamples; // Number of subsamples in |subsamples|. 186 | 187 | int64_t timestamp; // Presentation timestamp in microseconds. 188 | }; 189 | CHECK_TYPE(InputBuffer_1, 40, 72); 190 | 191 | // Represents an input buffer to be decrypted (and possibly decoded). It does 192 | // not own any pointers in this struct. If |encryption_scheme| = kUnencrypted, 193 | // the data is unencrypted. 194 | // Note that this struct is organized so that sizeof(InputBuffer_2) 195 | // equals the sum of sizeof() all members in both 32-bit and 64-bit compiles. 196 | // Padding has been added to keep the fields aligned. 197 | struct InputBuffer_2 { 198 | const uint8_t* data; // Pointer to the beginning of the input data. 199 | uint32_t data_size; // Size (in bytes) of |data|. 200 | 201 | EncryptionScheme encryption_scheme; 202 | 203 | const uint8_t* key_id; // Key ID to identify the decryption key. 204 | uint32_t key_id_size; // Size (in bytes) of |key_id|. 205 | uint32_t : 32; // Padding. 206 | 207 | const uint8_t* iv; // Initialization vector. 208 | uint32_t iv_size; // Size (in bytes) of |iv|. 209 | uint32_t : 32; // Padding. 210 | 211 | const struct SubsampleEntry* subsamples; 212 | uint32_t num_subsamples; // Number of subsamples in |subsamples|. 213 | uint32_t : 32; // Padding. 214 | 215 | // |pattern| is required if |encryption_scheme| specifies pattern encryption. 216 | Pattern pattern; 217 | 218 | int64_t timestamp; // Presentation timestamp in microseconds. 219 | }; 220 | CHECK_TYPE(InputBuffer_2, 64, 80); 221 | 222 | enum AudioCodec : uint32_t { kUnknownAudioCodec = 0, kCodecVorbis, kCodecAac }; 223 | CHECK_TYPE(AudioCodec, 4, 4); 224 | 225 | // Deprecated: New CDM implementations should use AudioDecoderConfig_2. 226 | struct AudioDecoderConfig_1 { 227 | AudioCodec codec; 228 | int32_t channel_count; 229 | int32_t bits_per_channel; 230 | int32_t samples_per_second; 231 | 232 | // Optional byte data required to initialize audio decoders, such as the 233 | // vorbis setup header. 234 | uint8_t* extra_data; 235 | uint32_t extra_data_size; 236 | }; 237 | CHECK_TYPE(AudioDecoderConfig_1, 24, 32); 238 | 239 | struct AudioDecoderConfig_2 { 240 | AudioCodec codec; 241 | int32_t channel_count; 242 | int32_t bits_per_channel; 243 | int32_t samples_per_second; 244 | 245 | // Optional byte data required to initialize audio decoders, such as the 246 | // vorbis setup header. 247 | uint8_t* extra_data; 248 | uint32_t extra_data_size; 249 | 250 | // Encryption scheme. 251 | EncryptionScheme encryption_scheme; 252 | }; 253 | CHECK_TYPE(AudioDecoderConfig_2, 28, 32); 254 | 255 | // Supported sample formats for AudioFrames. 256 | enum AudioFormat : uint32_t { 257 | kUnknownAudioFormat = 0, // Unknown format value. Used for error reporting. 258 | kAudioFormatU8, // Interleaved unsigned 8-bit w/ bias of 128. 259 | kAudioFormatS16, // Interleaved signed 16-bit. 260 | kAudioFormatS32, // Interleaved signed 32-bit. 261 | kAudioFormatF32, // Interleaved float 32-bit. 262 | kAudioFormatPlanarS16, // Signed 16-bit planar. 263 | kAudioFormatPlanarF32, // Float 32-bit planar. 264 | }; 265 | CHECK_TYPE(AudioFormat, 4, 4); 266 | 267 | // Surface formats based on FOURCC labels, see: http://www.fourcc.org/yuv.php 268 | // Values are chosen to be consistent with Chromium's VideoPixelFormat values. 269 | enum VideoFormat : uint32_t { 270 | kUnknownVideoFormat = 0, // Unknown format value. Used for error reporting. 271 | kYv12 = 1, // 12bpp YVU planar 1x1 Y, 2x2 VU samples. 272 | kI420 = 2, // 12bpp YUV planar 1x1 Y, 2x2 UV samples. 273 | 274 | // In the following formats, each sample uses 16-bit in storage, while the 275 | // sample value is stored in the least significant N bits where N is 276 | // specified by the number after "P". For example, for YUV420P9, each Y, U, 277 | // and V sample is stored in the least significant 9 bits in a 2-byte block. 278 | kYUV420P9 = 16, 279 | kYUV420P10 = 17, 280 | kYUV422P9 = 18, 281 | kYUV422P10 = 19, 282 | kYUV444P9 = 20, 283 | kYUV444P10 = 21, 284 | kYUV420P12 = 22, 285 | kYUV422P12 = 23, 286 | kYUV444P12 = 24, 287 | }; 288 | CHECK_TYPE(VideoFormat, 4, 4); 289 | 290 | struct Size { 291 | int32_t width; 292 | int32_t height; 293 | }; 294 | CHECK_TYPE(Size, 8, 8); 295 | 296 | enum VideoCodec : uint32_t { 297 | kUnknownVideoCodec = 0, 298 | kCodecVp8, 299 | kCodecH264, 300 | kCodecVp9, 301 | kCodecAv1 302 | }; 303 | CHECK_TYPE(VideoCodec, 4, 4); 304 | 305 | enum VideoCodecProfile : uint32_t { 306 | kUnknownVideoCodecProfile = 0, 307 | kProfileNotNeeded, 308 | kH264ProfileBaseline, 309 | kH264ProfileMain, 310 | kH264ProfileExtended, 311 | kH264ProfileHigh, 312 | kH264ProfileHigh10, 313 | kH264ProfileHigh422, 314 | kH264ProfileHigh444Predictive, 315 | // VP9 Profiles are only passed in starting from CDM_9. 316 | kVP9Profile0, 317 | kVP9Profile1, 318 | kVP9Profile2, 319 | kVP9Profile3, 320 | kAv1ProfileMain, 321 | kAv1ProfileHigh, 322 | kAv1ProfilePro 323 | }; 324 | CHECK_TYPE(VideoCodecProfile, 4, 4); 325 | 326 | // Deprecated: New CDM implementations should use VideoDecoderConfig_3. 327 | struct VideoDecoderConfig_1 { 328 | VideoCodec codec; 329 | VideoCodecProfile profile; 330 | VideoFormat format; 331 | 332 | // Width and height of video frame immediately post-decode. Not all pixels 333 | // in this region are valid. 334 | Size coded_size; 335 | 336 | // Optional byte data required to initialize video decoders, such as H.264 337 | // AAVC data. 338 | uint8_t* extra_data; 339 | uint32_t extra_data_size; 340 | }; 341 | CHECK_TYPE(VideoDecoderConfig_1, 28, 40); 342 | 343 | // Deprecated: New CDM implementations should use VideoDecoderConfig_3. 344 | // Note that this struct is organized so that sizeof(VideoDecoderConfig_2) 345 | // equals the sum of sizeof() all members in both 32-bit and 64-bit compiles. 346 | // Padding has been added to keep the fields aligned. 347 | struct VideoDecoderConfig_2 { 348 | VideoCodec codec; 349 | VideoCodecProfile profile; 350 | VideoFormat format; 351 | uint32_t : 32; // Padding. 352 | 353 | // Width and height of video frame immediately post-decode. Not all pixels 354 | // in this region are valid. 355 | Size coded_size; 356 | 357 | // Optional byte data required to initialize video decoders, such as H.264 358 | // AAVC data. 359 | uint8_t* extra_data; 360 | uint32_t extra_data_size; 361 | 362 | // Encryption scheme. 363 | EncryptionScheme encryption_scheme; 364 | }; 365 | CHECK_TYPE(VideoDecoderConfig_2, 36, 40); 366 | 367 | struct VideoDecoderConfig_3 { 368 | VideoCodec codec; 369 | VideoCodecProfile profile; 370 | VideoFormat format; 371 | ColorSpace color_space; 372 | 373 | // Width and height of video frame immediately post-decode. Not all pixels 374 | // in this region are valid. 375 | Size coded_size; 376 | 377 | // Optional byte data required to initialize video decoders, such as H.264 378 | // AAVC data. 379 | uint8_t* extra_data; 380 | uint32_t extra_data_size; 381 | 382 | EncryptionScheme encryption_scheme; 383 | }; 384 | CHECK_TYPE(VideoDecoderConfig_3, 36, 40); 385 | 386 | enum StreamType : uint32_t { kStreamTypeAudio = 0, kStreamTypeVideo = 1 }; 387 | CHECK_TYPE(StreamType, 4, 4); 388 | 389 | // Structure provided to ContentDecryptionModule::OnPlatformChallengeResponse() 390 | // after a platform challenge was initiated via Host::SendPlatformChallenge(). 391 | // All values will be NULL / zero in the event of a challenge failure. 392 | struct PlatformChallengeResponse { 393 | // |challenge| provided during Host::SendPlatformChallenge() combined with 394 | // nonce data and signed with the platform's private key. 395 | const uint8_t* signed_data; 396 | uint32_t signed_data_length; 397 | 398 | // RSASSA-PKCS1-v1_5-SHA256 signature of the |signed_data| block. 399 | const uint8_t* signed_data_signature; 400 | uint32_t signed_data_signature_length; 401 | 402 | // X.509 device specific certificate for the |service_id| requested. 403 | const uint8_t* platform_key_certificate; 404 | uint32_t platform_key_certificate_length; 405 | }; 406 | CHECK_TYPE(PlatformChallengeResponse, 24, 48); 407 | 408 | // The current status of the associated key. The valid types are defined in the 409 | // spec: https://w3c.github.io/encrypted-media/#idl-def-MediaKeyStatus 410 | enum KeyStatus : uint32_t { 411 | kUsable = 0, 412 | kInternalError = 1, 413 | kExpired = 2, 414 | kOutputRestricted = 3, 415 | kOutputDownscaled = 4, 416 | kStatusPending = 5, 417 | kReleased = 6 418 | }; 419 | CHECK_TYPE(KeyStatus, 4, 4); 420 | 421 | // Used when passing arrays of key information. Does not own the referenced 422 | // data. |system_code| is an additional error code for unusable keys and 423 | // should be 0 when |status| == kUsable. 424 | struct KeyInformation { 425 | const uint8_t* key_id; 426 | uint32_t key_id_size; 427 | KeyStatus status; 428 | uint32_t system_code; 429 | }; 430 | CHECK_TYPE(KeyInformation, 16, 24); 431 | 432 | // Supported output protection methods for use with EnableOutputProtection() and 433 | // returned by OnQueryOutputProtectionStatus(). 434 | enum OutputProtectionMethods : uint32_t { 435 | kProtectionNone = 0, 436 | kProtectionHDCP = 1 << 0 437 | }; 438 | CHECK_TYPE(OutputProtectionMethods, 4, 4); 439 | 440 | // Connected output link types returned by OnQueryOutputProtectionStatus(). 441 | enum OutputLinkTypes : uint32_t { 442 | kLinkTypeNone = 0, 443 | kLinkTypeUnknown = 1 << 0, 444 | kLinkTypeInternal = 1 << 1, 445 | kLinkTypeVGA = 1 << 2, 446 | kLinkTypeHDMI = 1 << 3, 447 | kLinkTypeDVI = 1 << 4, 448 | kLinkTypeDisplayPort = 1 << 5, 449 | kLinkTypeNetwork = 1 << 6 450 | }; 451 | CHECK_TYPE(OutputLinkTypes, 4, 4); 452 | 453 | // Result of the QueryOutputProtectionStatus() call. 454 | enum QueryResult : uint32_t { kQuerySucceeded = 0, kQueryFailed }; 455 | CHECK_TYPE(QueryResult, 4, 4); 456 | 457 | // The Initialization Data Type. The valid types are defined in the spec: 458 | // https://w3c.github.io/encrypted-media/format-registry/initdata/index.html#registry 459 | enum InitDataType : uint32_t { kCenc = 0, kKeyIds = 1, kWebM = 2 }; 460 | CHECK_TYPE(InitDataType, 4, 4); 461 | 462 | // The type of session to create. The valid types are defined in the spec: 463 | // https://w3c.github.io/encrypted-media/#idl-def-SessionType 464 | enum SessionType : uint32_t { 465 | kTemporary = 0, 466 | kPersistentLicense = 1, 467 | kPersistentUsageRecord = 2 468 | }; 469 | CHECK_TYPE(SessionType, 4, 4); 470 | 471 | // The type of the message event. The valid types are defined in the spec: 472 | // https://w3c.github.io/encrypted-media/#idl-def-MediaKeyMessageType 473 | enum MessageType : uint32_t { 474 | kLicenseRequest = 0, 475 | kLicenseRenewal = 1, 476 | kLicenseRelease = 2, 477 | // Only supported by Host_10 and later. On Host_9 and earlier, it's undefined 478 | // behavior. For example, the host can drop the message or send it using 479 | // other message type. 480 | kIndividualizationRequest = 3 481 | }; 482 | CHECK_TYPE(MessageType, 4, 4); 483 | 484 | enum HdcpVersion : uint32_t { 485 | kHdcpVersionNone, 486 | kHdcpVersion1_0, 487 | kHdcpVersion1_1, 488 | kHdcpVersion1_2, 489 | kHdcpVersion1_3, 490 | kHdcpVersion1_4, 491 | kHdcpVersion2_0, 492 | kHdcpVersion2_1, 493 | kHdcpVersion2_2, 494 | kHdcpVersion2_3 495 | }; 496 | CHECK_TYPE(HdcpVersion, 4, 4); 497 | 498 | struct Policy { 499 | HdcpVersion min_hdcp_version; 500 | }; 501 | CHECK_TYPE(Policy, 4, 4); 502 | 503 | // Represents a buffer created by Allocator implementations. 504 | class CDM_CLASS_API Buffer { 505 | public: 506 | // Destroys the buffer in the same context as it was created. 507 | virtual void Destroy() = 0; 508 | 509 | virtual uint32_t Capacity() const = 0; 510 | virtual uint8_t* Data() = 0; 511 | virtual void SetSize(uint32_t size) = 0; 512 | virtual uint32_t Size() const = 0; 513 | 514 | protected: 515 | Buffer() {} 516 | virtual ~Buffer() {} 517 | 518 | private: 519 | Buffer(const Buffer&); 520 | void operator=(const Buffer&); 521 | }; 522 | 523 | // Represents a decrypted block that has not been decoded. 524 | class CDM_CLASS_API DecryptedBlock { 525 | public: 526 | virtual void SetDecryptedBuffer(Buffer* buffer) = 0; 527 | virtual Buffer* DecryptedBuffer() = 0; 528 | 529 | // TODO(tomfinegan): Figure out if timestamp is really needed. If it is not, 530 | // we can just pass Buffer pointers around. 531 | virtual void SetTimestamp(int64_t timestamp) = 0; 532 | virtual int64_t Timestamp() const = 0; 533 | 534 | protected: 535 | DecryptedBlock() {} 536 | virtual ~DecryptedBlock() {} 537 | }; 538 | 539 | enum VideoPlane : uint32_t { 540 | kYPlane = 0, 541 | kUPlane = 1, 542 | kVPlane = 2, 543 | kMaxPlanes = 3, 544 | }; 545 | CHECK_TYPE(VideoPlane, 4, 4); 546 | 547 | class CDM_CLASS_API VideoFrame { 548 | public: 549 | virtual void SetFormat(VideoFormat format) = 0; 550 | virtual VideoFormat Format() const = 0; 551 | 552 | virtual void SetSize(cdm::Size size) = 0; 553 | virtual cdm::Size Size() const = 0; 554 | 555 | virtual void SetFrameBuffer(Buffer* frame_buffer) = 0; 556 | virtual Buffer* FrameBuffer() = 0; 557 | 558 | virtual void SetPlaneOffset(VideoPlane plane, uint32_t offset) = 0; 559 | virtual uint32_t PlaneOffset(VideoPlane plane) = 0; 560 | 561 | virtual void SetStride(VideoPlane plane, uint32_t stride) = 0; 562 | virtual uint32_t Stride(VideoPlane plane) = 0; 563 | 564 | // Sets and gets the presentation timestamp which is in microseconds. 565 | virtual void SetTimestamp(int64_t timestamp) = 0; 566 | virtual int64_t Timestamp() const = 0; 567 | 568 | protected: 569 | VideoFrame() {} 570 | virtual ~VideoFrame() {} 571 | }; 572 | 573 | // Represents a decoded video frame. The CDM should call the interface methods 574 | // to set the frame attributes. See DecryptAndDecodeFrame(). 575 | class CDM_CLASS_API VideoFrame_2 { 576 | public: 577 | virtual void SetFormat(VideoFormat format) = 0; 578 | virtual void SetSize(cdm::Size size) = 0; 579 | virtual void SetFrameBuffer(Buffer* frame_buffer) = 0; 580 | virtual void SetPlaneOffset(VideoPlane plane, uint32_t offset) = 0; 581 | virtual void SetStride(VideoPlane plane, uint32_t stride) = 0; 582 | // Sets the presentation timestamp which is in microseconds. 583 | virtual void SetTimestamp(int64_t timestamp) = 0; 584 | virtual void SetColorSpace(ColorSpace color_space) = 0; 585 | 586 | protected: 587 | VideoFrame_2() {} 588 | virtual ~VideoFrame_2() {} 589 | }; 590 | 591 | // Represents decrypted and decoded audio frames. AudioFrames can contain 592 | // multiple audio output buffers, which are serialized into this format: 593 | // 594 | // |<------------------- serialized audio buffer ------------------->| 595 | // | int64_t timestamp | int64_t length | length bytes of audio data | 596 | // 597 | // For example, with three audio output buffers, the AudioFrames will look 598 | // like this: 599 | // 600 | // |<----------------- AudioFrames ------------------>| 601 | // | audio buffer 0 | audio buffer 1 | audio buffer 2 | 602 | class CDM_CLASS_API AudioFrames { 603 | public: 604 | virtual void SetFrameBuffer(Buffer* buffer) = 0; 605 | virtual Buffer* FrameBuffer() = 0; 606 | 607 | // The CDM must call this method, providing a valid format, when providing 608 | // frame buffers. Planar data should be stored end to end; e.g., 609 | // |ch1 sample1||ch1 sample2|....|ch1 sample_last||ch2 sample1|... 610 | virtual void SetFormat(AudioFormat format) = 0; 611 | virtual AudioFormat Format() const = 0; 612 | 613 | protected: 614 | AudioFrames() {} 615 | virtual ~AudioFrames() {} 616 | }; 617 | 618 | // FileIO interface provides a way for the CDM to store data in a file in 619 | // persistent storage. This interface aims only at providing basic read/write 620 | // capabilities and should not be used as a full fledged file IO API. 621 | // Each CDM and origin (e.g. HTTPS, "foo.example.com", 443) combination has 622 | // its own persistent storage. All instances of a given CDM associated with a 623 | // given origin share the same persistent storage. 624 | // Note to implementors of this interface: 625 | // Per-origin storage and the ability for users to clear it are important. 626 | // See http://www.w3.org/TR/encrypted-media/#privacy-storedinfo. 627 | class CDM_CLASS_API FileIO { 628 | public: 629 | // Opens the file with |file_name| for read and write. 630 | // FileIOClient::OnOpenComplete() will be called after the opening 631 | // operation finishes. 632 | // - When the file is opened by a CDM instance, it will be classified as "in 633 | // use". In this case other CDM instances in the same domain may receive 634 | // kInUse status when trying to open it. 635 | // - |file_name| must only contain letters (A-Za-z), digits(0-9), or "._-". 636 | // It must not start with an underscore ('_'), and must be at least 1 637 | // character and no more than 256 characters long. 638 | virtual void Open(const char* file_name, uint32_t file_name_size) = 0; 639 | 640 | // Reads the contents of the file. FileIOClient::OnReadComplete() will be 641 | // called with the read status. Read() should not be called if a previous 642 | // Read() or Write() call is still pending; otherwise OnReadComplete() will 643 | // be called with kInUse. 644 | virtual void Read() = 0; 645 | 646 | // Writes |data_size| bytes of |data| into the file. 647 | // FileIOClient::OnWriteComplete() will be called with the write status. 648 | // All existing contents in the file will be overwritten. Calling Write() with 649 | // NULL |data| will clear all contents in the file. Write() should not be 650 | // called if a previous Write() or Read() call is still pending; otherwise 651 | // OnWriteComplete() will be called with kInUse. 652 | virtual void Write(const uint8_t* data, uint32_t data_size) = 0; 653 | 654 | // Closes the file if opened, destroys this FileIO object and releases any 655 | // resources allocated. The CDM must call this method when it finished using 656 | // this object. A FileIO object must not be used after Close() is called. 657 | virtual void Close() = 0; 658 | 659 | protected: 660 | FileIO() {} 661 | virtual ~FileIO() {} 662 | }; 663 | 664 | // Responses to FileIO calls. All responses will be called asynchronously. 665 | // When kError is returned, the FileIO object could be in an error state. All 666 | // following calls (other than Close()) could return kError. The CDM should 667 | // still call Close() to destroy the FileIO object. 668 | class CDM_CLASS_API FileIOClient { 669 | public: 670 | enum class Status : uint32_t { kSuccess = 0, kInUse, kError }; 671 | 672 | // Response to a FileIO::Open() call with the open |status|. 673 | virtual void OnOpenComplete(Status status) = 0; 674 | 675 | // Response to a FileIO::Read() call to provide |data_size| bytes of |data| 676 | // read from the file. 677 | // - kSuccess indicates that all contents of the file has been successfully 678 | // read. In this case, 0 |data_size| means that the file is empty. 679 | // - kInUse indicates that there are other read/write operations pending. 680 | // - kError indicates read failure, e.g. the storage is not open or cannot be 681 | // fully read. 682 | virtual void OnReadComplete(Status status, 683 | const uint8_t* data, 684 | uint32_t data_size) = 0; 685 | 686 | // Response to a FileIO::Write() call. 687 | // - kSuccess indicates that all the data has been written into the file 688 | // successfully. 689 | // - kInUse indicates that there are other read/write operations pending. 690 | // - kError indicates write failure, e.g. the storage is not open or cannot be 691 | // fully written. Upon write failure, the contents of the file should be 692 | // regarded as corrupt and should not used. 693 | virtual void OnWriteComplete(Status status) = 0; 694 | 695 | protected: 696 | FileIOClient() {} 697 | virtual ~FileIOClient() {} 698 | }; 699 | 700 | class CDM_CLASS_API Host_9; 701 | class CDM_CLASS_API Host_10; 702 | class CDM_CLASS_API Host_11; 703 | 704 | // ContentDecryptionModule interface that all CDMs need to implement. 705 | // The interface is versioned for backward compatibility. 706 | // Note: ContentDecryptionModule implementations must use the allocator 707 | // provided in CreateCdmInstance() to allocate any Buffer that needs to 708 | // be passed back to the caller. Implementations must call Buffer::Destroy() 709 | // when a Buffer is created that will never be returned to the caller. 710 | class CDM_CLASS_API ContentDecryptionModule_9 { 711 | public: 712 | static const int kVersion = 9; 713 | typedef Host_9 Host; 714 | 715 | // Initializes the CDM instance, providing information about permitted 716 | // functionalities. 717 | // If |allow_distinctive_identifier| is false, messages from the CDM, 718 | // such as message events, must not contain a Distinctive Identifier, 719 | // even in an encrypted form. 720 | // If |allow_persistent_state| is false, the CDM must not attempt to 721 | // persist state. Calls to CreateFileIO() will fail. 722 | virtual void Initialize(bool allow_distinctive_identifier, 723 | bool allow_persistent_state) = 0; 724 | 725 | // Gets the key status if the CDM has a hypothetical key with the |policy|. 726 | // The CDM must respond by calling either Host::OnResolveKeyStatusPromise() 727 | // with the result key status or Host::OnRejectPromise() if an unexpected 728 | // error happened or this method is not supported. 729 | virtual void GetStatusForPolicy(uint32_t promise_id, 730 | const Policy& policy) = 0; 731 | 732 | // SetServerCertificate(), CreateSessionAndGenerateRequest(), LoadSession(), 733 | // UpdateSession(), CloseSession(), and RemoveSession() all accept a 734 | // |promise_id|, which must be passed to the completion Host method 735 | // (e.g. Host::OnResolveNewSessionPromise()). 736 | 737 | // Provides a server certificate to be used to encrypt messages to the 738 | // license server. The CDM must respond by calling either 739 | // Host::OnResolvePromise() or Host::OnRejectPromise(). 740 | virtual void SetServerCertificate(uint32_t promise_id, 741 | const uint8_t* server_certificate_data, 742 | uint32_t server_certificate_data_size) = 0; 743 | 744 | // Creates a session given |session_type|, |init_data_type|, and |init_data|. 745 | // The CDM must respond by calling either Host::OnResolveNewSessionPromise() 746 | // or Host::OnRejectPromise(). 747 | virtual void CreateSessionAndGenerateRequest(uint32_t promise_id, 748 | SessionType session_type, 749 | InitDataType init_data_type, 750 | const uint8_t* init_data, 751 | uint32_t init_data_size) = 0; 752 | 753 | // Loads the session of type |session_type| specified by |session_id|. 754 | // The CDM must respond by calling either Host::OnResolveNewSessionPromise() 755 | // or Host::OnRejectPromise(). If the session is not found, call 756 | // Host::OnResolveNewSessionPromise() with session_id = NULL. 757 | virtual void LoadSession(uint32_t promise_id, 758 | SessionType session_type, 759 | const char* session_id, 760 | uint32_t session_id_size) = 0; 761 | 762 | // Updates the session with |response|. The CDM must respond by calling 763 | // either Host::OnResolvePromise() or Host::OnRejectPromise(). 764 | virtual void UpdateSession(uint32_t promise_id, 765 | const char* session_id, 766 | uint32_t session_id_size, 767 | const uint8_t* response, 768 | uint32_t response_size) = 0; 769 | 770 | // Requests that the CDM close the session. The CDM must respond by calling 771 | // either Host::OnResolvePromise() or Host::OnRejectPromise() when the request 772 | // has been processed. This may be before the session is closed. Once the 773 | // session is closed, Host::OnSessionClosed() must also be called. 774 | virtual void CloseSession(uint32_t promise_id, 775 | const char* session_id, 776 | uint32_t session_id_size) = 0; 777 | 778 | // Removes any stored session data associated with this session. Will only be 779 | // called for persistent sessions. The CDM must respond by calling either 780 | // Host::OnResolvePromise() or Host::OnRejectPromise() when the request has 781 | // been processed. 782 | virtual void RemoveSession(uint32_t promise_id, 783 | const char* session_id, 784 | uint32_t session_id_size) = 0; 785 | 786 | // Performs scheduled operation with |context| when the timer fires. 787 | virtual void TimerExpired(void* context) = 0; 788 | 789 | // Decrypts the |encrypted_buffer|. 790 | // 791 | // Returns kSuccess if decryption succeeded, in which case the callee 792 | // should have filled the |decrypted_buffer| and passed the ownership of 793 | // |data| in |decrypted_buffer| to the caller. 794 | // Returns kNoKey if the CDM did not have the necessary decryption key 795 | // to decrypt. 796 | // Returns kDecryptError if any other error happened. 797 | // If the return value is not kSuccess, |decrypted_buffer| should be ignored 798 | // by the caller. 799 | virtual Status Decrypt(const InputBuffer_1& encrypted_buffer, 800 | DecryptedBlock* decrypted_buffer) = 0; 801 | 802 | // Initializes the CDM audio decoder with |audio_decoder_config|. This 803 | // function must be called before DecryptAndDecodeSamples() is called. 804 | // 805 | // Returns kSuccess if the |audio_decoder_config| is supported and the CDM 806 | // audio decoder is successfully initialized. 807 | // Returns kInitializationError if |audio_decoder_config| is not supported. 808 | // The CDM may still be able to do Decrypt(). 809 | // Returns kDeferredInitialization if the CDM is not ready to initialize the 810 | // decoder at this time. Must call Host::OnDeferredInitializationDone() once 811 | // initialization is complete. 812 | virtual Status InitializeAudioDecoder( 813 | const AudioDecoderConfig_1& audio_decoder_config) = 0; 814 | 815 | // Initializes the CDM video decoder with |video_decoder_config|. This 816 | // function must be called before DecryptAndDecodeFrame() is called. 817 | // 818 | // Returns kSuccess if the |video_decoder_config| is supported and the CDM 819 | // video decoder is successfully initialized. 820 | // Returns kInitializationError if |video_decoder_config| is not supported. 821 | // The CDM may still be able to do Decrypt(). 822 | // Returns kDeferredInitialization if the CDM is not ready to initialize the 823 | // decoder at this time. Must call Host::OnDeferredInitializationDone() once 824 | // initialization is complete. 825 | virtual Status InitializeVideoDecoder( 826 | const VideoDecoderConfig_1& video_decoder_config) = 0; 827 | 828 | // De-initializes the CDM decoder and sets it to an uninitialized state. The 829 | // caller can initialize the decoder again after this call to re-initialize 830 | // it. This can be used to reconfigure the decoder if the configuration 831 | // changes. 832 | virtual void DeinitializeDecoder(StreamType decoder_type) = 0; 833 | 834 | // Resets the CDM decoder to an initialized clean state. All internal buffers 835 | // MUST be flushed. 836 | virtual void ResetDecoder(StreamType decoder_type) = 0; 837 | 838 | // Decrypts the |encrypted_buffer| and decodes the decrypted buffer into a 839 | // |video_frame|. Upon end-of-stream, the caller should call this function 840 | // repeatedly with empty |encrypted_buffer| (|data| == NULL) until 841 | // kNeedMoreData is returned. 842 | // 843 | // Returns kSuccess if decryption and decoding both succeeded, in which case 844 | // the callee will have filled the |video_frame| and passed the ownership of 845 | // |frame_buffer| in |video_frame| to the caller. 846 | // Returns kNoKey if the CDM did not have the necessary decryption key 847 | // to decrypt. 848 | // Returns kNeedMoreData if more data was needed by the decoder to generate 849 | // a decoded frame (e.g. during initialization and end-of-stream). 850 | // Returns kDecryptError if any decryption error happened. 851 | // Returns kDecodeError if any decoding error happened. 852 | // If the return value is not kSuccess, |video_frame| should be ignored by 853 | // the caller. 854 | virtual Status DecryptAndDecodeFrame(const InputBuffer_1& encrypted_buffer, 855 | VideoFrame* video_frame) = 0; 856 | 857 | // Decrypts the |encrypted_buffer| and decodes the decrypted buffer into 858 | // |audio_frames|. Upon end-of-stream, the caller should call this function 859 | // repeatedly with empty |encrypted_buffer| (|data| == NULL) until only empty 860 | // |audio_frames| is produced. 861 | // 862 | // Returns kSuccess if decryption and decoding both succeeded, in which case 863 | // the callee will have filled |audio_frames| and passed the ownership of 864 | // |data| in |audio_frames| to the caller. 865 | // Returns kNoKey if the CDM did not have the necessary decryption key 866 | // to decrypt. 867 | // Returns kNeedMoreData if more data was needed by the decoder to generate 868 | // audio samples (e.g. during initialization and end-of-stream). 869 | // Returns kDecryptError if any decryption error happened. 870 | // Returns kDecodeError if any decoding error happened. 871 | // If the return value is not kSuccess, |audio_frames| should be ignored by 872 | // the caller. 873 | virtual Status DecryptAndDecodeSamples(const InputBuffer_1& encrypted_buffer, 874 | AudioFrames* audio_frames) = 0; 875 | 876 | // Called by the host after a platform challenge was initiated via 877 | // Host::SendPlatformChallenge(). 878 | virtual void OnPlatformChallengeResponse( 879 | const PlatformChallengeResponse& response) = 0; 880 | 881 | // Called by the host after a call to Host::QueryOutputProtectionStatus(). The 882 | // |link_mask| is a bit mask of OutputLinkTypes and |output_protection_mask| 883 | // is a bit mask of OutputProtectionMethods. If |result| is kQueryFailed, 884 | // then |link_mask| and |output_protection_mask| are undefined and should 885 | // be ignored. 886 | virtual void OnQueryOutputProtectionStatus( 887 | QueryResult result, 888 | uint32_t link_mask, 889 | uint32_t output_protection_mask) = 0; 890 | 891 | // Called by the host after a call to Host::RequestStorageId(). If the 892 | // version of the storage ID requested is available, |storage_id| and 893 | // |storage_id_size| are set appropriately. |version| will be the same as 894 | // what was requested, unless 0 (latest) was requested, in which case 895 | // |version| will be the actual version number for the |storage_id| returned. 896 | // If the requested version is not available, null/zero will be provided as 897 | // |storage_id| and |storage_id_size|, respectively, and |version| should be 898 | // ignored. 899 | virtual void OnStorageId(uint32_t version, 900 | const uint8_t* storage_id, 901 | uint32_t storage_id_size) = 0; 902 | 903 | // Destroys the object in the same context as it was created. 904 | virtual void Destroy() = 0; 905 | 906 | protected: 907 | ContentDecryptionModule_9() {} 908 | virtual ~ContentDecryptionModule_9() {} 909 | }; 910 | 911 | // ContentDecryptionModule interface that all CDMs need to implement. 912 | // The interface is versioned for backward compatibility. 913 | // Note: ContentDecryptionModule implementations must use the allocator 914 | // provided in CreateCdmInstance() to allocate any Buffer that needs to 915 | // be passed back to the caller. Implementations must call Buffer::Destroy() 916 | // when a Buffer is created that will never be returned to the caller. 917 | class CDM_CLASS_API ContentDecryptionModule_10 { 918 | public: 919 | static const int kVersion = 10; 920 | static const bool kIsStable = true; 921 | typedef Host_10 Host; 922 | 923 | // Initializes the CDM instance, providing information about permitted 924 | // functionalities. The CDM must respond by calling Host::OnInitialized() 925 | // with whether the initialization succeeded. No other calls will be made by 926 | // the host before Host::OnInitialized() returns. 927 | // If |allow_distinctive_identifier| is false, messages from the CDM, 928 | // such as message events, must not contain a Distinctive Identifier, 929 | // even in an encrypted form. 930 | // If |allow_persistent_state| is false, the CDM must not attempt to 931 | // persist state. Calls to CreateFileIO() will fail. 932 | // If |use_hw_secure_codecs| is true, the CDM must ensure the decryption key 933 | // and video buffers (compressed and uncompressed) are securely protected by 934 | // hardware. 935 | virtual void Initialize(bool allow_distinctive_identifier, 936 | bool allow_persistent_state, 937 | bool use_hw_secure_codecs) = 0; 938 | 939 | // Gets the key status if the CDM has a hypothetical key with the |policy|. 940 | // The CDM must respond by calling either Host::OnResolveKeyStatusPromise() 941 | // with the result key status or Host::OnRejectPromise() if an unexpected 942 | // error happened or this method is not supported. 943 | virtual void GetStatusForPolicy(uint32_t promise_id, 944 | const Policy& policy) = 0; 945 | 946 | // SetServerCertificate(), CreateSessionAndGenerateRequest(), LoadSession(), 947 | // UpdateSession(), CloseSession(), and RemoveSession() all accept a 948 | // |promise_id|, which must be passed to the completion Host method 949 | // (e.g. Host::OnResolveNewSessionPromise()). 950 | 951 | // Provides a server certificate to be used to encrypt messages to the 952 | // license server. The CDM must respond by calling either 953 | // Host::OnResolvePromise() or Host::OnRejectPromise(). 954 | // If the CDM does not support server certificates, the promise should be 955 | // rejected with kExceptionNotSupportedError. If |server_certificate_data| 956 | // is empty, reject with kExceptionTypeError. Any other error should be 957 | // rejected with kExceptionInvalidStateError or kExceptionQuotaExceededError. 958 | // TODO(crbug.com/796417): Add support for the promise to return true or 959 | // false, rather than using kExceptionNotSupportedError to mean false. 960 | virtual void SetServerCertificate(uint32_t promise_id, 961 | const uint8_t* server_certificate_data, 962 | uint32_t server_certificate_data_size) = 0; 963 | 964 | // Creates a session given |session_type|, |init_data_type|, and |init_data|. 965 | // The CDM must respond by calling either Host::OnResolveNewSessionPromise() 966 | // or Host::OnRejectPromise(). 967 | virtual void CreateSessionAndGenerateRequest(uint32_t promise_id, 968 | SessionType session_type, 969 | InitDataType init_data_type, 970 | const uint8_t* init_data, 971 | uint32_t init_data_size) = 0; 972 | 973 | // Loads the session of type |session_type| specified by |session_id|. 974 | // The CDM must respond by calling either Host::OnResolveNewSessionPromise() 975 | // or Host::OnRejectPromise(). If the session is not found, call 976 | // Host::OnResolveNewSessionPromise() with session_id = NULL. 977 | virtual void LoadSession(uint32_t promise_id, 978 | SessionType session_type, 979 | const char* session_id, 980 | uint32_t session_id_size) = 0; 981 | 982 | // Updates the session with |response|. The CDM must respond by calling 983 | // either Host::OnResolvePromise() or Host::OnRejectPromise(). 984 | virtual void UpdateSession(uint32_t promise_id, 985 | const char* session_id, 986 | uint32_t session_id_size, 987 | const uint8_t* response, 988 | uint32_t response_size) = 0; 989 | 990 | // Requests that the CDM close the session. The CDM must respond by calling 991 | // either Host::OnResolvePromise() or Host::OnRejectPromise() when the request 992 | // has been processed. This may be before the session is closed. Once the 993 | // session is closed, Host::OnSessionClosed() must also be called. 994 | virtual void CloseSession(uint32_t promise_id, 995 | const char* session_id, 996 | uint32_t session_id_size) = 0; 997 | 998 | // Removes any stored session data associated with this session. Will only be 999 | // called for persistent sessions. The CDM must respond by calling either 1000 | // Host::OnResolvePromise() or Host::OnRejectPromise() when the request has 1001 | // been processed. 1002 | virtual void RemoveSession(uint32_t promise_id, 1003 | const char* session_id, 1004 | uint32_t session_id_size) = 0; 1005 | 1006 | // Performs scheduled operation with |context| when the timer fires. 1007 | virtual void TimerExpired(void* context) = 0; 1008 | 1009 | // Decrypts the |encrypted_buffer|. 1010 | // 1011 | // Returns kSuccess if decryption succeeded, in which case the callee 1012 | // should have filled the |decrypted_buffer| and passed the ownership of 1013 | // |data| in |decrypted_buffer| to the caller. 1014 | // Returns kNoKey if the CDM did not have the necessary decryption key 1015 | // to decrypt. 1016 | // Returns kDecryptError if any other error happened. 1017 | // If the return value is not kSuccess, |decrypted_buffer| should be ignored 1018 | // by the caller. 1019 | virtual Status Decrypt(const InputBuffer_2& encrypted_buffer, 1020 | DecryptedBlock* decrypted_buffer) = 0; 1021 | 1022 | // Initializes the CDM audio decoder with |audio_decoder_config|. This 1023 | // function must be called before DecryptAndDecodeSamples() is called. 1024 | // 1025 | // Returns kSuccess if the |audio_decoder_config| is supported and the CDM 1026 | // audio decoder is successfully initialized. 1027 | // Returns kInitializationError if |audio_decoder_config| is not supported. 1028 | // The CDM may still be able to do Decrypt(). 1029 | // Returns kDeferredInitialization if the CDM is not ready to initialize the 1030 | // decoder at this time. Must call Host::OnDeferredInitializationDone() once 1031 | // initialization is complete. 1032 | virtual Status InitializeAudioDecoder( 1033 | const AudioDecoderConfig_2& audio_decoder_config) = 0; 1034 | 1035 | // Initializes the CDM video decoder with |video_decoder_config|. This 1036 | // function must be called before DecryptAndDecodeFrame() is called. 1037 | // 1038 | // Returns kSuccess if the |video_decoder_config| is supported and the CDM 1039 | // video decoder is successfully initialized. 1040 | // Returns kInitializationError if |video_decoder_config| is not supported. 1041 | // The CDM may still be able to do Decrypt(). 1042 | // Returns kDeferredInitialization if the CDM is not ready to initialize the 1043 | // decoder at this time. Must call Host::OnDeferredInitializationDone() once 1044 | // initialization is complete. 1045 | virtual Status InitializeVideoDecoder( 1046 | const VideoDecoderConfig_2& video_decoder_config) = 0; 1047 | 1048 | // De-initializes the CDM decoder and sets it to an uninitialized state. The 1049 | // caller can initialize the decoder again after this call to re-initialize 1050 | // it. This can be used to reconfigure the decoder if the configuration 1051 | // changes. 1052 | virtual void DeinitializeDecoder(StreamType decoder_type) = 0; 1053 | 1054 | // Resets the CDM decoder to an initialized clean state. All internal buffers 1055 | // MUST be flushed. 1056 | virtual void ResetDecoder(StreamType decoder_type) = 0; 1057 | 1058 | // Decrypts the |encrypted_buffer| and decodes the decrypted buffer into a 1059 | // |video_frame|. Upon end-of-stream, the caller should call this function 1060 | // repeatedly with empty |encrypted_buffer| (|data| == NULL) until 1061 | // kNeedMoreData is returned. 1062 | // 1063 | // Returns kSuccess if decryption and decoding both succeeded, in which case 1064 | // the callee will have filled the |video_frame| and passed the ownership of 1065 | // |frame_buffer| in |video_frame| to the caller. 1066 | // Returns kNoKey if the CDM did not have the necessary decryption key 1067 | // to decrypt. 1068 | // Returns kNeedMoreData if more data was needed by the decoder to generate 1069 | // a decoded frame (e.g. during initialization and end-of-stream). 1070 | // Returns kDecryptError if any decryption error happened. 1071 | // Returns kDecodeError if any decoding error happened. 1072 | // If the return value is not kSuccess, |video_frame| should be ignored by 1073 | // the caller. 1074 | virtual Status DecryptAndDecodeFrame(const InputBuffer_2& encrypted_buffer, 1075 | VideoFrame* video_frame) = 0; 1076 | 1077 | // Decrypts the |encrypted_buffer| and decodes the decrypted buffer into 1078 | // |audio_frames|. Upon end-of-stream, the caller should call this function 1079 | // repeatedly with empty |encrypted_buffer| (|data| == NULL) until only empty 1080 | // |audio_frames| is produced. 1081 | // 1082 | // Returns kSuccess if decryption and decoding both succeeded, in which case 1083 | // the callee will have filled |audio_frames| and passed the ownership of 1084 | // |data| in |audio_frames| to the caller. 1085 | // Returns kNoKey if the CDM did not have the necessary decryption key 1086 | // to decrypt. 1087 | // Returns kNeedMoreData if more data was needed by the decoder to generate 1088 | // audio samples (e.g. during initialization and end-of-stream). 1089 | // Returns kDecryptError if any decryption error happened. 1090 | // Returns kDecodeError if any decoding error happened. 1091 | // If the return value is not kSuccess, |audio_frames| should be ignored by 1092 | // the caller. 1093 | virtual Status DecryptAndDecodeSamples(const InputBuffer_2& encrypted_buffer, 1094 | AudioFrames* audio_frames) = 0; 1095 | 1096 | // Called by the host after a platform challenge was initiated via 1097 | // Host::SendPlatformChallenge(). 1098 | virtual void OnPlatformChallengeResponse( 1099 | const PlatformChallengeResponse& response) = 0; 1100 | 1101 | // Called by the host after a call to Host::QueryOutputProtectionStatus(). The 1102 | // |link_mask| is a bit mask of OutputLinkTypes and |output_protection_mask| 1103 | // is a bit mask of OutputProtectionMethods. If |result| is kQueryFailed, 1104 | // then |link_mask| and |output_protection_mask| are undefined and should 1105 | // be ignored. 1106 | virtual void OnQueryOutputProtectionStatus( 1107 | QueryResult result, 1108 | uint32_t link_mask, 1109 | uint32_t output_protection_mask) = 0; 1110 | 1111 | // Called by the host after a call to Host::RequestStorageId(). If the 1112 | // version of the storage ID requested is available, |storage_id| and 1113 | // |storage_id_size| are set appropriately. |version| will be the same as 1114 | // what was requested, unless 0 (latest) was requested, in which case 1115 | // |version| will be the actual version number for the |storage_id| returned. 1116 | // If the requested version is not available, null/zero will be provided as 1117 | // |storage_id| and |storage_id_size|, respectively, and |version| should be 1118 | // ignored. 1119 | virtual void OnStorageId(uint32_t version, 1120 | const uint8_t* storage_id, 1121 | uint32_t storage_id_size) = 0; 1122 | 1123 | // Destroys the object in the same context as it was created. 1124 | virtual void Destroy() = 0; 1125 | 1126 | protected: 1127 | ContentDecryptionModule_10() {} 1128 | virtual ~ContentDecryptionModule_10() {} 1129 | }; 1130 | 1131 | // ----- Note: CDM interface(s) below still in development and not stable! ----- 1132 | 1133 | // ContentDecryptionModule interface that all CDMs need to implement. 1134 | // The interface is versioned for backward compatibility. 1135 | // Note: ContentDecryptionModule implementations must use the allocator 1136 | // provided in CreateCdmInstance() to allocate any Buffer that needs to 1137 | // be passed back to the caller. Implementations must call Buffer::Destroy() 1138 | // when a Buffer is created that will never be returned to the caller. 1139 | class CDM_CLASS_API ContentDecryptionModule_11 { 1140 | public: 1141 | static const int kVersion = 11; 1142 | static const bool kIsStable = false; 1143 | typedef Host_11 Host; 1144 | 1145 | // Initializes the CDM instance, providing information about permitted 1146 | // functionalities. The CDM must respond by calling Host::OnInitialized() 1147 | // with whether the initialization succeeded. No other calls will be made by 1148 | // the host before Host::OnInitialized() returns. 1149 | // If |allow_distinctive_identifier| is false, messages from the CDM, 1150 | // such as message events, must not contain a Distinctive Identifier, 1151 | // even in an encrypted form. 1152 | // If |allow_persistent_state| is false, the CDM must not attempt to 1153 | // persist state. Calls to CreateFileIO() will fail. 1154 | // If |use_hw_secure_codecs| is true, the CDM must ensure the decryption key 1155 | // and video buffers (compressed and uncompressed) are securely protected by 1156 | // hardware. 1157 | virtual void Initialize(bool allow_distinctive_identifier, 1158 | bool allow_persistent_state, 1159 | bool use_hw_secure_codecs) = 0; 1160 | 1161 | // Gets the key status if the CDM has a hypothetical key with the |policy|. 1162 | // The CDM must respond by calling either Host::OnResolveKeyStatusPromise() 1163 | // with the result key status or Host::OnRejectPromise() if an unexpected 1164 | // error happened or this method is not supported. 1165 | virtual void GetStatusForPolicy(uint32_t promise_id, 1166 | const Policy& policy) = 0; 1167 | 1168 | // SetServerCertificate(), CreateSessionAndGenerateRequest(), LoadSession(), 1169 | // UpdateSession(), CloseSession(), and RemoveSession() all accept a 1170 | // |promise_id|, which must be passed to the completion Host method 1171 | // (e.g. Host::OnResolveNewSessionPromise()). 1172 | 1173 | // Provides a server certificate to be used to encrypt messages to the 1174 | // license server. The CDM must respond by calling either 1175 | // Host::OnResolvePromise() or Host::OnRejectPromise(). 1176 | // If the CDM does not support server certificates, the promise should be 1177 | // rejected with kExceptionNotSupportedError. If |server_certificate_data| 1178 | // is empty, reject with kExceptionTypeError. Any other error should be 1179 | // rejected with kExceptionInvalidStateError or kExceptionQuotaExceededError. 1180 | // TODO(crbug.com/796417): Add support for the promise to return true or 1181 | // false, rather than using kExceptionNotSupportedError to mean false. 1182 | virtual void SetServerCertificate(uint32_t promise_id, 1183 | const uint8_t* server_certificate_data, 1184 | uint32_t server_certificate_data_size) = 0; 1185 | 1186 | // Creates a session given |session_type|, |init_data_type|, and |init_data|. 1187 | // The CDM must respond by calling either Host::OnResolveNewSessionPromise() 1188 | // or Host::OnRejectPromise(). 1189 | virtual void CreateSessionAndGenerateRequest(uint32_t promise_id, 1190 | SessionType session_type, 1191 | InitDataType init_data_type, 1192 | const uint8_t* init_data, 1193 | uint32_t init_data_size) = 0; 1194 | 1195 | // Loads the session of type |session_type| specified by |session_id|. 1196 | // The CDM must respond by calling either Host::OnResolveNewSessionPromise() 1197 | // or Host::OnRejectPromise(). If the session is not found, call 1198 | // Host::OnResolveNewSessionPromise() with session_id = NULL. 1199 | virtual void LoadSession(uint32_t promise_id, 1200 | SessionType session_type, 1201 | const char* session_id, 1202 | uint32_t session_id_size) = 0; 1203 | 1204 | // Updates the session with |response|. The CDM must respond by calling 1205 | // either Host::OnResolvePromise() or Host::OnRejectPromise(). 1206 | virtual void UpdateSession(uint32_t promise_id, 1207 | const char* session_id, 1208 | uint32_t session_id_size, 1209 | const uint8_t* response, 1210 | uint32_t response_size) = 0; 1211 | 1212 | // Requests that the CDM close the session. The CDM must respond by calling 1213 | // either Host::OnResolvePromise() or Host::OnRejectPromise() when the request 1214 | // has been processed. This may be before the session is closed. Once the 1215 | // session is closed, Host::OnSessionClosed() must also be called. 1216 | virtual void CloseSession(uint32_t promise_id, 1217 | const char* session_id, 1218 | uint32_t session_id_size) = 0; 1219 | 1220 | // Removes any stored session data associated with this session. Removes all 1221 | // license(s) and key(s) associated with the session, whether they are in 1222 | // memory, persistent store, or both. For persistent session types, other 1223 | // session data (e.g. record of license destruction) will be cleared as 1224 | // defined for each session type once a release message acknowledgment is 1225 | // processed by UpdateSession(). The CDM must respond by calling either 1226 | // Host::OnResolvePromise() or Host::OnRejectPromise() when the request has 1227 | // been processed. 1228 | virtual void RemoveSession(uint32_t promise_id, 1229 | const char* session_id, 1230 | uint32_t session_id_size) = 0; 1231 | 1232 | // Performs scheduled operation with |context| when the timer fires. 1233 | virtual void TimerExpired(void* context) = 0; 1234 | 1235 | // Decrypts the |encrypted_buffer|. 1236 | // 1237 | // Returns kSuccess if decryption succeeded, in which case the callee 1238 | // should have filled the |decrypted_buffer| and passed the ownership of 1239 | // |data| in |decrypted_buffer| to the caller. 1240 | // Returns kNoKey if the CDM did not have the necessary decryption key 1241 | // to decrypt. 1242 | // Returns kDecryptError if any other error happened. 1243 | // If the return value is not kSuccess, |decrypted_buffer| should be ignored 1244 | // by the caller. 1245 | virtual Status Decrypt(const InputBuffer_2& encrypted_buffer, 1246 | DecryptedBlock* decrypted_buffer) = 0; 1247 | 1248 | // Initializes the CDM audio decoder with |audio_decoder_config|. This 1249 | // function must be called before DecryptAndDecodeSamples() is called. 1250 | // 1251 | // Returns kSuccess if the |audio_decoder_config| is supported and the CDM 1252 | // audio decoder is successfully initialized. 1253 | // Returns kInitializationError if |audio_decoder_config| is not supported. 1254 | // The CDM may still be able to do Decrypt(). 1255 | // Returns kDeferredInitialization if the CDM is not ready to initialize the 1256 | // decoder at this time. Must call Host::OnDeferredInitializationDone() once 1257 | // initialization is complete. 1258 | virtual Status InitializeAudioDecoder( 1259 | const AudioDecoderConfig_2& audio_decoder_config) = 0; 1260 | 1261 | // Initializes the CDM video decoder with |video_decoder_config|. This 1262 | // function must be called before DecryptAndDecodeFrame() is called. 1263 | // 1264 | // Returns kSuccess if the |video_decoder_config| is supported and the CDM 1265 | // video decoder is successfully initialized. 1266 | // Returns kInitializationError if |video_decoder_config| is not supported. 1267 | // The CDM may still be able to do Decrypt(). 1268 | // Returns kDeferredInitialization if the CDM is not ready to initialize the 1269 | // decoder at this time. Must call Host::OnDeferredInitializationDone() once 1270 | // initialization is complete. 1271 | virtual Status InitializeVideoDecoder( 1272 | const VideoDecoderConfig_3& video_decoder_config) = 0; 1273 | 1274 | // De-initializes the CDM decoder and sets it to an uninitialized state. The 1275 | // caller can initialize the decoder again after this call to re-initialize 1276 | // it. This can be used to reconfigure the decoder if the configuration 1277 | // changes. 1278 | virtual void DeinitializeDecoder(StreamType decoder_type) = 0; 1279 | 1280 | // Resets the CDM decoder to an initialized clean state. All internal buffers 1281 | // MUST be flushed. 1282 | virtual void ResetDecoder(StreamType decoder_type) = 0; 1283 | 1284 | // Decrypts the |encrypted_buffer| and decodes the decrypted buffer into a 1285 | // |video_frame|. Upon end-of-stream, the caller should call this function 1286 | // repeatedly with empty |encrypted_buffer| (|data| == NULL) until 1287 | // kNeedMoreData is returned. 1288 | // 1289 | // Returns kSuccess if decryption and decoding both succeeded, in which case 1290 | // the callee will have filled the |video_frame| and passed the ownership of 1291 | // |frame_buffer| in |video_frame| to the caller. 1292 | // Returns kNoKey if the CDM did not have the necessary decryption key 1293 | // to decrypt. 1294 | // Returns kNeedMoreData if more data was needed by the decoder to generate 1295 | // a decoded frame (e.g. during initialization and end-of-stream). 1296 | // Returns kDecryptError if any decryption error happened. 1297 | // Returns kDecodeError if any decoding error happened. 1298 | // If the return value is not kSuccess, |video_frame| should be ignored by 1299 | // the caller. 1300 | virtual Status DecryptAndDecodeFrame(const InputBuffer_2& encrypted_buffer, 1301 | VideoFrame_2* video_frame) = 0; 1302 | 1303 | // Decrypts the |encrypted_buffer| and decodes the decrypted buffer into 1304 | // |audio_frames|. Upon end-of-stream, the caller should call this function 1305 | // repeatedly with empty |encrypted_buffer| (|data| == NULL) until only empty 1306 | // |audio_frames| is produced. 1307 | // 1308 | // Returns kSuccess if decryption and decoding both succeeded, in which case 1309 | // the callee will have filled |audio_frames| and passed the ownership of 1310 | // |data| in |audio_frames| to the caller. 1311 | // Returns kNoKey if the CDM did not have the necessary decryption key 1312 | // to decrypt. 1313 | // Returns kNeedMoreData if more data was needed by the decoder to generate 1314 | // audio samples (e.g. during initialization and end-of-stream). 1315 | // Returns kDecryptError if any decryption error happened. 1316 | // Returns kDecodeError if any decoding error happened. 1317 | // If the return value is not kSuccess, |audio_frames| should be ignored by 1318 | // the caller. 1319 | virtual Status DecryptAndDecodeSamples(const InputBuffer_2& encrypted_buffer, 1320 | AudioFrames* audio_frames) = 0; 1321 | 1322 | // Called by the host after a platform challenge was initiated via 1323 | // Host::SendPlatformChallenge(). 1324 | virtual void OnPlatformChallengeResponse( 1325 | const PlatformChallengeResponse& response) = 0; 1326 | 1327 | // Called by the host after a call to Host::QueryOutputProtectionStatus(). The 1328 | // |link_mask| is a bit mask of OutputLinkTypes and |output_protection_mask| 1329 | // is a bit mask of OutputProtectionMethods. If |result| is kQueryFailed, 1330 | // then |link_mask| and |output_protection_mask| are undefined and should 1331 | // be ignored. 1332 | virtual void OnQueryOutputProtectionStatus( 1333 | QueryResult result, 1334 | uint32_t link_mask, 1335 | uint32_t output_protection_mask) = 0; 1336 | 1337 | // Called by the host after a call to Host::RequestStorageId(). If the 1338 | // version of the storage ID requested is available, |storage_id| and 1339 | // |storage_id_size| are set appropriately. |version| will be the same as 1340 | // what was requested, unless 0 (latest) was requested, in which case 1341 | // |version| will be the actual version number for the |storage_id| returned. 1342 | // If the requested version is not available, null/zero will be provided as 1343 | // |storage_id| and |storage_id_size|, respectively, and |version| should be 1344 | // ignored. 1345 | virtual void OnStorageId(uint32_t version, 1346 | const uint8_t* storage_id, 1347 | uint32_t storage_id_size) = 0; 1348 | 1349 | // Destroys the object in the same context as it was created. 1350 | virtual void Destroy() = 0; 1351 | 1352 | protected: 1353 | ContentDecryptionModule_11() {} 1354 | virtual ~ContentDecryptionModule_11() {} 1355 | }; 1356 | 1357 | class CDM_CLASS_API Host_9 { 1358 | public: 1359 | static const int kVersion = 9; 1360 | 1361 | // Returns a Buffer* containing non-zero members upon success, or NULL on 1362 | // failure. The caller owns the Buffer* after this call. The buffer is not 1363 | // guaranteed to be zero initialized. The capacity of the allocated Buffer 1364 | // is guaranteed to be not less than |capacity|. 1365 | virtual Buffer* Allocate(uint32_t capacity) = 0; 1366 | 1367 | // Requests the host to call ContentDecryptionModule::TimerFired() |delay_ms| 1368 | // from now with |context|. 1369 | virtual void SetTimer(int64_t delay_ms, void* context) = 0; 1370 | 1371 | // Returns the current wall time. 1372 | virtual Time GetCurrentWallTime() = 0; 1373 | 1374 | // Called by the CDM when a key status is available in response to 1375 | // GetStatusForPolicy(). 1376 | virtual void OnResolveKeyStatusPromise(uint32_t promise_id, 1377 | KeyStatus key_status) = 0; 1378 | 1379 | // Called by the CDM when a session is created or loaded and the value for the 1380 | // MediaKeySession's sessionId attribute is available (|session_id|). 1381 | // This must be called before OnSessionMessage() or 1382 | // OnSessionKeysChange() is called for the same session. |session_id_size| 1383 | // should not include null termination. 1384 | // When called in response to LoadSession(), the |session_id| must be the 1385 | // same as the |session_id| passed in LoadSession(), or NULL if the 1386 | // session could not be loaded. 1387 | virtual void OnResolveNewSessionPromise(uint32_t promise_id, 1388 | const char* session_id, 1389 | uint32_t session_id_size) = 0; 1390 | 1391 | // Called by the CDM when a session is updated or released. 1392 | virtual void OnResolvePromise(uint32_t promise_id) = 0; 1393 | 1394 | // Called by the CDM when an error occurs as a result of one of the 1395 | // ContentDecryptionModule calls that accept a |promise_id|. 1396 | // |exception| must be specified. |error_message| and |system_code| 1397 | // are optional. |error_message_size| should not include null termination. 1398 | virtual void OnRejectPromise(uint32_t promise_id, 1399 | Exception exception, 1400 | uint32_t system_code, 1401 | const char* error_message, 1402 | uint32_t error_message_size) = 0; 1403 | 1404 | // Called by the CDM when it has a message for session |session_id|. 1405 | // Size parameters should not include null termination. 1406 | virtual void OnSessionMessage(const char* session_id, 1407 | uint32_t session_id_size, 1408 | MessageType message_type, 1409 | const char* message, 1410 | uint32_t message_size) = 0; 1411 | 1412 | // Called by the CDM when there has been a change in keys or their status for 1413 | // session |session_id|. |has_additional_usable_key| should be set if a 1414 | // key is newly usable (e.g. new key available, previously expired key has 1415 | // been renewed, etc.) and the browser should attempt to resume playback. 1416 | // |keys_info| is the list of key IDs for this session along with their 1417 | // current status. |keys_info_count| is the number of entries in |keys_info|. 1418 | // Size parameter for |session_id| should not include null termination. 1419 | virtual void OnSessionKeysChange(const char* session_id, 1420 | uint32_t session_id_size, 1421 | bool has_additional_usable_key, 1422 | const KeyInformation* keys_info, 1423 | uint32_t keys_info_count) = 0; 1424 | 1425 | // Called by the CDM when there has been a change in the expiration time for 1426 | // session |session_id|. This can happen as the result of an Update() call 1427 | // or some other event. If this happens as a result of a call to Update(), 1428 | // it must be called before resolving the Update() promise. |new_expiry_time| 1429 | // represents the time after which the key(s) in the session will no longer 1430 | // be usable for decryption. It can be 0 if no such time exists or if the 1431 | // license explicitly never expires. Size parameter should not include null 1432 | // termination. 1433 | virtual void OnExpirationChange(const char* session_id, 1434 | uint32_t session_id_size, 1435 | Time new_expiry_time) = 0; 1436 | 1437 | // Called by the CDM when session |session_id| is closed. Size 1438 | // parameter should not include null termination. 1439 | virtual void OnSessionClosed(const char* session_id, 1440 | uint32_t session_id_size) = 0; 1441 | 1442 | // The following are optional methods that may not be implemented on all 1443 | // platforms. 1444 | 1445 | // Sends a platform challenge for the given |service_id|. |challenge| is at 1446 | // most 256 bits of data to be signed. Once the challenge has been completed, 1447 | // the host will call ContentDecryptionModule::OnPlatformChallengeResponse() 1448 | // with the signed challenge response and platform certificate. Size 1449 | // parameters should not include null termination. 1450 | virtual void SendPlatformChallenge(const char* service_id, 1451 | uint32_t service_id_size, 1452 | const char* challenge, 1453 | uint32_t challenge_size) = 0; 1454 | 1455 | // Attempts to enable output protection (e.g. HDCP) on the display link. The 1456 | // |desired_protection_mask| is a bit mask of OutputProtectionMethods. No 1457 | // status callback is issued, the CDM must call QueryOutputProtectionStatus() 1458 | // periodically to ensure the desired protections are applied. 1459 | virtual void EnableOutputProtection(uint32_t desired_protection_mask) = 0; 1460 | 1461 | // Requests the current output protection status. Once the host has the status 1462 | // it will call ContentDecryptionModule::OnQueryOutputProtectionStatus(). 1463 | virtual void QueryOutputProtectionStatus() = 0; 1464 | 1465 | // Must be called by the CDM if it returned kDeferredInitialization during 1466 | // InitializeAudioDecoder() or InitializeVideoDecoder(). 1467 | virtual void OnDeferredInitializationDone(StreamType stream_type, 1468 | Status decoder_status) = 0; 1469 | 1470 | // Creates a FileIO object from the host to do file IO operation. Returns NULL 1471 | // if a FileIO object cannot be obtained. Once a valid FileIO object is 1472 | // returned, |client| must be valid until FileIO::Close() is called. The 1473 | // CDM can call this method multiple times to operate on different files. 1474 | virtual FileIO* CreateFileIO(FileIOClient* client) = 0; 1475 | 1476 | // Requests a specific version of the storage ID. A storage ID is a stable, 1477 | // device specific ID used by the CDM to securely store persistent data. The 1478 | // ID will be returned by the host via ContentDecryptionModule::OnStorageId(). 1479 | // If |version| is 0, the latest version will be returned. All |version|s 1480 | // that are greater than or equal to 0x80000000 are reserved for the CDM and 1481 | // should not be supported or returned by the host. The CDM must not expose 1482 | // the ID outside the client device, even in encrypted form. 1483 | virtual void RequestStorageId(uint32_t version) = 0; 1484 | 1485 | protected: 1486 | Host_9() {} 1487 | virtual ~Host_9() {} 1488 | }; 1489 | 1490 | class CDM_CLASS_API Host_10 { 1491 | public: 1492 | static const int kVersion = 10; 1493 | 1494 | // Returns a Buffer* containing non-zero members upon success, or NULL on 1495 | // failure. The caller owns the Buffer* after this call. The buffer is not 1496 | // guaranteed to be zero initialized. The capacity of the allocated Buffer 1497 | // is guaranteed to be not less than |capacity|. 1498 | virtual Buffer* Allocate(uint32_t capacity) = 0; 1499 | 1500 | // Requests the host to call ContentDecryptionModule::TimerFired() |delay_ms| 1501 | // from now with |context|. 1502 | virtual void SetTimer(int64_t delay_ms, void* context) = 0; 1503 | 1504 | // Returns the current wall time. 1505 | virtual Time GetCurrentWallTime() = 0; 1506 | 1507 | // Called by the CDM with the result after the CDM instance was initialized. 1508 | virtual void OnInitialized(bool success) = 0; 1509 | 1510 | // Called by the CDM when a key status is available in response to 1511 | // GetStatusForPolicy(). 1512 | virtual void OnResolveKeyStatusPromise(uint32_t promise_id, 1513 | KeyStatus key_status) = 0; 1514 | 1515 | // Called by the CDM when a session is created or loaded and the value for the 1516 | // MediaKeySession's sessionId attribute is available (|session_id|). 1517 | // This must be called before OnSessionMessage() or 1518 | // OnSessionKeysChange() is called for the same session. |session_id_size| 1519 | // should not include null termination. 1520 | // When called in response to LoadSession(), the |session_id| must be the 1521 | // same as the |session_id| passed in LoadSession(), or NULL if the 1522 | // session could not be loaded. 1523 | virtual void OnResolveNewSessionPromise(uint32_t promise_id, 1524 | const char* session_id, 1525 | uint32_t session_id_size) = 0; 1526 | 1527 | // Called by the CDM when a session is updated or released. 1528 | virtual void OnResolvePromise(uint32_t promise_id) = 0; 1529 | 1530 | // Called by the CDM when an error occurs as a result of one of the 1531 | // ContentDecryptionModule calls that accept a |promise_id|. 1532 | // |exception| must be specified. |error_message| and |system_code| 1533 | // are optional. |error_message_size| should not include null termination. 1534 | virtual void OnRejectPromise(uint32_t promise_id, 1535 | Exception exception, 1536 | uint32_t system_code, 1537 | const char* error_message, 1538 | uint32_t error_message_size) = 0; 1539 | 1540 | // Called by the CDM when it has a message for session |session_id|. 1541 | // Size parameters should not include null termination. 1542 | virtual void OnSessionMessage(const char* session_id, 1543 | uint32_t session_id_size, 1544 | MessageType message_type, 1545 | const char* message, 1546 | uint32_t message_size) = 0; 1547 | 1548 | // Called by the CDM when there has been a change in keys or their status for 1549 | // session |session_id|. |has_additional_usable_key| should be set if a 1550 | // key is newly usable (e.g. new key available, previously expired key has 1551 | // been renewed, etc.) and the browser should attempt to resume playback. 1552 | // |keys_info| is the list of key IDs for this session along with their 1553 | // current status. |keys_info_count| is the number of entries in |keys_info|. 1554 | // Size parameter for |session_id| should not include null termination. 1555 | virtual void OnSessionKeysChange(const char* session_id, 1556 | uint32_t session_id_size, 1557 | bool has_additional_usable_key, 1558 | const KeyInformation* keys_info, 1559 | uint32_t keys_info_count) = 0; 1560 | 1561 | // Called by the CDM when there has been a change in the expiration time for 1562 | // session |session_id|. This can happen as the result of an Update() call 1563 | // or some other event. If this happens as a result of a call to Update(), 1564 | // it must be called before resolving the Update() promise. |new_expiry_time| 1565 | // represents the time after which the key(s) in the session will no longer 1566 | // be usable for decryption. It can be 0 if no such time exists or if the 1567 | // license explicitly never expires. Size parameter should not include null 1568 | // termination. 1569 | virtual void OnExpirationChange(const char* session_id, 1570 | uint32_t session_id_size, 1571 | Time new_expiry_time) = 0; 1572 | 1573 | // Called by the CDM when session |session_id| is closed. Size 1574 | // parameter should not include null termination. 1575 | virtual void OnSessionClosed(const char* session_id, 1576 | uint32_t session_id_size) = 0; 1577 | 1578 | // The following are optional methods that may not be implemented on all 1579 | // platforms. 1580 | 1581 | // Sends a platform challenge for the given |service_id|. |challenge| is at 1582 | // most 256 bits of data to be signed. Once the challenge has been completed, 1583 | // the host will call ContentDecryptionModule::OnPlatformChallengeResponse() 1584 | // with the signed challenge response and platform certificate. Size 1585 | // parameters should not include null termination. 1586 | virtual void SendPlatformChallenge(const char* service_id, 1587 | uint32_t service_id_size, 1588 | const char* challenge, 1589 | uint32_t challenge_size) = 0; 1590 | 1591 | // Attempts to enable output protection (e.g. HDCP) on the display link. The 1592 | // |desired_protection_mask| is a bit mask of OutputProtectionMethods. No 1593 | // status callback is issued, the CDM must call QueryOutputProtectionStatus() 1594 | // periodically to ensure the desired protections are applied. 1595 | virtual void EnableOutputProtection(uint32_t desired_protection_mask) = 0; 1596 | 1597 | // Requests the current output protection status. Once the host has the status 1598 | // it will call ContentDecryptionModule::OnQueryOutputProtectionStatus(). 1599 | virtual void QueryOutputProtectionStatus() = 0; 1600 | 1601 | // Must be called by the CDM if it returned kDeferredInitialization during 1602 | // InitializeAudioDecoder() or InitializeVideoDecoder(). 1603 | virtual void OnDeferredInitializationDone(StreamType stream_type, 1604 | Status decoder_status) = 0; 1605 | 1606 | // Creates a FileIO object from the host to do file IO operation. Returns NULL 1607 | // if a FileIO object cannot be obtained. Once a valid FileIO object is 1608 | // returned, |client| must be valid until FileIO::Close() is called. The 1609 | // CDM can call this method multiple times to operate on different files. 1610 | virtual FileIO* CreateFileIO(FileIOClient* client) = 0; 1611 | 1612 | // Requests a specific version of the storage ID. A storage ID is a stable, 1613 | // device specific ID used by the CDM to securely store persistent data. The 1614 | // ID will be returned by the host via ContentDecryptionModule::OnStorageId(). 1615 | // If |version| is 0, the latest version will be returned. All |version|s 1616 | // that are greater than or equal to 0x80000000 are reserved for the CDM and 1617 | // should not be supported or returned by the host. The CDM must not expose 1618 | // the ID outside the client device, even in encrypted form. 1619 | virtual void RequestStorageId(uint32_t version) = 0; 1620 | 1621 | protected: 1622 | Host_10() {} 1623 | virtual ~Host_10() {} 1624 | }; 1625 | 1626 | class CDM_CLASS_API Host_11 { 1627 | public: 1628 | static const int kVersion = 11; 1629 | 1630 | // Returns a Buffer* containing non-zero members upon success, or NULL on 1631 | // failure. The caller owns the Buffer* after this call. The buffer is not 1632 | // guaranteed to be zero initialized. The capacity of the allocated Buffer 1633 | // is guaranteed to be not less than |capacity|. 1634 | virtual Buffer* Allocate(uint32_t capacity) = 0; 1635 | 1636 | // Requests the host to call ContentDecryptionModule::TimerFired() |delay_ms| 1637 | // from now with |context|. 1638 | virtual void SetTimer(int64_t delay_ms, void* context) = 0; 1639 | 1640 | // Returns the current wall time. 1641 | virtual Time GetCurrentWallTime() = 0; 1642 | 1643 | // Called by the CDM with the result after the CDM instance was initialized. 1644 | virtual void OnInitialized(bool success) = 0; 1645 | 1646 | // Called by the CDM when a key status is available in response to 1647 | // GetStatusForPolicy(). 1648 | virtual void OnResolveKeyStatusPromise(uint32_t promise_id, 1649 | KeyStatus key_status) = 0; 1650 | 1651 | // Called by the CDM when a session is created or loaded and the value for the 1652 | // MediaKeySession's sessionId attribute is available (|session_id|). 1653 | // This must be called before OnSessionMessage() or 1654 | // OnSessionKeysChange() is called for the same session. |session_id_size| 1655 | // should not include null termination. 1656 | // When called in response to LoadSession(), the |session_id| must be the 1657 | // same as the |session_id| passed in LoadSession(), or NULL if the 1658 | // session could not be loaded. 1659 | virtual void OnResolveNewSessionPromise(uint32_t promise_id, 1660 | const char* session_id, 1661 | uint32_t session_id_size) = 0; 1662 | 1663 | // Called by the CDM when a session is updated or released. 1664 | virtual void OnResolvePromise(uint32_t promise_id) = 0; 1665 | 1666 | // Called by the CDM when an error occurs as a result of one of the 1667 | // ContentDecryptionModule calls that accept a |promise_id|. 1668 | // |exception| must be specified. |error_message| and |system_code| 1669 | // are optional. |error_message_size| should not include null termination. 1670 | virtual void OnRejectPromise(uint32_t promise_id, 1671 | Exception exception, 1672 | uint32_t system_code, 1673 | const char* error_message, 1674 | uint32_t error_message_size) = 0; 1675 | 1676 | // Called by the CDM when it has a message for session |session_id|. 1677 | // Size parameters should not include null termination. 1678 | virtual void OnSessionMessage(const char* session_id, 1679 | uint32_t session_id_size, 1680 | MessageType message_type, 1681 | const char* message, 1682 | uint32_t message_size) = 0; 1683 | 1684 | // Called by the CDM when there has been a change in keys or their status for 1685 | // session |session_id|. |has_additional_usable_key| should be set if a 1686 | // key is newly usable (e.g. new key available, previously expired key has 1687 | // been renewed, etc.) and the browser should attempt to resume playback. 1688 | // |keys_info| is the list of key IDs for this session along with their 1689 | // current status. |keys_info_count| is the number of entries in |keys_info|. 1690 | // Size parameter for |session_id| should not include null termination. 1691 | virtual void OnSessionKeysChange(const char* session_id, 1692 | uint32_t session_id_size, 1693 | bool has_additional_usable_key, 1694 | const KeyInformation* keys_info, 1695 | uint32_t keys_info_count) = 0; 1696 | 1697 | // Called by the CDM when there has been a change in the expiration time for 1698 | // session |session_id|. This can happen as the result of an Update() call 1699 | // or some other event. If this happens as a result of a call to Update(), 1700 | // it must be called before resolving the Update() promise. |new_expiry_time| 1701 | // represents the time after which the key(s) in the session will no longer 1702 | // be usable for decryption. It can be 0 if no such time exists or if the 1703 | // license explicitly never expires. Size parameter should not include null 1704 | // termination. 1705 | virtual void OnExpirationChange(const char* session_id, 1706 | uint32_t session_id_size, 1707 | Time new_expiry_time) = 0; 1708 | 1709 | // Called by the CDM when session |session_id| is closed. Size 1710 | // parameter should not include null termination. 1711 | virtual void OnSessionClosed(const char* session_id, 1712 | uint32_t session_id_size) = 0; 1713 | 1714 | // The following are optional methods that may not be implemented on all 1715 | // platforms. 1716 | 1717 | // Sends a platform challenge for the given |service_id|. |challenge| is at 1718 | // most 256 bits of data to be signed. Once the challenge has been completed, 1719 | // the host will call ContentDecryptionModule::OnPlatformChallengeResponse() 1720 | // with the signed challenge response and platform certificate. Size 1721 | // parameters should not include null termination. 1722 | virtual void SendPlatformChallenge(const char* service_id, 1723 | uint32_t service_id_size, 1724 | const char* challenge, 1725 | uint32_t challenge_size) = 0; 1726 | 1727 | // Attempts to enable output protection (e.g. HDCP) on the display link. The 1728 | // |desired_protection_mask| is a bit mask of OutputProtectionMethods. No 1729 | // status callback is issued, the CDM must call QueryOutputProtectionStatus() 1730 | // periodically to ensure the desired protections are applied. 1731 | virtual void EnableOutputProtection(uint32_t desired_protection_mask) = 0; 1732 | 1733 | // Requests the current output protection status. Once the host has the status 1734 | // it will call ContentDecryptionModule::OnQueryOutputProtectionStatus(). 1735 | virtual void QueryOutputProtectionStatus() = 0; 1736 | 1737 | // Must be called by the CDM if it returned kDeferredInitialization during 1738 | // InitializeAudioDecoder() or InitializeVideoDecoder(). 1739 | virtual void OnDeferredInitializationDone(StreamType stream_type, 1740 | Status decoder_status) = 0; 1741 | 1742 | // Creates a FileIO object from the host to do file IO operation. Returns NULL 1743 | // if a FileIO object cannot be obtained. Once a valid FileIO object is 1744 | // returned, |client| must be valid until FileIO::Close() is called. The 1745 | // CDM can call this method multiple times to operate on different files. 1746 | virtual FileIO* CreateFileIO(FileIOClient* client) = 0; 1747 | 1748 | // Requests a CdmProxy that proxies part of CDM functionalities to a different 1749 | // entity, e.g. a hardware CDM module. A CDM instance can have at most one 1750 | // CdmProxy throughout its lifetime, which must be requested and initialized 1751 | // during CDM instance initialization time, i.e. in or after CDM::Initialize() 1752 | // and before OnInitialized() is called, to ensure proper connection of the 1753 | // CdmProxy and the media player (e.g. hardware decoder). The CdmProxy is 1754 | // owned by the host and is guaranteed to be valid throughout the CDM 1755 | // instance's lifetime. The CDM must ensure that the |client| remain valid 1756 | // before the CDM instance is destroyed. Returns null if CdmProxy is not 1757 | // supported, called before CDM::Initialize(), RequestCdmProxy() is called 1758 | // more than once, or called after the CDM instance has been initialized. 1759 | virtual CdmProxy* RequestCdmProxy(CdmProxyClient* client) = 0; 1760 | 1761 | // Requests a specific version of the storage ID. A storage ID is a stable, 1762 | // device specific ID used by the CDM to securely store persistent data. The 1763 | // ID will be returned by the host via ContentDecryptionModule::OnStorageId(). 1764 | // If |version| is 0, the latest version will be returned. All |version|s 1765 | // that are greater than or equal to 0x80000000 are reserved for the CDM and 1766 | // should not be supported or returned by the host. The CDM must not expose 1767 | // the ID outside the client device, even in encrypted form. 1768 | virtual void RequestStorageId(uint32_t version) = 0; 1769 | 1770 | protected: 1771 | Host_11() {} 1772 | virtual ~Host_11() {} 1773 | }; 1774 | 1775 | } // namespace cdm 1776 | 1777 | #endif // CDM_CONTENT_DECRYPTION_MODULE_H_ -------------------------------------------------------------------------------- /cdm/media/cdm/api/content_decryption_module_export.h: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | #ifndef CDM_CONTENT_DECRYPTION_MODULE_EXPORT_H_ 6 | #define CDM_CONTENT_DECRYPTION_MODULE_EXPORT_H_ 7 | 8 | // Define CDM_API so that functionality implemented by the CDM module 9 | // can be exported to consumers. 10 | #if defined(_WIN32) 11 | 12 | #if defined(CDM_IMPLEMENTATION) 13 | #define CDM_API __declspec(dllexport) 14 | #else 15 | #define CDM_API __declspec(dllimport) 16 | #endif // defined(CDM_IMPLEMENTATION) 17 | 18 | #else // defined(_WIN32) 19 | #define CDM_API __attribute__((visibility("default"))) 20 | #endif // defined(_WIN32) 21 | 22 | // Define CDM_CLASS_API to export class types. We have to add visibility 23 | // attributes to make sure virtual tables in CDM consumer and CDM implementation 24 | // are the same. Generally, it was always a good idea, as there're no guarantees 25 | // about that for the internal symbols, but it has only become a practical issue 26 | // after introduction of LTO devirtualization. See more details on 27 | // https://crbug.com/609564#c35 28 | #if defined(_WIN32) 29 | #if defined(__clang__) 30 | #define CDM_CLASS_API [[clang::lto_visibility_public]] 31 | #else 32 | #define CDM_CLASS_API 33 | #endif 34 | #else // defined(_WIN32) 35 | #define CDM_CLASS_API __attribute__((visibility("default"))) 36 | #endif // defined(_WIN32) 37 | 38 | #endif // CDM_CONTENT_DECRYPTION_MODULE_EXPORT_H_ 39 | -------------------------------------------------------------------------------- /cdm/media/cdm/api/content_decryption_module_proxy.h: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | #ifndef CDM_CONTENT_DECRYPTION_MODULE_PROXY_H_ 5 | #define CDM_CONTENT_DECRYPTION_MODULE_PROXY_H_ 6 | #include "content_decryption_module_export.h" 7 | #if defined(_MSC_VER) 8 | typedef unsigned char uint8_t; 9 | typedef unsigned int uint32_t; 10 | typedef unsigned __int64 uint64_t; 11 | #else 12 | #include 13 | #endif 14 | namespace cdm { 15 | class CDM_CLASS_API CdmProxyClient; 16 | // A proxy class for the CDM. 17 | // In general, the interpretation of the CdmProxy and CdmProxyClient method 18 | // parameters are protocol dependent. For enum parameters, values outside the 19 | // enum range may not work. 20 | class CDM_CLASS_API CdmProxy { 21 | public: 22 | enum Function : uint32_t { 23 | // For Intel Negotiate Crypto SessionKey Exchange (CSME) path to call 24 | // ID3D11VideoContext::NegotiateCryptoSessionKeyExchange. 25 | kIntelNegotiateCryptoSessionKeyExchange = 1, 26 | // There will be more values in the future e.g. for D3D11 RSA method. 27 | }; 28 | // Initializes the proxy. The results will be returned in 29 | // CdmProxyClient::OnInitialized(). 30 | virtual void Initialize() = 0; 31 | // Processes and updates the state of the proxy. 32 | // |output_data_size| is required by some protocol to set up the output data. 33 | // The operation may fail if the |output_data_size| is wrong. The results will 34 | // be returned in CdmProxyClient::OnProcessed(). 35 | virtual void Process(Function function, 36 | uint32_t crypto_session_id, 37 | const uint8_t* input_data, 38 | uint32_t input_data_size, 39 | uint32_t output_data_size) = 0; 40 | // Creates a crypto session for handling media. 41 | // If extra data has to be passed to further setup the media crypto session, 42 | // pass the data as |input_data|. The results will be returned in 43 | // CdmProxyClient::OnMediaCryptoSessionCreated(). 44 | virtual void CreateMediaCryptoSession(const uint8_t* input_data, 45 | uint32_t input_data_size) = 0; 46 | // Sets a key for the session identified by |crypto_session_id|. 47 | virtual void SetKey(uint32_t crypto_session_id, 48 | const uint8_t* key_id, 49 | uint32_t key_id_size, 50 | const uint8_t* key_blob, 51 | uint32_t key_blob_size) = 0; 52 | // Removes a key for the session identified by |crypto_session_id|. 53 | virtual void RemoveKey(uint32_t crypto_session_id, 54 | const uint8_t* key_id, 55 | uint32_t key_id_size) = 0; 56 | protected: 57 | CdmProxy() {} 58 | virtual ~CdmProxy() {} 59 | }; 60 | // Responses to CdmProxy calls. All responses will be called asynchronously. 61 | class CDM_CLASS_API CdmProxyClient { 62 | public: 63 | enum Status : uint32_t { 64 | kOk, 65 | kFail, 66 | }; 67 | enum Protocol : uint32_t { 68 | kNone = 0, // No protocol supported. Can be used in failure cases. 69 | kIntelConvergedSecurityAndManageabilityEngine, // Method using Intel CSME. 70 | // There will be more values in the future e.g. kD3D11RsaHardware, 71 | // kD3D11RsaSoftware to use the D3D11 RSA method. 72 | }; 73 | // Callback for Initialize(). If the proxy created a crypto session, then the 74 | // ID for the crypto session is |crypto_session_id|. 75 | virtual void OnInitialized(Status status, 76 | Protocol protocol, 77 | uint32_t crypto_session_id) = 0; 78 | // Callback for Process(). |output_data| is the output of processing. 79 | virtual void OnProcessed(Status status, 80 | const uint8_t* output_data, 81 | uint32_t output_data_size) = 0; 82 | // Callback for CreateMediaCryptoSession(). On success: 83 | // - |crypto_session_id| is the ID for the created crypto session. 84 | // - |output_data| is extra value, if any. 85 | // Otherwise, |crypto_session_id| and |output_data| should be ignored. 86 | virtual void OnMediaCryptoSessionCreated(Status status, 87 | uint32_t crypto_session_id, 88 | uint64_t output_data) = 0; 89 | // Called when there is a hardware reset and all the hardware context is lost. 90 | virtual void NotifyHardwareReset() = 0; 91 | protected: 92 | CdmProxyClient() {} 93 | virtual ~CdmProxyClient() {} 94 | }; 95 | } // namespace cdm 96 | #endif // CDM_CONTENT_DECRYPTION_MODULE_PROXY_H_ -------------------------------------------------------------------------------- /cdm/media/cdm/cdm_adapter.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | #include "cdm_adapter.h" 6 | #include 7 | #include 8 | #include 9 | 10 | #define DCHECK(condition) assert(condition) 11 | 12 | #include "../base/limits.h" 13 | 14 | #ifdef __APPLE__ 15 | #include 16 | //clock_gettime is not implemented on OSX 17 | int clock_gettime(int clk_id, struct timespec* t) { 18 | struct timeval now; 19 | int rv = gettimeofday(&now, NULL); 20 | if (rv) return rv; 21 | t->tv_sec = now.tv_sec; 22 | t->tv_nsec = now.tv_usec * 1000; 23 | return 0; 24 | } 25 | #ifndef CLOCK_REALTIME 26 | #define CLOCK_REALTIME 1 27 | #endif 28 | #endif 29 | 30 | namespace media { 31 | 32 | uint64_t gtc() 33 | { 34 | #ifdef OS_WIN 35 | return GetTickCount64(); 36 | #else 37 | struct timespec tp; 38 | clock_gettime(CLOCK_REALTIME, &tp); 39 | return tp.tv_sec * 1000 + tp.tv_nsec / 1000000; 40 | #endif 41 | } 42 | 43 | namespace { 44 | 45 | void* GetCdmHost(int host_interface_version, void* user_data) 46 | { 47 | if (!user_data) 48 | return nullptr; 49 | 50 | CdmAdapter *adapter = static_cast(user_data); 51 | 52 | switch (host_interface_version) 53 | { 54 | case cdm::Host_9::kVersion: 55 | return static_cast(adapter); 56 | case cdm::Host_10::kVersion: 57 | return static_cast(adapter); 58 | case cdm::Host_11::kVersion: 59 | return static_cast(adapter); 60 | default: 61 | return nullptr; 62 | } 63 | } 64 | 65 | } // namespace 66 | 67 | void timerfunc(std::shared_ptr adp, uint64_t delay, void* context) 68 | { 69 | std::this_thread::sleep_for(std::chrono::milliseconds(delay)); 70 | adp->TimerExpired(context); 71 | } 72 | 73 | cdm::AudioDecoderConfig_1 ToAudioDecoderConfig_1( 74 | const cdm::AudioDecoderConfig_2& config) { 75 | return{ config.codec, 76 | config.channel_count, 77 | config.bits_per_channel, 78 | config.samples_per_second, 79 | config.extra_data, 80 | config.extra_data_size }; 81 | } 82 | 83 | cdm::VideoDecoderConfig_1 ToVideoDecoderConfig_1( 84 | const cdm::VideoDecoderConfig_3& config) { 85 | return{ config.codec, config.profile, config.format, 86 | config.coded_size, config.extra_data, config.extra_data_size }; 87 | } 88 | 89 | cdm::VideoDecoderConfig_2 ToVideoDecoderConfig_2( 90 | const cdm::VideoDecoderConfig_3& config) { 91 | return{ config.codec, 92 | config.profile, 93 | config.format, 94 | config.coded_size, 95 | config.extra_data, 96 | config.extra_data_size, 97 | config.encryption_scheme }; 98 | } 99 | 100 | cdm::InputBuffer_1 ToInputBuffer_1(const cdm::InputBuffer_2& buffer) { 101 | return{ buffer.data, buffer.data_size, 102 | buffer.key_id, buffer.key_id_size, 103 | buffer.iv, buffer.iv_size, 104 | buffer.subsamples, buffer.num_subsamples, 105 | buffer.timestamp }; 106 | } 107 | 108 | /******************************* CdmAdapter ****************************************/ 109 | 110 | 111 | CdmAdapter::CdmAdapter( 112 | const std::string& key_system, 113 | const std::string& cdm_path, 114 | const std::string& base_path, 115 | const CdmConfig& cdm_config, 116 | CdmAdapterClient *client) 117 | : library_(0) 118 | , cdm_path_(cdm_path) 119 | , cdm_base_path_(base_path) 120 | , client_(client) 121 | , key_system_(key_system) 122 | , cdm_config_(cdm_config) 123 | , active_buffer_(0) 124 | , cdm9_(0), cdm10_(0), cdm11_(0) 125 | { 126 | //DCHECK(!key_system_.empty()); 127 | Initialize(); 128 | } 129 | 130 | CdmAdapter::~CdmAdapter() 131 | { 132 | if (cdm9_) 133 | cdm9_->Destroy(), cdm9_ = nullptr; 134 | else if (cdm10_) 135 | cdm10_->Destroy(), cdm10_ = nullptr; 136 | else if (cdm11_) 137 | cdm11_->Destroy(), cdm11_ = nullptr; 138 | else 139 | return; 140 | 141 | deinit_cdm_func(); 142 | 143 | base::UnloadNativeLibrary(library_); 144 | } 145 | 146 | void CdmAdapter::Initialize() 147 | { 148 | if (cdm9_ || cdm10_ || cdm11_) 149 | { 150 | if (cdm9_) 151 | cdm9_->Destroy(), cdm9_ = nullptr; 152 | else if (cdm10_) 153 | cdm10_->Destroy(), cdm10_ = nullptr; 154 | else if (cdm11_) 155 | cdm11_->Destroy(), cdm11_ = nullptr; 156 | base::UnloadNativeLibrary(library_); 157 | library_ = 0; 158 | } 159 | 160 | base::NativeLibraryLoadError error; 161 | library_ = base::LoadNativeLibrary(cdm_path_, &error); 162 | 163 | if (!library_) 164 | return; 165 | 166 | init_cdm_func = reinterpret_cast(base::GetFunctionPointerFromNativeLibrary(library_, MAKE_STRING(INITIALIZE_CDM_MODULE))); 167 | deinit_cdm_func = reinterpret_cast(base::GetFunctionPointerFromNativeLibrary(library_, "DeinitializeCdmModule")); 168 | create_cdm_func = reinterpret_cast(base::GetFunctionPointerFromNativeLibrary(library_, "CreateCdmInstance")); 169 | get_cdm_verion_func = reinterpret_cast(base::GetFunctionPointerFromNativeLibrary(library_, "GetCdmVersion")); 170 | 171 | if (!init_cdm_func || !create_cdm_func || !get_cdm_verion_func || !deinit_cdm_func) 172 | { 173 | base::UnloadNativeLibrary(library_); 174 | library_ = 0; 175 | return; 176 | } 177 | 178 | std::string version = get_cdm_verion_func(); 179 | version = "CDM version: " + version; 180 | 181 | #if defined(OS_WIN) 182 | // Load DXVA before sandbox lockdown to give CDM access to Output Protection 183 | // Manager (OPM). 184 | base::LoadNativeLibrary("dxva2.dll", &error); 185 | #endif // defined(OS_WIN) 186 | 187 | init_cdm_func(); 188 | 189 | cdm11_ = static_cast(create_cdm_func(11, key_system_.data(), key_system_.size(), GetCdmHost, this)); 190 | 191 | if (!cdm11_) 192 | { 193 | cdm10_ = static_cast(create_cdm_func(10, key_system_.data(), key_system_.size(), GetCdmHost, this)); 194 | 195 | if (!cdm10_) 196 | cdm9_ = reinterpret_cast(create_cdm_func(9, key_system_.data(), key_system_.size(), GetCdmHost, this)); 197 | } 198 | 199 | if (cdm9_ || cdm10_ || cdm11_) 200 | { 201 | if (cdm9_) 202 | cdm9_->Initialize(cdm_config_.allow_distinctive_identifier, 203 | cdm_config_.allow_persistent_state); 204 | else if(cdm10_) 205 | cdm10_->Initialize(cdm_config_.allow_distinctive_identifier, 206 | cdm_config_.allow_persistent_state, false); 207 | else if (cdm11_) 208 | cdm11_->Initialize(cdm_config_.allow_distinctive_identifier, 209 | cdm_config_.allow_persistent_state, false); 210 | } 211 | else 212 | { 213 | base::UnloadNativeLibrary(library_); 214 | library_ = 0; 215 | } 216 | } 217 | 218 | void CdmAdapter::SendClientMessage(const char* session, uint32_t session_size, CdmAdapterClient::CDMADPMSG msg, const uint8_t *data, size_t data_size, uint32_t status) 219 | { 220 | if (client_) 221 | client_->OnCDMMessage(session, session_size, msg, data, data_size, status); 222 | } 223 | 224 | void CdmAdapter::RemoveClient() 225 | { 226 | client_ = nullptr; 227 | } 228 | 229 | void CdmAdapter::SetServerCertificate(uint32_t promise_id, 230 | const uint8_t* server_certificate_data, 231 | uint32_t server_certificate_data_size) 232 | { 233 | if (server_certificate_data_size < limits::kMinCertificateLength || 234 | server_certificate_data_size > limits::kMaxCertificateLength) { 235 | return; 236 | } 237 | if (cdm9_) 238 | cdm9_->SetServerCertificate(promise_id, server_certificate_data, 239 | server_certificate_data_size); 240 | else if (cdm10_) 241 | cdm10_->SetServerCertificate(promise_id, server_certificate_data, 242 | server_certificate_data_size); 243 | else if (cdm11_) 244 | cdm11_->SetServerCertificate(promise_id, server_certificate_data, 245 | server_certificate_data_size); 246 | } 247 | 248 | void CdmAdapter::CreateSessionAndGenerateRequest(uint32_t promise_id, 249 | cdm::SessionType session_type, 250 | cdm::InitDataType init_data_type, 251 | const uint8_t* init_data, 252 | uint32_t init_data_size) 253 | { 254 | if (cdm9_) 255 | cdm9_->CreateSessionAndGenerateRequest( 256 | promise_id, session_type, 257 | init_data_type, init_data, 258 | init_data_size); 259 | else if (cdm10_) 260 | cdm10_->CreateSessionAndGenerateRequest( 261 | promise_id, session_type, 262 | init_data_type, init_data, 263 | init_data_size); 264 | else if (cdm11_) 265 | cdm11_->CreateSessionAndGenerateRequest( 266 | promise_id, session_type, 267 | init_data_type, init_data, 268 | init_data_size); 269 | } 270 | 271 | void CdmAdapter::LoadSession(uint32_t promise_id, 272 | cdm::SessionType session_type, 273 | const char* session_id, 274 | uint32_t session_id_size) 275 | { 276 | if (cdm9_) 277 | cdm9_->LoadSession(promise_id, session_type, 278 | session_id, session_id_size); 279 | else if (cdm10_) 280 | cdm10_->LoadSession(promise_id, session_type, 281 | session_id, session_id_size); 282 | else if (cdm11_) 283 | cdm11_->LoadSession(promise_id, session_type, 284 | session_id, session_id_size); 285 | } 286 | 287 | void CdmAdapter::UpdateSession(uint32_t promise_id, 288 | const char* session_id, 289 | uint32_t session_id_size, 290 | const uint8_t* response, 291 | uint32_t response_size) 292 | { 293 | if (cdm9_) 294 | cdm9_->UpdateSession(promise_id, session_id, session_id_size, 295 | response, response_size); 296 | else if(cdm10_) 297 | cdm10_->UpdateSession(promise_id, session_id, session_id_size, 298 | response, response_size); 299 | else if (cdm11_) 300 | cdm11_->UpdateSession(promise_id, session_id, session_id_size, 301 | response, response_size); 302 | } 303 | 304 | void CdmAdapter::CloseSession(uint32_t promise_id, 305 | const char* session_id, 306 | uint32_t session_id_size) 307 | { 308 | if (cdm9_) 309 | cdm9_->CloseSession(promise_id, session_id, session_id_size); 310 | else if (cdm10_) 311 | cdm10_->CloseSession(promise_id, session_id, session_id_size); 312 | else if (cdm11_) 313 | cdm11_->CloseSession(promise_id, session_id, session_id_size); 314 | } 315 | 316 | void CdmAdapter::RemoveSession(uint32_t promise_id, 317 | const char* session_id, 318 | uint32_t session_id_size) 319 | { 320 | if (cdm9_) 321 | cdm9_->RemoveSession(promise_id, session_id, session_id_size); 322 | else if (cdm10_) 323 | cdm10_->RemoveSession(promise_id, session_id, session_id_size); 324 | else if (cdm11_) 325 | cdm11_->RemoveSession(promise_id, session_id, session_id_size); 326 | } 327 | 328 | void CdmAdapter::TimerExpired(void* context) 329 | { 330 | if (cdm9_) 331 | cdm9_->TimerExpired(context); 332 | else if (cdm10_) 333 | cdm10_->TimerExpired(context); 334 | else if (cdm11_) 335 | cdm11_->TimerExpired(context); 336 | } 337 | 338 | cdm::Status CdmAdapter::Decrypt(const cdm::InputBuffer_2& encrypted_buffer, 339 | cdm::DecryptedBlock* decrypted_buffer) 340 | { 341 | //We need this wait here for fast systems, during buffering 342 | //widewine stopps if some seconds (5??) are fetched too fast 343 | //std::this_thread::sleep_for(std::chrono::milliseconds(5)); 344 | 345 | active_buffer_ = decrypted_buffer->DecryptedBuffer(); 346 | cdm::Status ret; 347 | 348 | if (cdm9_) 349 | ret = cdm9_->Decrypt(ToInputBuffer_1(encrypted_buffer), decrypted_buffer); 350 | else if (cdm10_) 351 | ret = cdm10_->Decrypt(encrypted_buffer, decrypted_buffer); 352 | else if (cdm11_) 353 | { 354 | cdm::InputBuffer_2 tmp(encrypted_buffer); 355 | ret = cdm11_->Decrypt(tmp, decrypted_buffer); 356 | } 357 | 358 | active_buffer_ = 0; 359 | return ret; 360 | } 361 | 362 | cdm::Status CdmAdapter::InitializeAudioDecoder( 363 | const cdm::AudioDecoderConfig_2& audio_decoder_config) 364 | { 365 | if (cdm9_) 366 | return cdm9_->InitializeAudioDecoder(ToAudioDecoderConfig_1(audio_decoder_config)); 367 | else if (cdm10_) 368 | return cdm10_->InitializeAudioDecoder(audio_decoder_config); 369 | else if (cdm11_) 370 | return cdm11_->InitializeAudioDecoder(audio_decoder_config); 371 | return cdm::kDeferredInitialization; 372 | } 373 | 374 | cdm::Status CdmAdapter::InitializeVideoDecoder( 375 | const cdm::VideoDecoderConfig_3& video_decoder_config) 376 | { 377 | if (cdm9_) 378 | return cdm9_->InitializeVideoDecoder(ToVideoDecoderConfig_1(video_decoder_config)); 379 | else if (cdm10_) 380 | return cdm10_->InitializeVideoDecoder(ToVideoDecoderConfig_2(video_decoder_config)); 381 | else if (cdm11_) 382 | return cdm11_->InitializeVideoDecoder(video_decoder_config); 383 | return cdm::kDeferredInitialization; 384 | } 385 | 386 | void CdmAdapter::DeinitializeDecoder(cdm::StreamType decoder_type) 387 | { 388 | if (cdm9_) 389 | cdm9_->DeinitializeDecoder(decoder_type); 390 | else if (cdm10_) 391 | cdm10_->DeinitializeDecoder(decoder_type); 392 | else if (cdm11_) 393 | cdm11_->DeinitializeDecoder(decoder_type); 394 | } 395 | 396 | void CdmAdapter::ResetDecoder(cdm::StreamType decoder_type) 397 | { 398 | if (cdm9_) 399 | cdm9_->ResetDecoder(decoder_type); 400 | else if (cdm10_) 401 | cdm10_->ResetDecoder(decoder_type); 402 | else if (cdm11_) 403 | cdm11_->ResetDecoder(decoder_type); 404 | } 405 | 406 | cdm::Status CdmAdapter::DecryptAndDecodeFrame(const cdm::InputBuffer_2& encrypted_buffer, 407 | CdmVideoFrame* video_frame) 408 | { 409 | cdm::Status ret(cdm::kDeferredInitialization); 410 | 411 | if (cdm9_) 412 | ret = cdm9_->DecryptAndDecodeFrame(ToInputBuffer_1(encrypted_buffer), video_frame); 413 | else if (cdm10_) 414 | ret = cdm10_->DecryptAndDecodeFrame(encrypted_buffer, video_frame); 415 | else if (cdm11_) 416 | ret = cdm11_->DecryptAndDecodeFrame(encrypted_buffer, video_frame); 417 | 418 | active_buffer_ = 0; 419 | return ret; 420 | } 421 | 422 | cdm::Status CdmAdapter::DecryptAndDecodeSamples(const cdm::InputBuffer_2& encrypted_buffer, 423 | cdm::AudioFrames* audio_frames) 424 | { 425 | if (cdm9_) 426 | return cdm9_->DecryptAndDecodeSamples(ToInputBuffer_1(encrypted_buffer), audio_frames); 427 | else if (cdm10_) 428 | return cdm10_->DecryptAndDecodeSamples(encrypted_buffer, audio_frames); 429 | else if (cdm11_) 430 | return cdm11_->DecryptAndDecodeSamples(encrypted_buffer, audio_frames); 431 | return cdm::kDeferredInitialization; 432 | } 433 | 434 | void CdmAdapter::OnPlatformChallengeResponse( 435 | const cdm::PlatformChallengeResponse& response) 436 | { 437 | if (cdm9_) 438 | cdm9_->OnPlatformChallengeResponse(response); 439 | else if (cdm10_) 440 | cdm10_->OnPlatformChallengeResponse(response); 441 | else if (cdm11_) 442 | cdm11_->OnPlatformChallengeResponse(response); 443 | } 444 | 445 | void CdmAdapter::OnQueryOutputProtectionStatus(cdm::QueryResult result, 446 | uint32_t link_mask, 447 | uint32_t output_protection_mask) 448 | { 449 | if (cdm9_) 450 | cdm9_->OnQueryOutputProtectionStatus(result, link_mask, 451 | output_protection_mask); 452 | else if (cdm10_) 453 | cdm10_->OnQueryOutputProtectionStatus(result, link_mask, 454 | output_protection_mask); 455 | else if (cdm11_) 456 | cdm11_->OnQueryOutputProtectionStatus(result, link_mask, 457 | output_protection_mask); 458 | } 459 | 460 | /******************************** HOST *****************************************/ 461 | 462 | cdm::Buffer* CdmAdapter::Allocate(uint32_t capacity) 463 | { 464 | if (active_buffer_) 465 | return active_buffer_; 466 | else 467 | return 0; 468 | } 469 | 470 | void CdmAdapter::SetTimer(int64_t delay_ms, void* context) 471 | { 472 | //LICENSERENEWAL std::thread(timerfunc, shared_from_this(), delay_ms, context).detach(); 473 | } 474 | 475 | cdm::Time CdmAdapter::GetCurrentWallTime() 476 | { 477 | cdm::Time res = static_cast(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); 478 | return res / 1000.0; 479 | } 480 | 481 | void CdmAdapter::OnResolvePromise(uint32_t promise_id) 482 | { 483 | } 484 | 485 | void CdmAdapter::OnResolveNewSessionPromise(uint32_t promise_id, 486 | const char* session_id, 487 | uint32_t session_id_size) 488 | { 489 | } 490 | 491 | void CdmAdapter::OnSessionKeysChange(const char* session_id, 492 | uint32_t session_id_size, 493 | bool has_additional_usable_key, 494 | const cdm::KeyInformation* keys_info, 495 | uint32_t keys_info_count) 496 | { 497 | for (uint32_t i(0); i < keys_info_count; ++i) 498 | { 499 | char fmtbuf[128], *fmtptr(fmtbuf+11); 500 | strcpy(fmtbuf, "Sessionkey: "); 501 | for (unsigned int j(0); j < keys_info[i].key_id_size; ++j) 502 | fmtptr += sprintf(fmtptr, "%02X", (int)keys_info[i].key_id[j]); 503 | sprintf(fmtptr, " status: %d syscode: %u", keys_info[i].status, keys_info[i].system_code); 504 | client_->CDMLog(fmtbuf); 505 | 506 | SendClientMessage(session_id, session_id_size, CdmAdapterClient::kSessionKeysChange, 507 | keys_info[i].key_id, keys_info[i].key_id_size, keys_info[i].status); 508 | } 509 | } 510 | 511 | void CdmAdapter::OnExpirationChange(const char* session_id, 512 | uint32_t session_id_size, 513 | cdm::Time new_expiry_time) 514 | { 515 | SendClientMessage(session_id, session_id_size, CdmAdapterClient::kSessionExpired, nullptr, 0, 0); 516 | } 517 | 518 | void CdmAdapter::OnSessionClosed(const char* session_id, 519 | uint32_t session_id_size) 520 | { 521 | SendClientMessage(session_id, session_id_size, CdmAdapterClient::kSessionClosed, nullptr, 0, 0); 522 | } 523 | 524 | void CdmAdapter::SendPlatformChallenge(const char* service_id, 525 | uint32_t service_id_size, 526 | const char* challenge, 527 | uint32_t challenge_size) 528 | { 529 | } 530 | 531 | void CdmAdapter::EnableOutputProtection(uint32_t desired_protection_mask) 532 | { 533 | QueryOutputProtectionStatus(); 534 | } 535 | 536 | void CdmAdapter::QueryOutputProtectionStatus() 537 | { 538 | OnQueryOutputProtectionStatus(cdm::kQuerySucceeded, cdm::kLinkTypeInternal, cdm::kProtectionHDCP); 539 | } 540 | 541 | void CdmAdapter::OnDeferredInitializationDone(cdm::StreamType stream_type, 542 | cdm::Status decoder_status) 543 | { 544 | } 545 | 546 | // The CDM owns the returned object and must call FileIO::Close() to release it. 547 | cdm::FileIO* CdmAdapter::CreateFileIO(cdm::FileIOClient* client) 548 | { 549 | return new CdmFileIoImpl(cdm_base_path_, client); 550 | } 551 | 552 | 553 | // Host_9 specific implementations 554 | void CdmAdapter::OnResolveKeyStatusPromise(uint32_t promise_id, cdm::KeyStatus key_status) 555 | { 556 | } 557 | 558 | void CdmAdapter::OnRejectPromise(uint32_t promise_id, cdm::Exception exception, 559 | uint32_t system_code, const char* error_message, uint32_t error_message_size) 560 | { 561 | } 562 | 563 | void CdmAdapter::OnSessionMessage(const char* session_id, uint32_t session_id_size, 564 | cdm::MessageType message_type, const char* message, uint32_t message_size) 565 | { 566 | SendClientMessage(session_id, session_id_size, CdmAdapterClient::kSessionMessage, reinterpret_cast(message), message_size, 0); 567 | } 568 | 569 | void CdmAdapter::RequestStorageId(uint32_t version) 570 | { 571 | if (cdm10_) 572 | cdm10_->OnStorageId(1, nullptr, 0); 573 | else if (cdm11_) 574 | cdm11_->OnStorageId(1, nullptr, 0); 575 | } 576 | 577 | void CdmAdapter::OnInitialized(bool success) 578 | { 579 | char fmtbuf[64]; 580 | sprintf(fmtbuf, "cdm::OnInitialized: %s", success ? "true" : "false"); 581 | } 582 | 583 | 584 | /******************************* CdmFileIoImpl ****************************************/ 585 | 586 | CdmFileIoImpl::CdmFileIoImpl(std::string base_path, cdm::FileIOClient* client) 587 | : base_path_(base_path) 588 | , client_(client) 589 | , file_descriptor_(0) 590 | , data_buffer_(0) 591 | , opened_(false) 592 | { 593 | } 594 | 595 | void CdmFileIoImpl::Open(const char* file_name, uint32_t file_name_size) 596 | { 597 | if (!opened_) 598 | { 599 | opened_ = true; 600 | base_path_ += std::string(file_name, file_name_size); 601 | client_->OnOpenComplete(cdm::FileIOClient::Status::kSuccess); 602 | } 603 | else 604 | client_->OnOpenComplete(cdm::FileIOClient::Status::kInUse); 605 | } 606 | 607 | void CdmFileIoImpl::Read() 608 | { 609 | cdm::FileIOClient::Status status(cdm::FileIOClient::Status::kError); 610 | size_t sz(0); 611 | 612 | free(reinterpret_cast(data_buffer_)); 613 | data_buffer_ = nullptr; 614 | 615 | file_descriptor_ = fopen(base_path_.c_str(), "rb"); 616 | 617 | if (file_descriptor_) 618 | { 619 | status = cdm::FileIOClient::Status::kSuccess; 620 | fseek(file_descriptor_, 0, SEEK_END); 621 | sz = ftell(file_descriptor_); 622 | if (sz) 623 | { 624 | fseek(file_descriptor_, 0, SEEK_SET); 625 | if ((data_buffer_ = reinterpret_cast(malloc(sz))) == nullptr || fread(data_buffer_, 1, sz, file_descriptor_) != sz) 626 | status = cdm::FileIOClient::Status::kError; 627 | } 628 | } else 629 | status = cdm::FileIOClient::Status::kSuccess; 630 | client_->OnReadComplete(status, data_buffer_, sz); 631 | } 632 | 633 | void CdmFileIoImpl::Write(const uint8_t* data, uint32_t data_size) 634 | { 635 | cdm::FileIOClient::Status status(cdm::FileIOClient::Status::kError); 636 | file_descriptor_ = fopen(base_path_.c_str(), "wb"); 637 | 638 | if (file_descriptor_) 639 | { 640 | if (fwrite(data, 1, data_size, file_descriptor_) == data_size) 641 | status = cdm::FileIOClient::Status::kSuccess; 642 | } 643 | client_->OnWriteComplete(status); 644 | } 645 | 646 | void CdmFileIoImpl::Close() 647 | { 648 | if (file_descriptor_) 649 | { 650 | fclose(file_descriptor_); 651 | file_descriptor_ = 0; 652 | } 653 | client_ = 0; 654 | free(reinterpret_cast(data_buffer_)); 655 | data_buffer_ = 0; 656 | delete this; 657 | } 658 | 659 | } // namespace media 660 | -------------------------------------------------------------------------------- /cdm/media/cdm/cdm_adapter.h: -------------------------------------------------------------------------------- 1 | #ifndef MEDIA_CDM_CDM_ADAPTER_H_ 2 | #define MEDIA_CDM_CDM_ADAPTER_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "../../base/native_library.h" 10 | #include "../../base/compiler_specific.h" 11 | #include "../../base/macros.h" 12 | #include "api/content_decryption_module.h" 13 | #include "../base/cdm_config.h" 14 | 15 | namespace media { 16 | 17 | uint64_t gtc(); 18 | 19 | class CdmAdapterClient 20 | { 21 | public: 22 | enum CDMADPMSG 23 | { 24 | kError, 25 | kSessionMessage, 26 | kSessionExpired, 27 | kSessionKeysChange, 28 | kSessionClosed, 29 | kLegacySessionError 30 | }; 31 | virtual void OnCDMMessage(const char* session, uint32_t session_size, CDMADPMSG msg, const uint8_t *data, size_t data_size, uint32_t status) = 0; 32 | virtual void CDMLog(const char *msg) = 0; 33 | }; 34 | 35 | class CdmVideoFrame : public cdm::VideoFrame, public cdm::VideoFrame_2 { 36 | public: 37 | CdmVideoFrame() = default; 38 | 39 | void SetFormat(cdm::VideoFormat format) override { m_format = format; } 40 | cdm::VideoFormat Format() const override { return m_format; } 41 | void SetSize(cdm::Size size) override { m_size = size; } 42 | cdm::Size Size() const override { return m_size; } 43 | void SetFrameBuffer(cdm::Buffer* frame_buffer) override { m_buffer = frame_buffer; } 44 | cdm::Buffer* FrameBuffer() override { return m_buffer; } 45 | void SetPlaneOffset(cdm::VideoPlane plane, uint32_t offset) override { m_planeOffsets[plane] = offset; } 46 | void SetColorSpace(cdm::ColorSpace color_space) { m_colorSpace = color_space; }; 47 | 48 | virtual uint32_t PlaneOffset(cdm::VideoPlane plane) override { return m_planeOffsets[plane]; } 49 | virtual void SetStride(cdm::VideoPlane plane, uint32_t stride) override { m_stride[plane] = stride; } 50 | virtual uint32_t Stride(cdm::VideoPlane plane) override { return m_stride[plane]; } 51 | virtual void SetTimestamp(int64_t timestamp) override { m_pts = timestamp; } 52 | 53 | virtual int64_t Timestamp() const override { return m_pts; } 54 | private: 55 | cdm::VideoFormat m_format; 56 | cdm::Buffer *m_buffer = nullptr; 57 | cdm::Size m_size; 58 | cdm::ColorSpace m_colorSpace; 59 | 60 | uint32_t m_planeOffsets[cdm::VideoPlane::kMaxPlanes]; 61 | uint32_t m_stride[cdm::VideoPlane::kMaxPlanes]; 62 | 63 | uint64_t m_pts; 64 | }; 65 | 66 | class CdmAdapter : public std::enable_shared_from_this 67 | , public cdm::Host_9 68 | , public cdm::Host_10 69 | , public cdm::Host_11 70 | { 71 | public: 72 | CdmAdapter(const std::string& key_system, 73 | const std::string& cdm_path, 74 | const std::string& base_path, 75 | const CdmConfig& cdm_config, 76 | CdmAdapterClient *client); 77 | 78 | void RemoveClient(); 79 | 80 | void SetServerCertificate(uint32_t promise_id, 81 | const uint8_t* server_certificate_data, 82 | uint32_t server_certificate_data_size); 83 | 84 | void CreateSessionAndGenerateRequest(uint32_t promise_id, 85 | cdm::SessionType session_type, 86 | cdm::InitDataType init_data_type, 87 | const uint8_t* init_data, 88 | uint32_t init_data_size); 89 | 90 | void LoadSession(uint32_t promise_id, 91 | cdm::SessionType session_type, 92 | const char* session_id, 93 | uint32_t session_id_size); 94 | 95 | void UpdateSession(uint32_t promise_id, 96 | const char* session_id, 97 | uint32_t session_id_size, 98 | const uint8_t* response, 99 | uint32_t response_size); 100 | 101 | void CloseSession(uint32_t promise_id, 102 | const char* session_id, 103 | uint32_t session_id_size); 104 | 105 | void RemoveSession(uint32_t promise_id, 106 | const char* session_id, 107 | uint32_t session_id_size); 108 | 109 | void TimerExpired(void* context); 110 | 111 | cdm::Status Decrypt(const cdm::InputBuffer_2& encrypted_buffer, 112 | cdm::DecryptedBlock* decrypted_buffer); 113 | 114 | cdm::Status InitializeAudioDecoder( 115 | const cdm::AudioDecoderConfig_2& audio_decoder_config); 116 | 117 | cdm::Status InitializeVideoDecoder( 118 | const cdm::VideoDecoderConfig_3& video_decoder_config); 119 | 120 | void DeinitializeDecoder(cdm::StreamType decoder_type); 121 | 122 | void ResetDecoder(cdm::StreamType decoder_type); 123 | 124 | cdm::Status DecryptAndDecodeFrame(const cdm::InputBuffer_2& encrypted_buffer, 125 | CdmVideoFrame* video_frame); 126 | 127 | cdm::Status DecryptAndDecodeSamples(const cdm::InputBuffer_2& encrypted_buffer, 128 | cdm::AudioFrames* audio_frames); 129 | 130 | void OnPlatformChallengeResponse( 131 | const cdm::PlatformChallengeResponse& response); 132 | 133 | void OnQueryOutputProtectionStatus(cdm::QueryResult result, 134 | uint32_t link_mask, 135 | uint32_t output_protection_mask); 136 | 137 | // cdm::Host implementation. 138 | 139 | cdm::Buffer* Allocate(uint32_t capacity) override; 140 | 141 | void SetTimer(int64_t delay_ms, void* context) override; 142 | 143 | cdm::Time GetCurrentWallTime() override; 144 | 145 | void OnResolveKeyStatusPromise(uint32_t promise_id, 146 | cdm::KeyStatus key_status) override; 147 | 148 | void OnResolveNewSessionPromise(uint32_t promise_id, 149 | const char* session_id, 150 | uint32_t session_id_size) override; 151 | 152 | void OnResolvePromise(uint32_t promise_id) override; 153 | 154 | void OnRejectPromise(uint32_t promise_id, 155 | cdm::Exception exception, 156 | uint32_t system_code, 157 | const char* error_message, 158 | uint32_t error_message_size) override; 159 | 160 | void OnSessionMessage(const char* session_id, 161 | uint32_t session_id_size, 162 | cdm::MessageType message_type, 163 | const char* message, 164 | uint32_t message_size) override; 165 | 166 | void OnSessionKeysChange(const char* session_id, 167 | uint32_t session_id_size, 168 | bool has_additional_usable_key, 169 | const cdm::KeyInformation* keys_info, 170 | uint32_t keys_info_count) override; 171 | 172 | void OnExpirationChange(const char* session_id, 173 | uint32_t session_id_size, 174 | cdm::Time new_expiry_time) override; 175 | 176 | void OnSessionClosed(const char* session_id, 177 | uint32_t session_id_size) override; 178 | 179 | void SendPlatformChallenge(const char* service_id, 180 | uint32_t service_id_size, 181 | const char* challenge, 182 | uint32_t challenge_size) override; 183 | 184 | void EnableOutputProtection(uint32_t desired_protection_mask) override; 185 | 186 | void QueryOutputProtectionStatus() override; 187 | 188 | void OnDeferredInitializationDone(cdm::StreamType stream_type, 189 | cdm::Status decoder_status) override; 190 | 191 | cdm::FileIO* CreateFileIO(cdm::FileIOClient* client) override; 192 | 193 | void RequestStorageId(uint32_t version) override; 194 | 195 | cdm::CdmProxy* RequestCdmProxy(cdm::CdmProxyClient* client) override { return nullptr; }; 196 | 197 | void OnInitialized(bool success) override; 198 | 199 | 200 | public: //Misc 201 | ~CdmAdapter(); 202 | bool valid(){ return library_ != 0; }; 203 | private: 204 | using InitializeCdmModuleFunc = void(*)(); 205 | using DeinitializeCdmModuleFunc = void(*)(); 206 | using GetCdmVersionFunc = char* (*)(); 207 | using CreateCdmFunc = void* (*)(int cdm_interface_version, 208 | const char* key_system, 209 | uint32_t key_system_size, 210 | GetCdmHostFunc get_cdm_host_func, 211 | void* user_data); 212 | 213 | InitializeCdmModuleFunc init_cdm_func; 214 | CreateCdmFunc create_cdm_func; 215 | GetCdmVersionFunc get_cdm_verion_func; 216 | DeinitializeCdmModuleFunc deinit_cdm_func; 217 | 218 | void Initialize(); 219 | void SendClientMessage(const char* session, uint32_t session_size, CdmAdapterClient::CDMADPMSG msg, const uint8_t *data, size_t data_size, uint32_t status); 220 | 221 | // Keep a reference to the CDM. 222 | base::NativeLibrary library_; 223 | 224 | std::string cdm_path_; 225 | std::string cdm_base_path_; 226 | CdmAdapterClient *client_; 227 | 228 | std::string key_system_; 229 | CdmConfig cdm_config_; 230 | 231 | cdm::MessageType message_type_; 232 | cdm::Buffer *active_buffer_; 233 | 234 | cdm::ContentDecryptionModule_9 *cdm9_; 235 | cdm::ContentDecryptionModule_10 *cdm10_; 236 | cdm::ContentDecryptionModule_11 *cdm11_; 237 | 238 | DISALLOW_COPY_AND_ASSIGN(CdmAdapter); 239 | }; 240 | 241 | class CdmFileIoImpl : NON_EXPORTED_BASE(public cdm::FileIO) 242 | { 243 | public: 244 | CdmFileIoImpl(std::string base_path, cdm::FileIOClient* client); 245 | 246 | virtual void Open(const char* file_name, uint32_t file_name_size) override; 247 | virtual void Read() override; 248 | virtual void Write(const uint8_t* data, uint32_t data_size) override; 249 | virtual void Close() override; 250 | 251 | private: 252 | std::string base_path_; 253 | cdm::FileIOClient* client_; 254 | FILE *file_descriptor_; 255 | uint8_t *data_buffer_; 256 | bool opened_; 257 | }; 258 | 259 | 260 | } // namespace media 261 | 262 | #endif // MEDIA_CDM_CDM_ADAPTER_H_ 263 | -------------------------------------------------------------------------------- /wvadapter.cpp: -------------------------------------------------------------------------------- 1 | #include "wvadapter.h" 2 | #include 3 | #include 4 | #include 5 | 6 | const uint8_t init_data[50] = { 7 | 0x00, 0x00, 0x00, 0x32, 0x70, 0x73, 0x73, 0x68, 0x00, 0x00, 0x00, 0x00, 8 | 0xed, 0xef, 0x8b, 0xa9, 0x79, 0xd6, 0x4a, 0xce, 0xa3, 0xc8, 0x27, 0xdc, 9 | 0xd5, 0x1d, 0x21, 0xed, 0x00, 0x00, 0x00, 0x12, 0x12, 0x10, 0x2c, 0x56, 10 | 0x12, 0x69, 0x3a, 0xc9, 0x49, 0x5b, 0xa5, 0x04, 0xab, 0xac, 0xa2, 0xd4, 11 | 0x5b, 0x3c 12 | }; 13 | 14 | uint8_t* _block; 15 | bool first_except; 16 | HANDLE wv_handle; 17 | 18 | LONG NTAPI crypt_injection(PEXCEPTION_POINTERS except_info) 19 | { 20 | if (first_except) 21 | { 22 | first_except = false; 23 | 24 | byte* code = new byte[19]{ 0x48, 0xBA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x89, 0x94, 0x24, 0x68, 0x24, 0x00, 0x00, 0x90 }; 25 | memcpy(&code[2], &_block, 8); 26 | 27 | intptr_t inject_address = (intptr_t)wv_handle + 0x32f0de; 28 | 29 | DWORD old_protect; 30 | VirtualProtect((void*)inject_address, 19, PAGE_EXECUTE_READWRITE, &old_protect); 31 | memcpy((void*)inject_address, code, 19); 32 | VirtualProtect((void*)inject_address, 19, old_protect, &old_protect); 33 | } 34 | else 35 | { 36 | except_info->ContextRecord->Dr1 = 0x0; 37 | except_info->ContextRecord->Dr6 = 0x0; 38 | except_info->ContextRecord->Dr7 = 0x0; 39 | except_info->ContextRecord->EFlags = 0x0001; 40 | } 41 | 42 | return EXCEPTION_CONTINUE_EXECUTION; 43 | } 44 | 45 | Adapter::Adapter() 46 | { 47 | 48 | } 49 | 50 | Adapter::~Adapter() 51 | { 52 | if (!session_id.empty()) 53 | { 54 | wv_adapter->CloseSession(++promise_id, session_id.data(), session_id.size()); 55 | wv_adapter->RemoveSession(++promise_id, session_id.data(), session_id.size()); 56 | } 57 | wv_adapter->~CdmAdapter(); 58 | } 59 | 60 | void Adapter::OnCDMMessage(const char* session, uint32_t session_size, CDMADPMSG msg, const uint8_t* data, size_t data_size, uint32_t status) 61 | { 62 | if (msg == CDMADPMSG::kSessionMessage) 63 | { 64 | challenge_len = data_size; 65 | challenge = new uint8_t[challenge_len]; 66 | memcpy(challenge, data, challenge_len); 67 | 68 | session_id = session; 69 | } 70 | } 71 | 72 | void Adapter::CDMLog(const char* msg) 73 | { 74 | return; 75 | } 76 | 77 | bool Adapter::rsa_crypt(uint8_t* in, uint8_t* out, char* cdm_path) 78 | { 79 | _block = in; 80 | std::string basepath = cdm_path; 81 | basepath = basepath.substr(0, basepath.size() - 15); 82 | 83 | wv_adapter = std::shared_ptr(new media::CdmAdapter( 84 | "com.widevine.alpha", 85 | cdm_path, 86 | basepath, 87 | media::CdmConfig(false, false), 88 | (dynamic_cast(this)))); 89 | 90 | if (!wv_adapter->valid()) 91 | { 92 | wv_adapter = nullptr; 93 | return NULL; 94 | } 95 | 96 | wv_handle = GetModuleHandle("widevinecdm.dll"); 97 | 98 | intptr_t breakpoint_address = (intptr_t)wv_handle + 0x6addcb; 99 | 100 | current_thread = GetCurrentThread(); 101 | GetThreadContext(current_thread, ¤t_context); 102 | 103 | CONTEXT ctx = {}; 104 | ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS; 105 | 106 | ctx.Dr0 = breakpoint_address; 107 | ctx.Dr1 = 0x00000000; 108 | ctx.Dr2 = 0x00000000; 109 | ctx.Dr3 = 0x00000000; 110 | ctx.Dr6 = 0xFFFF0FF1; 111 | ctx.Dr7 = 0x00000401; 112 | 113 | SetThreadContext(current_thread, &ctx); 114 | if (except_handler = AddVectoredExceptionHandler(0, crypt_injection)) 115 | { 116 | first_except = true; 117 | wv_adapter->CreateSessionAndGenerateRequest(++promise_id, cdm::SessionType::kTemporary, cdm::InitDataType::kCenc, init_data, 50); 118 | RemoveVectoredExceptionHandler(except_handler); 119 | } 120 | 121 | int retries = 0; 122 | while (session_id.empty() && ++retries < 10) 123 | std::this_thread::sleep_for(std::chrono::milliseconds(10)); 124 | 125 | if (session_id.empty() || !challenge_len) 126 | { 127 | return false; 128 | } 129 | 130 | memcpy(out, &challenge[challenge_len - 256], 256); 131 | 132 | return true; 133 | } 134 | 135 | extern "C" 136 | { 137 | EXPORT_API void rsa_crypt(uint8_t* in, uint8_t* out, char* cdm_path) 138 | { 139 | Adapter* a = new Adapter(); 140 | a->rsa_crypt(in, out, cdm_path); 141 | } 142 | } 143 | 144 | #pragma region cli 145 | 146 | int char_to_int(char input) 147 | { 148 | if (input >= '0' && input <= '9') 149 | return input - '0'; 150 | if (input >= 'A' && input <= 'F') 151 | return input - 'A' + 10; 152 | if (input >= 'a' && input <= 'f') 153 | return input - 'a' + 10; 154 | return 0; 155 | } 156 | 157 | void hex_to_bytes(const char* hex, uint8_t* bytes) 158 | { 159 | while (*hex && hex[1]) 160 | { 161 | *(bytes++) = char_to_int(*hex) * 16 + char_to_int(hex[1]); 162 | hex += 2; 163 | } 164 | } 165 | 166 | std::string bytes_to_hex(uint8_t* bytes, int len) 167 | { 168 | std::stringstream ss; 169 | ss << std::hex; 170 | 171 | for (int i(0); i < len; ++i) 172 | ss << std::setw(2) << std::setfill('0') << (int)bytes[i]; 173 | 174 | return ss.str(); 175 | } 176 | 177 | int main(int argc, char* argv[]) 178 | { 179 | if (argc != 3) 180 | { 181 | std::cout << "Wrong arg count\nUsage: wvadapter [data (hex)] [cdm_path]" << std::endl; 182 | return 0; 183 | } 184 | 185 | char* in_hex = argv[1]; 186 | char* cdm_path = argv[2]; 187 | 188 | uint8_t* in = new uint8_t[256]; 189 | uint8_t* out = new uint8_t[256]; 190 | hex_to_bytes(in_hex, in); 191 | 192 | Adapter* a = new Adapter(); 193 | a->rsa_crypt(in, out, cdm_path); 194 | 195 | std::cout << bytes_to_hex(out, 256) << std::endl; 196 | } 197 | 198 | #pragma endregion -------------------------------------------------------------------------------- /wvadapter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "cdm/media/cdm/cdm_adapter.h" 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | class Adapter : public media::CdmAdapterClient 13 | { 14 | private: 15 | std::shared_ptr wv_adapter; 16 | std::string session_id; 17 | uint8_t* challenge; 18 | int challenge_len = 0; 19 | int promise_id = 1; 20 | 21 | PVOID except_handler; 22 | HANDLE current_thread; 23 | CONTEXT current_context; 24 | 25 | public: 26 | Adapter(); 27 | ~Adapter(); 28 | 29 | virtual void OnCDMMessage(const char* session, uint32_t session_size, CDMADPMSG msg, const uint8_t* data, size_t data_size, uint32_t status); 30 | virtual void CDMLog(const char* msg); 31 | 32 | bool rsa_crypt(uint8_t* in, uint8_t* out, char* cdm_path); 33 | }; 34 | 35 | #define EXPORT_API __declspec(dllexport) 36 | -------------------------------------------------------------------------------- /wvadapter.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | {03C0089A-91EA-4941-A735-73E4D5938100} 24 | Win32Proj 25 | 26 | 27 | 28 | Application 29 | true 30 | v142 31 | 32 | 33 | Application 34 | false 35 | v142 36 | 37 | 38 | Application 39 | true 40 | v142 41 | 42 | 43 | Application 44 | false 45 | v142 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | true 67 | 68 | 69 | true 70 | 71 | 72 | 73 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 74 | MultiThreadedDebugDLL 75 | Level3 76 | ProgramDatabase 77 | Disabled 78 | 79 | 80 | MachineX86 81 | true 82 | Console 83 | 84 | 85 | 86 | 87 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 88 | MultiThreadedDLL 89 | Level3 90 | ProgramDatabase 91 | 92 | 93 | MachineX86 94 | true 95 | Console 96 | true 97 | true 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | --------------------------------------------------------------------------------