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