1 // Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary 2 // source code may only be used and distributed under the Widevine Master 3 // License Agreement. 4 5 #include <utils/Log.h> 6 7 #include <string> 8 #include <sys/stat.h> 9 10 #include "DeviceFiles.h" 11 #include "Utils.h" 12 13 #include <openssl/sha.h> 14 15 // Protobuf generated classes. 16 using android::hardware::drm::V1_2::clearkey::OfflineFile; 17 using android::hardware::drm::V1_2::clearkey::HashedFile; 18 using android::hardware::drm::V1_2::clearkey::License; 19 using android::hardware::drm::V1_2::clearkey::License_LicenseState_ACTIVE; 20 using android::hardware::drm::V1_2::clearkey::License_LicenseState_RELEASING; 21 22 namespace { 23 const char kLicenseFileNameExt[] = ".lic"; 24 25 bool Hash(const std::string& data, std::string* hash) { 26 if (!hash) return false; 27 28 hash->resize(SHA256_DIGEST_LENGTH); 29 30 const unsigned char* input = reinterpret_cast<const unsigned char*>(data.data()); 31 unsigned char* output = reinterpret_cast<unsigned char*>(&(*hash)[0]); 32 SHA256(input, data.size(), output); 33 return true; 34 } 35 36 } // namespace 37 38 namespace android { 39 namespace hardware { 40 namespace drm { 41 namespace V1_2 { 42 namespace clearkey { 43 44 bool DeviceFiles::StoreLicense( 45 const std::string& keySetId, LicenseState state, 46 const std::string& licenseResponse) { 47 48 OfflineFile file; 49 file.set_type(OfflineFile::LICENSE); 50 file.set_version(OfflineFile::VERSION_1); 51 52 License* license = file.mutable_license(); 53 switch (state) { 54 case kLicenseStateActive: 55 license->set_state(License_LicenseState_ACTIVE); 56 license->set_license(licenseResponse); 57 break; 58 case kLicenseStateReleasing: 59 license->set_state(License_LicenseState_RELEASING); 60 license->set_license(licenseResponse); 61 break; 62 default: 63 ALOGW("StoreLicense: Unknown license state: %u", state); 64 return false; 65 } 66 67 std::string serializedFile; 68 file.SerializeToString(&serializedFile); 69 70 return StoreFileWithHash(keySetId + kLicenseFileNameExt, serializedFile); 71 } 72 73 bool DeviceFiles::StoreFileWithHash(const std::string& fileName, 74 const std::string& serializedFile) { 75 std::string hash; 76 if (!Hash(serializedFile, &hash)) { 77 ALOGE("StoreFileWithHash: Failed to compute hash"); 78 return false; 79 } 80 81 HashedFile hashFile; 82 hashFile.set_file(serializedFile); 83 hashFile.set_hash(hash); 84 85 std::string serializedHashFile; 86 hashFile.SerializeToString(&serializedHashFile); 87 88 return StoreFileRaw(fileName, serializedHashFile); 89 } 90 91 bool DeviceFiles::StoreFileRaw(const std::string& fileName, const std::string& serializedHashFile) { 92 MemoryFileSystem::MemoryFile memFile; 93 memFile.setFileName(fileName); 94 memFile.setContent(serializedHashFile); 95 memFile.setFileSize(serializedHashFile.size()); 96 size_t len = mFileHandle.Write(fileName, memFile); 97 98 if (len != static_cast<size_t>(serializedHashFile.size())) { 99 ALOGE("StoreFileRaw: Failed to write %s", fileName.c_str()); 100 ALOGD("StoreFileRaw: expected=%zd, actual=%zu", serializedHashFile.size(), len); 101 return false; 102 } 103 104 ALOGD("StoreFileRaw: wrote %zu bytes to %s", serializedHashFile.size(), fileName.c_str()); 105 return true; 106 } 107 108 bool DeviceFiles::RetrieveLicense( 109 const std::string& keySetId, LicenseState* state, std::string* offlineLicense) { 110 111 OfflineFile file; 112 if (!RetrieveHashedFile(keySetId + kLicenseFileNameExt, &file)) { 113 return false; 114 } 115 116 if (file.type() != OfflineFile::LICENSE) { 117 ALOGE("RetrieveLicense: Invalid file type"); 118 return false; 119 } 120 121 if (file.version() != OfflineFile::VERSION_1) { 122 ALOGE("RetrieveLicense: Invalid file version"); 123 return false; 124 } 125 126 if (!file.has_license()) { 127 ALOGE("RetrieveLicense: License not present"); 128 return false; 129 } 130 131 License license = file.license(); 132 switch (license.state()) { 133 case License_LicenseState_ACTIVE: 134 *state = kLicenseStateActive; 135 break; 136 case License_LicenseState_RELEASING: 137 *state = kLicenseStateReleasing; 138 break; 139 default: 140 ALOGW("RetrieveLicense: Unrecognized license state: %u", 141 kLicenseStateUnknown); 142 *state = kLicenseStateUnknown; 143 break; 144 } 145 *offlineLicense = license.license(); 146 return true; 147 } 148 149 bool DeviceFiles::DeleteLicense(const std::string& keySetId) { 150 return mFileHandle.RemoveFile(keySetId + kLicenseFileNameExt); 151 } 152 153 bool DeviceFiles::DeleteAllLicenses() { 154 return mFileHandle.RemoveAllFiles(); 155 } 156 157 bool DeviceFiles::LicenseExists(const std::string& keySetId) { 158 return mFileHandle.FileExists(keySetId + kLicenseFileNameExt); 159 } 160 161 std::vector<std::string> DeviceFiles::ListLicenses() const { 162 std::vector<std::string> licenses = mFileHandle.ListFiles(); 163 for (size_t i = 0; i < licenses.size(); i++) { 164 std::string& license = licenses[i]; 165 license = license.substr(0, license.size() - strlen(kLicenseFileNameExt)); 166 } 167 return licenses; 168 } 169 170 bool DeviceFiles::RetrieveHashedFile(const std::string& fileName, OfflineFile* deSerializedFile) { 171 if (!deSerializedFile) { 172 ALOGE("RetrieveHashedFile: invalid file parameter"); 173 return false; 174 } 175 176 if (!FileExists(fileName)) { 177 ALOGE("RetrieveHashedFile: %s does not exist", fileName.c_str()); 178 return false; 179 } 180 181 ssize_t bytes = GetFileSize(fileName); 182 if (bytes <= 0) { 183 ALOGE("RetrieveHashedFile: invalid file size: %s", fileName.c_str()); 184 // Remove the corrupted file so the caller will not get the same error 185 // when trying to access the file repeatedly, causing the system to stall. 186 RemoveFile(fileName); 187 return false; 188 } 189 190 std::string serializedHashFile; 191 serializedHashFile.resize(bytes); 192 bytes = mFileHandle.Read(fileName, &serializedHashFile); 193 194 if (bytes != static_cast<ssize_t>(serializedHashFile.size())) { 195 ALOGE("RetrieveHashedFile: Failed to read from %s", fileName.c_str()); 196 ALOGV("RetrieveHashedFile: expected: %zd, actual: %zd", serializedHashFile.size(), bytes); 197 // Remove the corrupted file so the caller will not get the same error 198 // when trying to access the file repeatedly, causing the system to stall. 199 RemoveFile(fileName); 200 return false; 201 } 202 203 ALOGV("RetrieveHashedFile: read %zd from %s", bytes, fileName.c_str()); 204 205 HashedFile hashFile; 206 if (!hashFile.ParseFromString(serializedHashFile)) { 207 ALOGE("RetrieveHashedFile: Unable to parse hash file"); 208 // Remove corrupt file. 209 RemoveFile(fileName); 210 return false; 211 } 212 213 std::string hash; 214 if (!Hash(hashFile.file(), &hash)) { 215 ALOGE("RetrieveHashedFile: Hash computation failed"); 216 return false; 217 } 218 219 if (hash != hashFile.hash()) { 220 ALOGE("RetrieveHashedFile: Hash mismatch"); 221 // Remove corrupt file. 222 RemoveFile(fileName); 223 return false; 224 } 225 226 if (!deSerializedFile->ParseFromString(hashFile.file())) { 227 ALOGE("RetrieveHashedFile: Unable to parse file"); 228 // Remove corrupt file. 229 RemoveFile(fileName); 230 return false; 231 } 232 233 return true; 234 } 235 236 bool DeviceFiles::FileExists(const std::string& fileName) const { 237 return mFileHandle.FileExists(fileName); 238 } 239 240 bool DeviceFiles::RemoveFile(const std::string& fileName) { 241 return mFileHandle.RemoveFile(fileName); 242 } 243 244 ssize_t DeviceFiles::GetFileSize(const std::string& fileName) const { 245 return mFileHandle.GetFileSize(fileName); 246 } 247 248 } // namespace clearkey 249 } // namespace V1_2 250 } // namespace drm 251 } // namespace hardware 252 } // namespace android 253