• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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>
26 #include <binder/IPCThreadState.h>
27 #include <binder/Parcel.h>
28 
29 #include "keystore_aidl_hidl_marshalling_utils.h"
30 
31 namespace keystore {
32 
33 using android::IBinder;
34 using android::sp;
35 using android::String16;
36 using android::String8;
37 using android::wp;
38 using android::binder::Status;
39 using android::hardware::hidl_vec;
40 using android::hardware::Return;
41 using android::hardware::confirmationui::V1_0::IConfirmationResultCallback;
42 using android::hardware::confirmationui::V1_0::IConfirmationUI;
43 using android::hardware::confirmationui::V1_0::UIOption;
44 
45 using android::security::BpConfirmationPromptCallback;
46 using std::lock_guard;
47 using std::mutex;
48 using std::vector;
49 
ConfirmationManager(IBinder::DeathRecipient * deathRecipient)50 ConfirmationManager::ConfirmationManager(IBinder::DeathRecipient* deathRecipient)
51     : IConfirmationResultCallback(), mDeathRecipient(deathRecipient) {}
52 
53 // Called by keystore main thread.
presentConfirmationPrompt(const sp<IBinder> & listener,const String16 & promptText,const hidl_vec<uint8_t> & extraData,const String16 & locale,int uiOptionsAsFlags,int32_t * aidl_return)54 Status 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 
73     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 
79     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.
cancelConfirmationPrompt(const sp<IBinder> & listener,int32_t * aidl_return)107 Status 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 
119     finalizeTransaction(ConfirmationResponseCode::Aborted, {}, true);
120 
121     *aidl_return = static_cast<int32_t>(ConfirmationResponseCode::OK);
122     return Status::ok();
123 }
124 
125 // Called by keystore main thread.
isConfirmationPromptSupported(bool * aidl_return)126 Status ConfirmationManager::isConfirmationPromptSupported(bool* aidl_return) {
127     sp<IConfirmationUI> confirmationUI = IConfirmationUI::tryGetService();
128     if (confirmationUI == nullptr) {
129         ALOGW("Error getting confirmationUI service\n");
130         *aidl_return = false;
131         return Status::ok();
132     }
133 
134     *aidl_return = true;
135     return Status::ok();
136 }
137 
finalizeTransaction(ConfirmationResponseCode responseCode,hidl_vec<uint8_t> dataThatWasConfirmed,bool callAbortOnHal)138 void ConfirmationManager::finalizeTransaction(ConfirmationResponseCode responseCode,
139                                               hidl_vec<uint8_t> dataThatWasConfirmed,
140                                               bool callAbortOnHal) {
141     // Note that confirmationUI->abort() may make the remote HAL process do an IPC call back
142     // into our process resulting in confirmationResultCallback() to be called... this in turn
143     // calls finalizeTransaction(). So we have to be careful a) not holding any locks;
144     // and b) ensure state has been cleared; before doing this...
145 
146     mMutex.lock();
147     mRateLimiting.processResult(responseCode);
148     sp<IBinder> listener = mCurrentListener;
149     if (mCurrentListener != nullptr) {
150         mCurrentListener->unlinkToDeath(mDeathRecipient);
151         mCurrentListener = nullptr;
152     }
153     sp<IConfirmationUI> confirmationUI = mCurrentConfirmationUI;
154     if (mCurrentConfirmationUI != nullptr) {
155         mCurrentConfirmationUI->unlinkToDeath(this);
156         mCurrentConfirmationUI = nullptr;
157     }
158     mMutex.unlock();
159 
160     // Tell the HAL to shut down the confirmation dialog, if requested.
161     if (confirmationUI != nullptr && callAbortOnHal) {
162         confirmationUI->abort();
163     }
164 
165     // Deliver result to the application that started the operation.
166     if (listener != nullptr) {
167         sp<BpConfirmationPromptCallback> obj = new BpConfirmationPromptCallback(listener);
168         Status status = obj->onConfirmationPromptCompleted(static_cast<int32_t>(responseCode),
169                                                            dataThatWasConfirmed);
170         if (!status.isOk()) {
171             ALOGW("Error sending onConfirmationPromptCompleted - status: %s\n",
172                   status.toString8().c_str());
173         }
174     }
175 }
176 
177 // Called by hwbinder thread (not keystore main thread).
result(ConfirmationResponseCode responseCode,const hidl_vec<uint8_t> & dataThatWasConfirmed,const hidl_vec<uint8_t> & confirmationToken)178 Return<void> ConfirmationManager::result(ConfirmationResponseCode responseCode,
179                                          const hidl_vec<uint8_t>& dataThatWasConfirmed,
180                                          const hidl_vec<uint8_t>& confirmationToken) {
181     finalizeTransaction(responseCode, dataThatWasConfirmed, false);
182     lock_guard<mutex> lock(mMutex);
183     mLatestConfirmationToken = confirmationToken;
184     return Return<void>();
185 }
186 
187 // Called by keystore main thread or keymaster worker
getLatestConfirmationToken()188 hidl_vec<uint8_t> ConfirmationManager::getLatestConfirmationToken() {
189     lock_guard<mutex> lock(mMutex);
190     return mLatestConfirmationToken;
191 }
192 
binderDied(const wp<IBinder> & who)193 void ConfirmationManager::binderDied(const wp<IBinder>& who) {
194     // This is also called for other binders so need to check it's for
195     // us before acting on it.
196     mMutex.lock();
197     if (who == mCurrentListener) {
198         // Clear this so we don't call back into the already dead
199         // binder in finalizeTransaction().
200         mCurrentListener->unlinkToDeath(mDeathRecipient);
201         mCurrentListener = nullptr;
202         mMutex.unlock();
203         ALOGW("The process which requested the confirmation dialog died.\n");
204         finalizeTransaction(ConfirmationResponseCode::SystemError, {}, true);
205     } else {
206         mMutex.unlock();
207     }
208 }
209 
serviceDied(uint64_t,const wp<android::hidl::base::V1_0::IBase> &)210 void ConfirmationManager::serviceDied(uint64_t /* cookie */,
211                                       const wp<android::hidl::base::V1_0::IBase>& /* who */) {
212     ALOGW("The ConfirmationUI HAL died.\n");
213     finalizeTransaction(ConfirmationResponseCode::SystemError, {}, false);
214 }
215 
216 }  // namespace keystore
217