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 43 void get_property_file_name(char *buffer, const char *property_name) { 44 sprintf(buffer, "%s%s", encrypted_fs_property_dir, property_name); 45 } 46 47 int 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 72 int 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 94 int 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 116 int 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 139 int 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 163 int 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 186 int read_encrypted_fs_info(encrypted_fs_info *encrypted_fs_data) { 187 int result; 188 int value; 189 result = ensure_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_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 233 int restore_encrypted_fs_info(encrypted_fs_info *encrypted_fs_data) { 234 int result; 235 result = ensure_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_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