1 /*
2 * Copyright (C) 2009 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 <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <sys/mount.h>
21 #include <sys/stat.h>
22 #include <sys/types.h>
23 #include <unistd.h>
24
25 #include "encryptedfs_provisioning.h"
26 #include "cutils/misc.h"
27 #include "cutils/properties.h"
28 #include "common.h"
29 #include "mtdutils/mtdutils.h"
30 #include "mtdutils/mounts.h"
31 #include "roots.h"
32
33 const char* encrypted_fs_enabled_property = "persist.security.secfs.enabled";
34 const char* encrypted_fs_property_dir = "/data/property/";
35 const char* encrypted_fs_system_dir = "/data/system/";
36 const char* encrypted_fs_key_file_name = "/data/fs_key.dat";
37 const char* encrypted_fs_salt_file_name = "/data/hash_salt.dat";
38 const char* encrypted_fs_hash_file_src_name = "/data/system/password.key";
39 const char* encrypted_fs_hash_file_dst_name = "/data/hash.dat";
40 const char* encrypted_fs_entropy_file_src_name = "/data/system/entropy.dat";
41 const char* encrypted_fs_entropy_file_dst_name = "/data/ported_entropy.dat";
42
get_property_file_name(char * buffer,const char * property_name)43 void get_property_file_name(char *buffer, const char *property_name)
44 {
45 sprintf(buffer, "%s%s", encrypted_fs_property_dir, property_name);
46 }
47
get_binary_file_contents(char * buffer,int buf_size,const char * file_name,int * out_size)48 int get_binary_file_contents(char *buffer, int buf_size, const char *file_name, int *out_size)
49 {
50 FILE *in_file;
51 int read_bytes;
52
53 in_file = fopen(file_name, "r");
54 if (in_file == NULL) {
55 LOGE("Secure FS: error accessing key file.");
56 return ENCRYPTED_FS_ERROR;
57 }
58
59 read_bytes = fread(buffer, 1, buf_size, in_file);
60 if (out_size == NULL) {
61 if (read_bytes != buf_size) {
62 // Error or unexpected data
63 fclose(in_file);
64 LOGE("Secure FS: error reading conmplete key.");
65 return ENCRYPTED_FS_ERROR;
66 }
67 } else {
68 *out_size = read_bytes;
69 }
70 fclose(in_file);
71 return ENCRYPTED_FS_OK;
72 }
73
set_binary_file_contents(char * buffer,int buf_size,const char * file_name)74 int set_binary_file_contents(char *buffer, int buf_size, const char *file_name)
75 {
76 FILE *out_file;
77 int write_bytes;
78
79 out_file = fopen(file_name, "w");
80 if (out_file == NULL) {
81 LOGE("Secure FS: error setting up key file.");
82 return ENCRYPTED_FS_ERROR;
83 }
84
85 write_bytes = fwrite(buffer, 1, buf_size, out_file);
86 if (write_bytes != buf_size) {
87 // Error or unexpected data
88 fclose(out_file);
89 LOGE("Secure FS: error reading conmplete key.");
90 return ENCRYPTED_FS_ERROR;
91 }
92
93 fclose(out_file);
94 return ENCRYPTED_FS_OK;
95 }
96
get_text_file_contents(char * buffer,int buf_size,char * file_name)97 int get_text_file_contents(char *buffer, int buf_size, char *file_name)
98 {
99 FILE *in_file;
100 char *read_data;
101
102 in_file = fopen(file_name, "r");
103 if (in_file == NULL) {
104 LOGE("Secure FS: error accessing properties.");
105 return ENCRYPTED_FS_ERROR;
106 }
107
108 read_data = fgets(buffer, buf_size, in_file);
109 if (read_data == NULL) {
110 // Error or unexpected data
111 fclose(in_file);
112 LOGE("Secure FS: error accessing properties.");
113 return ENCRYPTED_FS_ERROR;
114 }
115
116 fclose(in_file);
117 return ENCRYPTED_FS_OK;
118 }
119
set_text_file_contents(char * buffer,char * file_name)120 int set_text_file_contents(char *buffer, char *file_name)
121 {
122 FILE *out_file;
123 int result;
124
125 out_file = fopen(file_name, "w");
126 if (out_file == NULL) {
127 LOGE("Secure FS: error setting up properties.");
128 return ENCRYPTED_FS_ERROR;
129 }
130
131 result = fputs(buffer, out_file);
132 if (result != 0) {
133 // Error or unexpected data
134 fclose(out_file);
135 LOGE("Secure FS: error setting up properties.");
136 return ENCRYPTED_FS_ERROR;
137 }
138
139 fflush(out_file);
140 fclose(out_file);
141 return ENCRYPTED_FS_OK;
142 }
143
read_encrypted_fs_boolean_property(const char * prop_name,int * value)144 int read_encrypted_fs_boolean_property(const char *prop_name, int *value)
145 {
146 char prop_file_name[PROPERTY_KEY_MAX + 32];
147 char prop_value[PROPERTY_VALUE_MAX];
148 int result;
149
150 get_property_file_name(prop_file_name, prop_name);
151 result = get_text_file_contents(prop_value, PROPERTY_VALUE_MAX, prop_file_name);
152
153 if (result < 0) {
154 return result;
155 }
156
157 if (strncmp(prop_value, "1", 1) == 0) {
158 *value = 1;
159 } else if (strncmp(prop_value, "0", 1) == 0) {
160 *value = 0;
161 } else {
162 LOGE("Secure FS: error accessing properties.");
163 return ENCRYPTED_FS_ERROR;
164 }
165
166 return ENCRYPTED_FS_OK;
167 }
168
write_encrypted_fs_boolean_property(const char * prop_name,int value)169 int write_encrypted_fs_boolean_property(const char *prop_name, int value)
170 {
171 char prop_file_name[PROPERTY_KEY_MAX + 32];
172 char prop_value[PROPERTY_VALUE_MAX];
173 int result;
174
175 get_property_file_name(prop_file_name, prop_name);
176
177 // Create the directory if needed
178 mkdir(encrypted_fs_property_dir, 0755);
179 if (value == 1) {
180 result = set_text_file_contents("1", prop_file_name);
181 } else if (value == 0) {
182 result = set_text_file_contents("0", prop_file_name);
183 } else {
184 return ENCRYPTED_FS_ERROR;
185 }
186 if (result < 0) {
187 return result;
188 }
189
190 return ENCRYPTED_FS_OK;
191 }
192
read_encrypted_fs_info(encrypted_fs_info * encrypted_fs_data)193 int read_encrypted_fs_info(encrypted_fs_info *encrypted_fs_data)
194 {
195 int result;
196 int value;
197 result = ensure_path_mounted("/data");
198 if (result != 0) {
199 LOGE("Secure FS: error mounting userdata partition.");
200 return ENCRYPTED_FS_ERROR;
201 }
202
203 // Read the pre-generated encrypted FS key, password hash and salt.
204 result = get_binary_file_contents(encrypted_fs_data->key, ENCRYPTED_FS_KEY_SIZE,
205 encrypted_fs_key_file_name, NULL);
206 if (result != 0) {
207 LOGE("Secure FS: error reading generated file system key.");
208 return ENCRYPTED_FS_ERROR;
209 }
210
211 result = get_binary_file_contents(encrypted_fs_data->salt, ENCRYPTED_FS_SALT_SIZE,
212 encrypted_fs_salt_file_name, &(encrypted_fs_data->salt_length));
213 if (result != 0) {
214 LOGE("Secure FS: error reading file system salt.");
215 return ENCRYPTED_FS_ERROR;
216 }
217
218 result = get_binary_file_contents(encrypted_fs_data->hash, ENCRYPTED_FS_MAX_HASH_SIZE,
219 encrypted_fs_hash_file_src_name, &(encrypted_fs_data->hash_length));
220 if (result != 0) {
221 LOGE("Secure FS: error reading password hash.");
222 return ENCRYPTED_FS_ERROR;
223 }
224
225 result = get_binary_file_contents(encrypted_fs_data->entropy, ENTROPY_MAX_SIZE,
226 encrypted_fs_entropy_file_src_name, &(encrypted_fs_data->entropy_length));
227 if (result != 0) {
228 LOGE("Secure FS: error reading ported entropy.");
229 return ENCRYPTED_FS_ERROR;
230 }
231
232 result = ensure_path_unmounted("/data");
233 if (result != 0) {
234 LOGE("Secure FS: error unmounting data partition.");
235 return ENCRYPTED_FS_ERROR;
236 }
237
238 return ENCRYPTED_FS_OK;
239 }
240
restore_encrypted_fs_info(encrypted_fs_info * encrypted_fs_data)241 int restore_encrypted_fs_info(encrypted_fs_info *encrypted_fs_data)
242 {
243 int result;
244 result = ensure_path_mounted("/data");
245 if (result != 0) {
246 LOGE("Secure FS: error mounting userdata partition.");
247 return ENCRYPTED_FS_ERROR;
248 }
249
250 // Write the pre-generated secure FS key, password hash and salt.
251 result = set_binary_file_contents(encrypted_fs_data->key, ENCRYPTED_FS_KEY_SIZE,
252 encrypted_fs_key_file_name);
253 if (result != 0) {
254 LOGE("Secure FS: error writing generated file system key.");
255 return ENCRYPTED_FS_ERROR;
256 }
257
258 result = set_binary_file_contents(encrypted_fs_data->salt, encrypted_fs_data->salt_length,
259 encrypted_fs_salt_file_name);
260 if (result != 0) {
261 LOGE("Secure FS: error writing file system salt.");
262 return ENCRYPTED_FS_ERROR;
263 }
264
265 result = set_binary_file_contents(encrypted_fs_data->hash, encrypted_fs_data->hash_length,
266 encrypted_fs_hash_file_dst_name);
267 if (result != 0) {
268 LOGE("Secure FS: error writing password hash.");
269 return ENCRYPTED_FS_ERROR;
270 }
271
272 result = set_binary_file_contents(encrypted_fs_data->entropy, encrypted_fs_data->entropy_length,
273 encrypted_fs_entropy_file_dst_name);
274 if (result != 0) {
275 LOGE("Secure FS: error writing ported entropy.");
276 return ENCRYPTED_FS_ERROR;
277 }
278
279 // Set the secure FS properties to their respective values
280 result = write_encrypted_fs_boolean_property(encrypted_fs_enabled_property, encrypted_fs_data->mode);
281 if (result != 0) {
282 return result;
283 }
284
285 result = ensure_path_unmounted("/data");
286 if (result != 0) {
287 LOGE("Secure FS: error unmounting data partition.");
288 return ENCRYPTED_FS_ERROR;
289 }
290
291 return ENCRYPTED_FS_OK;
292 }
293