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