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
Hash(const std::string & data,std::string * hash)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_4 {
42 namespace clearkey {
43
StoreLicense(const std::string & keySetId,LicenseState state,const std::string & licenseResponse)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
StoreFileWithHash(const std::string & fileName,const std::string & serializedFile)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
StoreFileRaw(const std::string & fileName,const std::string & serializedHashFile)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
RetrieveLicense(const std::string & keySetId,LicenseState * state,std::string * offlineLicense)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
DeleteLicense(const std::string & keySetId)149 bool DeviceFiles::DeleteLicense(const std::string& keySetId) {
150 return mFileHandle.RemoveFile(keySetId + kLicenseFileNameExt);
151 }
152
DeleteAllLicenses()153 bool DeviceFiles::DeleteAllLicenses() {
154 return mFileHandle.RemoveAllFiles();
155 }
156
LicenseExists(const std::string & keySetId)157 bool DeviceFiles::LicenseExists(const std::string& keySetId) {
158 return mFileHandle.FileExists(keySetId + kLicenseFileNameExt);
159 }
160
ListLicenses() const161 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
RetrieveHashedFile(const std::string & fileName,OfflineFile * deSerializedFile)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
FileExists(const std::string & fileName) const236 bool DeviceFiles::FileExists(const std::string& fileName) const {
237 return mFileHandle.FileExists(fileName);
238 }
239
RemoveFile(const std::string & fileName)240 bool DeviceFiles::RemoveFile(const std::string& fileName) {
241 return mFileHandle.RemoveFile(fileName);
242 }
243
GetFileSize(const std::string & fileName) const244 ssize_t DeviceFiles::GetFileSize(const std::string& fileName) const {
245 return mFileHandle.GetFileSize(fileName);
246 }
247
248 } // namespace clearkey
249 } // namespace V1_4
250 } // namespace drm
251 } // namespace hardware
252 } // namespace android
253