• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  * Copyright 2019, The Android Open Source Project
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include "TrustyConfirmationUI.h"
19 
20 #include <android-base/logging.h>
21 #include <android/hardware/confirmationui/1.0/types.h>
22 #include <android/hardware/keymaster/4.0/types.h>
23 #include <fcntl.h>
24 #include <linux/input.h>
25 #include <poll.h>
26 #include <pthread.h>
27 #include <secure_input/evdev.h>
28 #include <secure_input/secure_input_device.h>
29 #include <secure_input/secure_input_proto.h>
30 #include <signal.h>
31 #include <sys/ioctl.h>
32 #include <sys/stat.h>
33 #include <sys/types.h>
34 #include <teeui/msg_formatting.h>
35 #include <teeui/utils.h>
36 #include <time.h>
37 
38 #include <atomic>
39 #include <functional>
40 #include <memory>
41 #include <thread>
42 #include <tuple>
43 #include <vector>
44 
45 namespace android {
46 namespace hardware {
47 namespace confirmationui {
48 namespace V1_0 {
49 namespace implementation {
50 
51 using namespace secure_input;
52 
53 using ::android::trusty::TrustyAppError;
54 
55 using ::teeui::AbortMsg;
56 using ::teeui::DeliverTestCommandMessage;
57 using ::teeui::DeliverTestCommandResponse;
58 using ::teeui::FetchConfirmationResult;
59 using ::teeui::MsgString;
60 using ::teeui::MsgVector;
61 using ::teeui::PromptUserConfirmationMsg;
62 using ::teeui::PromptUserConfirmationResponse;
63 using ::teeui::ResultMsg;
64 
65 using ::secure_input::createSecureInput;
66 
67 using ::android::hardware::keymaster::V4_0::HardwareAuthToken;
68 
69 using ::std::tie;
70 
71 using TeeuiRc = ::teeui::ResponseCode;
72 
73 constexpr const char kTrustyDeviceName[] = "/dev/trusty-ipc-dev0";
74 constexpr const char kConfirmationuiAppName[] = "com.android.trusty.confirmationui";
75 
76 namespace {
77 
78 class Finalize {
79   private:
80     std::function<void()> f_;
81 
82   public:
Finalize(std::function<void ()> f)83     Finalize(std::function<void()> f) : f_(f) {}
~Finalize()84     ~Finalize() {
85         if (f_) f_();
86     }
release()87     void release() { f_ = {}; }
88 };
89 
convertRc(TeeuiRc trc)90 ResponseCode convertRc(TeeuiRc trc) {
91     static_assert(
92         uint32_t(TeeuiRc::OK) == uint32_t(ResponseCode::OK) &&
93             uint32_t(TeeuiRc::Canceled) == uint32_t(ResponseCode::Canceled) &&
94             uint32_t(TeeuiRc::Aborted) == uint32_t(ResponseCode::Aborted) &&
95             uint32_t(TeeuiRc::OperationPending) == uint32_t(ResponseCode::OperationPending) &&
96             uint32_t(TeeuiRc::Ignored) == uint32_t(ResponseCode::Ignored) &&
97             uint32_t(TeeuiRc::SystemError) == uint32_t(ResponseCode::SystemError) &&
98             uint32_t(TeeuiRc::Unimplemented) == uint32_t(ResponseCode::Unimplemented) &&
99             uint32_t(TeeuiRc::Unexpected) == uint32_t(ResponseCode::Unexpected) &&
100             uint32_t(TeeuiRc::UIError) == uint32_t(ResponseCode::UIError) &&
101             uint32_t(TeeuiRc::UIErrorMissingGlyph) == uint32_t(ResponseCode::UIErrorMissingGlyph) &&
102             uint32_t(TeeuiRc::UIErrorMessageTooLong) ==
103                 uint32_t(ResponseCode::UIErrorMessageTooLong) &&
104             uint32_t(TeeuiRc::UIErrorMalformedUTF8Encoding) ==
105                 uint32_t(ResponseCode::UIErrorMalformedUTF8Encoding),
106         "teeui::ResponseCode and "
107         "::android::hardware::confirmationui::V1_0::Responsecude are out of "
108         "sync");
109     return ResponseCode(trc);
110 }
111 
convertUIOption(UIOption uio)112 teeui::UIOption convertUIOption(UIOption uio) {
113     static_assert(uint32_t(UIOption::AccessibilityInverted) ==
114                           uint32_t(teeui::UIOption::AccessibilityInverted) &&
115                       uint32_t(UIOption::AccessibilityMagnified) ==
116                           uint32_t(teeui::UIOption::AccessibilityMagnified),
117                   "teeui::UIOPtion and ::android::hardware::confirmationui::V1_0::UIOption "
118                   "anre out of sync");
119     return teeui::UIOption(uio);
120 }
121 
hidl2MsgString(const hidl_string & s)122 inline MsgString hidl2MsgString(const hidl_string& s) {
123     return {s.c_str(), s.c_str() + s.size()};
124 }
hidl2MsgVector(const hidl_vec<T> & v)125 template <typename T> inline MsgVector<T> hidl2MsgVector(const hidl_vec<T>& v) {
126     return {v};
127 }
128 
hidl2MsgVector(const hidl_vec<UIOption> & v)129 inline MsgVector<teeui::UIOption> hidl2MsgVector(const hidl_vec<UIOption>& v) {
130     MsgVector<teeui::UIOption> result(v.size());
131     for (unsigned int i = 0; i < v.size(); ++i) {
132         result[i] = convertUIOption(v[i]);
133     }
134     return result;
135 }
136 
137 }  // namespace
138 
TrustyConfirmationUI()139 TrustyConfirmationUI::TrustyConfirmationUI()
140     : listener_state_(ListenerState::None), prompt_result_(ResponseCode::Ignored) {}
141 
~TrustyConfirmationUI()142 TrustyConfirmationUI::~TrustyConfirmationUI() {
143     ListenerState state = listener_state_;
144     if (state == ListenerState::SetupDone || state == ListenerState::Interactive) {
145         abort();
146     }
147     if (state != ListenerState::None) {
148         callback_thread_.join();
149     }
150 }
151 
152 std::tuple<TeeuiRc, MsgVector<uint8_t>, MsgVector<uint8_t>>
promptUserConfirmation_(const MsgString & promptText,const MsgVector<uint8_t> & extraData,const MsgString & locale,const MsgVector<teeui::UIOption> & uiOptions)153 TrustyConfirmationUI::promptUserConfirmation_(const MsgString& promptText,
154                                               const MsgVector<uint8_t>& extraData,
155                                               const MsgString& locale,
156                                               const MsgVector<teeui::UIOption>& uiOptions) {
157     std::unique_lock<std::mutex> stateLock(listener_state_lock_);
158     /*
159      * This is the main listener thread function. The listener thread life cycle
160      * is equivalent to the life cycle of a single confirmation request. The life
161      * cycle is devided in four phases.
162      *  * The starting phase:
163      *    * The Trusted App gets loaded and/or the connection to it gets established.
164      *    * A connection to the secure input device is established.
165      *    * The prompt is initiated. This sends all information required by the
166      *      confirmation dialog to the TA. The dialog is not yet displayed.
167      *    * An event loop is created.
168      *      * The event loop listens for user input events, fetches them from the
169      *        secure input device, and delivers them to the TA.
170      *    * All evdev devices are grabbed to give confirmationui exclusive access
171      *      to user input.
172      *
173      * Note: During the starting phase the hwbinder service thread is blocked and
174      * waiting for possible Errors. If the setup phase concludes sucessfully, the
175      * hwbinder service thread gets unblocked and returns successfully. Errors
176      * that occur after the first phase are delivered by callback interface.
177      *
178      *  * The 2nd phase - non interactive phase
179      *    * The event loop thread is started.
180      *    * After a grace period:
181      *      * A handshake between the secure input device SecureInput and the TA
182      *        is performed.
183      *      * The input event handler are armed to process user input events.
184      *
185      *  * The 3rd phase - interactive phase
186      *    * We wait to any external event
187      *      * Abort
188      *      * Secure user input asserted
189      *      * Secure input delivered (for non interactive VTS testing)
190      *    * The result is fetched from the TA.
191      *
192      *  * The 4th phase - cleanup
193      *    The cleanup phase is given by the scope of automatic variables created
194      *    in this function. The cleanup commences in reverse order of their creation.
195      *    Here is a list of more complex items in the order in which they go out of
196      *    scope
197      *    * finalizeSecureTouch - signals and joins the secure touch thread.
198      *    * eventloop - signals and joins the event loop thread. The event
199      *      handlers also own all EventDev instances which ungrab the event devices.
200      *      When the eventloop goes out of scope the EventDevs get destroyed
201      *      relinquishing the exclusive hold on the event devices.
202      *    * finalizeConfirmationPrompt - calls abort on the TA, making sure a
203      *      pending operation gets canceled. If the prompt concluded successfully this
204      *      is a spurious call but semantically a no op.
205      *    * secureInput - shuts down the connection to the secure input device
206      *      SecureInput.
207      *    * app - disconnects the TA. Since app is a shared pointer this may not
208      *      unload the app here. It is possible that more instances of the shared
209      *      pointer are held in TrustyConfirmationUI::deliverSecureInputEvent and
210      *      TrustyConfirmationUI::abort. But these instances are extremely short lived
211      *      and it is safe if they are destroyed by either.
212      *    * stateLock - unlocks the listener_state_lock_ if it happens to be held
213      *      at the time of return.
214      */
215 
216     std::tuple<TeeuiRc, MsgVector<uint8_t>, MsgVector<uint8_t>> result;
217     TeeuiRc& rc = std::get<TeeuiRc>(result);
218     rc = TeeuiRc::SystemError;
219 
220     listener_state_ = ListenerState::Starting;
221 
222     auto app = std::make_shared<TrustyApp>(kTrustyDeviceName, kConfirmationuiAppName);
223     if (!app) return result;  // TeeuiRc::SystemError
224 
225     app_ = app;
226 
227     auto hsBegin = [&]() -> std::tuple<TeeuiRc, Nonce> {
228         auto [error, result] =
229             app->issueCmd<secure_input::InputHandshake, secure_input::InputHandshakeResponse>();
230         auto& [rc, nCo] = result;
231 
232         if (error != TrustyAppError::OK || rc != TeeuiRc::OK) {
233             LOG(ERROR) << "Failed to begin secure input handshake (" << int32_t(error) << "/"
234                        << uint32_t(rc) << ")";
235             rc = error != TrustyAppError::OK ? TeeuiRc::SystemError : rc;
236         }
237         return result;
238     };
239 
240     auto hsFinalize = [&](const Signature& sig, const Nonce& nCi) -> TeeuiRc {
241         auto [error, finalizeResponse] =
242             app->issueCmd<FinalizeInputSessionHandshake, FinalizeInputSessionHandshakeResponse>(
243                 nCi, sig);
244         auto& [rc] = finalizeResponse;
245         if (error != TrustyAppError::OK || rc != TeeuiRc::OK) {
246             LOG(ERROR) << "Failed to finalize secure input handshake (" << int32_t(error) << "/"
247                        << uint32_t(rc) << ")";
248             rc = error != TrustyAppError::OK ? TeeuiRc::SystemError : rc;
249         }
250         return rc;
251     };
252 
253     auto deliverInput = [&](DTupKeyEvent event,
254                             const Signature& sig) -> std::tuple<TeeuiRc, InputResponse> {
255         auto [error, result] =
256             app->issueCmd<DeliverInputEvent, DeliverInputEventResponse>(event, sig);
257         auto& [rc, ir] = result;
258         if (error != TrustyAppError::OK) {
259             LOG(ERROR) << "Failed to deliver input command";
260             rc = TeeuiRc::SystemError;
261         }
262         return result;
263     };
264 
265     std::atomic<TeeuiRc> eventRC = TeeuiRc::OperationPending;
266     auto inputResult = [&](TeeuiRc rc) {
267         TeeuiRc expected = TeeuiRc::OperationPending;
268         if (eventRC.compare_exchange_strong(expected, rc)) {
269             listener_state_condv_.notify_all();
270         }
271     };
272 
273     // create Secure Input device.
274     auto secureInput = createSecureInput(hsBegin, hsFinalize, deliverInput, inputResult);
275     if (!secureInput || !(*secureInput)) {
276         LOG(ERROR) << "Failed to open secure input device";
277         return result;  // TeeuiRc::SystemError;
278     }
279 
280     Finalize finalizeConfirmationPrompt([app] {
281         LOG(INFO) << "Calling abort for cleanup";
282         app->issueCmd<AbortMsg>();
283     });
284 
285     // initiate prompt
286     LOG(INFO) << "Initiating prompt";
287     TrustyAppError error;
288     auto initResponse = std::tie(rc);
289     std::tie(error, initResponse) =
290         app->issueCmd<PromptUserConfirmationMsg, PromptUserConfirmationResponse>(
291             promptText, extraData, locale, uiOptions);
292     if (error == TrustyAppError::MSG_TOO_LONG) {
293         LOG(ERROR) << "PromptUserConfirmationMsg failed: message too long";
294         rc = TeeuiRc::UIErrorMessageTooLong;
295         return result;
296     } else if (error != TrustyAppError::OK) {
297         LOG(ERROR) << "PromptUserConfirmationMsg failed: " << int32_t(error);
298         return result;  // TeeuiRc::SystemError;
299     }
300     if (rc != TeeuiRc::OK) {
301         LOG(ERROR) << "PromptUserConfirmationMsg failed: " << uint32_t(rc);
302         return result;
303     }
304 
305     LOG(INFO) << "Grabbing event devices";
306     EventLoop eventloop;
307     bool grabbed =
308         grabAllEvDevsAndRegisterCallbacks(&eventloop, [&](short flags, const EventDev& evDev) {
309             if (!(flags & POLLIN)) return;
310             secureInput->handleEvent(evDev);
311         });
312 
313     if (!grabbed) {
314         rc = TeeuiRc::SystemError;
315         return result;
316     }
317 
318     abort_called_ = false;
319     secureInputDelivered_ = false;
320 
321     //  ############################## Start 2nd Phase #############################################
322     listener_state_ = ListenerState::SetupDone;
323     stateLock.unlock();
324     listener_state_condv_.notify_all();
325 
326     if (!eventloop.start()) {
327         rc = TeeuiRc::SystemError;
328         return result;
329     }
330 
331     stateLock.lock();
332 
333     LOG(INFO) << "going to sleep for the grace period";
334     auto then = std::chrono::system_clock::now() +
335                 std::chrono::milliseconds(kUserPreInputGracePeriodMillis) +
336                 std::chrono::microseconds(50);
337     listener_state_condv_.wait_until(stateLock, then, [&]() { return abort_called_; });
338     LOG(INFO) << "waking up";
339 
340     if (abort_called_) {
341         LOG(ERROR) << "Abort called";
342         result = {TeeuiRc::Aborted, {}, {}};
343         return result;
344     }
345 
346     LOG(INFO) << "Arming event poller";
347     // tell the event poller to act on received input events from now on.
348     secureInput->start();
349 
350     //  ############################## Start 3rd Phase - interactive phase #########################
351     LOG(INFO) << "Transition to Interactive";
352     listener_state_ = ListenerState::Interactive;
353     stateLock.unlock();
354     listener_state_condv_.notify_all();
355 
356     stateLock.lock();
357     listener_state_condv_.wait(stateLock, [&]() {
358         return eventRC != TeeuiRc::OperationPending || abort_called_ || secureInputDelivered_;
359     });
360     LOG(INFO) << "Listener waking up";
361     if (abort_called_) {
362         LOG(ERROR) << "Abort called";
363         result = {TeeuiRc::Aborted, {}, {}};
364         return result;
365     }
366 
367     if (!secureInputDelivered_) {
368         if (eventRC != TeeuiRc::OK) {
369             LOG(ERROR) << "Bad input response";
370             result = {eventRC, {}, {}};
371             return result;
372         }
373     }
374 
375     stateLock.unlock();
376 
377     LOG(INFO) << "Fetching Result";
378     std::tie(error, result) = app->issueCmd<FetchConfirmationResult, ResultMsg>();
379     LOG(INFO) << "Result yields " << int32_t(error) << "/" << uint32_t(rc);
380     if (error != TrustyAppError::OK) {
381         result = {TeeuiRc::SystemError, {}, {}};
382     }
383     return result;
384 
385     //  ############################## Start 4th Phase - cleanup ##################################
386 }
387 
388 // Methods from ::android::hardware::confirmationui::V1_0::IConfirmationUI
389 // follow.
promptUserConfirmation(const sp<IConfirmationResultCallback> & resultCB,const hidl_string & promptText,const hidl_vec<uint8_t> & extraData,const hidl_string & locale,const hidl_vec<UIOption> & uiOptions)390 Return<ResponseCode> TrustyConfirmationUI::promptUserConfirmation(
391     const sp<IConfirmationResultCallback>& resultCB, const hidl_string& promptText,
392     const hidl_vec<uint8_t>& extraData, const hidl_string& locale,
393     const hidl_vec<UIOption>& uiOptions) {
394     std::unique_lock<std::mutex> stateLock(listener_state_lock_, std::defer_lock);
395     if (!stateLock.try_lock()) {
396         return ResponseCode::OperationPending;
397     }
398     switch (listener_state_) {
399     case ListenerState::None:
400         break;
401     case ListenerState::Starting:
402     case ListenerState::SetupDone:
403     case ListenerState::Interactive:
404         return ResponseCode::OperationPending;
405     case ListenerState::Terminating:
406         callback_thread_.join();
407         listener_state_ = ListenerState::None;
408         break;
409     default:
410         return ResponseCode::Unexpected;
411     }
412 
413     assert(listener_state_ == ListenerState::None);
414 
415     callback_thread_ = std::thread(
416         [this](sp<IConfirmationResultCallback> resultCB, hidl_string promptText,
417                hidl_vec<uint8_t> extraData, hidl_string locale, hidl_vec<UIOption> uiOptions) {
418             auto [trc, msg, token] =
419                 promptUserConfirmation_(hidl2MsgString(promptText), hidl2MsgVector(extraData),
420                                         hidl2MsgString(locale), hidl2MsgVector(uiOptions));
421             bool do_callback = (listener_state_ == ListenerState::Interactive ||
422                                 listener_state_ == ListenerState::SetupDone) &&
423                                resultCB;
424             prompt_result_ = convertRc(trc);
425             listener_state_ = ListenerState::Terminating;
426             if (do_callback) {
427                 auto error = resultCB->result(prompt_result_, msg, token);
428                 if (!error.isOk()) {
429                     LOG(ERROR) << "Result callback failed " << error.description();
430                 }
431             } else {
432                 listener_state_condv_.notify_all();
433             }
434         },
435         resultCB, promptText, extraData, locale, uiOptions);
436 
437     listener_state_condv_.wait(stateLock, [this] {
438         return listener_state_ == ListenerState::SetupDone ||
439                listener_state_ == ListenerState::Interactive ||
440                listener_state_ == ListenerState::Terminating;
441     });
442     if (listener_state_ == ListenerState::Terminating) {
443         callback_thread_.join();
444         listener_state_ = ListenerState::None;
445         return prompt_result_;
446     }
447     return ResponseCode::OK;
448 }
449 
450 Return<ResponseCode>
deliverSecureInputEvent(const HardwareAuthToken & secureInputToken)451 TrustyConfirmationUI::deliverSecureInputEvent(const HardwareAuthToken& secureInputToken) {
452     ResponseCode rc = ResponseCode::Ignored;
453     {
454         /*
455          * deliverSecureInputEvent is only used by the VTS test to mock human input. A correct
456          * implementation responds with a mock confirmation token signed with a test key. The
457          * problem is that the non interactive grace period was not formalized in the HAL spec,
458          * so that the VTS test does not account for the grace period. (It probably should.)
459          * This means we can only pass the VTS test if we block until the grace period is over
460          * (SetupDone -> Interactive) before we deliver the input event.
461          *
462          * The true secure input is delivered by a different mechanism and gets ignored -
463          * not queued - until the grace period is over.
464          *
465          */
466         std::unique_lock<std::mutex> stateLock(listener_state_lock_);
467         listener_state_condv_.wait(stateLock,
468                                    [this] { return listener_state_ != ListenerState::SetupDone; });
469 
470         if (listener_state_ != ListenerState::Interactive) return ResponseCode::Ignored;
471         auto sapp = app_.lock();
472         if (!sapp) return ResponseCode::Ignored;
473         auto [error, response] =
474             sapp->issueCmd<DeliverTestCommandMessage, DeliverTestCommandResponse>(
475                 static_cast<teeui::TestModeCommands>(secureInputToken.challenge));
476         if (error != TrustyAppError::OK) return ResponseCode::SystemError;
477         auto& [trc] = response;
478         if (trc != TeeuiRc::Ignored) secureInputDelivered_ = true;
479         rc = convertRc(trc);
480     }
481     if (secureInputDelivered_) listener_state_condv_.notify_all();
482     // VTS test expect an OK response if the event was successfully delivered.
483     // But since the TA returns the callback response now, we have to translate
484     // Canceled into OK. Canceled is only returned if the delivered event canceled
485     // the operation, which means that the event was successfully delivered. Thus
486     // we return OK.
487     if (rc == ResponseCode::Canceled) return ResponseCode::OK;
488     return rc;
489 }
490 
abort()491 Return<void> TrustyConfirmationUI::abort() {
492     {
493         std::unique_lock<std::mutex> stateLock(listener_state_lock_);
494         if (listener_state_ == ListenerState::SetupDone ||
495             listener_state_ == ListenerState::Interactive) {
496             auto sapp = app_.lock();
497             if (sapp) sapp->issueCmd<AbortMsg>();
498             abort_called_ = true;
499         }
500     }
501     listener_state_condv_.notify_all();
502     return Void();
503 }
504 
createTrustyConfirmationUI()505 android::sp<IConfirmationUI> createTrustyConfirmationUI() {
506     return new TrustyConfirmationUI();
507 }
508 
509 }  // namespace implementation
510 }  // namespace V1_0
511 }  // namespace confirmationui
512 }  // namespace hardware
513 }  // namespace android
514