Home | History | Annotate | Download | only in ext4_utils
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      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 "ext4_utils/ext4_crypt_init_extensions.h"
     18 
     19 #include <dirent.h>
     20 #include <errno.h>
     21 #include <sys/mount.h>
     22 #include <sys/stat.h>
     23 #include <unistd.h>
     24 
     25 #include <string>
     26 #include <vector>
     27 
     28 #include <android-base/file.h>
     29 #include <android-base/logging.h>
     30 #include <android-base/stringprintf.h>
     31 #include <android-base/strings.h>
     32 #include <cutils/properties.h>
     33 #include <cutils/sockets.h>
     34 #include <keyutils.h>
     35 #include <logwrap/logwrap.h>
     36 
     37 #include "ext4_utils/ext4_crypt.h"
     38 
     39 #define TAG "ext4_utils"
     40 
     41 static const std::string arbitrary_sequence_number = "42";
     42 static const int vold_command_timeout_ms = 60 * 1000;
     43 
     44 static int set_system_de_policy_on(char const* dir);
     45 
     46 int e4crypt_install_keyring()
     47 {
     48     key_serial_t device_keyring = add_key("keyring", "e4crypt", 0, 0,
     49                                           KEY_SPEC_SESSION_KEYRING);
     50 
     51     if (device_keyring == -1) {
     52         PLOG(ERROR) << "Failed to create keyring";
     53         return -1;
     54     }
     55 
     56     LOG(INFO) << "Keyring created with id " << device_keyring << " in process " << getpid();
     57 
     58     return 0;
     59 }
     60 
     61 int e4crypt_set_directory_policy(const char* dir)
     62 {
     63     if (!dir || strncmp(dir, "/data/", 6)) {
     64         return 0;
     65     }
     66 
     67     // Special-case /data/media/obb per b/64566063
     68     if (strcmp(dir, "/data/media/obb") == 0) {
     69         // Try to set policy on this directory, but if it is non-empty this may fail.
     70         set_system_de_policy_on(dir);
     71         return 0;
     72     }
     73 
     74     // Only set policy on first level /data directories
     75     // To make this less restrictive, consider using a policy file.
     76     // However this is overkill for as long as the policy is simply
     77     // to apply a global policy to all /data folders created via makedir
     78     if (strchr(dir + 6, '/')) {
     79         return 0;
     80     }
     81 
     82     // Special case various directories that must not be encrypted,
     83     // often because their subdirectories must be encrypted.
     84     // This isn't a nice way to do this, see b/26641735
     85     std::vector<std::string> directories_to_exclude = {
     86         "lost+found",
     87         "system_ce", "system_de",
     88         "misc_ce", "misc_de",
     89         "media",
     90         "data", "user", "user_de",
     91     };
     92     std::string prefix = "/data/";
     93     for (auto d: directories_to_exclude) {
     94         if ((prefix + d) == dir) {
     95             LOG(INFO) << "Not setting policy on " << dir;
     96             return 0;
     97         }
     98     }
     99     return set_system_de_policy_on(dir);
    100 }
    101 
    102 static int set_system_de_policy_on(char const* dir) {
    103     std::string ref_filename = std::string("/data") + e4crypt_key_ref;
    104     std::string policy;
    105     if (!android::base::ReadFileToString(ref_filename, &policy)) {
    106         LOG(ERROR) << "Unable to read system policy to set on " << dir;
    107         return -1;
    108     }
    109 
    110     auto type_filename = std::string("/data") + e4crypt_key_mode;
    111     std::string modestring;
    112     if (!android::base::ReadFileToString(type_filename, &modestring)) {
    113         LOG(ERROR) << "Cannot read mode";
    114     }
    115 
    116     std::vector<std::string> modes = android::base::Split(modestring, ":");
    117 
    118     if (modes.size() < 1 || modes.size() > 2) {
    119         LOG(ERROR) << "Invalid encryption mode string: " << modestring;
    120         return -1;
    121     }
    122 
    123     LOG(INFO) << "Setting policy on " << dir;
    124     int result = e4crypt_policy_ensure(dir, policy.c_str(), policy.length(),
    125                                        modes[0].c_str(),
    126                                        modes.size() >= 2 ?
    127                                             modes[1].c_str() : "aes-256-cts");
    128     if (result) {
    129         LOG(ERROR) << android::base::StringPrintf(
    130             "Setting %02x%02x%02x%02x policy on %s failed!",
    131             policy[0], policy[1], policy[2], policy[3], dir);
    132         return -1;
    133     }
    134 
    135     return 0;
    136 }
    137