Home | History | Annotate | Download | only in hidl
      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