blob: a28a35ac5abc2ccbd1c3ab327ecbd9697453278b [file] [log] [blame]
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001/*
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
Janis Danisevskis011675d2016-09-01 11:41:29 +010017#define LOG_TAG "keystore"
18
Shawn Willdenc1d1fee2016-01-26 22:44:56 -070019#include "key_store_service.h"
20
21#include <fcntl.h>
22#include <sys/stat.h>
23
Janis Danisevskis7612fd42016-09-01 11:50:02 +010024#include <algorithm>
Shawn Willdenc1d1fee2016-01-26 22:44:56 -070025#include <sstream>
26
Bartosz Fabianowskia9452d92017-01-23 22:21:11 +010027#include <binder/IInterface.h>
Shawn Willdenc1d1fee2016-01-26 22:44:56 -070028#include <binder/IPCThreadState.h>
Bartosz Fabianowskia9452d92017-01-23 22:21:11 +010029#include <binder/IPermissionController.h>
30#include <binder/IServiceManager.h>
Shawn Willdenc1d1fee2016-01-26 22:44:56 -070031
32#include <private/android_filesystem_config.h>
33
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +010034#include <android/hardware/keymaster/3.0/IHwKeymasterDevice.h>
Shawn Willdenc1d1fee2016-01-26 22:44:56 -070035
36#include "defaults.h"
Janis Danisevskis18f27ad2016-06-01 13:57:40 -070037#include "keystore_attestation_id.h"
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +010038#include "keystore_keymaster_enforcement.h"
Shawn Willdenc1d1fee2016-01-26 22:44:56 -070039#include "keystore_utils.h"
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +010040#include <keystore/keystore_hidl_support.h>
Shawn Willdenc1d1fee2016-01-26 22:44:56 -070041
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +010042namespace keystore {
Shawn Willdend5a24e62017-02-28 13:53:24 -070043
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +010044using namespace android;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -070045
Shawn Willdene2a7b522017-04-11 09:27:40 -060046namespace {
47
48constexpr size_t kMaxOperations = 15;
49constexpr double kIdRotationPeriod = 30 * 24 * 60 * 60; /* Thirty days, in seconds */
50const char* kTimestampFilePath = "timestamp";
Shawn Willdenc1d1fee2016-01-26 22:44:56 -070051
52struct BIGNUM_Delete {
53 void operator()(BIGNUM* p) const { BN_free(p); }
54};
55typedef UniquePtr<BIGNUM, BIGNUM_Delete> Unique_BIGNUM;
56
Shawn Willdene2a7b522017-04-11 09:27:40 -060057bool containsTag(const hidl_vec<KeyParameter>& params, Tag tag) {
58 return params.end() != std::find_if(params.begin(), params.end(),
59 [&](auto& param) { return param.tag == tag; });
60}
61
Shawn Willdend5a24e62017-02-28 13:53:24 -070062bool isAuthenticationBound(const hidl_vec<KeyParameter>& params) {
63 return !containsTag(params, Tag::NO_AUTH_REQUIRED);
64}
65
Shawn Willdene2a7b522017-04-11 09:27:40 -060066std::pair<KeyStoreServiceReturnCode, bool> hadFactoryResetSinceIdRotation() {
67 struct stat sbuf;
68 if (stat(kTimestampFilePath, &sbuf) == 0) {
69 double diff_secs = difftime(time(NULL), sbuf.st_ctime);
70 return {ResponseCode::NO_ERROR, diff_secs < kIdRotationPeriod};
71 }
72
73 if (errno != ENOENT) {
74 ALOGE("Failed to stat \"timestamp\" file, with error %d", errno);
75 return {ResponseCode::SYSTEM_ERROR, false /* don't care */};
76 }
77
78 int fd = creat(kTimestampFilePath, 0600);
79 if (fd < 0) {
80 ALOGE("Couldn't create \"timestamp\" file, with error %d", errno);
81 return {ResponseCode::SYSTEM_ERROR, false /* don't care */};
82 }
83
84 if (close(fd)) {
85 ALOGE("Couldn't close \"timestamp\" file, with error %d", errno);
86 return {ResponseCode::SYSTEM_ERROR, false /* don't care */};
87 }
88
89 return {ResponseCode::NO_ERROR, true};
90}
91
92} // anonymous namespace
93
Shawn Willdenc1d1fee2016-01-26 22:44:56 -070094void KeyStoreService::binderDied(const wp<IBinder>& who) {
95 auto operations = mOperationMap.getOperationsForToken(who.unsafe_get());
Chih-Hung Hsieh24b2a392016-07-28 10:35:24 -070096 for (const auto& token : operations) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -070097 abort(token);
98 }
99}
100
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100101KeyStoreServiceReturnCode KeyStoreService::getState(int32_t userId) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700102 if (!checkBinderPermission(P_GET_STATE)) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100103 return ResponseCode::PERMISSION_DENIED;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700104 }
105
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100106 return ResponseCode(mKeyStore->getState(userId));
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700107}
108
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100109KeyStoreServiceReturnCode KeyStoreService::get(const String16& name, int32_t uid,
110 hidl_vec<uint8_t>* item) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700111 uid_t targetUid = getEffectiveUid(uid);
112 if (!checkBinderPermission(P_GET, targetUid)) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100113 return ResponseCode::PERMISSION_DENIED;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700114 }
115
116 String8 name8(name);
117 Blob keyBlob;
118
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100119 KeyStoreServiceReturnCode rc =
120 mKeyStore->getKeyForName(&keyBlob, name8, targetUid, TYPE_GENERIC);
121 if (!rc.isOk()) {
122 if (item) *item = hidl_vec<uint8_t>();
123 return rc;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700124 }
125
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100126 // Do not replace this with "if (item) *item = blob2hidlVec(keyBlob)"!
127 // blob2hidlVec creates a hidl_vec<uint8_t> that references, but not owns, the data in keyBlob
128 // the subsequent assignment (*item = resultBlob) makes a deep copy, so that *item will own the
129 // corresponding resources.
130 auto resultBlob = blob2hidlVec(keyBlob);
131 if (item) {
132 *item = resultBlob;
133 }
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700134
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100135 return ResponseCode::NO_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700136}
137
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100138KeyStoreServiceReturnCode KeyStoreService::insert(const String16& name,
139 const hidl_vec<uint8_t>& item, int targetUid,
140 int32_t flags) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700141 targetUid = getEffectiveUid(targetUid);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100142 auto result =
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700143 checkBinderPermissionAndKeystoreState(P_INSERT, targetUid, flags & KEYSTORE_FLAG_ENCRYPTED);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100144 if (!result.isOk()) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700145 return result;
146 }
147
148 String8 name8(name);
Tucker Sylvestro0ab28b72016-08-05 18:02:47 -0400149 String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, targetUid, ::TYPE_GENERIC));
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700150
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100151 Blob keyBlob(&item[0], item.size(), NULL, 0, ::TYPE_GENERIC);
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700152 keyBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
153
154 return mKeyStore->put(filename.string(), &keyBlob, get_user_id(targetUid));
155}
156
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100157KeyStoreServiceReturnCode KeyStoreService::del(const String16& name, int targetUid) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700158 targetUid = getEffectiveUid(targetUid);
159 if (!checkBinderPermission(P_DELETE, targetUid)) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100160 return ResponseCode::PERMISSION_DENIED;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700161 }
162 String8 name8(name);
Rubin Xu7675c9f2017-03-15 19:26:52 +0000163 ALOGI("del %s %d", name8.string(), targetUid);
Tucker Sylvestro0ab28b72016-08-05 18:02:47 -0400164 String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, targetUid, ::TYPE_ANY));
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100165 ResponseCode result = mKeyStore->del(filename.string(), ::TYPE_ANY, get_user_id(targetUid));
166 if (result != ResponseCode::NO_ERROR) {
Tucker Sylvestro0ab28b72016-08-05 18:02:47 -0400167 return result;
168 }
169
170 // Also delete any characteristics files
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100171 String8 chrFilename(
172 mKeyStore->getKeyNameForUidWithDir(name8, targetUid, ::TYPE_KEY_CHARACTERISTICS));
Tucker Sylvestro0ab28b72016-08-05 18:02:47 -0400173 return mKeyStore->del(chrFilename.string(), ::TYPE_KEY_CHARACTERISTICS, get_user_id(targetUid));
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700174}
175
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100176KeyStoreServiceReturnCode KeyStoreService::exist(const String16& name, int targetUid) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700177 targetUid = getEffectiveUid(targetUid);
178 if (!checkBinderPermission(P_EXIST, targetUid)) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100179 return ResponseCode::PERMISSION_DENIED;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700180 }
181
182 String8 name8(name);
Tucker Sylvestro0ab28b72016-08-05 18:02:47 -0400183 String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, targetUid, ::TYPE_ANY));
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700184
185 if (access(filename.string(), R_OK) == -1) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100186 return (errno != ENOENT) ? ResponseCode::SYSTEM_ERROR : ResponseCode::KEY_NOT_FOUND;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700187 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100188 return ResponseCode::NO_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700189}
190
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100191KeyStoreServiceReturnCode KeyStoreService::list(const String16& prefix, int targetUid,
192 Vector<String16>* matches) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700193 targetUid = getEffectiveUid(targetUid);
194 if (!checkBinderPermission(P_LIST, targetUid)) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100195 return ResponseCode::PERMISSION_DENIED;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700196 }
197 const String8 prefix8(prefix);
Tucker Sylvestro0ab28b72016-08-05 18:02:47 -0400198 String8 filename(mKeyStore->getKeyNameForUid(prefix8, targetUid, TYPE_ANY));
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700199
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100200 if (mKeyStore->list(filename, matches, get_user_id(targetUid)) != ResponseCode::NO_ERROR) {
201 return ResponseCode::SYSTEM_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700202 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100203 return ResponseCode::NO_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700204}
205
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100206KeyStoreServiceReturnCode KeyStoreService::reset() {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700207 if (!checkBinderPermission(P_RESET)) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100208 return ResponseCode::PERMISSION_DENIED;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700209 }
210
211 uid_t callingUid = IPCThreadState::self()->getCallingUid();
212 mKeyStore->resetUser(get_user_id(callingUid), false);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100213 return ResponseCode::NO_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700214}
215
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100216KeyStoreServiceReturnCode KeyStoreService::onUserPasswordChanged(int32_t userId,
217 const String16& password) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700218 if (!checkBinderPermission(P_PASSWORD)) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100219 return ResponseCode::PERMISSION_DENIED;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700220 }
221
222 const String8 password8(password);
223 // Flush the auth token table to prevent stale tokens from sticking
224 // around.
225 mAuthTokenTable.Clear();
226
227 if (password.size() == 0) {
228 ALOGI("Secure lockscreen for user %d removed, deleting encrypted entries", userId);
229 mKeyStore->resetUser(userId, true);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100230 return ResponseCode::NO_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700231 } else {
232 switch (mKeyStore->getState(userId)) {
233 case ::STATE_UNINITIALIZED: {
234 // generate master key, encrypt with password, write to file,
235 // initialize mMasterKey*.
236 return mKeyStore->initializeUser(password8, userId);
237 }
238 case ::STATE_NO_ERROR: {
239 // rewrite master key with new password.
240 return mKeyStore->writeMasterKey(password8, userId);
241 }
242 case ::STATE_LOCKED: {
243 ALOGE("Changing user %d's password while locked, clearing old encryption", userId);
244 mKeyStore->resetUser(userId, true);
245 return mKeyStore->initializeUser(password8, userId);
246 }
247 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100248 return ResponseCode::SYSTEM_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700249 }
250}
251
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100252KeyStoreServiceReturnCode KeyStoreService::onUserAdded(int32_t userId, int32_t parentId) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700253 if (!checkBinderPermission(P_USER_CHANGED)) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100254 return ResponseCode::PERMISSION_DENIED;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700255 }
256
257 // Sanity check that the new user has an empty keystore.
258 if (!mKeyStore->isEmpty(userId)) {
259 ALOGW("New user %d's keystore not empty. Clearing old entries.", userId);
260 }
261 // Unconditionally clear the keystore, just to be safe.
262 mKeyStore->resetUser(userId, false);
263 if (parentId != -1) {
264 // This profile must share the same master key password as the parent profile. Because the
265 // password of the parent profile is not known here, the best we can do is copy the parent's
266 // master key and master key file. This makes this profile use the same master key as the
267 // parent profile, forever.
268 return mKeyStore->copyMasterKey(parentId, userId);
269 } else {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100270 return ResponseCode::NO_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700271 }
272}
273
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100274KeyStoreServiceReturnCode KeyStoreService::onUserRemoved(int32_t userId) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700275 if (!checkBinderPermission(P_USER_CHANGED)) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100276 return ResponseCode::PERMISSION_DENIED;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700277 }
278
279 mKeyStore->resetUser(userId, false);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100280 return ResponseCode::NO_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700281}
282
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100283KeyStoreServiceReturnCode KeyStoreService::lock(int32_t userId) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700284 if (!checkBinderPermission(P_LOCK)) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100285 return ResponseCode::PERMISSION_DENIED;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700286 }
287
288 State state = mKeyStore->getState(userId);
289 if (state != ::STATE_NO_ERROR) {
290 ALOGD("calling lock in state: %d", state);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100291 return ResponseCode(state);
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700292 }
293
294 mKeyStore->lock(userId);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100295 return ResponseCode::NO_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700296}
297
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100298KeyStoreServiceReturnCode KeyStoreService::unlock(int32_t userId, const String16& pw) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700299 if (!checkBinderPermission(P_UNLOCK)) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100300 return ResponseCode::PERMISSION_DENIED;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700301 }
302
303 State state = mKeyStore->getState(userId);
304 if (state != ::STATE_LOCKED) {
305 switch (state) {
306 case ::STATE_NO_ERROR:
307 ALOGI("calling unlock when already unlocked, ignoring.");
308 break;
309 case ::STATE_UNINITIALIZED:
310 ALOGE("unlock called on uninitialized keystore.");
311 break;
312 default:
313 ALOGE("unlock called on keystore in unknown state: %d", state);
314 break;
315 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100316 return ResponseCode(state);
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700317 }
318
319 const String8 password8(pw);
320 // read master key, decrypt with password, initialize mMasterKey*.
321 return mKeyStore->readMasterKey(password8, userId);
322}
323
324bool KeyStoreService::isEmpty(int32_t userId) {
325 if (!checkBinderPermission(P_IS_EMPTY)) {
326 return false;
327 }
328
329 return mKeyStore->isEmpty(userId);
330}
331
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100332KeyStoreServiceReturnCode KeyStoreService::generate(const String16& name, int32_t targetUid,
333 int32_t keyType, int32_t keySize, int32_t flags,
334 Vector<sp<KeystoreArg>>* args) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700335 targetUid = getEffectiveUid(targetUid);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100336 auto result =
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700337 checkBinderPermissionAndKeystoreState(P_INSERT, targetUid, flags & KEYSTORE_FLAG_ENCRYPTED);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100338 if (!result.isOk()) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700339 return result;
340 }
341
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100342 keystore::AuthorizationSet params;
343 add_legacy_key_authorizations(keyType, &params);
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700344
345 switch (keyType) {
346 case EVP_PKEY_EC: {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100347 params.push_back(TAG_ALGORITHM, Algorithm::EC);
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700348 if (keySize == -1) {
349 keySize = EC_DEFAULT_KEY_SIZE;
350 } else if (keySize < EC_MIN_KEY_SIZE || keySize > EC_MAX_KEY_SIZE) {
351 ALOGI("invalid key size %d", keySize);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100352 return ResponseCode::SYSTEM_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700353 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100354 params.push_back(TAG_KEY_SIZE, keySize);
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700355 break;
356 }
357 case EVP_PKEY_RSA: {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100358 params.push_back(TAG_ALGORITHM, Algorithm::RSA);
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700359 if (keySize == -1) {
360 keySize = RSA_DEFAULT_KEY_SIZE;
361 } else if (keySize < RSA_MIN_KEY_SIZE || keySize > RSA_MAX_KEY_SIZE) {
362 ALOGI("invalid key size %d", keySize);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100363 return ResponseCode::SYSTEM_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700364 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100365 params.push_back(TAG_KEY_SIZE, keySize);
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700366 unsigned long exponent = RSA_DEFAULT_EXPONENT;
367 if (args->size() > 1) {
368 ALOGI("invalid number of arguments: %zu", args->size());
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100369 return ResponseCode::SYSTEM_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700370 } else if (args->size() == 1) {
Chih-Hung Hsieh24b2a392016-07-28 10:35:24 -0700371 const sp<KeystoreArg>& expArg = args->itemAt(0);
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700372 if (expArg != NULL) {
373 Unique_BIGNUM pubExpBn(BN_bin2bn(
374 reinterpret_cast<const unsigned char*>(expArg->data()), expArg->size(), NULL));
375 if (pubExpBn.get() == NULL) {
376 ALOGI("Could not convert public exponent to BN");
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100377 return ResponseCode::SYSTEM_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700378 }
379 exponent = BN_get_word(pubExpBn.get());
380 if (exponent == 0xFFFFFFFFL) {
381 ALOGW("cannot represent public exponent as a long value");
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100382 return ResponseCode::SYSTEM_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700383 }
384 } else {
385 ALOGW("public exponent not read");
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100386 return ResponseCode::SYSTEM_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700387 }
388 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100389 params.push_back(TAG_RSA_PUBLIC_EXPONENT, exponent);
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700390 break;
391 }
392 default: {
393 ALOGW("Unsupported key type %d", keyType);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100394 return ResponseCode::SYSTEM_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700395 }
396 }
397
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100398 auto rc = generateKey(name, params.hidl_data(), hidl_vec<uint8_t>(), targetUid, flags,
399 /*outCharacteristics*/ NULL);
400 if (!rc.isOk()) {
401 ALOGW("generate failed: %d", int32_t(rc));
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700402 }
403 return translateResultToLegacyResult(rc);
404}
405
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100406KeyStoreServiceReturnCode KeyStoreService::import(const String16& name,
407 const hidl_vec<uint8_t>& data, int targetUid,
408 int32_t flags) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700409
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100410 const uint8_t* ptr = &data[0];
411
412 Unique_PKCS8_PRIV_KEY_INFO pkcs8(d2i_PKCS8_PRIV_KEY_INFO(NULL, &ptr, data.size()));
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700413 if (!pkcs8.get()) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100414 return ResponseCode::SYSTEM_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700415 }
416 Unique_EVP_PKEY pkey(EVP_PKCS82PKEY(pkcs8.get()));
417 if (!pkey.get()) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100418 return ResponseCode::SYSTEM_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700419 }
420 int type = EVP_PKEY_type(pkey->type);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100421 AuthorizationSet params;
422 add_legacy_key_authorizations(type, &params);
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700423 switch (type) {
424 case EVP_PKEY_RSA:
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100425 params.push_back(TAG_ALGORITHM, Algorithm::RSA);
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700426 break;
427 case EVP_PKEY_EC:
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100428 params.push_back(TAG_ALGORITHM, Algorithm::EC);
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700429 break;
430 default:
431 ALOGW("Unsupported key type %d", type);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100432 return ResponseCode::SYSTEM_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700433 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100434
435 auto rc = importKey(name, params.hidl_data(), KeyFormat::PKCS8, data, targetUid, flags,
436 /*outCharacteristics*/ NULL);
437
438 if (!rc.isOk()) {
439 ALOGW("importKey failed: %d", int32_t(rc));
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700440 }
441 return translateResultToLegacyResult(rc);
442}
443
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100444KeyStoreServiceReturnCode KeyStoreService::sign(const String16& name, const hidl_vec<uint8_t>& data,
445 hidl_vec<uint8_t>* out) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700446 if (!checkBinderPermission(P_SIGN)) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100447 return ResponseCode::PERMISSION_DENIED;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700448 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100449 return doLegacySignVerify(name, data, out, hidl_vec<uint8_t>(), KeyPurpose::SIGN);
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700450}
451
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100452KeyStoreServiceReturnCode KeyStoreService::verify(const String16& name,
453 const hidl_vec<uint8_t>& data,
454 const hidl_vec<uint8_t>& signature) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700455 if (!checkBinderPermission(P_VERIFY)) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100456 return ResponseCode::PERMISSION_DENIED;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700457 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100458 return doLegacySignVerify(name, data, nullptr, signature, KeyPurpose::VERIFY);
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700459}
460
461/*
462 * TODO: The abstraction between things stored in hardware and regular blobs
463 * of data stored on the filesystem should be moved down to keystore itself.
464 * Unfortunately the Java code that calls this has naming conventions that it
465 * knows about. Ideally keystore shouldn't be used to store random blobs of
466 * data.
467 *
468 * Until that happens, it's necessary to have a separate "get_pubkey" and
469 * "del_key" since the Java code doesn't really communicate what it's
470 * intentions are.
471 */
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100472KeyStoreServiceReturnCode KeyStoreService::get_pubkey(const String16& name,
473 hidl_vec<uint8_t>* pubKey) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700474 ExportResult result;
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100475 exportKey(name, KeyFormat::X509, hidl_vec<uint8_t>(), hidl_vec<uint8_t>(), UID_SELF, &result);
476 if (!result.resultCode.isOk()) {
477 ALOGW("export failed: %d", int32_t(result.resultCode));
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700478 return translateResultToLegacyResult(result.resultCode);
479 }
480
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100481 if (pubKey) *pubKey = std::move(result.exportData);
482 return ResponseCode::NO_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700483}
484
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100485KeyStoreServiceReturnCode KeyStoreService::grant(const String16& name, int32_t granteeUid) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700486 uid_t callingUid = IPCThreadState::self()->getCallingUid();
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100487 auto result = checkBinderPermissionAndKeystoreState(P_GRANT);
488 if (!result.isOk()) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700489 return result;
490 }
491
492 String8 name8(name);
Tucker Sylvestro0ab28b72016-08-05 18:02:47 -0400493 String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, callingUid, ::TYPE_ANY));
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700494
495 if (access(filename.string(), R_OK) == -1) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100496 return (errno != ENOENT) ? ResponseCode::SYSTEM_ERROR : ResponseCode::KEY_NOT_FOUND;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700497 }
498
499 mKeyStore->addGrant(filename.string(), granteeUid);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100500 return ResponseCode::NO_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700501}
502
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100503KeyStoreServiceReturnCode KeyStoreService::ungrant(const String16& name, int32_t granteeUid) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700504 uid_t callingUid = IPCThreadState::self()->getCallingUid();
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100505 auto result = checkBinderPermissionAndKeystoreState(P_GRANT);
506 if (!result.isOk()) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700507 return result;
508 }
509
510 String8 name8(name);
Tucker Sylvestro0ab28b72016-08-05 18:02:47 -0400511 String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, callingUid, ::TYPE_ANY));
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700512
513 if (access(filename.string(), R_OK) == -1) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100514 return (errno != ENOENT) ? ResponseCode::SYSTEM_ERROR : ResponseCode::KEY_NOT_FOUND;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700515 }
516
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100517 return mKeyStore->removeGrant(filename.string(), granteeUid) ? ResponseCode::NO_ERROR
518 : ResponseCode::KEY_NOT_FOUND;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700519}
520
521int64_t KeyStoreService::getmtime(const String16& name, int32_t uid) {
522 uid_t targetUid = getEffectiveUid(uid);
523 if (!checkBinderPermission(P_GET, targetUid)) {
524 ALOGW("permission denied for %d: getmtime", targetUid);
525 return -1L;
526 }
527
528 String8 name8(name);
Tucker Sylvestro0ab28b72016-08-05 18:02:47 -0400529 String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, targetUid, ::TYPE_ANY));
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700530
531 if (access(filename.string(), R_OK) == -1) {
532 ALOGW("could not access %s for getmtime", filename.string());
533 return -1L;
534 }
535
536 int fd = TEMP_FAILURE_RETRY(open(filename.string(), O_NOFOLLOW, O_RDONLY));
537 if (fd < 0) {
538 ALOGW("could not open %s for getmtime", filename.string());
539 return -1L;
540 }
541
542 struct stat s;
543 int ret = fstat(fd, &s);
544 close(fd);
545 if (ret == -1) {
546 ALOGW("could not stat %s for getmtime", filename.string());
547 return -1L;
548 }
549
550 return static_cast<int64_t>(s.st_mtime);
551}
552
Tucker Sylvestro0ab28b72016-08-05 18:02:47 -0400553// TODO(tuckeris): This is dead code, remove it. Don't bother copying over key characteristics here
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100554KeyStoreServiceReturnCode KeyStoreService::duplicate(const String16& srcKey, int32_t srcUid,
555 const String16& destKey, int32_t destUid) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700556 uid_t callingUid = IPCThreadState::self()->getCallingUid();
557 pid_t spid = IPCThreadState::self()->getCallingPid();
558 if (!has_permission(callingUid, P_DUPLICATE, spid)) {
559 ALOGW("permission denied for %d: duplicate", callingUid);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100560 return ResponseCode::PERMISSION_DENIED;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700561 }
562
563 State state = mKeyStore->getState(get_user_id(callingUid));
564 if (!isKeystoreUnlocked(state)) {
565 ALOGD("calling duplicate in state: %d", state);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100566 return ResponseCode(state);
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700567 }
568
569 if (srcUid == -1 || static_cast<uid_t>(srcUid) == callingUid) {
570 srcUid = callingUid;
571 } else if (!is_granted_to(callingUid, srcUid)) {
572 ALOGD("migrate not granted from source: %d -> %d", callingUid, srcUid);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100573 return ResponseCode::PERMISSION_DENIED;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700574 }
575
576 if (destUid == -1) {
577 destUid = callingUid;
578 }
579
580 if (srcUid != destUid) {
581 if (static_cast<uid_t>(srcUid) != callingUid) {
582 ALOGD("can only duplicate from caller to other or to same uid: "
583 "calling=%d, srcUid=%d, destUid=%d",
584 callingUid, srcUid, destUid);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100585 return ResponseCode::PERMISSION_DENIED;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700586 }
587
588 if (!is_granted_to(callingUid, destUid)) {
589 ALOGD("duplicate not granted to dest: %d -> %d", callingUid, destUid);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100590 return ResponseCode::PERMISSION_DENIED;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700591 }
592 }
593
594 String8 source8(srcKey);
Tucker Sylvestro0ab28b72016-08-05 18:02:47 -0400595 String8 sourceFile(mKeyStore->getKeyNameForUidWithDir(source8, srcUid, ::TYPE_ANY));
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700596
597 String8 target8(destKey);
Tucker Sylvestro0ab28b72016-08-05 18:02:47 -0400598 String8 targetFile(mKeyStore->getKeyNameForUidWithDir(target8, destUid, ::TYPE_ANY));
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700599
600 if (access(targetFile.string(), W_OK) != -1 || errno != ENOENT) {
601 ALOGD("destination already exists: %s", targetFile.string());
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100602 return ResponseCode::SYSTEM_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700603 }
604
605 Blob keyBlob;
606 ResponseCode responseCode =
607 mKeyStore->get(sourceFile.string(), &keyBlob, TYPE_ANY, get_user_id(srcUid));
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100608 if (responseCode != ResponseCode::NO_ERROR) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700609 return responseCode;
610 }
611
612 return mKeyStore->put(targetFile.string(), &keyBlob, get_user_id(destUid));
613}
614
615int32_t KeyStoreService::is_hardware_backed(const String16& keyType) {
616 return mKeyStore->isHardwareBacked(keyType) ? 1 : 0;
617}
618
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100619KeyStoreServiceReturnCode KeyStoreService::clear_uid(int64_t targetUid64) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700620 uid_t targetUid = getEffectiveUid(targetUid64);
621 if (!checkBinderPermissionSelfOrSystem(P_CLEAR_UID, targetUid)) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100622 return ResponseCode::PERMISSION_DENIED;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700623 }
Rubin Xu7675c9f2017-03-15 19:26:52 +0000624 ALOGI("clear_uid %" PRId64, targetUid64);
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700625
626 String8 prefix = String8::format("%u_", targetUid);
627 Vector<String16> aliases;
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100628 if (mKeyStore->list(prefix, &aliases, get_user_id(targetUid)) != ResponseCode::NO_ERROR) {
629 return ResponseCode::SYSTEM_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700630 }
631
632 for (uint32_t i = 0; i < aliases.size(); i++) {
633 String8 name8(aliases[i]);
Tucker Sylvestro0ab28b72016-08-05 18:02:47 -0400634 String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, targetUid, ::TYPE_ANY));
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700635 mKeyStore->del(filename.string(), ::TYPE_ANY, get_user_id(targetUid));
Tucker Sylvestro0ab28b72016-08-05 18:02:47 -0400636
637 // del() will fail silently if no cached characteristics are present for this alias.
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100638 String8 chr_filename(
639 mKeyStore->getKeyNameForUidWithDir(name8, targetUid, ::TYPE_KEY_CHARACTERISTICS));
Tucker Sylvestro0ab28b72016-08-05 18:02:47 -0400640 mKeyStore->del(chr_filename.string(), ::TYPE_KEY_CHARACTERISTICS, get_user_id(targetUid));
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700641 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100642 return ResponseCode::NO_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700643}
644
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100645KeyStoreServiceReturnCode KeyStoreService::addRngEntropy(const hidl_vec<uint8_t>& entropy) {
646 const auto& device = mKeyStore->getDevice();
647 return KS_HANDLE_HIDL_ERROR(device->addRngEntropy(entropy));
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700648}
649
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100650KeyStoreServiceReturnCode KeyStoreService::generateKey(const String16& name,
651 const hidl_vec<KeyParameter>& params,
652 const hidl_vec<uint8_t>& entropy, int uid,
653 int flags,
654 KeyCharacteristics* outCharacteristics) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700655 uid = getEffectiveUid(uid);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100656 KeyStoreServiceReturnCode rc =
657 checkBinderPermissionAndKeystoreState(P_INSERT, uid, flags & KEYSTORE_FLAG_ENCRYPTED);
658 if (!rc.isOk()) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700659 return rc;
660 }
661
Shawn Willdene2a7b522017-04-11 09:27:40 -0600662 if (containsTag(params, Tag::INCLUDE_UNIQUE_ID)) {
663 if (!checkBinderPermission(P_GEN_UNIQUE_ID)) return ResponseCode::PERMISSION_DENIED;
664 }
665
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100666 bool usingFallback = false;
667 auto& dev = mKeyStore->getDevice();
668 AuthorizationSet keyCharacteristics = params;
Tucker Sylvestro0ab28b72016-08-05 18:02:47 -0400669
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700670 // TODO: Seed from Linux RNG before this.
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100671 rc = addRngEntropy(entropy);
672 if (!rc.isOk()) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700673 return rc;
674 }
675
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100676 KeyStoreServiceReturnCode error;
677 auto hidl_cb = [&](ErrorCode ret, const hidl_vec<uint8_t>& hidlKeyBlob,
678 const KeyCharacteristics& keyCharacteristics) {
679 error = ret;
680 if (!error.isOk()) {
681 return;
682 }
683 if (outCharacteristics) *outCharacteristics = keyCharacteristics;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700684
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100685 // Write the key
686 String8 name8(name);
687 String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, uid, ::TYPE_KEYMASTER_10));
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700688
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100689 Blob keyBlob(&hidlKeyBlob[0], hidlKeyBlob.size(), NULL, 0, ::TYPE_KEYMASTER_10);
690 keyBlob.setFallback(usingFallback);
Shawn Willdend5a24e62017-02-28 13:53:24 -0700691 if (isAuthenticationBound(params)) {
692 keyBlob.setSuperEncrypted(true);
693 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100694 keyBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700695
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100696 error = mKeyStore->put(filename.string(), &keyBlob, get_user_id(uid));
697 };
698
699 rc = KS_HANDLE_HIDL_ERROR(dev->generateKey(params, hidl_cb));
700 if (!rc.isOk()) {
Tucker Sylvestro0ab28b72016-08-05 18:02:47 -0400701 return rc;
702 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100703 if (!error.isOk()) {
704 ALOGE("Failed to generate key -> falling back to software keymaster");
705 usingFallback = true;
Janis Danisevskise8ba1802017-01-30 10:49:51 +0000706 auto fallback = mKeyStore->getFallbackDevice();
707 if (!fallback.isOk()) {
708 return error;
709 }
710 rc = KS_HANDLE_HIDL_ERROR(fallback.value()->generateKey(params, hidl_cb));
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100711 if (!rc.isOk()) {
712 return rc;
713 }
714 if (!error.isOk()) {
715 return error;
716 }
717 }
Tucker Sylvestro0ab28b72016-08-05 18:02:47 -0400718
719 // Write the characteristics:
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100720 String8 name8(name);
Tucker Sylvestro0ab28b72016-08-05 18:02:47 -0400721 String8 cFilename(mKeyStore->getKeyNameForUidWithDir(name8, uid, ::TYPE_KEY_CHARACTERISTICS));
722
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100723 std::stringstream kc_stream;
724 keyCharacteristics.Serialize(&kc_stream);
725 if (kc_stream.bad()) {
726 return ResponseCode::SYSTEM_ERROR;
727 }
728 auto kc_buf = kc_stream.str();
729 Blob charBlob(reinterpret_cast<const uint8_t*>(kc_buf.data()), kc_buf.size(), NULL, 0,
730 ::TYPE_KEY_CHARACTERISTICS);
731 charBlob.setFallback(usingFallback);
Tucker Sylvestro0ab28b72016-08-05 18:02:47 -0400732 charBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
733
734 return mKeyStore->put(cFilename.string(), &charBlob, get_user_id(uid));
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700735}
736
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100737KeyStoreServiceReturnCode
738KeyStoreService::getKeyCharacteristics(const String16& name, const hidl_vec<uint8_t>& clientId,
739 const hidl_vec<uint8_t>& appData, int32_t uid,
740 KeyCharacteristics* outCharacteristics) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700741 if (!outCharacteristics) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100742 return ErrorCode::UNEXPECTED_NULL_POINTER;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700743 }
744
745 uid_t targetUid = getEffectiveUid(uid);
746 uid_t callingUid = IPCThreadState::self()->getCallingUid();
747 if (!is_granted_to(callingUid, targetUid)) {
748 ALOGW("uid %d not permitted to act for uid %d in getKeyCharacteristics", callingUid,
749 targetUid);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100750 return ResponseCode::PERMISSION_DENIED;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700751 }
752
753 Blob keyBlob;
754 String8 name8(name);
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700755
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100756 KeyStoreServiceReturnCode rc =
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700757 mKeyStore->getKeyForName(&keyBlob, name8, targetUid, TYPE_KEYMASTER_10);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100758 if (!rc.isOk()) {
759 return rc;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700760 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100761
762 auto hidlKeyBlob = blob2hidlVec(keyBlob);
763 auto& dev = mKeyStore->getDevice(keyBlob);
764
765 KeyStoreServiceReturnCode error;
766
767 auto hidlCb = [&](ErrorCode ret, const KeyCharacteristics& keyCharacteristics) {
768 error = ret;
769 if (!error.isOk()) {
770 return;
Shawn Willden98c59162016-03-20 09:10:18 -0600771 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100772 *outCharacteristics = keyCharacteristics;
773 };
774
775 rc = KS_HANDLE_HIDL_ERROR(dev->getKeyCharacteristics(hidlKeyBlob, clientId, appData, hidlCb));
776 if (!rc.isOk()) {
777 return rc;
778 }
779
780 if (error == ErrorCode::KEY_REQUIRES_UPGRADE) {
781 AuthorizationSet upgradeParams;
782 if (clientId.size()) {
783 upgradeParams.push_back(TAG_APPLICATION_ID, clientId);
784 }
785 if (appData.size()) {
786 upgradeParams.push_back(TAG_APPLICATION_DATA, appData);
Shawn Willden98c59162016-03-20 09:10:18 -0600787 }
788 rc = upgradeKeyBlob(name, targetUid, upgradeParams, &keyBlob);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100789 if (!rc.isOk()) {
Shawn Willden98c59162016-03-20 09:10:18 -0600790 return rc;
791 }
Shawn Willden715d0232016-01-21 00:45:13 -0700792
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100793 auto upgradedHidlKeyBlob = blob2hidlVec(keyBlob);
794
795 rc = KS_HANDLE_HIDL_ERROR(
796 dev->getKeyCharacteristics(upgradedHidlKeyBlob, clientId, appData, hidlCb));
797 if (!rc.isOk()) {
798 return rc;
799 }
800 // Note that, on success, "error" will have been updated by the hidlCB callback.
801 // So it is fine to return "error" below.
802 }
803 return error;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700804}
805
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100806KeyStoreServiceReturnCode
807KeyStoreService::importKey(const String16& name, const hidl_vec<KeyParameter>& params,
808 KeyFormat format, const hidl_vec<uint8_t>& keyData, int uid, int flags,
809 KeyCharacteristics* outCharacteristics) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700810 uid = getEffectiveUid(uid);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100811 KeyStoreServiceReturnCode rc =
812 checkBinderPermissionAndKeystoreState(P_INSERT, uid, flags & KEYSTORE_FLAG_ENCRYPTED);
813 if (!rc.isOk()) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700814 return rc;
815 }
816
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100817 bool usingFallback = false;
818 auto& dev = mKeyStore->getDevice();
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700819
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700820 String8 name8(name);
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700821
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100822 KeyStoreServiceReturnCode error;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700823
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100824 auto hidlCb = [&](ErrorCode ret, const hidl_vec<uint8_t>& keyBlob,
825 const KeyCharacteristics& keyCharacteristics) {
826 error = ret;
827 if (!error.isOk()) {
828 return;
829 }
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700830
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100831 if (outCharacteristics) *outCharacteristics = keyCharacteristics;
832
833 // Write the key:
834 String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, uid, ::TYPE_KEYMASTER_10));
835
836 Blob ksBlob(&keyBlob[0], keyBlob.size(), NULL, 0, ::TYPE_KEYMASTER_10);
837 ksBlob.setFallback(usingFallback);
Shawn Willdend5a24e62017-02-28 13:53:24 -0700838 if (isAuthenticationBound(params)) {
839 ksBlob.setSuperEncrypted(true);
840 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100841 ksBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
842
843 error = mKeyStore->put(filename.string(), &ksBlob, get_user_id(uid));
844 };
845
846 rc = KS_HANDLE_HIDL_ERROR(dev->importKey(params, format, keyData, hidlCb));
847 // possible hidl error
848 if (!rc.isOk()) {
Tucker Sylvestro0ab28b72016-08-05 18:02:47 -0400849 return rc;
850 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100851 // now check error from callback
852 if (!error.isOk()) {
853 ALOGE("Failed to import key -> falling back to software keymaster");
854 usingFallback = true;
Janis Danisevskise8ba1802017-01-30 10:49:51 +0000855 auto fallback = mKeyStore->getFallbackDevice();
856 if (!fallback.isOk()) {
857 return error;
858 }
859 rc = KS_HANDLE_HIDL_ERROR(fallback.value()->importKey(params, format, keyData, hidlCb));
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100860 // possible hidl error
861 if (!rc.isOk()) {
862 return rc;
863 }
864 // now check error from callback
865 if (!error.isOk()) {
866 return error;
867 }
868 }
Tucker Sylvestro0ab28b72016-08-05 18:02:47 -0400869
870 // Write the characteristics:
871 String8 cFilename(mKeyStore->getKeyNameForUidWithDir(name8, uid, ::TYPE_KEY_CHARACTERISTICS));
872
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100873 AuthorizationSet opParams = params;
874 std::stringstream kcStream;
875 opParams.Serialize(&kcStream);
876 if (kcStream.bad()) return ResponseCode::SYSTEM_ERROR;
877 auto kcBuf = kcStream.str();
878
879 Blob charBlob(reinterpret_cast<const uint8_t*>(kcBuf.data()), kcBuf.size(), NULL, 0,
880 ::TYPE_KEY_CHARACTERISTICS);
881 charBlob.setFallback(usingFallback);
Tucker Sylvestro0ab28b72016-08-05 18:02:47 -0400882 charBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
883
884 return mKeyStore->put(cFilename.string(), &charBlob, get_user_id(uid));
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700885}
886
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100887void KeyStoreService::exportKey(const String16& name, KeyFormat format,
888 const hidl_vec<uint8_t>& clientId, const hidl_vec<uint8_t>& appData,
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700889 int32_t uid, ExportResult* result) {
890
891 uid_t targetUid = getEffectiveUid(uid);
892 uid_t callingUid = IPCThreadState::self()->getCallingUid();
893 if (!is_granted_to(callingUid, targetUid)) {
894 ALOGW("uid %d not permitted to act for uid %d in exportKey", callingUid, targetUid);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100895 result->resultCode = ResponseCode::PERMISSION_DENIED;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700896 return;
897 }
898
899 Blob keyBlob;
900 String8 name8(name);
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700901
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100902 result->resultCode = mKeyStore->getKeyForName(&keyBlob, name8, targetUid, TYPE_KEYMASTER_10);
903 if (!result->resultCode.isOk()) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700904 return;
905 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100906
907 auto key = blob2hidlVec(keyBlob);
908 auto& dev = mKeyStore->getDevice(keyBlob);
909
910 auto hidlCb = [&](ErrorCode ret, const ::android::hardware::hidl_vec<uint8_t>& keyMaterial) {
911 result->resultCode = ret;
912 if (!result->resultCode.isOk()) {
Ji Wang2c142312016-10-14 17:21:10 +0800913 return;
914 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100915 result->exportData = keyMaterial;
916 };
917 KeyStoreServiceReturnCode rc =
918 KS_HANDLE_HIDL_ERROR(dev->exportKey(format, key, clientId, appData, hidlCb));
919 // Overwrite result->resultCode only on HIDL error. Otherwise we want the result set in the
920 // callback hidlCb.
921 if (!rc.isOk()) {
922 result->resultCode = rc;
Ji Wang2c142312016-10-14 17:21:10 +0800923 }
924
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100925 if (result->resultCode == ErrorCode::KEY_REQUIRES_UPGRADE) {
926 AuthorizationSet upgradeParams;
927 if (clientId.size()) {
928 upgradeParams.push_back(TAG_APPLICATION_ID, clientId);
929 }
930 if (appData.size()) {
931 upgradeParams.push_back(TAG_APPLICATION_DATA, appData);
932 }
933 result->resultCode = upgradeKeyBlob(name, targetUid, upgradeParams, &keyBlob);
934 if (!result->resultCode.isOk()) {
935 return;
936 }
937
938 auto upgradedHidlKeyBlob = blob2hidlVec(keyBlob);
939
940 result->resultCode = KS_HANDLE_HIDL_ERROR(
941 dev->exportKey(format, upgradedHidlKeyBlob, clientId, appData, hidlCb));
942 if (!result->resultCode.isOk()) {
943 return;
944 }
945 }
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700946}
947
Shawn Willdend3ed3a22017-03-28 00:39:16 +0000948static inline void addAuthTokenToParams(AuthorizationSet* params, const HardwareAuthToken* token) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100949 if (token) {
Shawn Willdend3ed3a22017-03-28 00:39:16 +0000950 params->push_back(TAG_AUTH_TOKEN, authToken2HidlVec(*token));
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100951 }
952}
953
954void KeyStoreService::begin(const sp<IBinder>& appToken, const String16& name, KeyPurpose purpose,
955 bool pruneable, const hidl_vec<KeyParameter>& params,
956 const hidl_vec<uint8_t>& entropy, int32_t uid,
957 OperationResult* result) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700958 uid_t callingUid = IPCThreadState::self()->getCallingUid();
959 uid_t targetUid = getEffectiveUid(uid);
960 if (!is_granted_to(callingUid, targetUid)) {
961 ALOGW("uid %d not permitted to act for uid %d in begin", callingUid, targetUid);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100962 result->resultCode = ResponseCode::PERMISSION_DENIED;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700963 return;
964 }
965 if (!pruneable && get_app_id(callingUid) != AID_SYSTEM) {
966 ALOGE("Non-system uid %d trying to start non-pruneable operation", callingUid);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100967 result->resultCode = ResponseCode::PERMISSION_DENIED;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700968 return;
969 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100970 if (!checkAllowedOperationParams(params)) {
971 result->resultCode = ErrorCode::INVALID_ARGUMENT;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700972 return;
973 }
974 Blob keyBlob;
975 String8 name8(name);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100976 result->resultCode = mKeyStore->getKeyForName(&keyBlob, name8, targetUid, TYPE_KEYMASTER_10);
Shawn Willdend5a24e62017-02-28 13:53:24 -0700977 if (result->resultCode == ResponseCode::LOCKED && keyBlob.isSuperEncrypted()) {
978 result->resultCode = ErrorCode::KEY_USER_NOT_AUTHENTICATED;
979 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100980 if (!result->resultCode.isOk()) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700981 return;
982 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100983
984 auto key = blob2hidlVec(keyBlob);
985 auto& dev = mKeyStore->getDevice(keyBlob);
986 AuthorizationSet opParams = params;
987 KeyCharacteristics characteristics;
988 result->resultCode = getOperationCharacteristics(key, &dev, opParams, &characteristics);
989
990 if (result->resultCode == ErrorCode::KEY_REQUIRES_UPGRADE) {
991 result->resultCode = upgradeKeyBlob(name, targetUid, opParams, &keyBlob);
992 if (!result->resultCode.isOk()) {
Shawn Willden98c59162016-03-20 09:10:18 -0600993 return;
994 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100995 key = blob2hidlVec(keyBlob);
996 result->resultCode = getOperationCharacteristics(key, &dev, opParams, &characteristics);
Shawn Willden98c59162016-03-20 09:10:18 -0600997 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100998 if (!result->resultCode.isOk()) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -0700999 return;
1000 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001001
Shawn Willdend3ed3a22017-03-28 00:39:16 +00001002 const HardwareAuthToken* authToken = NULL;
Tucker Sylvestro0ab28b72016-08-05 18:02:47 -04001003
1004 // Merge these characteristics with the ones cached when the key was generated or imported
1005 Blob charBlob;
1006 AuthorizationSet persistedCharacteristics;
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001007 result->resultCode =
1008 mKeyStore->getKeyForName(&charBlob, name8, targetUid, TYPE_KEY_CHARACTERISTICS);
1009 if (result->resultCode.isOk()) {
1010 // TODO write one shot stream buffer to avoid copying (twice here)
1011 std::string charBuffer(reinterpret_cast<const char*>(charBlob.getValue()),
1012 charBlob.getLength());
1013 std::stringstream charStream(charBuffer);
1014 persistedCharacteristics.Deserialize(&charStream);
Tucker Sylvestro0ab28b72016-08-05 18:02:47 -04001015 } else {
1016 ALOGD("Unable to read cached characteristics for key");
1017 }
1018
1019 // Replace the sw_enforced set with those persisted to disk, minus hw_enforced
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001020 AuthorizationSet softwareEnforced = characteristics.softwareEnforced;
1021 AuthorizationSet teeEnforced = characteristics.teeEnforced;
1022 persistedCharacteristics.Union(softwareEnforced);
1023 persistedCharacteristics.Subtract(teeEnforced);
1024 characteristics.softwareEnforced = persistedCharacteristics.hidl_data();
Tucker Sylvestro0ab28b72016-08-05 18:02:47 -04001025
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001026 result->resultCode = getAuthToken(characteristics, 0, purpose, &authToken,
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001027 /*failOnTokenMissing*/ false);
1028 // If per-operation auth is needed we need to begin the operation and
1029 // the client will need to authorize that operation before calling
1030 // update. Any other auth issues stop here.
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001031 if (!result->resultCode.isOk() && result->resultCode != ResponseCode::OP_AUTH_NEEDED) return;
1032
1033 addAuthTokenToParams(&opParams, authToken);
1034
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001035 // Add entropy to the device first.
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001036 if (entropy.size()) {
1037 result->resultCode = addRngEntropy(entropy);
1038 if (!result->resultCode.isOk()) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001039 return;
1040 }
1041 }
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001042
1043 // Create a keyid for this key.
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001044 km_id_t keyid;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001045 if (!enforcement_policy.CreateKeyId(key, &keyid)) {
1046 ALOGE("Failed to create a key ID for authorization checking.");
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001047 result->resultCode = ErrorCode::UNKNOWN_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001048 return;
1049 }
1050
1051 // Check that all key authorization policy requirements are met.
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001052 AuthorizationSet key_auths = characteristics.teeEnforced;
1053 key_auths.append(&characteristics.softwareEnforced[0],
1054 &characteristics.softwareEnforced[characteristics.softwareEnforced.size()]);
1055
1056 result->resultCode = enforcement_policy.AuthorizeOperation(
1057 purpose, keyid, key_auths, opParams, 0 /* op_handle */, true /* is_begin_operation */);
1058 if (!result->resultCode.isOk()) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001059 return;
1060 }
1061
Shawn Willdene2a7b522017-04-11 09:27:40 -06001062 // If there are more than kMaxOperations, abort the oldest operation that was started as
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001063 // pruneable.
Shawn Willdene2a7b522017-04-11 09:27:40 -06001064 while (mOperationMap.getOperationCount() >= kMaxOperations) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001065 ALOGD("Reached or exceeded concurrent operations limit");
1066 if (!pruneOperation()) {
1067 break;
1068 }
1069 }
1070
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001071 auto hidlCb = [&](ErrorCode ret, const hidl_vec<KeyParameter>& outParams,
1072 uint64_t operationHandle) {
1073 result->resultCode = ret;
1074 if (!result->resultCode.isOk()) {
1075 return;
1076 }
1077 result->handle = operationHandle;
1078 result->outParams = outParams;
1079 };
1080
1081 ErrorCode rc = KS_HANDLE_HIDL_ERROR(dev->begin(purpose, key, opParams.hidl_data(), hidlCb));
1082 if (rc != ErrorCode::OK) {
1083 ALOGW("Got error %d from begin()", rc);
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001084 }
1085
1086 // If there are too many operations abort the oldest operation that was
1087 // started as pruneable and try again.
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001088 while (rc == ErrorCode::TOO_MANY_OPERATIONS && mOperationMap.hasPruneableOperation()) {
1089 ALOGW("Ran out of operation handles");
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001090 if (!pruneOperation()) {
1091 break;
1092 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001093 rc = KS_HANDLE_HIDL_ERROR(dev->begin(purpose, key, opParams.hidl_data(), hidlCb));
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001094 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001095 if (rc != ErrorCode::OK) {
1096 result->resultCode = rc;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001097 return;
1098 }
1099
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001100 // Note: The operation map takes possession of the contents of "characteristics".
1101 // It is safe to use characteristics after the following line but it will be empty.
1102 sp<IBinder> operationToken = mOperationMap.addOperation(
1103 result->handle, keyid, purpose, dev, appToken, std::move(characteristics), pruneable);
1104 assert(characteristics.teeEnforced.size() == 0);
1105 assert(characteristics.softwareEnforced.size() == 0);
1106
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001107 if (authToken) {
Shawn Willdend3ed3a22017-03-28 00:39:16 +00001108 mOperationMap.setOperationAuthToken(operationToken, authToken);
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001109 }
1110 // Return the authentication lookup result. If this is a per operation
1111 // auth'd key then the resultCode will be ::OP_AUTH_NEEDED and the
1112 // application should get an auth token using the handle before the
1113 // first call to update, which will fail if keystore hasn't received the
1114 // auth token.
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001115 // All fields but "token" were set in the begin operation's callback.
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001116 result->token = operationToken;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001117}
1118
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001119void KeyStoreService::update(const sp<IBinder>& token, const hidl_vec<KeyParameter>& params,
1120 const hidl_vec<uint8_t>& data, OperationResult* result) {
1121 if (!checkAllowedOperationParams(params)) {
1122 result->resultCode = ErrorCode::INVALID_ARGUMENT;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001123 return;
1124 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001125 km_device_t dev;
1126 uint64_t handle;
1127 KeyPurpose purpose;
1128 km_id_t keyid;
1129 const KeyCharacteristics* characteristics;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001130 if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, &characteristics)) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001131 result->resultCode = ErrorCode::INVALID_OPERATION_HANDLE;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001132 return;
1133 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001134 AuthorizationSet opParams = params;
1135 result->resultCode = addOperationAuthTokenIfNeeded(token, &opParams);
1136 if (!result->resultCode.isOk()) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001137 return;
1138 }
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001139
1140 // Check that all key authorization policy requirements are met.
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001141 AuthorizationSet key_auths(characteristics->teeEnforced);
1142 key_auths.append(&characteristics->softwareEnforced[0],
1143 &characteristics->softwareEnforced[characteristics->softwareEnforced.size()]);
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001144 result->resultCode = enforcement_policy.AuthorizeOperation(
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001145 purpose, keyid, key_auths, opParams, handle, false /* is_begin_operation */);
1146 if (!result->resultCode.isOk()) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001147 return;
1148 }
1149
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001150 auto hidlCb = [&](ErrorCode ret, uint32_t inputConsumed,
1151 const hidl_vec<KeyParameter>& outParams, const hidl_vec<uint8_t>& output) {
1152 result->resultCode = ret;
1153 if (!result->resultCode.isOk()) {
1154 return;
1155 }
1156 result->inputConsumed = inputConsumed;
1157 result->outParams = outParams;
1158 result->data = output;
1159 };
1160
Janis Danisevskisb0245ee2017-01-25 15:43:01 +00001161 KeyStoreServiceReturnCode rc = KS_HANDLE_HIDL_ERROR(dev->update(handle, opParams.hidl_data(),
1162 data, hidlCb));
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001163 // just a reminder: on success result->resultCode was set in the callback. So we only overwrite
1164 // it if there was a communication error indicated by the ErrorCode.
1165 if (!rc.isOk()) {
1166 result->resultCode = rc;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001167 }
1168}
1169
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001170void KeyStoreService::finish(const sp<IBinder>& token, const hidl_vec<KeyParameter>& params,
1171 const hidl_vec<uint8_t>& signature, const hidl_vec<uint8_t>& entropy,
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001172 OperationResult* result) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001173 if (!checkAllowedOperationParams(params)) {
1174 result->resultCode = ErrorCode::INVALID_ARGUMENT;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001175 return;
1176 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001177 km_device_t dev;
1178 uint64_t handle;
1179 KeyPurpose purpose;
1180 km_id_t keyid;
1181 const KeyCharacteristics* characteristics;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001182 if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, &characteristics)) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001183 result->resultCode = ErrorCode::INVALID_OPERATION_HANDLE;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001184 return;
1185 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001186 AuthorizationSet opParams = params;
1187 result->resultCode = addOperationAuthTokenIfNeeded(token, &opParams);
1188 if (!result->resultCode.isOk()) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001189 return;
1190 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001191
1192 if (entropy.size()) {
1193 result->resultCode = addRngEntropy(entropy);
1194 if (!result->resultCode.isOk()) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001195 return;
1196 }
1197 }
1198
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001199 // Check that all key authorization policy requirements are met.
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001200 AuthorizationSet key_auths(characteristics->teeEnforced);
1201 key_auths.append(&characteristics->softwareEnforced[0],
1202 &characteristics->softwareEnforced[characteristics->softwareEnforced.size()]);
1203 result->resultCode = enforcement_policy.AuthorizeOperation(
1204 purpose, keyid, key_auths, opParams, handle, false /* is_begin_operation */);
1205 if (!result->resultCode.isOk()) return;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001206
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001207 auto hidlCb = [&](ErrorCode ret, const hidl_vec<KeyParameter>& outParams,
1208 const hidl_vec<uint8_t>& output) {
1209 result->resultCode = ret;
1210 if (!result->resultCode.isOk()) {
1211 return;
1212 }
1213 result->outParams = outParams;
1214 result->data = output;
1215 };
1216
1217 KeyStoreServiceReturnCode rc = KS_HANDLE_HIDL_ERROR(dev->finish(
1218 handle, opParams.hidl_data(),
1219 hidl_vec<uint8_t>() /* TODO(swillden): wire up input to finish() */, signature, hidlCb));
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001220 // Remove the operation regardless of the result
1221 mOperationMap.removeOperation(token);
1222 mAuthTokenTable.MarkCompleted(handle);
1223
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001224 // just a reminder: on success result->resultCode was set in the callback. So we only overwrite
1225 // it if there was a communication error indicated by the ErrorCode.
1226 if (!rc.isOk()) {
1227 result->resultCode = rc;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001228 }
1229}
1230
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001231KeyStoreServiceReturnCode KeyStoreService::abort(const sp<IBinder>& token) {
1232 km_device_t dev;
1233 uint64_t handle;
1234 KeyPurpose purpose;
1235 km_id_t keyid;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001236 if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, NULL)) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001237 return ErrorCode::INVALID_OPERATION_HANDLE;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001238 }
1239 mOperationMap.removeOperation(token);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001240
1241 ErrorCode rc = KS_HANDLE_HIDL_ERROR(dev->abort(handle));
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001242 mAuthTokenTable.MarkCompleted(handle);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001243 return rc;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001244}
1245
1246bool KeyStoreService::isOperationAuthorized(const sp<IBinder>& token) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001247 km_device_t dev;
1248 uint64_t handle;
1249 const KeyCharacteristics* characteristics;
1250 KeyPurpose purpose;
1251 km_id_t keyid;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001252 if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, &characteristics)) {
1253 return false;
1254 }
Shawn Willdend3ed3a22017-03-28 00:39:16 +00001255 const HardwareAuthToken* authToken = NULL;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001256 mOperationMap.getOperationAuthToken(token, &authToken);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001257 AuthorizationSet ignored;
1258 auto authResult = addOperationAuthTokenIfNeeded(token, &ignored);
1259 return authResult.isOk();
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001260}
1261
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001262KeyStoreServiceReturnCode KeyStoreService::addAuthToken(const uint8_t* token, size_t length) {
Shawn Willdend3ed3a22017-03-28 00:39:16 +00001263 // TODO(swillden): When gatekeeper and fingerprint are ready, this should be updated to
1264 // receive a HardwareAuthToken, rather than an opaque byte array.
1265
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001266 if (!checkBinderPermission(P_ADD_AUTH)) {
1267 ALOGW("addAuthToken: permission denied for %d", IPCThreadState::self()->getCallingUid());
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001268 return ResponseCode::PERMISSION_DENIED;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001269 }
Shawn Willdend3ed3a22017-03-28 00:39:16 +00001270 if (length != sizeof(hw_auth_token_t)) {
1271 return ErrorCode::INVALID_ARGUMENT;
1272 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001273
Shawn Willdend3ed3a22017-03-28 00:39:16 +00001274 hw_auth_token_t authToken;
1275 memcpy(reinterpret_cast<void*>(&authToken), token, sizeof(hw_auth_token_t));
1276 if (authToken.version != 0) {
1277 return ErrorCode::INVALID_ARGUMENT;
1278 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001279
Shawn Willdend3ed3a22017-03-28 00:39:16 +00001280 std::unique_ptr<HardwareAuthToken> hidlAuthToken(new HardwareAuthToken);
1281 hidlAuthToken->challenge = authToken.challenge;
1282 hidlAuthToken->userId = authToken.user_id;
1283 hidlAuthToken->authenticatorId = authToken.authenticator_id;
1284 hidlAuthToken->authenticatorType = authToken.authenticator_type;
1285 hidlAuthToken->timestamp = authToken.timestamp;
1286 static_assert(
1287 std::is_same<decltype(hidlAuthToken->hmac),
1288 ::android::hardware::hidl_array<uint8_t, sizeof(authToken.hmac)>>::value,
1289 "This function assumes token HMAC is 32 bytes, but it might not be.");
1290 std::copy(authToken.hmac, authToken.hmac + sizeof(authToken.hmac), hidlAuthToken->hmac.data());
1291
1292 // The table takes ownership of authToken.
1293 mAuthTokenTable.AddAuthenticationToken(hidlAuthToken.release());
1294 return ResponseCode::NO_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001295}
1296
Janis Danisevskis7612fd42016-09-01 11:50:02 +01001297constexpr size_t KEY_ATTESTATION_APPLICATION_ID_MAX_SIZE = 1024;
1298
Bartosz Fabianowskia9452d92017-01-23 22:21:11 +01001299bool isDeviceIdAttestationRequested(const hidl_vec<KeyParameter>& params) {
1300 for (size_t i = 0; i < params.size(); ++i) {
1301 switch (params[i].tag) {
Shawn Willdene2a7b522017-04-11 09:27:40 -06001302 case Tag::ATTESTATION_ID_BRAND:
1303 case Tag::ATTESTATION_ID_DEVICE:
1304 case Tag::ATTESTATION_ID_IMEI:
1305 case Tag::ATTESTATION_ID_MANUFACTURER:
1306 case Tag::ATTESTATION_ID_MEID:
1307 case Tag::ATTESTATION_ID_MODEL:
1308 case Tag::ATTESTATION_ID_PRODUCT:
1309 case Tag::ATTESTATION_ID_SERIAL:
1310 return true;
1311 default:
1312 break;
Bartosz Fabianowskia9452d92017-01-23 22:21:11 +01001313 }
1314 }
1315 return false;
1316}
1317
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001318KeyStoreServiceReturnCode KeyStoreService::attestKey(const String16& name,
1319 const hidl_vec<KeyParameter>& params,
1320 hidl_vec<hidl_vec<uint8_t>>* outChain) {
1321 if (!outChain) {
1322 return ErrorCode::OUTPUT_PARAMETER_NULL;
1323 }
Shawn Willden50eb1b22016-01-21 12:41:23 -07001324
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001325 if (!checkAllowedOperationParams(params)) {
1326 return ErrorCode::INVALID_ARGUMENT;
Shawn Willden50eb1b22016-01-21 12:41:23 -07001327 }
1328
1329 uid_t callingUid = IPCThreadState::self()->getCallingUid();
1330
Bartosz Fabianowskia9452d92017-01-23 22:21:11 +01001331 bool attestingDeviceIds = isDeviceIdAttestationRequested(params);
1332 if (attestingDeviceIds) {
1333 sp<IBinder> binder = defaultServiceManager()->getService(String16("permission"));
1334 if (binder == 0) {
1335 return ErrorCode::CANNOT_ATTEST_IDS;
1336 }
1337 if (!interface_cast<IPermissionController>(binder)->checkPermission(
1338 String16("android.permission.READ_PRIVILEGED_PHONE_STATE"),
1339 IPCThreadState::self()->getCallingPid(), callingUid)) {
Shawn Willdene2a7b522017-04-11 09:27:40 -06001340 return ErrorCode::CANNOT_ATTEST_IDS;
Bartosz Fabianowskia9452d92017-01-23 22:21:11 +01001341 }
1342 }
1343
Shawn Willdene2a7b522017-04-11 09:27:40 -06001344 AuthorizationSet mutableParams = params;
1345
1346 KeyStoreServiceReturnCode responseCode;
1347 bool factoryResetSinceIdRotation;
1348 std::tie(responseCode, factoryResetSinceIdRotation) = hadFactoryResetSinceIdRotation();
1349
1350 if (!responseCode.isOk()) return responseCode;
1351 if (factoryResetSinceIdRotation) mutableParams.push_back(TAG_RESET_SINCE_ID_ROTATION);
1352
Shawn Willden50eb1b22016-01-21 12:41:23 -07001353 Blob keyBlob;
1354 String8 name8(name);
Shawn Willdene2a7b522017-04-11 09:27:40 -06001355 responseCode = mKeyStore->getKeyForName(&keyBlob, name8, callingUid, TYPE_KEYMASTER_10);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001356 if (!responseCode.isOk()) {
Shawn Willden50eb1b22016-01-21 12:41:23 -07001357 return responseCode;
1358 }
1359
Janis Danisevskis18f27ad2016-06-01 13:57:40 -07001360 auto asn1_attestation_id_result = security::gather_attestation_application_id(callingUid);
Janis Danisevskis011675d2016-09-01 11:41:29 +01001361 if (!asn1_attestation_id_result.isOk()) {
Janis Danisevskis18f27ad2016-06-01 13:57:40 -07001362 ALOGE("failed to gather attestation_id");
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001363 return ErrorCode::ATTESTATION_APPLICATION_ID_MISSING;
Janis Danisevskis18f27ad2016-06-01 13:57:40 -07001364 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001365 std::vector<uint8_t>& asn1_attestation_id = asn1_attestation_id_result;
Janis Danisevskis18f27ad2016-06-01 13:57:40 -07001366
1367 /*
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001368 * The attestation application ID cannot be longer than
1369 * KEY_ATTESTATION_APPLICATION_ID_MAX_SIZE, so we truncate if too long.
Janis Danisevskis18f27ad2016-06-01 13:57:40 -07001370 */
Shawn Willdene2a7b522017-04-11 09:27:40 -06001371 if (asn1_attestation_id.size() > KEY_ATTESTATION_APPLICATION_ID_MAX_SIZE) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001372 asn1_attestation_id.resize(KEY_ATTESTATION_APPLICATION_ID_MAX_SIZE);
Shawn Willdene2a7b522017-04-11 09:27:40 -06001373 }
Shawn Willden50eb1b22016-01-21 12:41:23 -07001374
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001375 mutableParams.push_back(TAG_ATTESTATION_APPLICATION_ID, blob2hidlVec(asn1_attestation_id));
1376
1377 KeyStoreServiceReturnCode error;
1378 auto hidlCb = [&](ErrorCode ret, const hidl_vec<hidl_vec<uint8_t>>& certChain) {
1379 error = ret;
1380 if (!error.isOk()) {
1381 return;
1382 }
1383 if (outChain) *outChain = certChain;
1384 };
1385
1386 auto hidlKey = blob2hidlVec(keyBlob);
1387 auto& dev = mKeyStore->getDevice(keyBlob);
Bartosz Fabianowskia9452d92017-01-23 22:21:11 +01001388 KeyStoreServiceReturnCode attestationRc =
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001389 KS_HANDLE_HIDL_ERROR(dev->attestKey(hidlKey, mutableParams.hidl_data(), hidlCb));
Bartosz Fabianowskia9452d92017-01-23 22:21:11 +01001390
1391 KeyStoreServiceReturnCode deletionRc;
1392 if (attestingDeviceIds) {
1393 // When performing device id attestation, treat the key as ephemeral and delete it straight
1394 // away.
1395 deletionRc = KS_HANDLE_HIDL_ERROR(dev->deleteKey(hidlKey));
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001396 }
Bartosz Fabianowskia9452d92017-01-23 22:21:11 +01001397
1398 if (!attestationRc.isOk()) {
1399 return attestationRc;
1400 }
1401 if (!error.isOk()) {
1402 return error;
1403 }
1404 return deletionRc;
Shawn Willden50eb1b22016-01-21 12:41:23 -07001405}
1406
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001407KeyStoreServiceReturnCode KeyStoreService::onDeviceOffBody() {
Tucker Sylvestro0ab28b72016-08-05 18:02:47 -04001408 // TODO(tuckeris): add permission check. This should be callable from ClockworkHome only.
1409 mAuthTokenTable.onDeviceOffBody();
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001410 return ResponseCode::NO_ERROR;
Tucker Sylvestro0ab28b72016-08-05 18:02:47 -04001411}
1412
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001413/**
1414 * Prune the oldest pruneable operation.
1415 */
1416bool KeyStoreService::pruneOperation() {
1417 sp<IBinder> oldest = mOperationMap.getOldestPruneableOperation();
1418 ALOGD("Trying to prune operation %p", oldest.get());
1419 size_t op_count_before_abort = mOperationMap.getOperationCount();
1420 // We mostly ignore errors from abort() because all we care about is whether at least
1421 // one operation has been removed.
1422 int abort_error = abort(oldest);
1423 if (mOperationMap.getOperationCount() >= op_count_before_abort) {
1424 ALOGE("Failed to abort pruneable operation %p, error: %d", oldest.get(), abort_error);
1425 return false;
1426 }
1427 return true;
1428}
1429
1430/**
1431 * Get the effective target uid for a binder operation that takes an
1432 * optional uid as the target.
1433 */
1434uid_t KeyStoreService::getEffectiveUid(int32_t targetUid) {
1435 if (targetUid == UID_SELF) {
1436 return IPCThreadState::self()->getCallingUid();
1437 }
1438 return static_cast<uid_t>(targetUid);
1439}
1440
1441/**
1442 * Check if the caller of the current binder method has the required
1443 * permission and if acting on other uids the grants to do so.
1444 */
1445bool KeyStoreService::checkBinderPermission(perm_t permission, int32_t targetUid) {
1446 uid_t callingUid = IPCThreadState::self()->getCallingUid();
1447 pid_t spid = IPCThreadState::self()->getCallingPid();
1448 if (!has_permission(callingUid, permission, spid)) {
1449 ALOGW("permission %s denied for %d", get_perm_label(permission), callingUid);
1450 return false;
1451 }
1452 if (!is_granted_to(callingUid, getEffectiveUid(targetUid))) {
1453 ALOGW("uid %d not granted to act for %d", callingUid, targetUid);
1454 return false;
1455 }
1456 return true;
1457}
1458
1459/**
1460 * Check if the caller of the current binder method has the required
1461 * permission and the target uid is the caller or the caller is system.
1462 */
1463bool KeyStoreService::checkBinderPermissionSelfOrSystem(perm_t permission, int32_t targetUid) {
1464 uid_t callingUid = IPCThreadState::self()->getCallingUid();
1465 pid_t spid = IPCThreadState::self()->getCallingPid();
1466 if (!has_permission(callingUid, permission, spid)) {
1467 ALOGW("permission %s denied for %d", get_perm_label(permission), callingUid);
1468 return false;
1469 }
1470 return getEffectiveUid(targetUid) == callingUid || callingUid == AID_SYSTEM;
1471}
1472
1473/**
1474 * Check if the caller of the current binder method has the required
1475 * permission or the target of the operation is the caller's uid. This is
1476 * for operation where the permission is only for cross-uid activity and all
1477 * uids are allowed to act on their own (ie: clearing all entries for a
1478 * given uid).
1479 */
1480bool KeyStoreService::checkBinderPermissionOrSelfTarget(perm_t permission, int32_t targetUid) {
1481 uid_t callingUid = IPCThreadState::self()->getCallingUid();
1482 if (getEffectiveUid(targetUid) == callingUid) {
1483 return true;
1484 } else {
1485 return checkBinderPermission(permission, targetUid);
1486 }
1487}
1488
1489/**
1490 * Helper method to check that the caller has the required permission as
1491 * well as the keystore is in the unlocked state if checkUnlocked is true.
1492 *
1493 * Returns NO_ERROR on success, PERMISSION_DENIED on a permission error and
1494 * otherwise the state of keystore when not unlocked and checkUnlocked is
1495 * true.
1496 */
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001497KeyStoreServiceReturnCode
1498KeyStoreService::checkBinderPermissionAndKeystoreState(perm_t permission, int32_t targetUid,
1499 bool checkUnlocked) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001500 if (!checkBinderPermission(permission, targetUid)) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001501 return ResponseCode::PERMISSION_DENIED;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001502 }
1503 State state = mKeyStore->getState(get_user_id(getEffectiveUid(targetUid)));
1504 if (checkUnlocked && !isKeystoreUnlocked(state)) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001505 // All State values coincide with ResponseCodes
1506 return static_cast<ResponseCode>(state);
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001507 }
1508
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001509 return ResponseCode::NO_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001510}
1511
1512bool KeyStoreService::isKeystoreUnlocked(State state) {
1513 switch (state) {
1514 case ::STATE_NO_ERROR:
1515 return true;
1516 case ::STATE_UNINITIALIZED:
1517 case ::STATE_LOCKED:
1518 return false;
1519 }
1520 return false;
1521}
1522
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001523/**
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001524 * Check that all KeyParameter's provided by the application are
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001525 * allowed. Any parameter that keystore adds itself should be disallowed here.
1526 */
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001527bool KeyStoreService::checkAllowedOperationParams(const hidl_vec<KeyParameter>& params) {
1528 for (size_t i = 0; i < params.size(); ++i) {
1529 switch (params[i].tag) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001530 case Tag::ATTESTATION_APPLICATION_ID:
Shawn Willdene2a7b522017-04-11 09:27:40 -06001531 case Tag::AUTH_TOKEN:
1532 case Tag::RESET_SINCE_ID_ROTATION:
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001533 return false;
1534 default:
1535 break;
1536 }
1537 }
1538 return true;
1539}
1540
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001541ErrorCode KeyStoreService::getOperationCharacteristics(const hidl_vec<uint8_t>& key,
1542 km_device_t* dev,
1543 const AuthorizationSet& params,
1544 KeyCharacteristics* out) {
1545 hidl_vec<uint8_t> appId;
1546 hidl_vec<uint8_t> appData;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001547 for (auto param : params) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001548 if (param.tag == Tag::APPLICATION_ID) {
1549 appId = authorizationValue(TAG_APPLICATION_ID, param).value();
1550 } else if (param.tag == Tag::APPLICATION_DATA) {
1551 appData = authorizationValue(TAG_APPLICATION_DATA, param).value();
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001552 }
1553 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001554 ErrorCode error = ErrorCode::OK;
1555
1556 auto hidlCb = [&](ErrorCode ret, const KeyCharacteristics& keyCharacteristics) {
1557 error = ret;
1558 if (error != ErrorCode::OK) {
1559 return;
1560 }
1561 if (out) *out = keyCharacteristics;
1562 };
1563
1564 ErrorCode rc = KS_HANDLE_HIDL_ERROR((*dev)->getKeyCharacteristics(key, appId, appData, hidlCb));
1565 if (rc != ErrorCode::OK) {
1566 return rc;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001567 }
1568 return error;
1569}
1570
1571/**
Shawn Willdend3ed3a22017-03-28 00:39:16 +00001572 * Get the auth token for this operation from the auth token table.
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001573 *
Shawn Willdend3ed3a22017-03-28 00:39:16 +00001574 * Returns ResponseCode::NO_ERROR if the auth token was set or none was required.
1575 * ::OP_AUTH_NEEDED if it is a per op authorization, no
1576 * authorization token exists for that operation and
1577 * failOnTokenMissing is false.
1578 * KM_ERROR_KEY_USER_NOT_AUTHENTICATED if there is no valid auth
1579 * token for the operation
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001580 */
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001581KeyStoreServiceReturnCode KeyStoreService::getAuthToken(const KeyCharacteristics& characteristics,
1582 uint64_t handle, KeyPurpose purpose,
Shawn Willdend3ed3a22017-03-28 00:39:16 +00001583 const HardwareAuthToken** authToken,
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001584 bool failOnTokenMissing) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001585
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001586 AuthorizationSet allCharacteristics;
1587 for (size_t i = 0; i < characteristics.softwareEnforced.size(); i++) {
1588 allCharacteristics.push_back(characteristics.softwareEnforced[i]);
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001589 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001590 for (size_t i = 0; i < characteristics.teeEnforced.size(); i++) {
1591 allCharacteristics.push_back(characteristics.teeEnforced[i]);
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001592 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001593 AuthTokenTable::Error err =
1594 mAuthTokenTable.FindAuthorization(allCharacteristics, purpose, handle, authToken);
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001595 switch (err) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001596 case AuthTokenTable::OK:
1597 case AuthTokenTable::AUTH_NOT_REQUIRED:
1598 return ResponseCode::NO_ERROR;
1599 case AuthTokenTable::AUTH_TOKEN_NOT_FOUND:
1600 case AuthTokenTable::AUTH_TOKEN_EXPIRED:
1601 case AuthTokenTable::AUTH_TOKEN_WRONG_SID:
1602 return ErrorCode::KEY_USER_NOT_AUTHENTICATED;
1603 case AuthTokenTable::OP_HANDLE_REQUIRED:
1604 return failOnTokenMissing ? KeyStoreServiceReturnCode(ErrorCode::KEY_USER_NOT_AUTHENTICATED)
1605 : KeyStoreServiceReturnCode(ResponseCode::OP_AUTH_NEEDED);
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001606 default:
1607 ALOGE("Unexpected FindAuthorization return value %d", err);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001608 return ErrorCode::INVALID_ARGUMENT;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001609 }
1610}
1611
1612/**
1613 * Add the auth token for the operation to the param list if the operation
1614 * requires authorization. Uses the cached result in the OperationMap if available
1615 * otherwise gets the token from the AuthTokenTable and caches the result.
1616 *
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001617 * Returns ResponseCode::NO_ERROR if the auth token was added or not needed.
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001618 * KM_ERROR_KEY_USER_NOT_AUTHENTICATED if the operation is not
1619 * authenticated.
1620 * KM_ERROR_INVALID_OPERATION_HANDLE if token is not a valid
1621 * operation token.
1622 */
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001623KeyStoreServiceReturnCode KeyStoreService::addOperationAuthTokenIfNeeded(const sp<IBinder>& token,
1624 AuthorizationSet* params) {
Shawn Willdend3ed3a22017-03-28 00:39:16 +00001625 const HardwareAuthToken* authToken = nullptr;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001626 mOperationMap.getOperationAuthToken(token, &authToken);
1627 if (!authToken) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001628 km_device_t dev;
1629 uint64_t handle;
1630 const KeyCharacteristics* characteristics = nullptr;
1631 KeyPurpose purpose;
1632 km_id_t keyid;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001633 if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, &characteristics)) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001634 return ErrorCode::INVALID_OPERATION_HANDLE;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001635 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001636 auto result = getAuthToken(*characteristics, handle, purpose, &authToken);
1637 if (!result.isOk()) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001638 return result;
1639 }
1640 if (authToken) {
Shawn Willdend3ed3a22017-03-28 00:39:16 +00001641 mOperationMap.setOperationAuthToken(token, authToken);
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001642 }
1643 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001644 addAuthTokenToParams(params, authToken);
1645 return ResponseCode::NO_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001646}
1647
1648/**
1649 * Translate a result value to a legacy return value. All keystore errors are
1650 * preserved and keymaster errors become SYSTEM_ERRORs
1651 */
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001652KeyStoreServiceReturnCode KeyStoreService::translateResultToLegacyResult(int32_t result) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001653 if (result > 0) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001654 return static_cast<ResponseCode>(result);
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001655 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001656 return ResponseCode::SYSTEM_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001657}
1658
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001659static NullOr<const Algorithm&>
1660getKeyAlgoritmFromKeyCharacteristics(const KeyCharacteristics& characteristics) {
1661 for (size_t i = 0; i < characteristics.teeEnforced.size(); ++i) {
1662 auto algo = authorizationValue(TAG_ALGORITHM, characteristics.teeEnforced[i]);
1663 if (algo.isOk()) return algo.value();
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001664 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001665 for (size_t i = 0; i < characteristics.softwareEnforced.size(); ++i) {
1666 auto algo = authorizationValue(TAG_ALGORITHM, characteristics.softwareEnforced[i]);
1667 if (algo.isOk()) return algo.value();
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001668 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001669 return {};
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001670}
1671
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001672void KeyStoreService::addLegacyBeginParams(const String16& name, AuthorizationSet* params) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001673 // All legacy keys are DIGEST_NONE/PAD_NONE.
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001674 params->push_back(TAG_DIGEST, Digest::NONE);
1675 params->push_back(TAG_PADDING, PaddingMode::NONE);
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001676
1677 // Look up the algorithm of the key.
1678 KeyCharacteristics characteristics;
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001679 auto rc = getKeyCharacteristics(name, hidl_vec<uint8_t>(), hidl_vec<uint8_t>(), UID_SELF,
1680 &characteristics);
1681 if (!rc.isOk()) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001682 ALOGE("Failed to get key characteristics");
1683 return;
1684 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001685 auto algorithm = getKeyAlgoritmFromKeyCharacteristics(characteristics);
1686 if (!algorithm.isOk()) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001687 ALOGE("getKeyCharacteristics did not include KM_TAG_ALGORITHM");
1688 return;
1689 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001690 params->push_back(TAG_ALGORITHM, algorithm.value());
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001691}
1692
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001693KeyStoreServiceReturnCode KeyStoreService::doLegacySignVerify(const String16& name,
1694 const hidl_vec<uint8_t>& data,
1695 hidl_vec<uint8_t>* out,
1696 const hidl_vec<uint8_t>& signature,
1697 KeyPurpose purpose) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001698
1699 std::basic_stringstream<uint8_t> outBuffer;
1700 OperationResult result;
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001701 AuthorizationSet inArgs;
1702 addLegacyBeginParams(name, &inArgs);
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001703 sp<IBinder> appToken(new BBinder);
1704 sp<IBinder> token;
1705
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001706 begin(appToken, name, purpose, true, inArgs.hidl_data(), hidl_vec<uint8_t>(), UID_SELF,
1707 &result);
1708 if (!result.resultCode.isOk()) {
1709 if (result.resultCode == ResponseCode::KEY_NOT_FOUND) {
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001710 ALOGW("Key not found");
1711 } else {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001712 ALOGW("Error in begin: %d", int32_t(result.resultCode));
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001713 }
1714 return translateResultToLegacyResult(result.resultCode);
1715 }
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001716 inArgs.Clear();
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001717 token = result.token;
1718 size_t consumed = 0;
1719 size_t lastConsumed = 0;
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001720 hidl_vec<uint8_t> data_view;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001721 do {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001722 data_view.setToExternal(const_cast<uint8_t*>(&data[consumed]), data.size() - consumed);
1723 update(token, inArgs.hidl_data(), data_view, &result);
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001724 if (result.resultCode != ResponseCode::NO_ERROR) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001725 ALOGW("Error in update: %d", int32_t(result.resultCode));
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001726 return translateResultToLegacyResult(result.resultCode);
1727 }
1728 if (out) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001729 outBuffer.write(&result.data[0], result.data.size());
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001730 }
1731 lastConsumed = result.inputConsumed;
1732 consumed += lastConsumed;
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001733 } while (consumed < data.size() && lastConsumed > 0);
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001734
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001735 if (consumed != data.size()) {
1736 ALOGW("Not all data consumed. Consumed %zu of %zu", consumed, data.size());
1737 return ResponseCode::SYSTEM_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001738 }
1739
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001740 finish(token, inArgs.hidl_data(), signature, hidl_vec<uint8_t>(), &result);
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001741 if (result.resultCode != ResponseCode::NO_ERROR) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001742 ALOGW("Error in finish: %d", int32_t(result.resultCode));
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001743 return translateResultToLegacyResult(result.resultCode);
1744 }
1745 if (out) {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001746 outBuffer.write(&result.data[0], result.data.size());
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001747 }
1748
1749 if (out) {
1750 auto buf = outBuffer.str();
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001751 out->resize(buf.size());
1752 memcpy(&(*out)[0], buf.data(), out->size());
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001753 }
1754
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001755 return ResponseCode::NO_ERROR;
Shawn Willdenc1d1fee2016-01-26 22:44:56 -07001756}
1757
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001758KeyStoreServiceReturnCode KeyStoreService::upgradeKeyBlob(const String16& name, uid_t uid,
1759 const AuthorizationSet& params,
1760 Blob* blob) {
Shawn Willden98c59162016-03-20 09:10:18 -06001761 // Read the blob rather than assuming the caller provided the right name/uid/blob triplet.
1762 String8 name8(name);
1763 ResponseCode responseCode = mKeyStore->getKeyForName(blob, name8, uid, TYPE_KEYMASTER_10);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001764 if (responseCode != ResponseCode::NO_ERROR) {
Shawn Willden98c59162016-03-20 09:10:18 -06001765 return responseCode;
1766 }
Rubin Xu7675c9f2017-03-15 19:26:52 +00001767 ALOGI("upgradeKeyBlob %s %d", name8.string(), uid);
Shawn Willden98c59162016-03-20 09:10:18 -06001768
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001769 auto hidlKey = blob2hidlVec(*blob);
1770 auto& dev = mKeyStore->getDevice(*blob);
Shawn Willden98c59162016-03-20 09:10:18 -06001771
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001772 KeyStoreServiceReturnCode error;
1773 auto hidlCb = [&](ErrorCode ret, const hidl_vec<uint8_t>& upgradedKeyBlob) {
1774 error = ret;
1775 if (!error.isOk()) {
1776 return;
1777 }
1778
1779 String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, uid, ::TYPE_KEYMASTER_10));
1780 error = mKeyStore->del(filename.string(), ::TYPE_ANY, get_user_id(uid));
1781 if (!error.isOk()) {
Rubin Xu7675c9f2017-03-15 19:26:52 +00001782 ALOGI("upgradeKeyBlob keystore->del failed %d", (int)error);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001783 return;
1784 }
1785
1786 Blob newBlob(&upgradedKeyBlob[0], upgradedKeyBlob.size(), nullptr /* info */,
1787 0 /* infoLength */, ::TYPE_KEYMASTER_10);
1788 newBlob.setFallback(blob->isFallback());
1789 newBlob.setEncrypted(blob->isEncrypted());
1790
1791 error = mKeyStore->put(filename.string(), &newBlob, get_user_id(uid));
1792 if (!error.isOk()) {
Rubin Xu7675c9f2017-03-15 19:26:52 +00001793 ALOGI("upgradeKeyBlob keystore->put failed %d", (int)error);
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001794 return;
1795 }
1796
1797 // Re-read blob for caller. We can't use newBlob because writing it modified it.
1798 error = mKeyStore->getKeyForName(blob, name8, uid, TYPE_KEYMASTER_10);
1799 };
1800
1801 KeyStoreServiceReturnCode rc =
1802 KS_HANDLE_HIDL_ERROR(dev->upgradeKey(hidlKey, params.hidl_data(), hidlCb));
1803 if (!rc.isOk()) {
Shawn Willden98c59162016-03-20 09:10:18 -06001804 return rc;
1805 }
1806
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +01001807 return error;
Shawn Willden98c59162016-03-20 09:10:18 -06001808}
1809
Shawn Willdene2a7b522017-04-11 09:27:40 -06001810} // namespace keystore