1 /*
2  * Copyright (C) 2022 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 #include <fcntl.h>
18 #include <inttypes.h>
19 #include <sys/epoll.h>
20 #include <sys/socket.h>
21 #include <chrono>
22 #include <limits>
23 #include <aidl/android/hardware/biometrics/common/BnCancellationSignal.h>
24 #include <android-base/unique_fd.h>
25 #include <debug.h>
26 #include <log/log.h>
27 #include <qemud.h>
28 #include <utils/Timers.h>
29 
30 #include "session.h"
31 #include "storage.h"
32 
33 #define SESSION_DEBUG(FMT, ...) \
34     ALOGD("%p:%s:%d: " FMT, this, __func__, __LINE__, __VA_ARGS__)
35 #define SESSION_ERR(FMT, ...) \
36     ALOGE("%p:%s:%d: " FMT, this, __func__, __LINE__, __VA_ARGS__)
37 
38 #define SESSION_DEBUG0(STR) SESSION_DEBUG("%s", STR)
39 
40 namespace aidl::android::hardware::biometrics::fingerprint {
41 
42 using ::android::base::unique_fd;
43 
44 namespace {
45 constexpr char kSensorServiceName[] = "fingerprintlisten";
46 constexpr char kSensorListenerQuitCmd = 'Q';
47 
generateSeed(void * p)48 int64_t generateSeed(void* p) {
49     auto now = std::chrono::high_resolution_clock::now();
50     decltype(now) epoch;
51     return (now - epoch).count() ^ reinterpret_cast<uintptr_t>(p);
52 }
53 
epollCtlAdd(int epollFd,int fd)54 int epollCtlAdd(int epollFd, int fd) {
55     int ret;
56 
57     /* make the fd non-blocking */
58     ret = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFL));
59     if (ret < 0) {
60         return ret;
61     }
62 
63     ret = TEMP_FAILURE_RETRY(fcntl(fd, F_SETFL, ret | O_NONBLOCK));
64     if (ret < 0) {
65         return ret;
66     }
67 
68     struct epoll_event ev;
69     ev.events  = EPOLLIN;
70     ev.data.fd = fd;
71 
72     return TEMP_FAILURE_RETRY(epoll_ctl(epollFd, EPOLL_CTL_ADD, fd, &ev));
73 }
74 
vec2str(const std::vector<T> & v)75 template <class T> std::string vec2str(const std::vector<T>& v) {
76     if (v.empty()) {
77         return "empty";
78     } else {
79         std::string result;
80 
81         for (const auto& x : v) {
82             if (result.empty()) {
83                 result = std::to_string(x);
84             } else {
85                 result += ",";
86                 result += std::to_string(x);
87             }
88         }
89 
90         return std::string("[") + result + std::string("]");
91     }
92 }
93 
state2str(const Session::State s)94 std::string state2str(const Session::State s) {
95     switch (s) {
96     case Session::State::IDLE:                  return "IDLE";
97     case Session::State::ENROLLING_START:       return "ENROLLING_START";
98     case Session::State::ENROLLING_END:         return "ENROLLING_END";
99     case Session::State::AUTHENTICATING:        return "AUTHENTICATING";
100     case Session::State::DETECTING_INTERACTION: return "DETECTING_INTERACTION";
101     default: return std::to_string(static_cast<int>(s));
102     }
103 }
104 
errorCode2str(const Session::ErrorCode ec)105 std::string errorCode2str(const Session::ErrorCode ec) {
106     switch (ec) {
107     case Session::ErrorCode::OK:                    return "OK";
108     case Session::ErrorCode::E_HAT_MAC_EMPTY:       return "E_HAT_MAC_EMPTY";
109     case Session::ErrorCode::E_HAT_WRONG_CHALLENGE: return "E_HAT_WRONG_CHALLENGE";
110     case Session::ErrorCode::E_INCORRECT_STATE:     return "E_INCORRECT_STATE";
111     case Session::ErrorCode::E_ENROLL_FAILED:       return "E_ENROLL_FAILED";
112     default: return std::to_string(static_cast<int>(ec));
113     }
114 }
115 
116 }  // namespace
117 
118 struct CancellationSignal : public common::BnCancellationSignal {
CancellationSignalaidl::android::hardware::biometrics::fingerprint::CancellationSignal119     CancellationSignal(std::function<void()> cb) : mCB(std::move(cb)) {}
120 
cancelaidl::android::hardware::biometrics::fingerprint::CancellationSignal121     ndk::ScopedAStatus  cancel() override {
122         mCB();
123         return ndk::ScopedAStatus::ok();
124     }
125 
126     const std::function<void()> mCB;
127 };
128 
Session(const int32_t sensorId,const int32_t userId,std::shared_ptr<ISessionCallback> scb)129 Session::Session(const int32_t sensorId, const int32_t userId,
130                  std::shared_ptr<ISessionCallback> scb)
131     : mSessionCb(std::move(scb))
132     , mStorage(sensorId, userId)
133     , mRandom(generateSeed(this))
134  {
135     SESSION_DEBUG("New session: sensorId=%d userId=%d", sensorId, userId);
136 
137     if (::android::base::Socketpair(AF_LOCAL, SOCK_STREAM, 0,
138                                     &mCallerFd, &mSensorThreadFd)) {
139         mSensorListener = std::thread(&Session::sensorListenerFunc, this);
140     } else {
141         mSensorListener = std::thread([](){});
142         LOG_ALWAYS_FATAL("%p:%s:%d: Socketpair failed", this, __func__, __LINE__);
143     }
144 }
145 
~Session()146 Session::~Session() {
147     SESSION_DEBUG0("Terminating session");
148 
149     TEMP_FAILURE_RETRY(write(mCallerFd.get(), &kSensorListenerQuitCmd, 1));
150     mSensorListener.join();
151 }
152 
generateChallenge()153 ndk::ScopedAStatus Session::generateChallenge() {
154     while (true) {
155         int64_t challenge;
156         {
157             std::lock_guard<std::mutex> lock(mMutex);
158             challenge = generateInt64();
159         }
160 
161         if (mChallenges.insert(challenge).second) {
162             SESSION_DEBUG("onChallengeGenerated(challenge=%" PRId64 ")", challenge);
163             mSessionCb->onChallengeGenerated(challenge);
164             return ndk::ScopedAStatus::ok();
165         }
166     }
167 }
168 
revokeChallenge(const int64_t challenge)169 ndk::ScopedAStatus Session::revokeChallenge(const int64_t challenge) {
170     mChallenges.erase(challenge);
171     SESSION_DEBUG("onChallengeRevoked(challenge=%" PRId64 ")", challenge);
172     mSessionCb->onChallengeRevoked(challenge);
173     return ndk::ScopedAStatus::ok();
174 }
175 
enroll(const keymaster::HardwareAuthToken & hat,std::shared_ptr<common::ICancellationSignal> * out)176 ndk::ScopedAStatus Session::enroll(const keymaster::HardwareAuthToken& hat,
177                                    std::shared_ptr<common::ICancellationSignal>* out) {
178     const ErrorCode err = validateHat(hat);
179     if (err == ErrorCode::OK) {
180         State previousState;
181         bool ok;
182         {
183             std::lock_guard<std::mutex> lock(mMutex);
184             previousState = mState;
185             if (previousState == State::IDLE) {
186                 mEnrollingSecUserId = hat.userId;
187                 mState = State::ENROLLING_START;
188                 ok = true;
189             } else {
190                 ok = false;
191             }
192         }
193 
194         if (ok) {
195             SESSION_DEBUG("ENROLLING_START hat.userId=%" PRId64, hat.userId);
196             *out = SharedRefBase::make<CancellationSignal>([this](){ cancellEnroll(); });
197         } else {
198             SESSION_ERR("onError(UNABLE_TO_PROCESS, %d): incorrect state, %s",
199                   int(ErrorCode::E_INCORRECT_STATE), state2str(previousState).c_str());
200             mSessionCb->onError(Error::UNABLE_TO_PROCESS,
201                                 int(ErrorCode::E_INCORRECT_STATE));
202         }
203     } else {
204         SESSION_ERR("onError(UNABLE_TO_PROCESS, %d): `hat` is invalid: %s",
205                     int(err), errorCode2str(err).c_str());
206         mSessionCb->onError(Error::UNABLE_TO_PROCESS, int(err));
207     }
208 
209     return ndk::ScopedAStatus::ok();
210 }
211 
authenticate(const int64_t operationId,std::shared_ptr<common::ICancellationSignal> * out)212 ndk::ScopedAStatus Session::authenticate(const int64_t operationId,
213                                          std::shared_ptr<common::ICancellationSignal>* out) {
214     State previousState;
215     bool ok;
216     {
217         std::lock_guard<std::mutex> lock(mMutex);
218         previousState = mState;
219         if (previousState == State::IDLE) {
220             mAuthChallenge = operationId;
221             mState = State::AUTHENTICATING;
222             ok = true;
223         } else {
224             ok = false;
225         }
226     }
227 
228     if (ok) {
229         SESSION_DEBUG("AUTHENTICATING operationId=%" PRId64, operationId);
230         *out = SharedRefBase::make<CancellationSignal>([this](){ cancellAuthenticate(); });
231     } else {
232         SESSION_ERR("onError(UNABLE_TO_PROCESS, %d): incorrect state, %s",
233                     int(ErrorCode::E_INCORRECT_STATE),
234                     state2str(previousState).c_str());
235         mSessionCb->onError(Error::UNABLE_TO_PROCESS,
236                             int(ErrorCode::E_INCORRECT_STATE));
237     }
238 
239     return ndk::ScopedAStatus::ok();
240 }
241 
detectInteraction(std::shared_ptr<common::ICancellationSignal> * out)242 ndk::ScopedAStatus Session::detectInteraction(
243         std::shared_ptr<common::ICancellationSignal>* out) {
244     State previousState;
245     bool ok;
246     {
247         std::lock_guard<std::mutex> lock(mMutex);
248         previousState = mState;
249         if (previousState == State::IDLE) {
250             mState = State::DETECTING_INTERACTION;
251             ok = true;
252         } else {
253             ok = false;
254         }
255     }
256 
257     if (ok) {
258         SESSION_DEBUG0("DETECTING_INTERACTION");
259         *out = SharedRefBase::make<CancellationSignal>([this](){ cancellDetectInteraction(); });
260     } else {
261         SESSION_ERR("onError(UNABLE_TO_PROCESS, %d): incorrect state, %s",
262                     int(ErrorCode::E_INCORRECT_STATE),
263                     state2str(previousState).c_str());
264         mSessionCb->onError(Error::UNABLE_TO_PROCESS,
265                             int(ErrorCode::E_INCORRECT_STATE));
266     }
267 
268     return ndk::ScopedAStatus::ok();
269 }
270 
enumerateEnrollments()271 ndk::ScopedAStatus Session::enumerateEnrollments() {
272     std::vector<int32_t> enrollmentIds;
273     {
274         std::lock_guard<std::mutex> lock(mMutex);
275         enrollmentIds = mStorage.enumerateEnrollments();
276     }
277 
278     SESSION_DEBUG("onEnrollmentsEnumerated(enrollmentIds=%s)",
279                   vec2str(enrollmentIds).c_str());
280     mSessionCb->onEnrollmentsEnumerated(enrollmentIds);
281     return ndk::ScopedAStatus::ok();
282 }
283 
removeEnrollments(const std::vector<int32_t> & enrollmentIds)284 ndk::ScopedAStatus Session::removeEnrollments(const std::vector<int32_t>& enrollmentIds) {
285     {
286         std::lock_guard<std::mutex> lock(mMutex);
287         mStorage.removeEnrollments(enrollmentIds);
288     }
289 
290     SESSION_DEBUG("onEnrollmentsRemoved(enrollmentIds=%s)",
291                   vec2str(enrollmentIds).c_str());
292     mSessionCb->onEnrollmentsRemoved(enrollmentIds);
293     return ndk::ScopedAStatus::ok();
294 }
295 
getAuthenticatorId()296 ndk::ScopedAStatus Session::getAuthenticatorId() {
297     int64_t authId;
298     {
299         std::lock_guard<std::mutex> lock(mMutex);
300         authId = mStorage.getAuthenticatorId();
301     }
302 
303     SESSION_DEBUG("onAuthenticatorIdRetrieved(authId=%" PRId64 ")", authId);
304     mSessionCb->onAuthenticatorIdRetrieved(authId);
305     return ndk::ScopedAStatus::ok();
306 }
307 
invalidateAuthenticatorId()308 ndk::ScopedAStatus Session::invalidateAuthenticatorId() {
309     int64_t authId;
310     {
311         std::lock_guard<std::mutex> lock(mMutex);
312         authId = mStorage.invalidateAuthenticatorId(generateInt64());
313     }
314 
315     SESSION_DEBUG("onAuthenticatorIdInvalidated(authId=%" PRId64 ")", authId);
316     mSessionCb->onAuthenticatorIdInvalidated(authId);
317     return ndk::ScopedAStatus::ok();
318 }
319 
resetLockout(const keymaster::HardwareAuthToken & hat)320 ndk::ScopedAStatus Session::resetLockout(const keymaster::HardwareAuthToken& hat) {
321     const ErrorCode err = validateHat(hat);
322     if (err == ErrorCode::OK) {
323         {
324             std::lock_guard<std::mutex> lock(mMutex);
325             mStorage.resetLockout();
326         }
327 
328         SESSION_DEBUG0("onLockoutCleared");
329         mSessionCb->onLockoutCleared();
330     } else {
331         SESSION_ERR("onError(UNABLE_TO_PROCESS, %d): `hat` is invalid: %s",
332                     int(err), errorCode2str(err).c_str());
333         mSessionCb->onError(Error::UNABLE_TO_PROCESS, int(err));
334     }
335     return ndk::ScopedAStatus::ok();
336 }
337 
close()338 ndk::ScopedAStatus Session::close() {
339     mChallenges.clear();
340     SESSION_DEBUG0("onSessionClosed");
341     mSessionCb->onSessionClosed();
342     return ndk::ScopedAStatus::ok();
343 }
344 
validateHat(const keymaster::HardwareAuthToken & hat) const345 Session::ErrorCode Session::validateHat(const keymaster::HardwareAuthToken& hat) const {
346     if (hat.mac.empty()) {
347         return FAILURE(ErrorCode::E_HAT_MAC_EMPTY);
348     }
349 
350     if (!mChallenges.count(hat.challenge)) {
351         return FAILURE_V(ErrorCode::E_HAT_WRONG_CHALLENGE,
352                          "unexpected challenge: %" PRId64, hat.challenge);
353     }
354 
355     return ErrorCode::OK;
356 }
357 
generateInt64()358 int64_t Session::generateInt64() {
359     std::uniform_int_distribution<int64_t> distrib(1, std::numeric_limits<int64_t>::max());
360     return distrib(mRandom);
361 }
362 
onSensorEventOn(const int32_t enrollmentId)363 void Session::onSensorEventOn(const int32_t enrollmentId) {
364     std::lock_guard<std::mutex> lock(mMutex);
365     switch (mState) {
366     case State::ENROLLING_START:
367     case State::ENROLLING_END:
368         {
369             SESSION_DEBUG("onAcquired(GOOD, %d)", 0);
370             mSessionCb->onAcquired(AcquiredInfo::GOOD, 0);
371 
372             const int left = int(State::ENROLLING_END) - int(mState);
373             if (left > 0) {
374                 SESSION_DEBUG("onEnrollmentProgress(enrollmentId=%d, left=%d)",
375                               enrollmentId, left);
376                 mSessionCb->onEnrollmentProgress(enrollmentId, left);
377                 mState = State(int(mState) + 1);
378             } else if (mStorage.enroll(enrollmentId, mEnrollingSecUserId, generateInt64())) {
379                 SESSION_DEBUG("onEnrollmentProgress(enrollmentId=%d, left=%d)",
380                               enrollmentId, left);
381                 mSessionCb->onEnrollmentProgress(enrollmentId, left);
382                 mState = State::IDLE;
383             } else {
384                 SESSION_ERR("onError(UNABLE_TO_PROCESS, %d): enrollmentId=%d, "
385                             "secureIserId=%" PRId64 ,
386                             int(ErrorCode::E_ENROLL_FAILED),
387                             enrollmentId, mEnrollingSecUserId);
388                 mSessionCb->onError(Error::UNABLE_TO_PROCESS,
389                                     int(ErrorCode::E_ENROLL_FAILED));
390                 mState = State::IDLE;
391             }
392         }
393         break;
394 
395     case State::AUTHENTICATING:
396         {
397             const auto [res, lockoutDurationMillis, tok] =
398                 mStorage.authenticate(enrollmentId);
399             if (res != Storage::AuthResult::LOCKED_OUT_PERMANENT) {
400                 SESSION_DEBUG("onAcquired(GOOD, %d)", 0);
401                 mSessionCb->onAcquired(AcquiredInfo::GOOD, 0);
402             }
403 
404             switch (res) {
405             case Storage::AuthResult::OK: {
406                     SESSION_DEBUG("onAuthenticationSucceeded(enrollmentId=%d, "
407                                   "hat={ .challenge=%" PRId64 ", .userId=%" PRId64 ", "
408                                   ".authenticatorId=%" PRId64 " })",
409                                   enrollmentId, mAuthChallenge,
410                                   tok.userId, tok.authenticatorId);
411 
412                     keymaster::HardwareAuthToken hat;
413                     hat.challenge = mAuthChallenge;
414                     hat.userId = tok.userId;
415                     hat.authenticatorId = tok.authenticatorId;
416                     hat.authenticatorType = keymaster::HardwareAuthenticatorType::FINGERPRINT;
417                     hat.timestamp.milliSeconds = ns2ms(systemTime(SYSTEM_TIME_BOOTTIME));
418                     mSessionCb->onAuthenticationSucceeded(enrollmentId, hat);
419                     mState = State::IDLE;
420                 }
421                 break;
422 
423             case Storage::AuthResult::FAILED:
424                 SESSION_ERR("onAuthenticationFailed: enrollmentId=%d", enrollmentId);
425                 mSessionCb->onAuthenticationFailed();
426                 break;
427 
428             case Storage::AuthResult::LOCKED_OUT_TIMED:
429                 SESSION_ERR("onLockoutTimed(durationMillis=%d): enrollmentId=%d",
430                             lockoutDurationMillis, enrollmentId);
431                 mSessionCb->onLockoutTimed(lockoutDurationMillis);
432                 mState = State::IDLE;
433                 break;
434 
435             case Storage::AuthResult::LOCKED_OUT_PERMANENT:
436                 SESSION_ERR("onLockoutPermanent: enrollmentId=%d", enrollmentId);
437                 mSessionCb->onLockoutPermanent();
438                 mState = State::IDLE;
439                 break;
440 
441             default:
442                 LOG_ALWAYS_FATAL("%p:%s:%d: Unexpected result from `mStorage.authenticate`",
443                                  this, __func__, __LINE__);
444                 break;
445             }
446         }
447         break;
448 
449     case State::DETECTING_INTERACTION:
450         mSessionCb->onInteractionDetected();
451         mState = State::IDLE;
452         break;
453 
454     case State::IDLE:
455         break;
456 
457     default:
458         LOG_ALWAYS_FATAL("%p:%s:%d: Unexpected session state", this, __func__, __LINE__);
459         break;
460     }
461 }
462 
onSensorEventOff()463 void Session::onSensorEventOff() {}
464 
cancellEnroll()465 void Session::cancellEnroll() {
466     {
467         std::lock_guard<std::mutex> lock(mMutex);
468         if ((mState >= State::ENROLLING_START) && (mState <= State::ENROLLING_END)) {
469             mState = State::IDLE;
470         }
471     }
472 
473     SESSION_DEBUG("onError(CANCELED, %d)", 0);
474     mSessionCb->onError(Error::CANCELED, 0);
475 }
476 
cancellAuthenticate()477 void Session::cancellAuthenticate() {
478     {
479         std::lock_guard<std::mutex> lock(mMutex);
480         if (mState == State::AUTHENTICATING) {
481             mState = State::IDLE;
482         }
483     }
484 
485     SESSION_DEBUG("onError(CANCELED, %d)", 0);
486     mSessionCb->onError(Error::CANCELED, 0);
487 }
488 
cancellDetectInteraction()489 void Session::cancellDetectInteraction() {
490     {
491         std::lock_guard<std::mutex> lock(mMutex);
492         if (mState == State::DETECTING_INTERACTION) {
493             mState = State::IDLE;
494         }
495     }
496 
497     SESSION_DEBUG("onError(CANCELED, %d)", 0);
498     mSessionCb->onError(Error::CANCELED, 0);
499 }
500 
sensorListenerFuncImpl()501 bool Session::sensorListenerFuncImpl() {
502     unique_fd sensorFd(qemud_channel_open(kSensorServiceName));
503     LOG_ALWAYS_FATAL_IF(!sensorFd.ok(),
504                         "%p:%s:%d: Could not open the sensor service: '%s'",
505                         this, __func__, __LINE__, kSensorServiceName);
506 
507     const unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
508     epollCtlAdd(epollFd.get(), sensorFd.get());
509     epollCtlAdd(epollFd.get(), mSensorThreadFd.get());
510 
511     qemud_channel_send(sensorFd.get(), "listen", 6);
512 
513     while (true) {
514         const int kTimeoutMs = 250;
515         struct epoll_event event;
516         const int n = TEMP_FAILURE_RETRY(epoll_wait(epollFd.get(),
517                                                     &event, 1,
518                                                     kTimeoutMs));
519         if (n <= 0) {
520             bool lockoutCleared;
521             {
522                 std::lock_guard<std::mutex> lock(mMutex);
523                 lockoutCleared = mStorage.checkIfLockoutCleared();
524             }
525 
526             if (lockoutCleared) {
527                 SESSION_DEBUG0("onLockoutCleared");
528                 mSessionCb->onLockoutCleared();
529             }
530             continue;
531         }
532 
533         const int fd = event.data.fd;
534         const int ev_events = event.events;
535         if (fd == sensorFd.get()) {
536             if (ev_events & (EPOLLERR | EPOLLHUP)) {
537                 SESSION_ERR("epoll_wait: devFd has an error, ev_events=%x", ev_events);
538                 return true;
539             } else if (ev_events & EPOLLIN) {
540                 char buf[64];
541                 int n = qemud_channel_recv(fd, buf, sizeof(buf) - 1);
542                 if (n > 0) {
543                     buf[n] = 0;
544                     int32_t fid;
545                     if (sscanf(buf, "on:%d", &fid) == 1) {
546                         if (fid > 0) {
547                             onSensorEventOn(fid);
548                         } else {
549                             SESSION_ERR("incorrect fingerprint: %d", fid);
550                         }
551                     } else if (!strcmp(buf, "off")) {
552                         onSensorEventOff();
553                     } else {
554                         SESSION_ERR("unexpected hw message: '%s'", buf);
555                         return true;
556                     }
557                 } else {
558                     SESSION_ERR("hw read error, n=%d, errno=%d", n, errno);
559                     return true;
560                 }
561             }
562         } else if (fd == mSensorThreadFd.get()) {
563             if (ev_events & (EPOLLERR | EPOLLHUP)) {
564                 LOG_ALWAYS_FATAL("%p:%s:%d: epoll_wait: threadsFd has an error, ev_events=%x",
565                                  this, __func__, __LINE__, ev_events);
566             } else if (ev_events & EPOLLIN) {
567                 char cmd;
568                 int n = TEMP_FAILURE_RETRY(read(fd, &cmd, sizeof(cmd)));
569                 if (n == 1) {
570                     switch (cmd) {
571                     case kSensorListenerQuitCmd:
572                         return false;  // quit
573 
574                     default:
575                         LOG_ALWAYS_FATAL("%p:%s:%d: unexpected command, cmd=%c",
576                                          this, __func__, __LINE__, cmd);
577                         break;
578                     }
579                 } else {
580                     LOG_ALWAYS_FATAL("%p:%s:%d: error readind from mThreadsFd, errno=%d",
581                                      this, __func__, __LINE__, errno);
582                 }
583             }
584         } else {
585             SESSION_ERR("%s", "epoll_wait() returned unexpected fd");
586         }
587     }
588 }
589 
590 }  // namespace aidl::android::hardware::biometrics::fingerprint
591