blob: 76df1cc659d9a1fb741f77ec71525d0f578fce66 [file] [log] [blame]
David Zeuthenc6eb7cd2017-11-27 11:33:55 -05001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "ConfirmationManager"
18
19#include "confirmation_manager.h"
20
21#include <android/hardware/confirmationui/1.0/IConfirmationResultCallback.h>
22#include <android/hardware/confirmationui/1.0/IConfirmationUI.h>
23#include <android/hardware/confirmationui/1.0/types.h>
24#include <android/security/BpConfirmationPromptCallback.h>
25#include <binder/BpBinder.h>
Janis Danisevskis064ce852018-03-12 16:49:16 -070026#include <binder/IPCThreadState.h>
David Zeuthenc6eb7cd2017-11-27 11:33:55 -050027#include <binder/Parcel.h>
28
29#include "keystore_aidl_hidl_marshalling_utils.h"
30
31namespace keystore {
32
33using android::IBinder;
34using android::sp;
35using android::String16;
36using android::String8;
37using android::wp;
38using android::binder::Status;
39using android::hardware::hidl_vec;
40using android::hardware::Return;
41using android::hardware::confirmationui::V1_0::IConfirmationResultCallback;
42using android::hardware::confirmationui::V1_0::IConfirmationUI;
43using android::hardware::confirmationui::V1_0::UIOption;
44
45using android::security::BpConfirmationPromptCallback;
46using std::lock_guard;
47using std::mutex;
48using std::vector;
49
50ConfirmationManager::ConfirmationManager(IBinder::DeathRecipient* deathRecipient)
51 : IConfirmationResultCallback(), mDeathRecipient(deathRecipient) {}
52
53// Called by keystore main thread.
54Status ConfirmationManager::presentConfirmationPrompt(const sp<IBinder>& listener,
55 const String16& promptText,
56 const hidl_vec<uint8_t>& extraData,
57 const String16& locale, int uiOptionsAsFlags,
58 int32_t* aidl_return) {
59 lock_guard<mutex> lock(mMutex);
60
61 if (mCurrentListener != nullptr) {
62 *aidl_return = static_cast<int32_t>(ConfirmationResponseCode::OperationPending);
63 return Status::ok();
64 }
65
66 sp<IConfirmationUI> confirmationUI = IConfirmationUI::tryGetService();
67 if (confirmationUI == nullptr) {
68 ALOGW("Error getting confirmationUI service\n");
69 *aidl_return = static_cast<int32_t>(ConfirmationResponseCode::Unimplemented);
70 return Status::ok();
71 }
72
Janis Danisevskis064ce852018-03-12 16:49:16 -070073 uid_t callingUid = android::IPCThreadState::self()->getCallingUid();
74 if (!mRateLimiting.tryPrompt(callingUid)) {
75 *aidl_return = static_cast<int32_t>(ConfirmationResponseCode::SystemError);
76 return Status::ok();
77 }
78
David Zeuthenc6eb7cd2017-11-27 11:33:55 -050079 String8 promptText8(promptText);
80 String8 locale8(locale);
81 vector<UIOption> uiOptionsVector;
82 for (int n = 0; n < 32; n++) {
83 if (uiOptionsAsFlags & (1 << n)) {
84 uiOptionsVector.push_back(UIOption(n));
85 }
86 }
87 ConfirmationResponseCode responseCode;
88 responseCode = confirmationUI->promptUserConfirmation(sp<IConfirmationResultCallback>(this),
89 promptText8.string(), extraData,
90 locale8.string(), uiOptionsVector);
91 if (responseCode != ConfirmationResponseCode::OK) {
92 ALOGW("Unexpecxted responseCode %d from promptUserConfirmation\n", responseCode);
93 *aidl_return = static_cast<int32_t>(responseCode);
94 return Status::ok();
95 }
96
97 listener->linkToDeath(mDeathRecipient);
98 confirmationUI->linkToDeath(this, 0);
99 mCurrentListener = listener;
100 mCurrentConfirmationUI = confirmationUI;
101
102 *aidl_return = static_cast<int32_t>(ConfirmationResponseCode::OK);
103 return Status::ok();
104}
105
106// Called by keystore main thread.
107Status ConfirmationManager::cancelConfirmationPrompt(const sp<IBinder>& listener,
108 int32_t* aidl_return) {
109 mMutex.lock();
110 if (mCurrentListener != listener) {
111 // If the prompt was displayed by another application, return
112 // OperationPending.
113 mMutex.unlock();
114 *aidl_return = static_cast<int32_t>(ConfirmationResponseCode::OperationPending);
115 return Status::ok();
116 }
117 mMutex.unlock();
118
Cindy Zhoub3bf30b2019-11-13 16:59:41 -0800119 cancelPrompt();
David Zeuthenc6eb7cd2017-11-27 11:33:55 -0500120
121 *aidl_return = static_cast<int32_t>(ConfirmationResponseCode::OK);
122 return Status::ok();
123}
124
Cindy Zhoub3bf30b2019-11-13 16:59:41 -0800125void ConfirmationManager::cancelPrompt() {
126 mMutex.lock();
127 mRateLimiting.cancelPrompt();
Cindy Zhoub3bf30b2019-11-13 16:59:41 -0800128 sp<IConfirmationUI> confirmationUI = mCurrentConfirmationUI;
Cindy Zhoub3bf30b2019-11-13 16:59:41 -0800129 mMutex.unlock();
130 if (confirmationUI != nullptr) {
131 confirmationUI->abort();
132 }
133}
134
David Zeuthen1a492312018-02-26 11:00:30 -0500135// Called by keystore main thread.
136Status ConfirmationManager::isConfirmationPromptSupported(bool* aidl_return) {
137 sp<IConfirmationUI> confirmationUI = IConfirmationUI::tryGetService();
138 if (confirmationUI == nullptr) {
139 ALOGW("Error getting confirmationUI service\n");
140 *aidl_return = false;
141 return Status::ok();
142 }
143
144 *aidl_return = true;
145 return Status::ok();
146}
147
David Zeuthenc6eb7cd2017-11-27 11:33:55 -0500148void ConfirmationManager::finalizeTransaction(ConfirmationResponseCode responseCode,
Cindy Zhoub3bf30b2019-11-13 16:59:41 -0800149 hidl_vec<uint8_t> dataThatWasConfirmed) {
David Zeuthenc6eb7cd2017-11-27 11:33:55 -0500150 mMutex.lock();
Janis Danisevskis064ce852018-03-12 16:49:16 -0700151 mRateLimiting.processResult(responseCode);
David Zeuthenc6eb7cd2017-11-27 11:33:55 -0500152 sp<IBinder> listener = mCurrentListener;
153 if (mCurrentListener != nullptr) {
154 mCurrentListener->unlinkToDeath(mDeathRecipient);
155 mCurrentListener = nullptr;
156 }
David Zeuthenc6eb7cd2017-11-27 11:33:55 -0500157 if (mCurrentConfirmationUI != nullptr) {
158 mCurrentConfirmationUI->unlinkToDeath(this);
159 mCurrentConfirmationUI = nullptr;
160 }
161 mMutex.unlock();
162
David Zeuthenc6eb7cd2017-11-27 11:33:55 -0500163 // Deliver result to the application that started the operation.
164 if (listener != nullptr) {
165 sp<BpConfirmationPromptCallback> obj = new BpConfirmationPromptCallback(listener);
166 Status status = obj->onConfirmationPromptCompleted(static_cast<int32_t>(responseCode),
167 dataThatWasConfirmed);
168 if (!status.isOk()) {
169 ALOGW("Error sending onConfirmationPromptCompleted - status: %s\n",
170 status.toString8().c_str());
171 }
172 }
173}
174
175// Called by hwbinder thread (not keystore main thread).
176Return<void> ConfirmationManager::result(ConfirmationResponseCode responseCode,
177 const hidl_vec<uint8_t>& dataThatWasConfirmed,
178 const hidl_vec<uint8_t>& confirmationToken) {
Cindy Zhoub3bf30b2019-11-13 16:59:41 -0800179 finalizeTransaction(responseCode, dataThatWasConfirmed);
David Zeuthenc6eb7cd2017-11-27 11:33:55 -0500180 lock_guard<mutex> lock(mMutex);
181 mLatestConfirmationToken = confirmationToken;
182 return Return<void>();
183}
184
Janis Danisevskisff3d7f42018-10-08 07:15:09 -0700185// Called by keystore main thread or keymaster worker
David Zeuthenc6eb7cd2017-11-27 11:33:55 -0500186hidl_vec<uint8_t> ConfirmationManager::getLatestConfirmationToken() {
187 lock_guard<mutex> lock(mMutex);
188 return mLatestConfirmationToken;
189}
190
191void ConfirmationManager::binderDied(const wp<IBinder>& who) {
192 // This is also called for other binders so need to check it's for
193 // us before acting on it.
194 mMutex.lock();
195 if (who == mCurrentListener) {
196 // Clear this so we don't call back into the already dead
197 // binder in finalizeTransaction().
198 mCurrentListener->unlinkToDeath(mDeathRecipient);
199 mCurrentListener = nullptr;
200 mMutex.unlock();
201 ALOGW("The process which requested the confirmation dialog died.\n");
Cindy Zhoub3bf30b2019-11-13 16:59:41 -0800202 cancelPrompt();
David Zeuthenc6eb7cd2017-11-27 11:33:55 -0500203 } else {
204 mMutex.unlock();
205 }
206}
207
208void ConfirmationManager::serviceDied(uint64_t /* cookie */,
209 const wp<android::hidl::base::V1_0::IBase>& /* who */) {
210 ALOGW("The ConfirmationUI HAL died.\n");
Cindy Zhoub3bf30b2019-11-13 16:59:41 -0800211 finalizeTransaction(ConfirmationResponseCode::SystemError, {});
David Zeuthenc6eb7cd2017-11-27 11:33:55 -0500212}
213
214} // namespace keystore