Home | History | Annotate | Download | only in keystore
      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 LOG_TAG "keystore"
     18 
     19 #include "user_state.h"
     20 
     21 #include <dirent.h>
     22 #include <fcntl.h>
     23 #include <stdio.h>
     24 #include <stdlib.h>
     25 #include <sys/stat.h>
     26 
     27 #include <openssl/evp.h>
     28 
     29 #include <cutils/log.h>
     30 
     31 #include "blob.h"
     32 #include "keystore_utils.h"
     33 
     34 
     35 UserState::UserState(uid_t userId) :
     36         mUserId(userId), mState(STATE_UNINITIALIZED), mRetry(MAX_RETRY) {
     37     asprintf(&mUserDir, "user_%u", mUserId);
     38     asprintf(&mMasterKeyFile, "%s/.masterkey", mUserDir);
     39 }
     40 
     41 UserState::~UserState() {
     42     free(mUserDir);
     43     free(mMasterKeyFile);
     44 }
     45 
     46 bool UserState::initialize() {
     47     if ((mkdir(mUserDir, S_IRUSR | S_IWUSR | S_IXUSR) < 0) && (errno != EEXIST)) {
     48         ALOGE("Could not create directory '%s'", mUserDir);
     49         return false;
     50     }
     51 
     52     if (access(mMasterKeyFile, R_OK) == 0) {
     53         setState(STATE_LOCKED);
     54     } else {
     55         setState(STATE_UNINITIALIZED);
     56     }
     57 
     58     return true;
     59 }
     60 
     61 void UserState::setState(State state) {
     62     mState = state;
     63     if (mState == STATE_NO_ERROR || mState == STATE_UNINITIALIZED) {
     64         mRetry = MAX_RETRY;
     65     }
     66 }
     67 
     68 void UserState::zeroizeMasterKeysInMemory() {
     69     memset(mMasterKey, 0, sizeof(mMasterKey));
     70     memset(mSalt, 0, sizeof(mSalt));
     71     memset(&mMasterKeyEncryption, 0, sizeof(mMasterKeyEncryption));
     72     memset(&mMasterKeyDecryption, 0, sizeof(mMasterKeyDecryption));
     73 }
     74 
     75 bool UserState::deleteMasterKey() {
     76     setState(STATE_UNINITIALIZED);
     77     zeroizeMasterKeysInMemory();
     78     return unlink(mMasterKeyFile) == 0 || errno == ENOENT;
     79 }
     80 
     81 ResponseCode UserState::initialize(const android::String8& pw, Entropy* entropy) {
     82     if (!generateMasterKey(entropy)) {
     83         return ResponseCode::SYSTEM_ERROR;
     84     }
     85     ResponseCode response = writeMasterKey(pw, entropy);
     86     if (response != ResponseCode::NO_ERROR) {
     87         return response;
     88     }
     89     setupMasterKeys();
     90     return ResponseCode::NO_ERROR;
     91 }
     92 
     93 ResponseCode UserState::copyMasterKey(UserState* src) {
     94     if (mState != STATE_UNINITIALIZED) {
     95         return ResponseCode::SYSTEM_ERROR;
     96     }
     97     if (src->getState() != STATE_NO_ERROR) {
     98         return ResponseCode::SYSTEM_ERROR;
     99     }
    100     memcpy(mMasterKey, src->mMasterKey, MASTER_KEY_SIZE_BYTES);
    101     setupMasterKeys();
    102     return copyMasterKeyFile(src);
    103 }
    104 
    105 ResponseCode UserState::copyMasterKeyFile(UserState* src) {
    106     /* Copy the master key file to the new user.  Unfortunately we don't have the src user's
    107      * password so we cannot generate a new file with a new salt.
    108      */
    109     int in = TEMP_FAILURE_RETRY(open(src->getMasterKeyFileName(), O_RDONLY));
    110     if (in < 0) {
    111         return ResponseCode::SYSTEM_ERROR;
    112     }
    113     blob rawBlob;
    114     size_t length = readFully(in, (uint8_t*)&rawBlob, sizeof(rawBlob));
    115     if (close(in) != 0) {
    116         return ResponseCode::SYSTEM_ERROR;
    117     }
    118     int out =
    119         TEMP_FAILURE_RETRY(open(mMasterKeyFile, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR));
    120     if (out < 0) {
    121         return ResponseCode::SYSTEM_ERROR;
    122     }
    123     size_t outLength = writeFully(out, (uint8_t*)&rawBlob, length);
    124     if (close(out) != 0) {
    125         return ResponseCode::SYSTEM_ERROR;
    126     }
    127     if (outLength != length) {
    128         ALOGW("blob not fully written %zu != %zu", outLength, length);
    129         unlink(mMasterKeyFile);
    130         return ResponseCode::SYSTEM_ERROR;
    131     }
    132     return ResponseCode::NO_ERROR;
    133 }
    134 
    135 ResponseCode UserState::writeMasterKey(const android::String8& pw, Entropy* entropy) {
    136     uint8_t passwordKey[MASTER_KEY_SIZE_BYTES];
    137     generateKeyFromPassword(passwordKey, MASTER_KEY_SIZE_BYTES, pw, mSalt);
    138     AES_KEY passwordAesKey;
    139     AES_set_encrypt_key(passwordKey, MASTER_KEY_SIZE_BITS, &passwordAesKey);
    140     Blob masterKeyBlob(mMasterKey, sizeof(mMasterKey), mSalt, sizeof(mSalt), TYPE_MASTER_KEY);
    141     return masterKeyBlob.writeBlob(mMasterKeyFile, &passwordAesKey, STATE_NO_ERROR, entropy);
    142 }
    143 
    144 ResponseCode UserState::readMasterKey(const android::String8& pw, Entropy* entropy) {
    145     int in = TEMP_FAILURE_RETRY(open(mMasterKeyFile, O_RDONLY));
    146     if (in < 0) {
    147         return ResponseCode::SYSTEM_ERROR;
    148     }
    149 
    150     // We read the raw blob to just to get the salt to generate the AES key, then we create the Blob
    151     // to use with decryptBlob
    152     blob rawBlob;
    153     size_t length = readFully(in, (uint8_t*)&rawBlob, sizeof(rawBlob));
    154     if (close(in) != 0) {
    155         return ResponseCode::SYSTEM_ERROR;
    156     }
    157     // find salt at EOF if present, otherwise we have an old file
    158     uint8_t* salt;
    159     if (length > SALT_SIZE && rawBlob.info == SALT_SIZE) {
    160         salt = (uint8_t*)&rawBlob + length - SALT_SIZE;
    161     } else {
    162         salt = NULL;
    163     }
    164     uint8_t passwordKey[MASTER_KEY_SIZE_BYTES];
    165     generateKeyFromPassword(passwordKey, MASTER_KEY_SIZE_BYTES, pw, salt);
    166     AES_KEY passwordAesKey;
    167     AES_set_decrypt_key(passwordKey, MASTER_KEY_SIZE_BITS, &passwordAesKey);
    168     Blob masterKeyBlob(rawBlob);
    169     ResponseCode response = masterKeyBlob.readBlob(mMasterKeyFile, &passwordAesKey, STATE_NO_ERROR);
    170     if (response == ResponseCode::SYSTEM_ERROR) {
    171         return response;
    172     }
    173     if (response == ResponseCode::NO_ERROR && masterKeyBlob.getLength() == MASTER_KEY_SIZE_BYTES) {
    174         // If salt was missing, generate one and write a new master key file with the salt.
    175         if (salt == NULL) {
    176             if (!generateSalt(entropy)) {
    177                 return ResponseCode::SYSTEM_ERROR;
    178             }
    179             response = writeMasterKey(pw, entropy);
    180         }
    181         if (response == ResponseCode::NO_ERROR) {
    182             memcpy(mMasterKey, masterKeyBlob.getValue(), MASTER_KEY_SIZE_BYTES);
    183             setupMasterKeys();
    184         }
    185         return response;
    186     }
    187     if (mRetry <= 0) {
    188         reset();
    189         return ResponseCode::UNINITIALIZED;
    190     }
    191     --mRetry;
    192     switch (mRetry) {
    193     case 0:
    194         return ResponseCode::WRONG_PASSWORD_0;
    195     case 1:
    196         return ResponseCode::WRONG_PASSWORD_1;
    197     case 2:
    198         return ResponseCode::WRONG_PASSWORD_2;
    199     case 3:
    200         return ResponseCode::WRONG_PASSWORD_3;
    201     default:
    202         return ResponseCode::WRONG_PASSWORD_3;
    203     }
    204 }
    205 
    206 bool UserState::reset() {
    207     DIR* dir = opendir(getUserDirName());
    208     if (!dir) {
    209         // If the directory doesn't exist then nothing to do.
    210         if (errno == ENOENT) {
    211             return true;
    212         }
    213         ALOGW("couldn't open user directory: %s", strerror(errno));
    214         return false;
    215     }
    216 
    217     struct dirent* file;
    218     while ((file = readdir(dir)) != NULL) {
    219         // skip . and ..
    220         if (!strcmp(".", file->d_name) || !strcmp("..", file->d_name)) {
    221             continue;
    222         }
    223 
    224         unlinkat(dirfd(dir), file->d_name, 0);
    225     }
    226     closedir(dir);
    227     return true;
    228 }
    229 
    230 void UserState::generateKeyFromPassword(uint8_t* key, ssize_t keySize, const android::String8& pw,
    231                                         uint8_t* salt) {
    232     size_t saltSize;
    233     if (salt != NULL) {
    234         saltSize = SALT_SIZE;
    235     } else {
    236         // Pre-gingerbread used this hardwired salt, readMasterKey will rewrite these when found
    237         salt = (uint8_t*)"keystore";
    238         // sizeof = 9, not strlen = 8
    239         saltSize = sizeof("keystore");
    240     }
    241 
    242     PKCS5_PBKDF2_HMAC_SHA1(reinterpret_cast<const char*>(pw.string()), pw.length(), salt, saltSize,
    243                            8192, keySize, key);
    244 }
    245 
    246 bool UserState::generateSalt(Entropy* entropy) {
    247     return entropy->generate_random_data(mSalt, sizeof(mSalt));
    248 }
    249 
    250 bool UserState::generateMasterKey(Entropy* entropy) {
    251     if (!entropy->generate_random_data(mMasterKey, sizeof(mMasterKey))) {
    252         return false;
    253     }
    254     if (!generateSalt(entropy)) {
    255         return false;
    256     }
    257     return true;
    258 }
    259 
    260 void UserState::setupMasterKeys() {
    261     AES_set_encrypt_key(mMasterKey, MASTER_KEY_SIZE_BITS, &mMasterKeyEncryption);
    262     AES_set_decrypt_key(mMasterKey, MASTER_KEY_SIZE_BITS, &mMasterKeyDecryption);
    263     setState(STATE_NO_ERROR);
    264 }
    265