blob: 997e73984a7b55ba16c8a5221da72ec53f0ebeb5 [file] [log] [blame]
Hasini Gunasinghe3410f792020-09-14 17:55:21 +00001// Copyright 2020, The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
Hasini Gunasinghe3410f792020-09-14 17:55:21 +000015//! This is the Keystore 2.0 Enforcements module.
16// TODO: more description to follow.
Janis Danisevskis5ed8c532021-01-11 14:19:42 -080017use crate::error::{map_binder_status, Error, ErrorCode};
18use crate::globals::{get_timestamp_service, ASYNC_TASK, DB, ENFORCEMENTS};
Hasini Gunasinghe52333ba2020-11-06 01:24:16 +000019use crate::key_parameter::{KeyParameter, KeyParameterValue};
Paul Crowley7a658392021-03-18 17:08:20 -070020use crate::{authorization::Error as AuthzError, super_key::SuperEncryptionType};
Paul Crowley44c02da2021-04-08 17:04:43 +000021use crate::{
22 database::{AuthTokenEntry, MonotonicRawTime},
23 globals::SUPER_KEY,
24};
Hasini Gunasinghe52333ba2020-11-06 01:24:16 +000025use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
Hasini Gunasinghe5112c702020-11-09 22:13:25 +000026 Algorithm::Algorithm, ErrorCode::ErrorCode as Ec, HardwareAuthToken::HardwareAuthToken,
Janis Danisevskis5ed8c532021-01-11 14:19:42 -080027 HardwareAuthenticatorType::HardwareAuthenticatorType,
28 KeyParameter::KeyParameter as KmKeyParameter, KeyPurpose::KeyPurpose, Tag::Tag,
Janis Danisevskisc3a496b2021-01-05 10:37:22 -080029};
30use android_hardware_security_secureclock::aidl::android::hardware::security::secureclock::{
Janis Danisevskis5f3a0572021-06-18 11:26:42 -070031 TimeStampToken::TimeStampToken,
Hasini Gunasinghe52333ba2020-11-06 01:24:16 +000032};
Hasini Gunasingheb3715fb2021-02-26 20:34:45 +000033use android_security_authorization::aidl::android::security::authorization::ResponseCode::ResponseCode as AuthzResponseCode;
Hasini Gunasinghedeab85d2021-02-01 21:10:02 +000034use android_system_keystore2::aidl::android::system::keystore2::{
Paul Crowley7a658392021-03-18 17:08:20 -070035 Domain::Domain, IKeystoreSecurityLevel::KEY_FLAG_AUTH_BOUND_WITHOUT_CRYPTOGRAPHIC_LSKF_BINDING,
Hasini Gunasinghedeab85d2021-02-01 21:10:02 +000036 OperationChallenge::OperationChallenge,
37};
Hasini Gunasinghe52333ba2020-11-06 01:24:16 +000038use anyhow::{Context, Result};
Janis Danisevskisb1673db2021-02-08 18:11:57 -080039use std::{
40 collections::{HashMap, HashSet},
Paul Crowley7c57bf12021-02-02 16:26:57 -080041 sync::{
Paul Crowley7c57bf12021-02-02 16:26:57 -080042 mpsc::{channel, Receiver, Sender, TryRecvError},
43 Arc, Mutex, Weak,
44 },
45 time::SystemTime,
Janis Danisevskisb1673db2021-02-08 18:11:57 -080046};
Hasini Gunasinghe3410f792020-09-14 17:55:21 +000047
Janis Danisevskis5ed8c532021-01-11 14:19:42 -080048#[derive(Debug)]
49enum AuthRequestState {
50 /// An outstanding per operation authorization request.
51 OpAuth,
52 /// An outstanding request for per operation authorization and secure timestamp.
53 TimeStampedOpAuth(Receiver<Result<TimeStampToken, Error>>),
54 /// An outstanding request for a timestamp token.
55 TimeStamp(Receiver<Result<TimeStampToken, Error>>),
56}
57
58#[derive(Debug)]
59struct AuthRequest {
60 state: AuthRequestState,
61 /// This need to be set to Some to fulfill a AuthRequestState::OpAuth or
62 /// AuthRequestState::TimeStampedOpAuth.
Janis Danisevskisbe1969e2021-04-20 15:16:24 -070063 hat: Mutex<Option<HardwareAuthToken>>,
Janis Danisevskis5ed8c532021-01-11 14:19:42 -080064}
65
Janis Danisevskisbe1969e2021-04-20 15:16:24 -070066unsafe impl Sync for AuthRequest {}
67
Janis Danisevskis5ed8c532021-01-11 14:19:42 -080068impl AuthRequest {
Janis Danisevskisbe1969e2021-04-20 15:16:24 -070069 fn op_auth() -> Arc<Self> {
70 Arc::new(Self { state: AuthRequestState::OpAuth, hat: Mutex::new(None) })
Janis Danisevskis5ed8c532021-01-11 14:19:42 -080071 }
72
Janis Danisevskisbe1969e2021-04-20 15:16:24 -070073 fn timestamped_op_auth(receiver: Receiver<Result<TimeStampToken, Error>>) -> Arc<Self> {
74 Arc::new(Self {
Janis Danisevskis5ed8c532021-01-11 14:19:42 -080075 state: AuthRequestState::TimeStampedOpAuth(receiver),
Janis Danisevskisbe1969e2021-04-20 15:16:24 -070076 hat: Mutex::new(None),
77 })
Janis Danisevskis5ed8c532021-01-11 14:19:42 -080078 }
79
80 fn timestamp(
81 hat: HardwareAuthToken,
82 receiver: Receiver<Result<TimeStampToken, Error>>,
Janis Danisevskisbe1969e2021-04-20 15:16:24 -070083 ) -> Arc<Self> {
84 Arc::new(Self { state: AuthRequestState::TimeStamp(receiver), hat: Mutex::new(Some(hat)) })
Janis Danisevskis5ed8c532021-01-11 14:19:42 -080085 }
86
Janis Danisevskisbe1969e2021-04-20 15:16:24 -070087 fn add_auth_token(&self, hat: HardwareAuthToken) {
88 *self.hat.lock().unwrap() = Some(hat)
Janis Danisevskis5ed8c532021-01-11 14:19:42 -080089 }
90
Janis Danisevskisbe1969e2021-04-20 15:16:24 -070091 fn get_auth_tokens(&self) -> Result<(HardwareAuthToken, Option<TimeStampToken>)> {
92 let hat = self
93 .hat
94 .lock()
95 .unwrap()
96 .take()
97 .ok_or(Error::Km(ErrorCode::KEY_USER_NOT_AUTHENTICATED))
98 .context("In get_auth_tokens: No operation auth token received.")?;
99
100 let tst = match &self.state {
101 AuthRequestState::TimeStampedOpAuth(recv) | AuthRequestState::TimeStamp(recv) => {
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800102 let result = recv.recv().context("In get_auth_tokens: Sender disconnected.")?;
Janis Danisevskisbe1969e2021-04-20 15:16:24 -0700103 Some(result.context(concat!(
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800104 "In get_auth_tokens: Worker responded with error ",
105 "from generating timestamp token."
Janis Danisevskisbe1969e2021-04-20 15:16:24 -0700106 ))?)
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800107 }
Janis Danisevskisbe1969e2021-04-20 15:16:24 -0700108 AuthRequestState::OpAuth => None,
109 };
110 Ok((hat, tst))
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800111 }
112}
113
114/// DeferredAuthState describes how auth tokens and timestamp tokens need to be provided when
115/// updating and finishing an operation.
116#[derive(Debug)]
117enum DeferredAuthState {
118 /// Used when an operation does not require further authorization.
119 NoAuthRequired,
120 /// Indicates that the operation requires an operation specific token. This means we have
121 /// to return an operation challenge to the client which should reward us with an
122 /// operation specific auth token. If it is not provided before the client calls update
123 /// or finish, the operation fails as not authorized.
124 OpAuthRequired,
125 /// Indicates that the operation requires a time stamp token. The auth token was already
126 /// loaded from the database, but it has to be accompanied by a time stamp token to inform
127 /// the target KM with a different clock about the time on the authenticators.
128 TimeStampRequired(HardwareAuthToken),
129 /// Indicates that both an operation bound auth token and a verification token are
130 /// before the operation can commence.
131 TimeStampedOpAuthRequired,
132 /// In this state the auth info is waiting for the deferred authorizations to come in.
133 /// We block on timestamp tokens, because we can always make progress on these requests.
134 /// The per-op auth tokens might never come, which means we fail if the client calls
135 /// update or finish before we got a per-op auth token.
Janis Danisevskisbe1969e2021-04-20 15:16:24 -0700136 Waiting(Arc<AuthRequest>),
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800137 /// In this state we have gotten all of the required tokens, we just cache them to
138 /// be used when the operation progresses.
139 Token(HardwareAuthToken, Option<TimeStampToken>),
140}
141
142/// Auth info hold all of the authorization related information of an operation. It is stored
143/// in and owned by the operation. It is constructed by authorize_create and stays with the
144/// operation until it completes.
145#[derive(Debug)]
146pub struct AuthInfo {
147 state: DeferredAuthState,
Qi Wub9433b52020-12-01 14:52:46 +0800148 /// An optional key id required to update the usage count if the key usage is limited.
149 key_usage_limited: Option<i64>,
Janis Danisevskisb1673db2021-02-08 18:11:57 -0800150 confirmation_token_receiver: Option<Arc<Mutex<Option<Receiver<Vec<u8>>>>>>,
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800151}
152
153struct TokenReceiverMap {
154 /// The map maps an outstanding challenge to a TokenReceiver. If an incoming Hardware Auth
155 /// Token (HAT) has the map key in its challenge field, it gets passed to the TokenReceiver
156 /// and the entry is removed from the map. In the case where no HAT is received before the
157 /// corresponding operation gets dropped, the entry goes stale. So every time the cleanup
158 /// counter (second field in the tuple) turns 0, the map is cleaned from stale entries.
159 /// The cleanup counter is decremented every time a new receiver is added.
160 /// and reset to TokenReceiverMap::CLEANUP_PERIOD + 1 after each cleanup.
161 map_and_cleanup_counter: Mutex<(HashMap<i64, TokenReceiver>, u8)>,
162}
163
164impl Default for TokenReceiverMap {
165 fn default() -> Self {
166 Self { map_and_cleanup_counter: Mutex::new((HashMap::new(), Self::CLEANUP_PERIOD + 1)) }
167 }
168}
169
170impl TokenReceiverMap {
171 /// There is a chance that receivers may become stale because their operation is dropped
172 /// without ever being authorized. So occasionally we iterate through the map and throw
173 /// out obsolete entries.
174 /// This is the number of calls to add_receiver between cleanups.
175 const CLEANUP_PERIOD: u8 = 25;
176
177 pub fn add_auth_token(&self, hat: HardwareAuthToken) {
Janis Danisevskisbe1969e2021-04-20 15:16:24 -0700178 let recv = {
179 // Limit the scope of the mutex guard, so that it is not held while the auth token is
180 // added.
181 let mut map = self.map_and_cleanup_counter.lock().unwrap();
182 let (ref mut map, _) = *map;
183 map.remove_entry(&hat.challenge)
184 };
185
186 if let Some((_, recv)) = recv {
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800187 recv.add_auth_token(hat);
188 }
189 }
190
191 pub fn add_receiver(&self, challenge: i64, recv: TokenReceiver) {
192 let mut map = self.map_and_cleanup_counter.lock().unwrap();
193 let (ref mut map, ref mut cleanup_counter) = *map;
194 map.insert(challenge, recv);
195
196 *cleanup_counter -= 1;
197 if *cleanup_counter == 0 {
198 map.retain(|_, v| !v.is_obsolete());
199 map.shrink_to_fit();
200 *cleanup_counter = Self::CLEANUP_PERIOD + 1;
201 }
202 }
203}
204
205#[derive(Debug)]
Janis Danisevskisbe1969e2021-04-20 15:16:24 -0700206struct TokenReceiver(Weak<AuthRequest>);
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800207
208impl TokenReceiver {
209 fn is_obsolete(&self) -> bool {
210 self.0.upgrade().is_none()
211 }
212
213 fn add_auth_token(&self, hat: HardwareAuthToken) {
214 if let Some(state_arc) = self.0.upgrade() {
Janis Danisevskisbe1969e2021-04-20 15:16:24 -0700215 state_arc.add_auth_token(hat);
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800216 }
217 }
218}
219
220fn get_timestamp_token(challenge: i64) -> Result<TimeStampToken, Error> {
Janis Danisevskis5f3a0572021-06-18 11:26:42 -0700221 let dev = get_timestamp_service().expect(concat!(
222 "Secure Clock service must be present ",
223 "if TimeStampTokens are required."
224 ));
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800225 map_binder_status(dev.generateTimeStamp(challenge))
226}
227
228fn timestamp_token_request(challenge: i64, sender: Sender<Result<TimeStampToken, Error>>) {
229 if let Err(e) = sender.send(get_timestamp_token(challenge)) {
230 log::info!(
231 concat!(
Hasini Gunasingheb3715fb2021-02-26 20:34:45 +0000232 "In timestamp_token_request: Receiver hung up ",
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800233 "before timestamp token could be delivered. {:?}"
234 ),
235 e
236 );
237 }
238}
239
240impl AuthInfo {
241 /// This function gets called after an operation was successfully created.
242 /// It makes all the preparations required, so that the operation has all the authentication
243 /// related artifacts to advance on update and finish.
244 pub fn finalize_create_authorization(&mut self, challenge: i64) -> Option<OperationChallenge> {
245 match &self.state {
246 DeferredAuthState::OpAuthRequired => {
247 let auth_request = AuthRequest::op_auth();
248 let token_receiver = TokenReceiver(Arc::downgrade(&auth_request));
249 ENFORCEMENTS.register_op_auth_receiver(challenge, token_receiver);
250
251 self.state = DeferredAuthState::Waiting(auth_request);
252 Some(OperationChallenge { challenge })
253 }
254 DeferredAuthState::TimeStampedOpAuthRequired => {
255 let (sender, receiver) = channel::<Result<TimeStampToken, Error>>();
256 let auth_request = AuthRequest::timestamped_op_auth(receiver);
257 let token_receiver = TokenReceiver(Arc::downgrade(&auth_request));
258 ENFORCEMENTS.register_op_auth_receiver(challenge, token_receiver);
259
Janis Danisevskis40f0e6b2021-02-10 15:48:44 -0800260 ASYNC_TASK.queue_hi(move |_| timestamp_token_request(challenge, sender));
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800261 self.state = DeferredAuthState::Waiting(auth_request);
262 Some(OperationChallenge { challenge })
263 }
264 DeferredAuthState::TimeStampRequired(hat) => {
265 let hat = (*hat).clone();
266 let (sender, receiver) = channel::<Result<TimeStampToken, Error>>();
267 let auth_request = AuthRequest::timestamp(hat, receiver);
Janis Danisevskis40f0e6b2021-02-10 15:48:44 -0800268 ASYNC_TASK.queue_hi(move |_| timestamp_token_request(challenge, sender));
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800269 self.state = DeferredAuthState::Waiting(auth_request);
270 None
271 }
272 _ => None,
273 }
274 }
275
Qi Wub9433b52020-12-01 14:52:46 +0800276 /// This function is the authorization hook called before operation update.
277 /// It returns the auth tokens required by the operation to commence update.
278 pub fn before_update(&mut self) -> Result<(Option<HardwareAuthToken>, Option<TimeStampToken>)> {
279 self.get_auth_tokens()
280 }
281
282 /// This function is the authorization hook called before operation finish.
283 /// It returns the auth tokens required by the operation to commence finish.
Janis Danisevskisb1673db2021-02-08 18:11:57 -0800284 /// The third token is a confirmation token.
285 pub fn before_finish(
286 &mut self,
287 ) -> Result<(Option<HardwareAuthToken>, Option<TimeStampToken>, Option<Vec<u8>>)> {
288 let mut confirmation_token: Option<Vec<u8>> = None;
289 if let Some(ref confirmation_token_receiver) = self.confirmation_token_receiver {
290 let locked_receiver = confirmation_token_receiver.lock().unwrap();
291 if let Some(ref receiver) = *locked_receiver {
292 loop {
293 match receiver.try_recv() {
294 // As long as we get tokens we loop and discard all but the most
295 // recent one.
296 Ok(t) => confirmation_token = Some(t),
297 Err(TryRecvError::Empty) => break,
298 Err(TryRecvError::Disconnected) => {
299 log::error!(concat!(
300 "We got disconnected from the APC service, ",
301 "this should never happen."
302 ));
303 break;
304 }
305 }
306 }
307 }
308 }
309 self.get_auth_tokens().map(|(hat, tst)| (hat, tst, confirmation_token))
Qi Wub9433b52020-12-01 14:52:46 +0800310 }
311
312 /// This function is the authorization hook called after finish succeeded.
313 /// As of this writing it checks if the key was a limited use key. If so it updates the
314 /// use counter of the key in the database. When the use counter is depleted, the key gets
315 /// marked for deletion and the garbage collector is notified.
316 pub fn after_finish(&self) -> Result<()> {
317 if let Some(key_id) = self.key_usage_limited {
318 // On the last successful use, the key gets deleted. In this case we
319 // have to notify the garbage collector.
Janis Danisevskis7e8b4622021-02-13 10:01:59 -0800320 DB.with(|db| {
321 db.borrow_mut()
322 .check_and_update_key_usage_count(key_id)
323 .context("Trying to update key usage count.")
324 })
325 .context("In after_finish.")?;
Qi Wub9433b52020-12-01 14:52:46 +0800326 }
327 Ok(())
328 }
329
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800330 /// This function returns the auth tokens as needed by the ongoing operation or fails
331 /// with ErrorCode::KEY_USER_NOT_AUTHENTICATED. If this was called for the first time
332 /// after a deferred authorization was requested by finalize_create_authorization, this
333 /// function may block on the generation of a time stamp token. It then moves the
334 /// tokens into the DeferredAuthState::Token state for future use.
Qi Wub9433b52020-12-01 14:52:46 +0800335 fn get_auth_tokens(&mut self) -> Result<(Option<HardwareAuthToken>, Option<TimeStampToken>)> {
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800336 let deferred_tokens = if let DeferredAuthState::Waiting(ref auth_request) = self.state {
Janis Danisevskisbe1969e2021-04-20 15:16:24 -0700337 Some(auth_request.get_auth_tokens().context("In AuthInfo::get_auth_tokens.")?)
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800338 } else {
339 None
340 };
341
342 if let Some((hat, tst)) = deferred_tokens {
343 self.state = DeferredAuthState::Token(hat, tst);
344 }
345
346 match &self.state {
347 DeferredAuthState::NoAuthRequired => Ok((None, None)),
348 DeferredAuthState::Token(hat, tst) => Ok((Some((*hat).clone()), (*tst).clone())),
349 DeferredAuthState::OpAuthRequired
350 | DeferredAuthState::TimeStampedOpAuthRequired
351 | DeferredAuthState::TimeStampRequired(_) => {
352 Err(Error::Km(ErrorCode::KEY_USER_NOT_AUTHENTICATED)).context(concat!(
353 "In AuthInfo::get_auth_tokens: No operation auth token requested??? ",
354 "This should not happen."
355 ))
356 }
357 // This should not be reachable, because it should have been handled above.
358 DeferredAuthState::Waiting(_) => {
359 Err(Error::sys()).context("In AuthInfo::get_auth_tokens: Cannot be reached.")
360 }
361 }
362 }
363}
364
Hasini Gunasinghe3410f792020-09-14 17:55:21 +0000365/// Enforcements data structure
Paul Crowley7c57bf12021-02-02 16:26:57 -0800366#[derive(Default)]
Hasini Gunasinghe3410f792020-09-14 17:55:21 +0000367pub struct Enforcements {
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800368 /// This hash set contains the user ids for whom the device is currently unlocked. If a user id
369 /// is not in the set, it implies that the device is locked for the user.
Hasini Gunasinghe3410f792020-09-14 17:55:21 +0000370 device_unlocked_set: Mutex<HashSet<i32>>,
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800371 /// This field maps outstanding auth challenges to their operations. When an auth token
372 /// with the right challenge is received it is passed to the map using
373 /// TokenReceiverMap::add_auth_token() which removes the entry from the map. If an entry goes
374 /// stale, because the operation gets dropped before an auth token is received, the map
375 /// is cleaned up in regular intervals.
376 op_auth_map: TokenReceiverMap,
Janis Danisevskisb1673db2021-02-08 18:11:57 -0800377 /// The enforcement module will try to get a confirmation token from this channel whenever
378 /// an operation that requires confirmation finishes.
379 confirmation_token_receiver: Arc<Mutex<Option<Receiver<Vec<u8>>>>>,
Hasini Gunasinghe3410f792020-09-14 17:55:21 +0000380}
381
382impl Enforcements {
Janis Danisevskisb1673db2021-02-08 18:11:57 -0800383 /// Install the confirmation token receiver. The enforcement module will try to get a
384 /// confirmation token from this channel whenever an operation that requires confirmation
385 /// finishes.
386 pub fn install_confirmation_token_receiver(
387 &self,
388 confirmation_token_receiver: Receiver<Vec<u8>>,
389 ) {
390 *self.confirmation_token_receiver.lock().unwrap() = Some(confirmation_token_receiver);
391 }
392
Hasini Gunasinghe5112c702020-11-09 22:13:25 +0000393 /// Checks if a create call is authorized, given key parameters and operation parameters.
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800394 /// It returns an optional immediate auth token which can be presented to begin, and an
395 /// AuthInfo object which stays with the authorized operation and is used to obtain
396 /// auth tokens and timestamp tokens as required by the operation.
Hasini Gunasinghe5112c702020-11-09 22:13:25 +0000397 /// With regard to auth tokens, the following steps are taken:
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800398 ///
399 /// If no key parameters are given (typically when the client is self managed
400 /// (see Domain.Blob)) nothing is enforced.
Hasini Gunasinghe5112c702020-11-09 22:13:25 +0000401 /// If the key is time-bound, find a matching auth token from the database.
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800402 /// If the above step is successful, and if requires_timestamp is given, the returned
403 /// AuthInfo will provide a Timestamp token as appropriate.
Hasini Gunasinghe5112c702020-11-09 22:13:25 +0000404 pub fn authorize_create(
405 &self,
406 purpose: KeyPurpose,
Qi Wub9433b52020-12-01 14:52:46 +0800407 key_properties: Option<&(i64, Vec<KeyParameter>)>,
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800408 op_params: &[KmKeyParameter],
409 requires_timestamp: bool,
410 ) -> Result<(Option<HardwareAuthToken>, AuthInfo)> {
Qi Wub9433b52020-12-01 14:52:46 +0800411 let (key_id, key_params) = match key_properties {
412 Some((key_id, key_params)) => (*key_id, key_params),
413 None => {
414 return Ok((
415 None,
Janis Danisevskisb1673db2021-02-08 18:11:57 -0800416 AuthInfo {
417 state: DeferredAuthState::NoAuthRequired,
418 key_usage_limited: None,
419 confirmation_token_receiver: None,
420 },
Qi Wub9433b52020-12-01 14:52:46 +0800421 ))
422 }
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800423 };
424
Hasini Gunasinghe5112c702020-11-09 22:13:25 +0000425 match purpose {
426 // Allow SIGN, DECRYPT for both symmetric and asymmetric keys.
427 KeyPurpose::SIGN | KeyPurpose::DECRYPT => {}
428 // Rule out WRAP_KEY purpose
429 KeyPurpose::WRAP_KEY => {
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800430 return Err(Error::Km(Ec::INCOMPATIBLE_PURPOSE))
Hasini Gunasinghe5112c702020-11-09 22:13:25 +0000431 .context("In authorize_create: WRAP_KEY purpose is not allowed here.");
432 }
Bram Bonnéa6b83822021-01-20 11:10:05 +0100433 // Allow AGREE_KEY for EC keys only.
434 KeyPurpose::AGREE_KEY => {
435 for kp in key_params.iter() {
436 if kp.get_tag() == Tag::ALGORITHM
437 && *kp.key_parameter_value() != KeyParameterValue::Algorithm(Algorithm::EC)
438 {
439 return Err(Error::Km(Ec::UNSUPPORTED_PURPOSE)).context(
440 "In authorize_create: key agreement is only supported for EC keys.",
441 );
442 }
443 }
444 }
Hasini Gunasinghe5112c702020-11-09 22:13:25 +0000445 KeyPurpose::VERIFY | KeyPurpose::ENCRYPT => {
446 // We do not support ENCRYPT and VERIFY (the remaining two options of purpose) for
447 // asymmetric keys.
448 for kp in key_params.iter() {
449 match *kp.key_parameter_value() {
450 KeyParameterValue::Algorithm(Algorithm::RSA)
451 | KeyParameterValue::Algorithm(Algorithm::EC) => {
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800452 return Err(Error::Km(Ec::UNSUPPORTED_PURPOSE)).context(
Hasini Gunasinghe5112c702020-11-09 22:13:25 +0000453 "In authorize_create: public operations on asymmetric keys are not
454 supported.",
455 );
456 }
457 _ => {}
458 }
459 }
460 }
461 _ => {
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800462 return Err(Error::Km(Ec::UNSUPPORTED_PURPOSE))
Hasini Gunasinghe5112c702020-11-09 22:13:25 +0000463 .context("In authorize_create: specified purpose is not supported.");
464 }
465 }
466 // The following variables are to record information from key parameters to be used in
467 // enforcements, when two or more such pieces of information are required for enforcements.
468 // There is only one additional variable than what legacy keystore has, but this helps
469 // reduce the number of for loops on key parameters from 3 to 1, compared to legacy keystore
470 let mut key_purpose_authorized: bool = false;
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +0000471 let mut user_auth_type: Option<HardwareAuthenticatorType> = None;
Hasini Gunasinghe5112c702020-11-09 22:13:25 +0000472 let mut no_auth_required: bool = false;
473 let mut caller_nonce_allowed = false;
474 let mut user_id: i32 = -1;
475 let mut user_secure_ids = Vec::<i64>::new();
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +0000476 let mut key_time_out: Option<i64> = None;
477 let mut allow_while_on_body = false;
Hasini Gunasinghea020b532021-01-07 21:42:35 +0000478 let mut unlocked_device_required = false;
Qi Wub9433b52020-12-01 14:52:46 +0800479 let mut key_usage_limited: Option<i64> = None;
Janis Danisevskisb1673db2021-02-08 18:11:57 -0800480 let mut confirmation_token_receiver: Option<Arc<Mutex<Option<Receiver<Vec<u8>>>>>> = None;
Paul Crowley7c57bf12021-02-02 16:26:57 -0800481 let mut max_boot_level: Option<i32> = None;
Hasini Gunasinghe5112c702020-11-09 22:13:25 +0000482
483 // iterate through key parameters, recording information we need for authorization
484 // enforcements later, or enforcing authorizations in place, where applicable
485 for key_param in key_params.iter() {
486 match key_param.key_parameter_value() {
487 KeyParameterValue::NoAuthRequired => {
488 no_auth_required = true;
489 }
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +0000490 KeyParameterValue::AuthTimeout(t) => {
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +0000491 key_time_out = Some(*t as i64);
Hasini Gunasinghe5112c702020-11-09 22:13:25 +0000492 }
493 KeyParameterValue::HardwareAuthenticatorType(a) => {
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +0000494 user_auth_type = Some(*a);
Hasini Gunasinghe5112c702020-11-09 22:13:25 +0000495 }
496 KeyParameterValue::KeyPurpose(p) => {
Janis Danisevskis104d8e42021-01-14 22:49:27 -0800497 // The following check has the effect of key_params.contains(purpose)
Hasini Gunasinghe5112c702020-11-09 22:13:25 +0000498 // Also, authorizing purpose can not be completed here, if there can be multiple
Janis Danisevskis104d8e42021-01-14 22:49:27 -0800499 // key parameters for KeyPurpose.
500 key_purpose_authorized = key_purpose_authorized || *p == purpose;
Hasini Gunasinghe5112c702020-11-09 22:13:25 +0000501 }
502 KeyParameterValue::CallerNonce => {
503 caller_nonce_allowed = true;
504 }
505 KeyParameterValue::ActiveDateTime(a) => {
506 if !Enforcements::is_given_time_passed(*a, true) {
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800507 return Err(Error::Km(Ec::KEY_NOT_YET_VALID))
Hasini Gunasinghe5112c702020-11-09 22:13:25 +0000508 .context("In authorize_create: key is not yet active.");
509 }
510 }
511 KeyParameterValue::OriginationExpireDateTime(o) => {
512 if (purpose == KeyPurpose::ENCRYPT || purpose == KeyPurpose::SIGN)
513 && Enforcements::is_given_time_passed(*o, false)
514 {
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800515 return Err(Error::Km(Ec::KEY_EXPIRED))
Hasini Gunasinghe5112c702020-11-09 22:13:25 +0000516 .context("In authorize_create: key is expired.");
517 }
518 }
519 KeyParameterValue::UsageExpireDateTime(u) => {
520 if (purpose == KeyPurpose::DECRYPT || purpose == KeyPurpose::VERIFY)
521 && Enforcements::is_given_time_passed(*u, false)
522 {
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800523 return Err(Error::Km(Ec::KEY_EXPIRED))
Hasini Gunasinghe5112c702020-11-09 22:13:25 +0000524 .context("In authorize_create: key is expired.");
525 }
526 }
527 KeyParameterValue::UserSecureID(s) => {
528 user_secure_ids.push(*s);
529 }
530 KeyParameterValue::UserID(u) => {
531 user_id = *u;
532 }
533 KeyParameterValue::UnlockedDeviceRequired => {
Hasini Gunasinghea020b532021-01-07 21:42:35 +0000534 unlocked_device_required = true;
Hasini Gunasinghe5112c702020-11-09 22:13:25 +0000535 }
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +0000536 KeyParameterValue::AllowWhileOnBody => {
537 allow_while_on_body = true;
538 }
Qi Wub9433b52020-12-01 14:52:46 +0800539 KeyParameterValue::UsageCountLimit(_) => {
540 // We don't examine the limit here because this is enforced on finish.
541 // Instead, we store the key_id so that finish can look up the key
542 // in the database again and check and update the counter.
543 key_usage_limited = Some(key_id);
544 }
Janis Danisevskisb1673db2021-02-08 18:11:57 -0800545 KeyParameterValue::TrustedConfirmationRequired => {
546 confirmation_token_receiver = Some(self.confirmation_token_receiver.clone());
547 }
Paul Crowley7c57bf12021-02-02 16:26:57 -0800548 KeyParameterValue::MaxBootLevel(level) => {
549 max_boot_level = Some(*level);
550 }
Hasini Gunasinghe5112c702020-11-09 22:13:25 +0000551 // NOTE: as per offline discussion, sanitizing key parameters and rejecting
552 // create operation if any non-allowed tags are present, is not done in
553 // authorize_create (unlike in legacy keystore where AuthorizeBegin is rejected if
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800554 // a subset of non-allowed tags are present). Because sanitizing key parameters
Hasini Gunasinghe5112c702020-11-09 22:13:25 +0000555 // should have been done during generate/import key, by KeyMint.
556 _ => { /*Do nothing on all the other key parameters, as in legacy keystore*/ }
557 }
558 }
559
560 // authorize the purpose
561 if !key_purpose_authorized {
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800562 return Err(Error::Km(Ec::INCOMPATIBLE_PURPOSE))
Hasini Gunasinghe5112c702020-11-09 22:13:25 +0000563 .context("In authorize_create: the purpose is not authorized.");
564 }
565
566 // if both NO_AUTH_REQUIRED and USER_SECURE_ID tags are present, return error
567 if !user_secure_ids.is_empty() && no_auth_required {
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800568 return Err(Error::Km(Ec::INVALID_KEY_BLOB)).context(
Hasini Gunasinghe5112c702020-11-09 22:13:25 +0000569 "In authorize_create: key has both NO_AUTH_REQUIRED
570 and USER_SECURE_ID tags.",
571 );
572 }
573
574 // if either of auth_type or secure_id is present and the other is not present, return error
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +0000575 if (user_auth_type.is_some() && user_secure_ids.is_empty())
576 || (user_auth_type.is_none() && !user_secure_ids.is_empty())
Hasini Gunasinghe5112c702020-11-09 22:13:25 +0000577 {
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800578 return Err(Error::Km(Ec::KEY_USER_NOT_AUTHENTICATED)).context(
Hasini Gunasinghe5112c702020-11-09 22:13:25 +0000579 "In authorize_create: Auth required, but either auth type or secure ids
580 are not present.",
581 );
582 }
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800583
Hasini Gunasinghe5112c702020-11-09 22:13:25 +0000584 // validate caller nonce for origination purposes
585 if (purpose == KeyPurpose::ENCRYPT || purpose == KeyPurpose::SIGN)
586 && !caller_nonce_allowed
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800587 && op_params.iter().any(|kp| kp.tag == Tag::NONCE)
Hasini Gunasinghe5112c702020-11-09 22:13:25 +0000588 {
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800589 return Err(Error::Km(Ec::CALLER_NONCE_PROHIBITED)).context(
Hasini Gunasinghe5112c702020-11-09 22:13:25 +0000590 "In authorize_create, NONCE is present,
591 although CALLER_NONCE is not present",
592 );
593 }
594
Hasini Gunasinghea020b532021-01-07 21:42:35 +0000595 if unlocked_device_required {
596 // check the device locked status. If locked, operations on the key are not
597 // allowed.
Hasini Gunasinghea020b532021-01-07 21:42:35 +0000598 if self.is_device_locked(user_id) {
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800599 return Err(Error::Km(Ec::DEVICE_LOCKED))
Hasini Gunasinghea020b532021-01-07 21:42:35 +0000600 .context("In authorize_create: device is locked.");
601 }
602 }
603
Paul Crowley7c57bf12021-02-02 16:26:57 -0800604 if let Some(level) = max_boot_level {
Paul Crowley44c02da2021-04-08 17:04:43 +0000605 if !SUPER_KEY.level_accessible(level) {
Paul Crowley7c57bf12021-02-02 16:26:57 -0800606 return Err(Error::Km(Ec::BOOT_LEVEL_EXCEEDED))
607 .context("In authorize_create: boot level is too late.");
608 }
609 }
610
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800611 if !unlocked_device_required && no_auth_required {
Qi Wub9433b52020-12-01 14:52:46 +0800612 return Ok((
613 None,
Janis Danisevskisb1673db2021-02-08 18:11:57 -0800614 AuthInfo {
615 state: DeferredAuthState::NoAuthRequired,
616 key_usage_limited,
617 confirmation_token_receiver,
618 },
Qi Wub9433b52020-12-01 14:52:46 +0800619 ));
Hasini Gunasinghe5112c702020-11-09 22:13:25 +0000620 }
621
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800622 let has_sids = !user_secure_ids.is_empty();
623
624 let timeout_bound = key_time_out.is_some() && has_sids;
625
626 let per_op_bound = key_time_out.is_none() && has_sids;
627
628 let need_auth_token = timeout_bound || unlocked_device_required;
629
630 let hat_and_last_off_body = if need_auth_token {
631 let hat_and_last_off_body = Self::find_auth_token(|hat: &AuthTokenEntry| {
632 if let (Some(auth_type), true) = (user_auth_type, has_sids) {
633 hat.satisfies(&user_secure_ids, auth_type)
634 } else {
635 unlocked_device_required
636 }
Matthew Maurerd7815ca2021-05-06 21:58:45 -0700637 });
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800638 Some(
639 hat_and_last_off_body
640 .ok_or(Error::Km(Ec::KEY_USER_NOT_AUTHENTICATED))
641 .context("In authorize_create: No suitable auth token found.")?,
642 )
643 } else {
644 None
645 };
646
647 // Now check the validity of the auth token if the key is timeout bound.
648 let hat = match (hat_and_last_off_body, key_time_out) {
649 (Some((hat, last_off_body)), Some(key_time_out)) => {
650 let now = MonotonicRawTime::now();
651 let token_age = now
652 .checked_sub(&hat.time_received())
653 .ok_or_else(Error::sys)
654 .context(concat!(
655 "In authorize_create: Overflow while computing Auth token validity. ",
656 "Validity cannot be established."
657 ))?;
658
659 let on_body_extended = allow_while_on_body && last_off_body < hat.time_received();
660
661 if token_age.seconds() > key_time_out && !on_body_extended {
662 return Err(Error::Km(Ec::KEY_USER_NOT_AUTHENTICATED))
663 .context("In authorize_create: matching auth token is expired.");
664 }
665 Some(hat)
666 }
667 (Some((hat, _)), None) => Some(hat),
668 // If timeout_bound is true, above code must have retrieved a HAT or returned with
669 // KEY_USER_NOT_AUTHENTICATED. This arm should not be reachable.
670 (None, Some(_)) => panic!("Logical error."),
671 _ => None,
672 };
673
674 Ok(match (hat, requires_timestamp, per_op_bound) {
675 // Per-op-bound and Some(hat) can only happen if we are both per-op bound and unlocked
676 // device required. In addition, this KM instance needs a timestamp token.
677 // So the HAT cannot be presented on create. So on update/finish we present both
678 // an per-op-bound auth token and a timestamp token.
679 (Some(_), true, true) => (None, DeferredAuthState::TimeStampedOpAuthRequired),
Hasini Gunasinghee093b552021-04-30 20:05:31 +0000680 (Some(hat), true, false) => (
681 Some(hat.auth_token().clone()),
682 DeferredAuthState::TimeStampRequired(hat.take_auth_token()),
683 ),
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800684 (Some(hat), false, true) => {
685 (Some(hat.take_auth_token()), DeferredAuthState::OpAuthRequired)
686 }
687 (Some(hat), false, false) => {
688 (Some(hat.take_auth_token()), DeferredAuthState::NoAuthRequired)
689 }
690 (None, _, true) => (None, DeferredAuthState::OpAuthRequired),
691 (None, _, false) => (None, DeferredAuthState::NoAuthRequired),
692 })
Janis Danisevskisb1673db2021-02-08 18:11:57 -0800693 .map(|(hat, state)| {
694 (hat, AuthInfo { state, key_usage_limited, confirmation_token_receiver })
695 })
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800696 }
697
Matthew Maurerd7815ca2021-05-06 21:58:45 -0700698 fn find_auth_token<F>(p: F) -> Option<(AuthTokenEntry, MonotonicRawTime)>
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800699 where
700 F: Fn(&AuthTokenEntry) -> bool,
701 {
Matthew Maurerd7815ca2021-05-06 21:58:45 -0700702 DB.with(|db| db.borrow().find_auth_token_entry(p))
Hasini Gunasinghe5112c702020-11-09 22:13:25 +0000703 }
704
705 /// Checks if the time now since epoch is greater than (or equal, if is_given_time_inclusive is
706 /// set) the given time (in milliseconds)
707 fn is_given_time_passed(given_time: i64, is_given_time_inclusive: bool) -> bool {
708 let duration_since_epoch = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH);
709
710 let time_since_epoch = match duration_since_epoch {
711 Ok(duration) => duration.as_millis(),
712 Err(_) => return false,
713 };
714
715 if is_given_time_inclusive {
716 time_since_epoch >= (given_time as u128)
717 } else {
718 time_since_epoch > (given_time as u128)
719 }
720 }
721
722 /// Check if the device is locked for the given user. If there's no entry yet for the user,
723 /// we assume that the device is locked
724 fn is_device_locked(&self, user_id: i32) -> bool {
725 // unwrap here because there's no way this mutex guard can be poisoned and
726 // because there's no way to recover, even if it is poisoned.
727 let set = self.device_unlocked_set.lock().unwrap();
728 !set.contains(&user_id)
729 }
Hasini Gunasinghe557b1032020-11-10 01:35:30 +0000730
731 /// Sets the device locked status for the user. This method is called externally.
732 pub fn set_device_locked(&self, user_id: i32, device_locked_status: bool) {
733 // unwrap here because there's no way this mutex guard can be poisoned and
734 // because there's no way to recover, even if it is poisoned.
735 let mut set = self.device_unlocked_set.lock().unwrap();
736 if device_locked_status {
737 set.remove(&user_id);
738 } else {
739 set.insert(user_id);
740 }
741 }
742
743 /// Add this auth token to the database.
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800744 /// Then present the auth token to the op auth map. If an operation is waiting for this
745 /// auth token this fulfills the request and removes the receiver from the map.
Matthew Maurerd7815ca2021-05-06 21:58:45 -0700746 pub fn add_auth_token(&self, hat: HardwareAuthToken) {
747 DB.with(|db| db.borrow_mut().insert_auth_token(&hat));
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800748 self.op_auth_map.add_auth_token(hat);
Hasini Gunasinghe557b1032020-11-10 01:35:30 +0000749 }
Hasini Gunasinghe888dd352020-11-17 23:08:39 +0000750
751 /// This allows adding an entry to the op_auth_map, indexed by the operation challenge.
752 /// This is to be called by create_operation, once it has received the operation challenge
753 /// from keymint for an operation whose authorization decision is OpAuthRequired, as signalled
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800754 /// by the DeferredAuthState.
755 fn register_op_auth_receiver(&self, challenge: i64, recv: TokenReceiver) {
756 self.op_auth_map.add_receiver(challenge, recv);
Hasini Gunasinghef04d07a2020-11-25 22:41:35 +0000757 }
Hasini Gunasinghedeab85d2021-02-01 21:10:02 +0000758
759 /// Given the set of key parameters and flags, check if super encryption is required.
Paul Crowley7a658392021-03-18 17:08:20 -0700760 pub fn super_encryption_required(
761 domain: &Domain,
762 key_parameters: &[KeyParameter],
763 flags: Option<i32>,
764 ) -> SuperEncryptionType {
Paul Crowley7a658392021-03-18 17:08:20 -0700765 if let Some(flags) = flags {
766 if (flags & KEY_FLAG_AUTH_BOUND_WITHOUT_CRYPTOGRAPHIC_LSKF_BINDING) != 0 {
767 return SuperEncryptionType::None;
768 }
769 }
Paul Crowley44c02da2021-04-08 17:04:43 +0000770 // Each answer has a priority, numerically largest priority wins.
771 struct Candidate {
772 priority: u32,
773 enc_type: SuperEncryptionType,
Paul Crowley7a658392021-03-18 17:08:20 -0700774 }
Paul Crowley44c02da2021-04-08 17:04:43 +0000775 let mut result = Candidate { priority: 0, enc_type: SuperEncryptionType::None };
776 for kp in key_parameters {
777 let t = match kp.key_parameter_value() {
778 KeyParameterValue::MaxBootLevel(level) => {
779 Candidate { priority: 3, enc_type: SuperEncryptionType::BootLevel(*level) }
780 }
781 KeyParameterValue::UnlockedDeviceRequired if *domain == Domain::APP => {
782 Candidate { priority: 2, enc_type: SuperEncryptionType::ScreenLockBound }
783 }
784 KeyParameterValue::UserSecureID(_) if *domain == Domain::APP => {
785 Candidate { priority: 1, enc_type: SuperEncryptionType::LskfBound }
786 }
787 _ => Candidate { priority: 0, enc_type: SuperEncryptionType::None },
788 };
789 if t.priority > result.priority {
790 result = t;
791 }
Ulyana Trafimovich229f2c02021-04-06 16:07:07 +0000792 }
Paul Crowley44c02da2021-04-08 17:04:43 +0000793 result.enc_type
Hasini Gunasinghedeab85d2021-02-01 21:10:02 +0000794 }
Hasini Gunasinghe3410f792020-09-14 17:55:21 +0000795
Hasini Gunasingheb3715fb2021-02-26 20:34:45 +0000796 /// Finds a matching auth token along with a timestamp token.
797 /// This method looks through auth-tokens cached by keystore which satisfy the given
798 /// authentication information (i.e. |secureUserId|).
799 /// The most recent matching auth token which has a |challenge| field which matches
800 /// the passed-in |challenge| parameter is returned.
801 /// In this case the |authTokenMaxAgeMillis| parameter is not used.
802 ///
803 /// Otherwise, the most recent matching auth token which is younger than |authTokenMaxAgeMillis|
804 /// is returned.
805 pub fn get_auth_tokens(
806 &self,
807 challenge: i64,
808 secure_user_id: i64,
809 auth_token_max_age_millis: i64,
810 ) -> Result<(HardwareAuthToken, TimeStampToken)> {
811 let auth_type = HardwareAuthenticatorType::ANY;
812 let sids: Vec<i64> = vec![secure_user_id];
813 // Filter the matching auth tokens by challenge
814 let result = Self::find_auth_token(|hat: &AuthTokenEntry| {
815 (challenge == hat.challenge()) && hat.satisfies(&sids, auth_type)
Matthew Maurerd7815ca2021-05-06 21:58:45 -0700816 });
Hasini Gunasingheb3715fb2021-02-26 20:34:45 +0000817
818 let auth_token = if let Some((auth_token_entry, _)) = result {
819 auth_token_entry.take_auth_token()
820 } else {
821 // Filter the matching auth tokens by age.
822 if auth_token_max_age_millis != 0 {
Hasini Gunasinghe66a24602021-05-12 19:03:12 +0000823 let now_in_millis = MonotonicRawTime::now();
Hasini Gunasingheb3715fb2021-02-26 20:34:45 +0000824 let result = Self::find_auth_token(|auth_token_entry: &AuthTokenEntry| {
825 let token_valid = now_in_millis
Hasini Gunasinghe66a24602021-05-12 19:03:12 +0000826 .checked_sub(&auth_token_entry.time_received())
Hasini Gunasingheb3715fb2021-02-26 20:34:45 +0000827 .map_or(false, |token_age_in_millis| {
Hasini Gunasinghe66a24602021-05-12 19:03:12 +0000828 auth_token_max_age_millis > token_age_in_millis.milliseconds()
Hasini Gunasingheb3715fb2021-02-26 20:34:45 +0000829 });
830 token_valid && auth_token_entry.satisfies(&sids, auth_type)
Matthew Maurerd7815ca2021-05-06 21:58:45 -0700831 });
Hasini Gunasingheb3715fb2021-02-26 20:34:45 +0000832
833 if let Some((auth_token_entry, _)) = result {
834 auth_token_entry.take_auth_token()
835 } else {
836 return Err(AuthzError::Rc(AuthzResponseCode::NO_AUTH_TOKEN_FOUND))
837 .context("In get_auth_tokens: No auth token found.");
838 }
839 } else {
Hasini Gunasinghe1ce72932021-09-14 15:43:19 +0000840 return Err(AuthzError::Rc(AuthzResponseCode::NO_AUTH_TOKEN_FOUND)).context(
841 concat!(
842 "In get_auth_tokens: No auth token found for ",
843 "the given challenge and passed-in auth token max age is zero."
844 ),
845 );
Hasini Gunasingheb3715fb2021-02-26 20:34:45 +0000846 }
847 };
848 // Wait and obtain the timestamp token from secure clock service.
849 let tst = get_timestamp_token(challenge)
850 .context("In get_auth_tokens. Error in getting timestamp token.")?;
851 Ok((auth_token, tst))
852 }
Hasini Gunasinghe3410f792020-09-14 17:55:21 +0000853}
854
Hasini Gunasinghe52333ba2020-11-06 01:24:16 +0000855// TODO: Add tests to enforcement module (b/175578618).