Home | History | Annotate | Download | only in recovery
      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