ext4_crypt_init_extensions.cpp revision e8299d81a18d16b006019f37ec9d84921d5ff845
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#define TAG "ext4_utils"
18
19#include "ext4_crypt_init_extensions.h"
20#include "ext4_crypt.h"
21
22#include <android-base/logging.h>
23
24#include <string>
25#include <vector>
26
27#include <android-base/file.h>
28
29#include <cutils/klog.h>
30#include <logwrap/logwrap.h>
31#include <util.h>
32
33#include "key_control.h"
34
35static const std::string arbitrary_sequence_number = "42";
36static const int vold_command_timeout_ms = 60 * 1000;
37
38static void kernel_logger(android::base::LogId, android::base::LogSeverity severity, const char*,
39        const char*, unsigned int, const char* message) {
40    if (severity == android::base::ERROR || severity == android::base::FATAL) {
41        KLOG_ERROR(TAG, "%s\n", message);
42    } else if (severity == android::base::WARNING) {
43        KLOG_WARNING(TAG, "%s\n", message);
44    } else {
45        KLOG_INFO(TAG, "%s\n", message);
46    }
47}
48
49static void init_logging() {
50    android::base::SetLogger(kernel_logger);
51}
52
53int e4crypt_create_device_key(const char* dir,
54                              int ensure_dir_exists(const char*))
55{
56    init_logging();
57
58    // Make sure folder exists. Use make_dir to set selinux permissions.
59    std::string unencrypted_dir = std::string(dir) + e4crypt_unencrypted_folder;
60    if (ensure_dir_exists(unencrypted_dir.c_str())) {
61        KLOG_ERROR(TAG, "Failed to create %s (%s)\n",
62                   unencrypted_dir.c_str(),
63                   strerror(errno));
64        return -1;
65    }
66
67    const char* argv[] = { "/system/bin/vdc", "--wait", "cryptfs", "enablefilecrypto" };
68    int rc = android_fork_execvp(4, (char**) argv, NULL, false, true);
69    LOG(INFO) << "enablefilecrypto result: " << rc;
70    return rc;
71}
72
73int e4crypt_install_keyring()
74{
75    init_logging();
76
77    key_serial_t device_keyring = add_key("keyring", "e4crypt", 0, 0,
78                                          KEY_SPEC_SESSION_KEYRING);
79
80    if (device_keyring == -1) {
81        KLOG_ERROR(TAG, "Failed to create keyring (%s)\n", strerror(errno));
82        return -1;
83    }
84
85    KLOG_INFO(TAG, "Keyring created with id %d in process %d\n",
86              device_keyring, getpid());
87
88    return 0;
89}
90
91int e4crypt_do_init_user0()
92{
93    init_logging();
94
95    const char* argv[] = { "/system/bin/vdc", "--wait", "cryptfs", "init_user0" };
96    int rc = android_fork_execvp(4, (char**) argv, NULL, false, true);
97    LOG(INFO) << "init_user0 result: " << rc;
98    return rc;
99}
100
101int e4crypt_set_directory_policy(const char* dir)
102{
103    init_logging();
104
105    // Only set policy on first level /data directories
106    // To make this less restrictive, consider using a policy file.
107    // However this is overkill for as long as the policy is simply
108    // to apply a global policy to all /data folders created via makedir
109    if (!dir || strncmp(dir, "/data/", 6) || strchr(dir + 6, '/')) {
110        return 0;
111    }
112
113    std::vector<std::string> directories_to_exclude = {
114        "lost+found",
115        "system_ce", "system_de",
116        "misc_ce", "misc_de",
117        "media",
118        "data", "user", "user_de",
119    };
120    std::string prefix = "/data/";
121    for (auto d: directories_to_exclude) {
122        if ((prefix + d) == dir) {
123            KLOG_INFO(TAG, "Not setting policy on %s\n", dir);
124            return 0;
125        }
126    }
127
128    std::string ref_filename = std::string("/data") + e4crypt_key_ref;
129    std::string policy;
130    if (!android::base::ReadFileToString(ref_filename, &policy)) {
131        KLOG_ERROR(TAG, "Unable to read system policy to set on %s\n", dir);
132        return -1;
133    }
134
135    std::string hex_policy = bytes_to_hex((const uint8_t*)policy.c_str(),
136                                          policy.length());
137
138    const char* argv[] = { "/system/bin/vdc", "--wait", "cryptfs",
139                           "ensure_policy", dir, hex_policy.c_str()};
140
141    KLOG_INFO(TAG, "Setting policy on %s\n", dir);
142    int rc = android_fork_execvp(6, (char**) argv, NULL, false, true);
143    if (rc) {
144        KLOG_ERROR(TAG, "Setting %s policy on %s failed!\n",
145                   hex_policy.c_str(), dir);
146        return rc;
147    }
148
149    return 0;
150}
151