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 "keystore.h"
20 
21 #include <dirent.h>
22 #include <fcntl.h>
23 
24 #include <openssl/bio.h>
25 
26 #include <utils/String16.h>
27 
28 #include <keystore/IKeystoreService.h>
29 
30 #include <android/hardware/keymaster/3.0/IKeymasterDevice.h>
31 
32 #include "keystore_utils.h"
33 #include "permissions.h"
34 #include <keystore/keystore_hidl_support.h>
35 
36 const char* KeyStore::sOldMasterKey = ".masterkey";
37 const char* KeyStore::sMetaDataFile = ".metadata";
38 
39 const android::String16 KeyStore::sRSAKeyType("RSA");
40 
41 using namespace keystore;
42 
KeyStore(Entropy * entropy,const km_device_t & device,const km_device_t & fallback,bool allowNewFallback)43 KeyStore::KeyStore(Entropy* entropy, const km_device_t& device, const km_device_t& fallback,
44                    bool allowNewFallback)
45     : mEntropy(entropy), mDevice(device), mFallbackDevice(fallback),
46       mAllowNewFallback(allowNewFallback) {
47     memset(&mMetaData, '\0', sizeof(mMetaData));
48 }
49 
~KeyStore()50 KeyStore::~KeyStore() {
51     for (android::Vector<grant_t*>::iterator it(mGrants.begin()); it != mGrants.end(); it++) {
52         delete *it;
53     }
54     mGrants.clear();
55 
56     for (android::Vector<UserState*>::iterator it(mMasterKeys.begin()); it != mMasterKeys.end();
57          it++) {
58         delete *it;
59     }
60     mMasterKeys.clear();
61 }
62 
initialize()63 ResponseCode KeyStore::initialize() {
64     readMetaData();
65     if (upgradeKeystore()) {
66         writeMetaData();
67     }
68 
69     return ResponseCode::NO_ERROR;
70 }
71 
initializeUser(const android::String8 & pw,uid_t userId)72 ResponseCode KeyStore::initializeUser(const android::String8& pw, uid_t userId) {
73     UserState* userState = getUserState(userId);
74     return userState->initialize(pw, mEntropy);
75 }
76 
copyMasterKey(uid_t srcUser,uid_t dstUser)77 ResponseCode KeyStore::copyMasterKey(uid_t srcUser, uid_t dstUser) {
78     UserState* userState = getUserState(dstUser);
79     UserState* initState = getUserState(srcUser);
80     return userState->copyMasterKey(initState);
81 }
82 
writeMasterKey(const android::String8 & pw,uid_t userId)83 ResponseCode KeyStore::writeMasterKey(const android::String8& pw, uid_t userId) {
84     UserState* userState = getUserState(userId);
85     return userState->writeMasterKey(pw, mEntropy);
86 }
87 
readMasterKey(const android::String8 & pw,uid_t userId)88 ResponseCode KeyStore::readMasterKey(const android::String8& pw, uid_t userId) {
89     UserState* userState = getUserState(userId);
90     return userState->readMasterKey(pw, mEntropy);
91 }
92 
93 /* Here is the encoding of keys. This is necessary in order to allow arbitrary
94  * characters in keys. Characters in [0-~] are not encoded. Others are encoded
95  * into two bytes. The first byte is one of [+-.] which represents the first
96  * two bits of the character. The second byte encodes the rest of the bits into
97  * [0-o]. Therefore in the worst case the length of a key gets doubled. Note
98  * that Base64 cannot be used here due to the need of prefix match on keys. */
99 
encode_key_length(const android::String8 & keyName)100 static size_t encode_key_length(const android::String8& keyName) {
101     const uint8_t* in = reinterpret_cast<const uint8_t*>(keyName.string());
102     size_t length = keyName.length();
103     for (int i = length; i > 0; --i, ++in) {
104         if (*in < '0' || *in > '~') {
105             ++length;
106         }
107     }
108     return length;
109 }
110 
encode_key(char * out,const android::String8 & keyName)111 static int encode_key(char* out, const android::String8& keyName) {
112     const uint8_t* in = reinterpret_cast<const uint8_t*>(keyName.string());
113     size_t length = keyName.length();
114     for (int i = length; i > 0; --i, ++in, ++out) {
115         if (*in < '0' || *in > '~') {
116             *out = '+' + (*in >> 6);
117             *++out = '0' + (*in & 0x3F);
118             ++length;
119         } else {
120             *out = *in;
121         }
122     }
123     *out = '\0';
124     return length;
125 }
126 
getKeyName(const android::String8 & keyName,const BlobType type)127 android::String8 KeyStore::getKeyName(const android::String8& keyName, const BlobType type) {
128     std::vector<char> encoded(encode_key_length(keyName) + 1);  // add 1 for null char
129     encode_key(encoded.data(), keyName);
130     if (type == TYPE_KEY_CHARACTERISTICS) {
131         return android::String8::format(".chr_%s", encoded.data());
132     } else {
133         return android::String8(encoded.data());
134     }
135 }
136 
getKeyNameForUid(const android::String8 & keyName,uid_t uid,const BlobType type)137 android::String8 KeyStore::getKeyNameForUid(
138     const android::String8& keyName, uid_t uid, const BlobType type) {
139     std::vector<char> encoded(encode_key_length(keyName) + 1);  // add 1 for null char
140     encode_key(encoded.data(), keyName);
141     if (type == TYPE_KEY_CHARACTERISTICS) {
142         return android::String8::format(".%u_chr_%s", uid, encoded.data());
143     } else {
144         return android::String8::format("%u_%s", uid, encoded.data());
145     }
146 }
147 
getKeyNameForUidWithDir(const android::String8 & keyName,uid_t uid,const BlobType type)148 android::String8 KeyStore::getKeyNameForUidWithDir(
149     const android::String8& keyName, uid_t uid, const BlobType type) {
150     std::vector<char> encoded(encode_key_length(keyName) + 1);  // add 1 for null char
151     encode_key(encoded.data(), keyName);
152 
153     if (type == TYPE_KEY_CHARACTERISTICS) {
154         return android::String8::format("%s/.%u_chr_%s", getUserStateByUid(uid)->getUserDirName(),
155                                         uid, encoded.data());
156     } else {
157         return android::String8::format("%s/%u_%s", getUserStateByUid(uid)->getUserDirName(), uid,
158                                         encoded.data());
159     }
160 }
161 
resetUser(uid_t userId,bool keepUnenryptedEntries)162 void KeyStore::resetUser(uid_t userId, bool keepUnenryptedEntries) {
163     android::String8 prefix("");
164     android::Vector<android::String16> aliases;
165     UserState* userState = getUserState(userId);
166     if (list(prefix, &aliases, userId) != ResponseCode::NO_ERROR) {
167         return;
168     }
169     for (uint32_t i = 0; i < aliases.size(); i++) {
170         android::String8 filename(aliases[i]);
171         filename = android::String8::format("%s/%s", userState->getUserDirName(),
172                                             getKeyName(filename, TYPE_ANY).string());
173         bool shouldDelete = true;
174         if (keepUnenryptedEntries) {
175             Blob blob;
176             ResponseCode rc = get(filename, &blob, ::TYPE_ANY, userId);
177 
178             switch (rc) {
179             case ResponseCode::SYSTEM_ERROR:
180             case ResponseCode::VALUE_CORRUPTED:
181                 // If we can't read blobs, delete them.
182                 shouldDelete = true;
183                 break;
184 
185             case ResponseCode::NO_ERROR:
186             case ResponseCode::LOCKED:
187                 // Delete encrypted blobs but keep unencrypted blobs and super-encrypted blobs.  We
188                 // need to keep super-encrypted blobs so we can report that the user is
189                 // unauthenticated if a caller tries to use them, rather than reporting that they
190                 // don't exist.
191                 shouldDelete = blob.isEncrypted();
192                 break;
193 
194             default:
195                 ALOGE("Got unexpected return code %d from KeyStore::get()", rc);
196                 // This shouldn't happen.  To be on the safe side, delete it.
197                 shouldDelete = true;
198                 break;
199             }
200         }
201         if (shouldDelete) {
202             del(filename, ::TYPE_ANY, userId);
203 
204             // del() will fail silently if no cached characteristics are present for this alias.
205             android::String8 chr_filename(aliases[i]);
206             chr_filename = android::String8::format("%s/%s", userState->getUserDirName(),
207                                             getKeyName(chr_filename,
208                                                 TYPE_KEY_CHARACTERISTICS).string());
209             del(chr_filename, ::TYPE_KEY_CHARACTERISTICS, userId);
210         }
211     }
212     if (!userState->deleteMasterKey()) {
213         ALOGE("Failed to delete user %d's master key", userId);
214     }
215     if (!keepUnenryptedEntries) {
216         if (!userState->reset()) {
217             ALOGE("Failed to remove user %d's directory", userId);
218         }
219     }
220 }
221 
isEmpty(uid_t userId) const222 bool KeyStore::isEmpty(uid_t userId) const {
223     const UserState* userState = getUserState(userId);
224     if (userState == NULL) {
225         return true;
226     }
227 
228     DIR* dir = opendir(userState->getUserDirName());
229     if (!dir) {
230         return true;
231     }
232 
233     bool result = true;
234     struct dirent* file;
235     while ((file = readdir(dir)) != NULL) {
236         // We only care about files.
237         if (file->d_type != DT_REG) {
238             continue;
239         }
240 
241         // Skip anything that starts with a "."
242         if (file->d_name[0] == '.') {
243             continue;
244         }
245 
246         result = false;
247         break;
248     }
249     closedir(dir);
250     return result;
251 }
252 
lock(uid_t userId)253 void KeyStore::lock(uid_t userId) {
254     UserState* userState = getUserState(userId);
255     userState->zeroizeMasterKeysInMemory();
256     userState->setState(STATE_LOCKED);
257 }
258 
get(const char * filename,Blob * keyBlob,const BlobType type,uid_t userId)259 ResponseCode KeyStore::get(const char* filename, Blob* keyBlob, const BlobType type, uid_t userId) {
260     UserState* userState = getUserState(userId);
261     ResponseCode rc =
262         keyBlob->readBlob(filename, userState->getDecryptionKey(), userState->getState());
263     if (rc != ResponseCode::NO_ERROR) {
264         return rc;
265     }
266 
267     const uint8_t version = keyBlob->getVersion();
268     if (version < CURRENT_BLOB_VERSION) {
269         /* If we upgrade the key, we need to write it to disk again. Then
270          * it must be read it again since the blob is encrypted each time
271          * it's written.
272          */
273         if (upgradeBlob(filename, keyBlob, version, type, userId)) {
274             if ((rc = this->put(filename, keyBlob, userId)) != ResponseCode::NO_ERROR ||
275                 (rc = keyBlob->readBlob(filename, userState->getDecryptionKey(),
276                                         userState->getState())) != ResponseCode::NO_ERROR) {
277                 return rc;
278             }
279         }
280     }
281 
282     /*
283      * This will upgrade software-backed keys to hardware-backed keys.
284      */
285     if (rc == ResponseCode::NO_ERROR && type == TYPE_KEY_PAIR && keyBlob->isFallback()) {
286         ResponseCode imported =
287             importKey(keyBlob->getValue(), keyBlob->getLength(), filename, userId,
288                       keyBlob->isEncrypted() ? KEYSTORE_FLAG_ENCRYPTED : KEYSTORE_FLAG_NONE);
289 
290         // The HAL allowed the import, reget the key to have the "fresh" version.
291         if (imported == ResponseCode::NO_ERROR) {
292             rc = get(filename, keyBlob, TYPE_KEY_PAIR, userId);
293         }
294     }
295 
296     // Keymaster 0.3 keys are valid keymaster 1.0 keys, so silently upgrade.
297     if (keyBlob->getType() == TYPE_KEY_PAIR) {
298         keyBlob->setType(TYPE_KEYMASTER_10);
299         rc = this->put(filename, keyBlob, userId);
300     }
301 
302     if (type != TYPE_ANY && keyBlob->getType() != type) {
303         ALOGW("key found but type doesn't match: %d vs %d", keyBlob->getType(), type);
304         return ResponseCode::KEY_NOT_FOUND;
305     }
306 
307     return rc;
308 }
309 
put(const char * filename,Blob * keyBlob,uid_t userId)310 ResponseCode KeyStore::put(const char* filename, Blob* keyBlob, uid_t userId) {
311     UserState* userState = getUserState(userId);
312     return keyBlob->writeBlob(filename, userState->getEncryptionKey(), userState->getState(),
313                               mEntropy);
314 }
315 
del(const char * filename,const BlobType type,uid_t userId)316 ResponseCode KeyStore::del(const char* filename, const BlobType type, uid_t userId) {
317     Blob keyBlob;
318     ResponseCode rc = get(filename, &keyBlob, type, userId);
319     if (rc == ResponseCode::VALUE_CORRUPTED) {
320         // The file is corrupt, the best we can do is rm it.
321         return (unlink(filename) && errno != ENOENT) ?
322                 ResponseCode::SYSTEM_ERROR : ResponseCode::NO_ERROR;
323     }
324     if (rc != ResponseCode::NO_ERROR) {
325         return rc;
326     }
327 
328     auto& dev = getDevice(keyBlob);
329 
330     if (keyBlob.getType() == ::TYPE_KEY_PAIR || keyBlob.getType() == ::TYPE_KEYMASTER_10) {
331         auto ret = KS_HANDLE_HIDL_ERROR(dev->deleteKey(blob2hidlVec(keyBlob)));
332 
333         // A device doesn't have to implement delete_key.
334         if (ret != ErrorCode::OK && ret != ErrorCode::UNIMPLEMENTED)
335             return ResponseCode::SYSTEM_ERROR;
336     }
337 
338     return (unlink(filename) && errno != ENOENT) ?
339             ResponseCode::SYSTEM_ERROR : ResponseCode::NO_ERROR;
340 }
341 
342 /*
343  * Converts from the "escaped" format on disk to actual name.
344  * This will be smaller than the input string.
345  *
346  * Characters that should combine with the next at the end will be truncated.
347  */
decode_key_length(const char * in,size_t length)348 static size_t decode_key_length(const char* in, size_t length) {
349     size_t outLength = 0;
350 
351     for (const char* end = in + length; in < end; in++) {
352         /* This combines with the next character. */
353         if (*in < '0' || *in > '~') {
354             continue;
355         }
356 
357         outLength++;
358     }
359     return outLength;
360 }
361 
decode_key(char * out,const char * in,size_t length)362 static void decode_key(char* out, const char* in, size_t length) {
363     for (const char* end = in + length; in < end; in++) {
364         if (*in < '0' || *in > '~') {
365             /* Truncate combining characters at the end. */
366             if (in + 1 >= end) {
367                 break;
368             }
369 
370             *out = (*in++ - '+') << 6;
371             *out++ |= (*in - '0') & 0x3F;
372         } else {
373             *out++ = *in;
374         }
375     }
376     *out = '\0';
377 }
378 
list(const android::String8 & prefix,android::Vector<android::String16> * matches,uid_t userId)379 ResponseCode KeyStore::list(const android::String8& prefix,
380                             android::Vector<android::String16>* matches, uid_t userId) {
381 
382     UserState* userState = getUserState(userId);
383     size_t n = prefix.length();
384 
385     DIR* dir = opendir(userState->getUserDirName());
386     if (!dir) {
387         ALOGW("can't open directory for user: %s", strerror(errno));
388         return ResponseCode::SYSTEM_ERROR;
389     }
390 
391     struct dirent* file;
392     while ((file = readdir(dir)) != NULL) {
393         // We only care about files.
394         if (file->d_type != DT_REG) {
395             continue;
396         }
397 
398         // Skip anything that starts with a "."
399         if (file->d_name[0] == '.') {
400             continue;
401         }
402 
403         if (!strncmp(prefix.string(), file->d_name, n)) {
404             const char* p = &file->d_name[n];
405             size_t plen = strlen(p);
406 
407             size_t extra = decode_key_length(p, plen);
408             char* match = (char*)malloc(extra + 1);
409             if (match != NULL) {
410                 decode_key(match, p, plen);
411                 matches->push(android::String16(match, extra));
412                 free(match);
413             } else {
414                 ALOGW("could not allocate match of size %zd", extra);
415             }
416         }
417     }
418     closedir(dir);
419     return ResponseCode::NO_ERROR;
420 }
421 
addGrant(const char * filename,uid_t granteeUid)422 void KeyStore::addGrant(const char* filename, uid_t granteeUid) {
423     const grant_t* existing = getGrant(filename, granteeUid);
424     if (existing == NULL) {
425         grant_t* grant = new grant_t;
426         grant->uid = granteeUid;
427         grant->filename = reinterpret_cast<const uint8_t*>(strdup(filename));
428         mGrants.add(grant);
429     }
430 }
431 
removeGrant(const char * filename,uid_t granteeUid)432 bool KeyStore::removeGrant(const char* filename, uid_t granteeUid) {
433     for (android::Vector<grant_t*>::iterator it(mGrants.begin()); it != mGrants.end(); it++) {
434         grant_t* grant = *it;
435         if (grant->uid == granteeUid &&
436             !strcmp(reinterpret_cast<const char*>(grant->filename), filename)) {
437             mGrants.erase(it);
438             return true;
439         }
440     }
441     return false;
442 }
443 
importKey(const uint8_t * key,size_t keyLen,const char * filename,uid_t userId,int32_t flags)444 ResponseCode KeyStore::importKey(const uint8_t* key, size_t keyLen, const char* filename,
445                                  uid_t userId, int32_t flags) {
446     Unique_PKCS8_PRIV_KEY_INFO pkcs8(d2i_PKCS8_PRIV_KEY_INFO(NULL, &key, keyLen));
447     if (!pkcs8.get()) {
448         return ResponseCode::SYSTEM_ERROR;
449     }
450     Unique_EVP_PKEY pkey(EVP_PKCS82PKEY(pkcs8.get()));
451     if (!pkey.get()) {
452         return ResponseCode::SYSTEM_ERROR;
453     }
454     int type = EVP_PKEY_type(pkey->type);
455     AuthorizationSet params;
456     add_legacy_key_authorizations(type, &params);
457     switch (type) {
458     case EVP_PKEY_RSA:
459         params.push_back(TAG_ALGORITHM, Algorithm::RSA);
460         break;
461     case EVP_PKEY_EC:
462         params.push_back(TAG_ALGORITHM, Algorithm::EC);
463         break;
464     default:
465         ALOGW("Unsupported key type %d", type);
466         return ResponseCode::SYSTEM_ERROR;
467     }
468 
469     AuthorizationSet opParams(params);
470     hidl_vec<uint8_t> blob;
471 
472     ErrorCode error;
473     auto hidlCb = [&] (ErrorCode ret, const hidl_vec<uint8_t>& keyBlob,
474             const KeyCharacteristics& /* ignored */) {
475         error = ret;
476         if (error != ErrorCode::OK) return;
477         blob = keyBlob;
478     };
479     auto input = blob2hidlVec(key, keyLen);
480 
481     ErrorCode rc = KS_HANDLE_HIDL_ERROR(
482             mDevice->importKey(params.hidl_data(), KeyFormat::PKCS8, input, hidlCb));
483     if (rc != ErrorCode::OK) return ResponseCode::SYSTEM_ERROR;
484     if (error != ErrorCode::OK) {
485         ALOGE("Keymaster error %d importing key pair", error);
486         return ResponseCode::SYSTEM_ERROR;
487     }
488 
489     Blob keyBlob(&blob[0], blob.size(), NULL, 0, TYPE_KEYMASTER_10);
490 
491     keyBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
492     keyBlob.setFallback(false);
493 
494     return put(filename, &keyBlob, userId);
495 }
496 
isHardwareBacked(const android::String16 &) const497 bool KeyStore::isHardwareBacked(const android::String16& /*keyType*/) const {
498     using ::android::hardware::hidl_string;
499     if (mDevice == NULL) {
500         ALOGW("can't get keymaster device");
501         return false;
502     }
503 
504     bool isSecure = false;
505     auto hidlcb = [&] (bool _isSecure, bool, bool, bool, bool, const hidl_string&,
506                        const hidl_string&) {
507         isSecure = _isSecure;
508     };
509     auto rc = mDevice->getHardwareFeatures(hidlcb);
510     if (!rc.isOk()) {
511         ALOGE("Communication with keymaster HAL failed while retrieving hardware features (%s)",
512                 rc.description().c_str());
513         return false;
514     }
515     return isSecure;
516 }
517 
getKeyForName(Blob * keyBlob,const android::String8 & keyName,const uid_t uid,const BlobType type)518 ResponseCode KeyStore::getKeyForName(Blob* keyBlob, const android::String8& keyName,
519                                      const uid_t uid, const BlobType type) {
520     android::String8 filepath8(getKeyNameForUidWithDir(keyName, uid, type));
521     uid_t userId = get_user_id(uid);
522 
523     ResponseCode responseCode = get(filepath8.string(), keyBlob, type, userId);
524     if (responseCode == ResponseCode::NO_ERROR) {
525         return responseCode;
526     }
527 
528     // If this is one of the legacy UID->UID mappings, use it.
529     uid_t euid = get_keystore_euid(uid);
530     if (euid != uid) {
531         filepath8 = getKeyNameForUidWithDir(keyName, euid, type);
532         responseCode = get(filepath8.string(), keyBlob, type, userId);
533         if (responseCode == ResponseCode::NO_ERROR) {
534             return responseCode;
535         }
536     }
537 
538     // They might be using a granted key.
539     android::String8 filename8 = getKeyName(keyName, type);
540     char* end;
541     strtoul(filename8.string(), &end, 10);
542     if (end[0] != '_' || end[1] == 0) {
543         return ResponseCode::KEY_NOT_FOUND;
544     }
545     filepath8 = android::String8::format("%s/%s", getUserState(userId)->getUserDirName(),
546                                          filename8.string());
547     if (!hasGrant(filepath8.string(), uid)) {
548         return responseCode;
549     }
550 
551     // It is a granted key. Try to load it.
552     return get(filepath8.string(), keyBlob, type, userId);
553 }
554 
getUserState(uid_t userId)555 UserState* KeyStore::getUserState(uid_t userId) {
556     for (android::Vector<UserState*>::iterator it(mMasterKeys.begin()); it != mMasterKeys.end();
557          it++) {
558         UserState* state = *it;
559         if (state->getUserId() == userId) {
560             return state;
561         }
562     }
563 
564     UserState* userState = new UserState(userId);
565     if (!userState->initialize()) {
566         /* There's not much we can do if initialization fails. Trying to
567          * unlock the keystore for that user will fail as well, so any
568          * subsequent request for this user will just return SYSTEM_ERROR.
569          */
570         ALOGE("User initialization failed for %u; subsuquent operations will fail", userId);
571     }
572     mMasterKeys.add(userState);
573     return userState;
574 }
575 
getUserStateByUid(uid_t uid)576 UserState* KeyStore::getUserStateByUid(uid_t uid) {
577     uid_t userId = get_user_id(uid);
578     return getUserState(userId);
579 }
580 
getUserState(uid_t userId) const581 const UserState* KeyStore::getUserState(uid_t userId) const {
582     for (android::Vector<UserState*>::const_iterator it(mMasterKeys.begin());
583          it != mMasterKeys.end(); it++) {
584         UserState* state = *it;
585         if (state->getUserId() == userId) {
586             return state;
587         }
588     }
589 
590     return NULL;
591 }
592 
getUserStateByUid(uid_t uid) const593 const UserState* KeyStore::getUserStateByUid(uid_t uid) const {
594     uid_t userId = get_user_id(uid);
595     return getUserState(userId);
596 }
597 
getGrant(const char * filename,uid_t uid) const598 const grant_t* KeyStore::getGrant(const char* filename, uid_t uid) const {
599     for (android::Vector<grant_t*>::const_iterator it(mGrants.begin()); it != mGrants.end(); it++) {
600         grant_t* grant = *it;
601         if (grant->uid == uid &&
602             !strcmp(reinterpret_cast<const char*>(grant->filename), filename)) {
603             return grant;
604         }
605     }
606     return NULL;
607 }
608 
upgradeBlob(const char * filename,Blob * blob,const uint8_t oldVersion,const BlobType type,uid_t uid)609 bool KeyStore::upgradeBlob(const char* filename, Blob* blob, const uint8_t oldVersion,
610                            const BlobType type, uid_t uid) {
611     bool updated = false;
612     uint8_t version = oldVersion;
613 
614     /* From V0 -> V1: All old types were unknown */
615     if (version == 0) {
616         ALOGV("upgrading to version 1 and setting type %d", type);
617 
618         blob->setType(type);
619         if (type == TYPE_KEY_PAIR) {
620             importBlobAsKey(blob, filename, uid);
621         }
622         version = 1;
623         updated = true;
624     }
625 
626     /* From V1 -> V2: All old keys were encrypted */
627     if (version == 1) {
628         ALOGV("upgrading to version 2");
629 
630         blob->setEncrypted(true);
631         version = 2;
632         updated = true;
633     }
634 
635     /*
636      * If we've updated, set the key blob to the right version
637      * and write it.
638      */
639     if (updated) {
640         ALOGV("updated and writing file %s", filename);
641         blob->setVersion(version);
642     }
643 
644     return updated;
645 }
646 
647 struct BIO_Delete {
operator ()BIO_Delete648     void operator()(BIO* p) const { BIO_free(p); }
649 };
650 typedef UniquePtr<BIO, BIO_Delete> Unique_BIO;
651 
importBlobAsKey(Blob * blob,const char * filename,uid_t uid)652 ResponseCode KeyStore::importBlobAsKey(Blob* blob, const char* filename, uid_t uid) {
653     // We won't even write to the blob directly with this BIO, so const_cast is okay.
654     Unique_BIO b(BIO_new_mem_buf(const_cast<uint8_t*>(blob->getValue()), blob->getLength()));
655     if (b.get() == NULL) {
656         ALOGE("Problem instantiating BIO");
657         return ResponseCode::SYSTEM_ERROR;
658     }
659 
660     Unique_EVP_PKEY pkey(PEM_read_bio_PrivateKey(b.get(), NULL, NULL, NULL));
661     if (pkey.get() == NULL) {
662         ALOGE("Couldn't read old PEM file");
663         return ResponseCode::SYSTEM_ERROR;
664     }
665 
666     Unique_PKCS8_PRIV_KEY_INFO pkcs8(EVP_PKEY2PKCS8(pkey.get()));
667     int len = i2d_PKCS8_PRIV_KEY_INFO(pkcs8.get(), NULL);
668     if (len < 0) {
669         ALOGE("Couldn't measure PKCS#8 length");
670         return ResponseCode::SYSTEM_ERROR;
671     }
672 
673     UniquePtr<unsigned char[]> pkcs8key(new unsigned char[len]);
674     uint8_t* tmp = pkcs8key.get();
675     if (i2d_PKCS8_PRIV_KEY_INFO(pkcs8.get(), &tmp) != len) {
676         ALOGE("Couldn't convert to PKCS#8");
677         return ResponseCode::SYSTEM_ERROR;
678     }
679 
680     ResponseCode rc = importKey(pkcs8key.get(), len, filename, get_user_id(uid),
681                                 blob->isEncrypted() ? KEYSTORE_FLAG_ENCRYPTED : KEYSTORE_FLAG_NONE);
682     if (rc != ResponseCode::NO_ERROR) {
683         return rc;
684     }
685 
686     return get(filename, blob, TYPE_KEY_PAIR, uid);
687 }
688 
readMetaData()689 void KeyStore::readMetaData() {
690     int in = TEMP_FAILURE_RETRY(open(sMetaDataFile, O_RDONLY));
691     if (in < 0) {
692         return;
693     }
694     size_t fileLength = readFully(in, (uint8_t*)&mMetaData, sizeof(mMetaData));
695     if (fileLength != sizeof(mMetaData)) {
696         ALOGI("Metadata file is %zd bytes (%zd experted); upgrade?", fileLength, sizeof(mMetaData));
697     }
698     close(in);
699 }
700 
writeMetaData()701 void KeyStore::writeMetaData() {
702     const char* tmpFileName = ".metadata.tmp";
703     int out =
704         TEMP_FAILURE_RETRY(open(tmpFileName, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR));
705     if (out < 0) {
706         ALOGE("couldn't write metadata file: %s", strerror(errno));
707         return;
708     }
709     size_t fileLength = writeFully(out, (uint8_t*)&mMetaData, sizeof(mMetaData));
710     if (fileLength != sizeof(mMetaData)) {
711         ALOGI("Could only write %zd bytes to metadata file (%zd expected)", fileLength,
712               sizeof(mMetaData));
713     }
714     close(out);
715     rename(tmpFileName, sMetaDataFile);
716 }
717 
upgradeKeystore()718 bool KeyStore::upgradeKeystore() {
719     bool upgraded = false;
720 
721     if (mMetaData.version == 0) {
722         UserState* userState = getUserStateByUid(0);
723 
724         // Initialize first so the directory is made.
725         userState->initialize();
726 
727         // Migrate the old .masterkey file to user 0.
728         if (access(sOldMasterKey, R_OK) == 0) {
729             if (rename(sOldMasterKey, userState->getMasterKeyFileName()) < 0) {
730                 ALOGE("couldn't migrate old masterkey: %s", strerror(errno));
731                 return false;
732             }
733         }
734 
735         // Initialize again in case we had a key.
736         userState->initialize();
737 
738         // Try to migrate existing keys.
739         DIR* dir = opendir(".");
740         if (!dir) {
741             // Give up now; maybe we can upgrade later.
742             ALOGE("couldn't open keystore's directory; something is wrong");
743             return false;
744         }
745 
746         struct dirent* file;
747         while ((file = readdir(dir)) != NULL) {
748             // We only care about files.
749             if (file->d_type != DT_REG) {
750                 continue;
751             }
752 
753             // Skip anything that starts with a "."
754             if (file->d_name[0] == '.') {
755                 continue;
756             }
757 
758             // Find the current file's user.
759             char* end;
760             unsigned long thisUid = strtoul(file->d_name, &end, 10);
761             if (end[0] != '_' || end[1] == 0) {
762                 continue;
763             }
764             UserState* otherUser = getUserStateByUid(thisUid);
765             if (otherUser->getUserId() != 0) {
766                 unlinkat(dirfd(dir), file->d_name, 0);
767             }
768 
769             // Rename the file into user directory.
770             DIR* otherdir = opendir(otherUser->getUserDirName());
771             if (otherdir == NULL) {
772                 ALOGW("couldn't open user directory for rename");
773                 continue;
774             }
775             if (renameat(dirfd(dir), file->d_name, dirfd(otherdir), file->d_name) < 0) {
776                 ALOGW("couldn't rename blob: %s: %s", file->d_name, strerror(errno));
777             }
778             closedir(otherdir);
779         }
780         closedir(dir);
781 
782         mMetaData.version = 1;
783         upgraded = true;
784     }
785 
786     return upgraded;
787 }
788