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