1 /*
2 * Copyright 2019, 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 "secure_input_tracker.h"
18 #include "trusty_operation.h"
19
20 #include <secure_input/secure_input_proto.h>
21
22 #include <lib/rng/trusty_rng.h>
23
24 #include <inttypes.h>
25 #include <stdio.h>
26
27 #include <teeui/utils.h>
28
29 #include <trusty_log.h>
30
31 #include <uapi/err.h>
32
33 #define TLOG_TAG "confirmationui"
34
35 using namespace secure_input;
36 using teeui::Array;
37 using teeui::AuthTokenKey;
38 using teeui::bytesCast;
39 using teeui::HMac;
40 using teeui::optional;
41 using teeui::ResponseCode;
42
mtsNow()43 inline auto mtsNow() {
44 return monotonic_time_stamper::now();
45 }
46
getNonce()47 static optional<Nonce> getNonce() {
48 Nonce result;
49 if (trusty_rng_secure_rand(result.data(), result.size()) == NO_ERROR) {
50 return result;
51 } else {
52 return {};
53 }
54 }
55
newSession()56 ResponseCode InputTracker::newSession() {
57 state_ = InputState::Fresh;
58 event_ = InputEvent::None;
59 auto now = mtsNow();
60 // Initialize all timestamps to something sane.
61 for (auto& t : timestamps_) {
62 t = now;
63 }
64 return ResponseCode::OK;
65 }
66
67 // input Handshake
beginHandshake()68 std::tuple<ResponseCode, Nonce> InputTracker::beginHandshake() {
69 ResponseCode rc;
70 auto now = mtsNow();
71 if ((state_ == InputState::Fresh &&
72 (now - timestamps_[uint32_t(InputState::Fresh)]) >=
73 kUserPreInputGracePeriodMillis) ||
74 state_ == InputState::InputDeliveredMorePending) {
75 auto nonce = getNonce();
76 if (nonce) {
77 input_nonce_ = *nonce;
78 TLOGD("%u", uint32_t(state_));
79 state_ = InputState::HandshakeOutstanding;
80 timestamps_[uint32_t(state_)] = now;
81 return {ResponseCode::OK, input_nonce_};
82 } else {
83 rc = ResponseCode::SystemError;
84 }
85 }
86 rc = ResponseCode::Unexpected;
87 state_ = InputState::None;
88 return {rc, {}};
89 }
90
91 // input Handshake finalize
finalizeHandshake(const Nonce & nCi,const Signature & signature,const AuthTokenKey & key)92 ResponseCode InputTracker::finalizeHandshake(const Nonce& nCi,
93 const Signature& signature,
94 const AuthTokenKey& key) {
95 ResponseCode rc;
96 if (state_ == InputState::HandshakeOutstanding) {
97 using HMacer = HMac<TrustyOperation>;
98 auto hmac = HMacer::hmac256(key, kConfirmationUIHandshakeLabel,
99 input_nonce_, nCi);
100 if (hmac) {
101 if (*hmac == signature) {
102 // we can forget the nCo and input_nonce now becomes nCi
103 input_nonce_ = nCi;
104 state_ = InputState::HandshakeComplete;
105 timestamps_[uint32_t(state_)] = mtsNow();
106 TLOGD("%u", uint32_t(state_));
107 return ResponseCode::OK;
108 } else {
109 rc = ResponseCode::Aborted;
110 }
111 } else {
112 rc = ResponseCode::SystemError;
113 }
114 } else {
115 rc = ResponseCode::Unexpected;
116 }
117 state_ = InputState::None;
118 return rc;
119 }
120
121 // process input event
processInputEvent(DTupKeyEvent keyEvent,const Signature & signature,const AuthTokenKey & key)122 std::tuple<ResponseCode, InputResponse> InputTracker::processInputEvent(
123 DTupKeyEvent keyEvent,
124 const Signature& signature,
125 const AuthTokenKey& key) {
126 std::tuple<ResponseCode, InputResponse> result = {ResponseCode::OK,
127 InputResponse::TIMED_OUT};
128 ResponseCode& rc = std::get<0>(result);
129 InputResponse& ir = std::get<1>(result);
130 using HMacer = HMac<TrustyOperation>;
131 auto now = mtsNow();
132
133 if (state_ != InputState::HandshakeComplete) {
134 state_ = InputState::None;
135 rc = ResponseCode::Unexpected;
136 return result;
137 }
138 uint32_t keyEventBE = htobe32(static_cast<uint32_t>(keyEvent));
139 auto hmac = HMacer::hmac256(key, kConfirmationUIEventLabel,
140 bytesCast(keyEventBE), input_nonce_);
141 if (!hmac) {
142 state_ = InputState::None;
143 rc = ResponseCode::SystemError;
144 return result;
145 }
146
147 if (!(*hmac == signature)) {
148 state_ = InputState::None;
149 rc = ResponseCode::Aborted;
150 TLOGE("signature on input event did not check out");
151 return result;
152 }
153
154 switch (keyEvent) {
155 // fall through intended
156 case DTupKeyEvent::VOL_DOWN:
157 case DTupKeyEvent::VOL_UP:
158 event_ = InputEvent::UserCancel;
159 state_ = InputState::InputDeliveredFinal;
160 ir = InputResponse::OK;
161 break;
162 case DTupKeyEvent::PWR:
163 if (state_ == InputState::HandshakeComplete &&
164 now - timestamps_[uint32_t(
165 InputState::InputDeliveredMorePending)] <=
166 kUserDoupleClickTimeoutMillis) {
167 state_ = InputState::InputDeliveredFinal;
168 ir = InputResponse::OK;
169 event_ = InputEvent::UserConfirm;
170 } else {
171 state_ = InputState::InputDeliveredMorePending;
172 ir = InputResponse::PENDING_MORE;
173 }
174 break;
175 case DTupKeyEvent::RESERVED:
176 default:
177 TLOGW("got RESERVED event");
178 rc = ResponseCode::Aborted;
179 state_ = InputState::None;
180 return result;
181 }
182 timestamps_[uint32_t(state_)] = now;
183 TLOGD("%u", uint32_t(state_));
184 return result;
185 }
186
fetchInputEvent()187 ResponseCode InputTracker::fetchInputEvent() {
188 if (state_ == InputState::InputDeliveredFinal) {
189 state_ = InputState::InputFetched;
190 if (event_ == InputEvent::UserConfirm)
191 return ResponseCode::OK;
192 else
193 return ResponseCode::Canceled;
194 } else {
195 TLOGD("%u", uint32_t(state_));
196 state_ = InputState::None;
197 return ResponseCode::Unexpected;
198 }
199 }
200
reportVerifiedInput(InputEvent event)201 ResponseCode InputTracker::reportVerifiedInput(InputEvent event) {
202 auto now = mtsNow();
203 if (state_ == InputState::Fresh &&
204 (now - timestamps_[uint32_t(InputState::Fresh)]) >=
205 kUserPreInputGracePeriodMillis) {
206 state_ = InputState::InputDeliveredFinal;
207 event_ = event;
208 }
209 return ResponseCode::OK;
210 }
211