tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

gmp-clearkey.cpp (5121B)


      1 /*
      2 * Copyright 2015, Mozilla Foundation and contributors
      3 *
      4 * Licensed under the Apache License, Version 2.0 (the "License");
      5 * you may not use this file except in compliance with the License.
      6 * You may obtain a copy of the License at
      7 *
      8 * http://www.apache.org/licenses/LICENSE-2.0
      9 *
     10 * Unless required by applicable law or agreed to in writing, software
     11 * distributed under the License is distributed on an "AS IS" BASIS,
     12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 * See the License for the specific language governing permissions and
     14 * limitations under the License.
     15 */
     16 
     17 #include <assert.h>
     18 // This include is required in order for content_decryption_module to work
     19 // on Unix systems.
     20 #include <stddef.h>
     21 #include <string.h>
     22 
     23 #include <string>
     24 #include <vector>
     25 
     26 #include "content_decryption_module.h"
     27 #include "content_decryption_module_ext.h"
     28 #include "nss.h"
     29 
     30 #include "ClearKeyCDM.h"
     31 #include "ClearKeySessionManager.h"
     32 #include "mozilla/dom/KeySystemNames.h"
     33 
     34 #ifndef XP_WIN
     35 #  include <sys/types.h>
     36 #  include <sys/stat.h>
     37 #  include <unistd.h>
     38 #endif
     39 
     40 #ifdef ENABLE_WMF
     41 #  include "WMFUtils.h"
     42 #endif  // ENABLE_WMF
     43 
     44 extern "C" {
     45 
     46 CDM_API
     47 void INITIALIZE_CDM_MODULE() {}
     48 
     49 static bool sCanReadHostVerificationFiles = false;
     50 
     51 CDM_API
     52 void* CreateCdmInstance(int cdm_interface_version, const char* key_system,
     53                        uint32_t key_system_size,
     54                        GetCdmHostFunc get_cdm_host_func, void* user_data) {
     55  CK_LOGE("ClearKey CreateCDMInstance");
     56 
     57  if (cdm_interface_version != cdm::ContentDecryptionModule_11::kVersion) {
     58    CK_LOGE(
     59        "ClearKey CreateCDMInstance failed due to requesting unsupported "
     60        "version %d.",
     61        cdm_interface_version);
     62    return nullptr;
     63  }
     64 #ifdef ENABLE_WMF
     65  if (!wmf::EnsureLibs()) {
     66    CK_LOGE("Required libraries were not found");
     67    return nullptr;
     68  }
     69 #endif
     70 
     71  if (NSS_NoDB_Init(nullptr) == SECFailure) {
     72    CK_LOGE("Unable to initialize NSS");
     73    return nullptr;
     74  }
     75 
     76 #ifdef MOZILLA_OFFICIAL
     77  // Test that we're able to read the host files.
     78  if (!sCanReadHostVerificationFiles) {
     79    return nullptr;
     80  }
     81 #endif
     82 
     83  cdm::Host_11* host = static_cast<cdm::Host_11*>(
     84      get_cdm_host_func(cdm_interface_version, user_data));
     85  ClearKeyCDM* clearKey = new ClearKeyCDM(host);
     86 
     87  CK_LOGE("Created ClearKeyCDM instance!");
     88 
     89  if (strncmp(key_system, mozilla::kClearKeyWithProtectionQueryKeySystemName,
     90              key_system_size) == 0) {
     91    CK_LOGE("Enabling protection query on ClearKeyCDM instance!");
     92    clearKey->EnableProtectionQuery();
     93  }
     94 
     95  return clearKey;
     96 }
     97 
     98 const size_t TEST_READ_SIZE = 16 * 1024;
     99 
    100 bool CanReadSome(cdm::PlatformFile aFile) {
    101  std::vector<uint8_t> data;
    102  data.resize(TEST_READ_SIZE);
    103 #ifdef XP_WIN
    104  DWORD bytesRead = 0;
    105  return ReadFile(aFile, &data.front(), TEST_READ_SIZE, &bytesRead, nullptr) &&
    106         bytesRead > 0;
    107 #else
    108  return read(aFile, &data.front(), TEST_READ_SIZE) > 0;
    109 #endif
    110 }
    111 
    112 void ClosePlatformFile(cdm::PlatformFile aFile) {
    113 #ifdef XP_WIN
    114  CloseHandle(aFile);
    115 #else
    116  close(aFile);
    117 #endif
    118 }
    119 
    120 static uint32_t NumExpectedHostFiles(const cdm::HostFile* aHostFiles,
    121                                     uint32_t aNumFiles) {
    122 #if defined(ANDROID)
    123  // We expect 1 binary: clearkey
    124  return 1;
    125 #elif !defined(XP_WIN)
    126  // We expect 4 binaries: clearkey, libxul, plugin-container, and Firefox.
    127  return 4;
    128 #else
    129  // Windows running x64 or x86 natively should also have 4 as above.
    130  // For Windows on ARM64, we run an x86 plugin-contianer process under
    131  // emulation, and so we expect one additional binary; the x86
    132  // xul.dll used by plugin-container.exe.
    133  bool i686underAArch64 = false;
    134  // Assume that we're running under x86 emulation on an aarch64 host if
    135  // one of the paths ends with the x86 plugin-container path we'd expect.
    136  const std::wstring plugincontainer = L"i686\\plugin-container.exe";
    137  for (uint32_t i = 0; i < aNumFiles; i++) {
    138    const cdm::HostFile& hostFile = aHostFiles[i];
    139    if (hostFile.file != cdm::kInvalidPlatformFile) {
    140      std::wstring path = hostFile.file_path;
    141      auto offset = path.find(plugincontainer);
    142      if (offset != std::string::npos &&
    143          offset == path.size() - plugincontainer.size()) {
    144        i686underAArch64 = true;
    145        break;
    146      }
    147    }
    148  }
    149  return i686underAArch64 ? 5 : 4;
    150 #endif
    151 }
    152 
    153 CDM_API
    154 bool VerifyCdmHost_0(const cdm::HostFile* aHostFiles, uint32_t aNumFiles) {
    155  // Check that we've received the expected number of host files.
    156  bool rv = (aNumFiles == NumExpectedHostFiles(aHostFiles, aNumFiles));
    157  // Verify that each binary is readable inside the sandbox,
    158  // and close the handle.
    159  for (uint32_t i = 0; i < aNumFiles; i++) {
    160    const cdm::HostFile& hostFile = aHostFiles[i];
    161    if (hostFile.file != cdm::kInvalidPlatformFile) {
    162      if (!CanReadSome(hostFile.file)) {
    163        rv = false;
    164      }
    165      ClosePlatformFile(hostFile.file);
    166    }
    167    if (hostFile.sig_file != cdm::kInvalidPlatformFile) {
    168      ClosePlatformFile(hostFile.sig_file);
    169    }
    170  }
    171  sCanReadHostVerificationFiles = rv;
    172  return rv;
    173 }
    174 
    175 }  // extern "C".