1*e1997b9aSAndroid Build Coastguard Worker // Copyright 2020, The Android Open Source Project
2*e1997b9aSAndroid Build Coastguard Worker //
3*e1997b9aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*e1997b9aSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*e1997b9aSAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*e1997b9aSAndroid Build Coastguard Worker //
7*e1997b9aSAndroid Build Coastguard Worker // http://www.apache.org/licenses/LICENSE-2.0
8*e1997b9aSAndroid Build Coastguard Worker //
9*e1997b9aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*e1997b9aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*e1997b9aSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*e1997b9aSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*e1997b9aSAndroid Build Coastguard Worker // limitations under the License.
14*e1997b9aSAndroid Build Coastguard Worker
15*e1997b9aSAndroid Build Coastguard Worker //! This is the Keystore 2.0 Enforcements module.
16*e1997b9aSAndroid Build Coastguard Worker // TODO: more description to follow.
17*e1997b9aSAndroid Build Coastguard Worker use crate::ks_err;
18*e1997b9aSAndroid Build Coastguard Worker use crate::error::{map_binder_status, Error, ErrorCode};
19*e1997b9aSAndroid Build Coastguard Worker use crate::globals::{get_timestamp_service, ASYNC_TASK, DB, ENFORCEMENTS};
20*e1997b9aSAndroid Build Coastguard Worker use crate::key_parameter::{KeyParameter, KeyParameterValue};
21*e1997b9aSAndroid Build Coastguard Worker use crate::{authorization::Error as AuthzError, super_key::SuperEncryptionType};
22*e1997b9aSAndroid Build Coastguard Worker use crate::{
23*e1997b9aSAndroid Build Coastguard Worker database::{AuthTokenEntry, BootTime},
24*e1997b9aSAndroid Build Coastguard Worker globals::SUPER_KEY,
25*e1997b9aSAndroid Build Coastguard Worker };
26*e1997b9aSAndroid Build Coastguard Worker use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
27*e1997b9aSAndroid Build Coastguard Worker Algorithm::Algorithm, ErrorCode::ErrorCode as Ec, HardwareAuthToken::HardwareAuthToken,
28*e1997b9aSAndroid Build Coastguard Worker HardwareAuthenticatorType::HardwareAuthenticatorType,
29*e1997b9aSAndroid Build Coastguard Worker KeyParameter::KeyParameter as KmKeyParameter, KeyPurpose::KeyPurpose, Tag::Tag,
30*e1997b9aSAndroid Build Coastguard Worker };
31*e1997b9aSAndroid Build Coastguard Worker use android_hardware_security_secureclock::aidl::android::hardware::security::secureclock::{
32*e1997b9aSAndroid Build Coastguard Worker TimeStampToken::TimeStampToken,
33*e1997b9aSAndroid Build Coastguard Worker };
34*e1997b9aSAndroid Build Coastguard Worker use android_security_authorization::aidl::android::security::authorization::ResponseCode::ResponseCode as AuthzResponseCode;
35*e1997b9aSAndroid Build Coastguard Worker use android_system_keystore2::aidl::android::system::keystore2::{
36*e1997b9aSAndroid Build Coastguard Worker Domain::Domain, IKeystoreSecurityLevel::KEY_FLAG_AUTH_BOUND_WITHOUT_CRYPTOGRAPHIC_LSKF_BINDING,
37*e1997b9aSAndroid Build Coastguard Worker OperationChallenge::OperationChallenge,
38*e1997b9aSAndroid Build Coastguard Worker };
39*e1997b9aSAndroid Build Coastguard Worker use anyhow::{Context, Result};
40*e1997b9aSAndroid Build Coastguard Worker use std::{
41*e1997b9aSAndroid Build Coastguard Worker collections::{HashMap, HashSet},
42*e1997b9aSAndroid Build Coastguard Worker sync::{
43*e1997b9aSAndroid Build Coastguard Worker mpsc::{channel, Receiver, Sender, TryRecvError},
44*e1997b9aSAndroid Build Coastguard Worker Arc, Mutex, Weak,
45*e1997b9aSAndroid Build Coastguard Worker },
46*e1997b9aSAndroid Build Coastguard Worker time::SystemTime,
47*e1997b9aSAndroid Build Coastguard Worker };
48*e1997b9aSAndroid Build Coastguard Worker
49*e1997b9aSAndroid Build Coastguard Worker #[derive(Debug)]
50*e1997b9aSAndroid Build Coastguard Worker enum AuthRequestState {
51*e1997b9aSAndroid Build Coastguard Worker /// An outstanding per operation authorization request.
52*e1997b9aSAndroid Build Coastguard Worker OpAuth,
53*e1997b9aSAndroid Build Coastguard Worker /// An outstanding request for a timestamp token.
54*e1997b9aSAndroid Build Coastguard Worker TimeStamp(Mutex<Receiver<Result<TimeStampToken, Error>>>),
55*e1997b9aSAndroid Build Coastguard Worker }
56*e1997b9aSAndroid Build Coastguard Worker
57*e1997b9aSAndroid Build Coastguard Worker #[derive(Debug)]
58*e1997b9aSAndroid Build Coastguard Worker struct AuthRequest {
59*e1997b9aSAndroid Build Coastguard Worker state: AuthRequestState,
60*e1997b9aSAndroid Build Coastguard Worker /// This need to be set to Some to fulfill an AuthRequestState::OpAuth.
61*e1997b9aSAndroid Build Coastguard Worker hat: Mutex<Option<HardwareAuthToken>>,
62*e1997b9aSAndroid Build Coastguard Worker }
63*e1997b9aSAndroid Build Coastguard Worker
64*e1997b9aSAndroid Build Coastguard Worker impl AuthRequest {
op_auth() -> Arc<Self>65*e1997b9aSAndroid Build Coastguard Worker fn op_auth() -> Arc<Self> {
66*e1997b9aSAndroid Build Coastguard Worker Arc::new(Self { state: AuthRequestState::OpAuth, hat: Mutex::new(None) })
67*e1997b9aSAndroid Build Coastguard Worker }
68*e1997b9aSAndroid Build Coastguard Worker
timestamp( hat: HardwareAuthToken, receiver: Receiver<Result<TimeStampToken, Error>>, ) -> Arc<Self>69*e1997b9aSAndroid Build Coastguard Worker fn timestamp(
70*e1997b9aSAndroid Build Coastguard Worker hat: HardwareAuthToken,
71*e1997b9aSAndroid Build Coastguard Worker receiver: Receiver<Result<TimeStampToken, Error>>,
72*e1997b9aSAndroid Build Coastguard Worker ) -> Arc<Self> {
73*e1997b9aSAndroid Build Coastguard Worker Arc::new(Self {
74*e1997b9aSAndroid Build Coastguard Worker state: AuthRequestState::TimeStamp(Mutex::new(receiver)),
75*e1997b9aSAndroid Build Coastguard Worker hat: Mutex::new(Some(hat)),
76*e1997b9aSAndroid Build Coastguard Worker })
77*e1997b9aSAndroid Build Coastguard Worker }
78*e1997b9aSAndroid Build Coastguard Worker
add_auth_token(&self, hat: HardwareAuthToken)79*e1997b9aSAndroid Build Coastguard Worker fn add_auth_token(&self, hat: HardwareAuthToken) {
80*e1997b9aSAndroid Build Coastguard Worker *self.hat.lock().unwrap() = Some(hat)
81*e1997b9aSAndroid Build Coastguard Worker }
82*e1997b9aSAndroid Build Coastguard Worker
get_auth_tokens(&self) -> Result<(HardwareAuthToken, Option<TimeStampToken>)>83*e1997b9aSAndroid Build Coastguard Worker fn get_auth_tokens(&self) -> Result<(HardwareAuthToken, Option<TimeStampToken>)> {
84*e1997b9aSAndroid Build Coastguard Worker let hat = self
85*e1997b9aSAndroid Build Coastguard Worker .hat
86*e1997b9aSAndroid Build Coastguard Worker .lock()
87*e1997b9aSAndroid Build Coastguard Worker .unwrap()
88*e1997b9aSAndroid Build Coastguard Worker .take()
89*e1997b9aSAndroid Build Coastguard Worker .ok_or(Error::Km(ErrorCode::KEY_USER_NOT_AUTHENTICATED))
90*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("No operation auth token received."))?;
91*e1997b9aSAndroid Build Coastguard Worker
92*e1997b9aSAndroid Build Coastguard Worker let tst = match &self.state {
93*e1997b9aSAndroid Build Coastguard Worker AuthRequestState::TimeStamp(recv) => {
94*e1997b9aSAndroid Build Coastguard Worker let result = recv
95*e1997b9aSAndroid Build Coastguard Worker .lock()
96*e1997b9aSAndroid Build Coastguard Worker .unwrap()
97*e1997b9aSAndroid Build Coastguard Worker .recv()
98*e1997b9aSAndroid Build Coastguard Worker .context("In get_auth_tokens: Sender disconnected.")?;
99*e1997b9aSAndroid Build Coastguard Worker Some(result.context(ks_err!(
100*e1997b9aSAndroid Build Coastguard Worker "Worker responded with error \
101*e1997b9aSAndroid Build Coastguard Worker from generating timestamp token.",
102*e1997b9aSAndroid Build Coastguard Worker ))?)
103*e1997b9aSAndroid Build Coastguard Worker }
104*e1997b9aSAndroid Build Coastguard Worker AuthRequestState::OpAuth => None,
105*e1997b9aSAndroid Build Coastguard Worker };
106*e1997b9aSAndroid Build Coastguard Worker Ok((hat, tst))
107*e1997b9aSAndroid Build Coastguard Worker }
108*e1997b9aSAndroid Build Coastguard Worker }
109*e1997b9aSAndroid Build Coastguard Worker
110*e1997b9aSAndroid Build Coastguard Worker /// DeferredAuthState describes how auth tokens and timestamp tokens need to be provided when
111*e1997b9aSAndroid Build Coastguard Worker /// updating and finishing an operation.
112*e1997b9aSAndroid Build Coastguard Worker #[derive(Debug)]
113*e1997b9aSAndroid Build Coastguard Worker enum DeferredAuthState {
114*e1997b9aSAndroid Build Coastguard Worker /// Used when an operation does not require further authorization.
115*e1997b9aSAndroid Build Coastguard Worker NoAuthRequired,
116*e1997b9aSAndroid Build Coastguard Worker /// Indicates that the operation requires an operation specific token. This means we have
117*e1997b9aSAndroid Build Coastguard Worker /// to return an operation challenge to the client which should reward us with an
118*e1997b9aSAndroid Build Coastguard Worker /// operation specific auth token. If it is not provided before the client calls update
119*e1997b9aSAndroid Build Coastguard Worker /// or finish, the operation fails as not authorized.
120*e1997b9aSAndroid Build Coastguard Worker OpAuthRequired,
121*e1997b9aSAndroid Build Coastguard Worker /// Indicates that the operation requires a time stamp token. The auth token was already
122*e1997b9aSAndroid Build Coastguard Worker /// loaded from the database, but it has to be accompanied by a time stamp token to inform
123*e1997b9aSAndroid Build Coastguard Worker /// the target KM with a different clock about the time on the authenticators.
124*e1997b9aSAndroid Build Coastguard Worker TimeStampRequired(HardwareAuthToken),
125*e1997b9aSAndroid Build Coastguard Worker /// In this state the auth info is waiting for the deferred authorizations to come in.
126*e1997b9aSAndroid Build Coastguard Worker /// We block on timestamp tokens, because we can always make progress on these requests.
127*e1997b9aSAndroid Build Coastguard Worker /// The per-op auth tokens might never come, which means we fail if the client calls
128*e1997b9aSAndroid Build Coastguard Worker /// update or finish before we got a per-op auth token.
129*e1997b9aSAndroid Build Coastguard Worker Waiting(Arc<AuthRequest>),
130*e1997b9aSAndroid Build Coastguard Worker /// In this state we have gotten all of the required tokens, we just cache them to
131*e1997b9aSAndroid Build Coastguard Worker /// be used when the operation progresses.
132*e1997b9aSAndroid Build Coastguard Worker Token(HardwareAuthToken, Option<TimeStampToken>),
133*e1997b9aSAndroid Build Coastguard Worker }
134*e1997b9aSAndroid Build Coastguard Worker
135*e1997b9aSAndroid Build Coastguard Worker /// Auth info hold all of the authorization related information of an operation. It is stored
136*e1997b9aSAndroid Build Coastguard Worker /// in and owned by the operation. It is constructed by authorize_create and stays with the
137*e1997b9aSAndroid Build Coastguard Worker /// operation until it completes.
138*e1997b9aSAndroid Build Coastguard Worker #[derive(Debug)]
139*e1997b9aSAndroid Build Coastguard Worker pub struct AuthInfo {
140*e1997b9aSAndroid Build Coastguard Worker state: DeferredAuthState,
141*e1997b9aSAndroid Build Coastguard Worker /// An optional key id required to update the usage count if the key usage is limited.
142*e1997b9aSAndroid Build Coastguard Worker key_usage_limited: Option<i64>,
143*e1997b9aSAndroid Build Coastguard Worker confirmation_token_receiver: Option<Arc<Mutex<Option<Receiver<Vec<u8>>>>>>,
144*e1997b9aSAndroid Build Coastguard Worker }
145*e1997b9aSAndroid Build Coastguard Worker
146*e1997b9aSAndroid Build Coastguard Worker struct TokenReceiverMap {
147*e1997b9aSAndroid Build Coastguard Worker /// The map maps an outstanding challenge to a TokenReceiver. If an incoming Hardware Auth
148*e1997b9aSAndroid Build Coastguard Worker /// Token (HAT) has the map key in its challenge field, it gets passed to the TokenReceiver
149*e1997b9aSAndroid Build Coastguard Worker /// and the entry is removed from the map. In the case where no HAT is received before the
150*e1997b9aSAndroid Build Coastguard Worker /// corresponding operation gets dropped, the entry goes stale. So every time the cleanup
151*e1997b9aSAndroid Build Coastguard Worker /// counter (second field in the tuple) turns 0, the map is cleaned from stale entries.
152*e1997b9aSAndroid Build Coastguard Worker /// The cleanup counter is decremented every time a new receiver is added.
153*e1997b9aSAndroid Build Coastguard Worker /// and reset to TokenReceiverMap::CLEANUP_PERIOD + 1 after each cleanup.
154*e1997b9aSAndroid Build Coastguard Worker map_and_cleanup_counter: Mutex<(HashMap<i64, TokenReceiver>, u8)>,
155*e1997b9aSAndroid Build Coastguard Worker }
156*e1997b9aSAndroid Build Coastguard Worker
157*e1997b9aSAndroid Build Coastguard Worker impl Default for TokenReceiverMap {
default() -> Self158*e1997b9aSAndroid Build Coastguard Worker fn default() -> Self {
159*e1997b9aSAndroid Build Coastguard Worker Self { map_and_cleanup_counter: Mutex::new((HashMap::new(), Self::CLEANUP_PERIOD + 1)) }
160*e1997b9aSAndroid Build Coastguard Worker }
161*e1997b9aSAndroid Build Coastguard Worker }
162*e1997b9aSAndroid Build Coastguard Worker
163*e1997b9aSAndroid Build Coastguard Worker impl TokenReceiverMap {
164*e1997b9aSAndroid Build Coastguard Worker /// There is a chance that receivers may become stale because their operation is dropped
165*e1997b9aSAndroid Build Coastguard Worker /// without ever being authorized. So occasionally we iterate through the map and throw
166*e1997b9aSAndroid Build Coastguard Worker /// out obsolete entries.
167*e1997b9aSAndroid Build Coastguard Worker /// This is the number of calls to add_receiver between cleanups.
168*e1997b9aSAndroid Build Coastguard Worker const CLEANUP_PERIOD: u8 = 25;
169*e1997b9aSAndroid Build Coastguard Worker
add_auth_token(&self, hat: HardwareAuthToken)170*e1997b9aSAndroid Build Coastguard Worker pub fn add_auth_token(&self, hat: HardwareAuthToken) {
171*e1997b9aSAndroid Build Coastguard Worker let recv = {
172*e1997b9aSAndroid Build Coastguard Worker // Limit the scope of the mutex guard, so that it is not held while the auth token is
173*e1997b9aSAndroid Build Coastguard Worker // added.
174*e1997b9aSAndroid Build Coastguard Worker let mut map = self.map_and_cleanup_counter.lock().unwrap();
175*e1997b9aSAndroid Build Coastguard Worker let (ref mut map, _) = *map;
176*e1997b9aSAndroid Build Coastguard Worker map.remove_entry(&hat.challenge)
177*e1997b9aSAndroid Build Coastguard Worker };
178*e1997b9aSAndroid Build Coastguard Worker
179*e1997b9aSAndroid Build Coastguard Worker if let Some((_, recv)) = recv {
180*e1997b9aSAndroid Build Coastguard Worker recv.add_auth_token(hat);
181*e1997b9aSAndroid Build Coastguard Worker }
182*e1997b9aSAndroid Build Coastguard Worker }
183*e1997b9aSAndroid Build Coastguard Worker
add_receiver(&self, challenge: i64, recv: TokenReceiver)184*e1997b9aSAndroid Build Coastguard Worker pub fn add_receiver(&self, challenge: i64, recv: TokenReceiver) {
185*e1997b9aSAndroid Build Coastguard Worker let mut map = self.map_and_cleanup_counter.lock().unwrap();
186*e1997b9aSAndroid Build Coastguard Worker let (ref mut map, ref mut cleanup_counter) = *map;
187*e1997b9aSAndroid Build Coastguard Worker map.insert(challenge, recv);
188*e1997b9aSAndroid Build Coastguard Worker
189*e1997b9aSAndroid Build Coastguard Worker *cleanup_counter -= 1;
190*e1997b9aSAndroid Build Coastguard Worker if *cleanup_counter == 0 {
191*e1997b9aSAndroid Build Coastguard Worker map.retain(|_, v| !v.is_obsolete());
192*e1997b9aSAndroid Build Coastguard Worker map.shrink_to_fit();
193*e1997b9aSAndroid Build Coastguard Worker *cleanup_counter = Self::CLEANUP_PERIOD + 1;
194*e1997b9aSAndroid Build Coastguard Worker }
195*e1997b9aSAndroid Build Coastguard Worker }
196*e1997b9aSAndroid Build Coastguard Worker }
197*e1997b9aSAndroid Build Coastguard Worker
198*e1997b9aSAndroid Build Coastguard Worker #[derive(Debug)]
199*e1997b9aSAndroid Build Coastguard Worker struct TokenReceiver(Weak<AuthRequest>);
200*e1997b9aSAndroid Build Coastguard Worker
201*e1997b9aSAndroid Build Coastguard Worker impl TokenReceiver {
is_obsolete(&self) -> bool202*e1997b9aSAndroid Build Coastguard Worker fn is_obsolete(&self) -> bool {
203*e1997b9aSAndroid Build Coastguard Worker self.0.upgrade().is_none()
204*e1997b9aSAndroid Build Coastguard Worker }
205*e1997b9aSAndroid Build Coastguard Worker
add_auth_token(&self, hat: HardwareAuthToken)206*e1997b9aSAndroid Build Coastguard Worker fn add_auth_token(&self, hat: HardwareAuthToken) {
207*e1997b9aSAndroid Build Coastguard Worker if let Some(state_arc) = self.0.upgrade() {
208*e1997b9aSAndroid Build Coastguard Worker state_arc.add_auth_token(hat);
209*e1997b9aSAndroid Build Coastguard Worker }
210*e1997b9aSAndroid Build Coastguard Worker }
211*e1997b9aSAndroid Build Coastguard Worker }
212*e1997b9aSAndroid Build Coastguard Worker
get_timestamp_token(challenge: i64) -> Result<TimeStampToken, Error>213*e1997b9aSAndroid Build Coastguard Worker fn get_timestamp_token(challenge: i64) -> Result<TimeStampToken, Error> {
214*e1997b9aSAndroid Build Coastguard Worker let dev = get_timestamp_service().expect(concat!(
215*e1997b9aSAndroid Build Coastguard Worker "Secure Clock service must be present ",
216*e1997b9aSAndroid Build Coastguard Worker "if TimeStampTokens are required."
217*e1997b9aSAndroid Build Coastguard Worker ));
218*e1997b9aSAndroid Build Coastguard Worker map_binder_status(dev.generateTimeStamp(challenge))
219*e1997b9aSAndroid Build Coastguard Worker }
220*e1997b9aSAndroid Build Coastguard Worker
timestamp_token_request(challenge: i64, sender: Sender<Result<TimeStampToken, Error>>)221*e1997b9aSAndroid Build Coastguard Worker fn timestamp_token_request(challenge: i64, sender: Sender<Result<TimeStampToken, Error>>) {
222*e1997b9aSAndroid Build Coastguard Worker if let Err(e) = sender.send(get_timestamp_token(challenge)) {
223*e1997b9aSAndroid Build Coastguard Worker log::info!(
224*e1997b9aSAndroid Build Coastguard Worker concat!("Receiver hung up ", "before timestamp token could be delivered. {:?}"),
225*e1997b9aSAndroid Build Coastguard Worker e
226*e1997b9aSAndroid Build Coastguard Worker );
227*e1997b9aSAndroid Build Coastguard Worker }
228*e1997b9aSAndroid Build Coastguard Worker }
229*e1997b9aSAndroid Build Coastguard Worker
230*e1997b9aSAndroid Build Coastguard Worker impl AuthInfo {
231*e1997b9aSAndroid Build Coastguard Worker /// This function gets called after an operation was successfully created.
232*e1997b9aSAndroid Build Coastguard Worker /// It makes all the preparations required, so that the operation has all the authentication
233*e1997b9aSAndroid Build Coastguard Worker /// related artifacts to advance on update and finish.
finalize_create_authorization(&mut self, challenge: i64) -> Option<OperationChallenge>234*e1997b9aSAndroid Build Coastguard Worker pub fn finalize_create_authorization(&mut self, challenge: i64) -> Option<OperationChallenge> {
235*e1997b9aSAndroid Build Coastguard Worker match &self.state {
236*e1997b9aSAndroid Build Coastguard Worker DeferredAuthState::OpAuthRequired => {
237*e1997b9aSAndroid Build Coastguard Worker let auth_request = AuthRequest::op_auth();
238*e1997b9aSAndroid Build Coastguard Worker let token_receiver = TokenReceiver(Arc::downgrade(&auth_request));
239*e1997b9aSAndroid Build Coastguard Worker ENFORCEMENTS.register_op_auth_receiver(challenge, token_receiver);
240*e1997b9aSAndroid Build Coastguard Worker
241*e1997b9aSAndroid Build Coastguard Worker self.state = DeferredAuthState::Waiting(auth_request);
242*e1997b9aSAndroid Build Coastguard Worker Some(OperationChallenge { challenge })
243*e1997b9aSAndroid Build Coastguard Worker }
244*e1997b9aSAndroid Build Coastguard Worker DeferredAuthState::TimeStampRequired(hat) => {
245*e1997b9aSAndroid Build Coastguard Worker let hat = (*hat).clone();
246*e1997b9aSAndroid Build Coastguard Worker let (sender, receiver) = channel::<Result<TimeStampToken, Error>>();
247*e1997b9aSAndroid Build Coastguard Worker let auth_request = AuthRequest::timestamp(hat, receiver);
248*e1997b9aSAndroid Build Coastguard Worker ASYNC_TASK.queue_hi(move |_| timestamp_token_request(challenge, sender));
249*e1997b9aSAndroid Build Coastguard Worker self.state = DeferredAuthState::Waiting(auth_request);
250*e1997b9aSAndroid Build Coastguard Worker None
251*e1997b9aSAndroid Build Coastguard Worker }
252*e1997b9aSAndroid Build Coastguard Worker _ => None,
253*e1997b9aSAndroid Build Coastguard Worker }
254*e1997b9aSAndroid Build Coastguard Worker }
255*e1997b9aSAndroid Build Coastguard Worker
256*e1997b9aSAndroid Build Coastguard Worker /// This function is the authorization hook called before operation update.
257*e1997b9aSAndroid Build Coastguard Worker /// It returns the auth tokens required by the operation to commence update.
before_update(&mut self) -> Result<(Option<HardwareAuthToken>, Option<TimeStampToken>)>258*e1997b9aSAndroid Build Coastguard Worker pub fn before_update(&mut self) -> Result<(Option<HardwareAuthToken>, Option<TimeStampToken>)> {
259*e1997b9aSAndroid Build Coastguard Worker self.get_auth_tokens()
260*e1997b9aSAndroid Build Coastguard Worker }
261*e1997b9aSAndroid Build Coastguard Worker
262*e1997b9aSAndroid Build Coastguard Worker /// This function is the authorization hook called before operation finish.
263*e1997b9aSAndroid Build Coastguard Worker /// It returns the auth tokens required by the operation to commence finish.
264*e1997b9aSAndroid Build Coastguard Worker /// The third token is a confirmation token.
before_finish( &mut self, ) -> Result<(Option<HardwareAuthToken>, Option<TimeStampToken>, Option<Vec<u8>>)>265*e1997b9aSAndroid Build Coastguard Worker pub fn before_finish(
266*e1997b9aSAndroid Build Coastguard Worker &mut self,
267*e1997b9aSAndroid Build Coastguard Worker ) -> Result<(Option<HardwareAuthToken>, Option<TimeStampToken>, Option<Vec<u8>>)> {
268*e1997b9aSAndroid Build Coastguard Worker let mut confirmation_token: Option<Vec<u8>> = None;
269*e1997b9aSAndroid Build Coastguard Worker if let Some(ref confirmation_token_receiver) = self.confirmation_token_receiver {
270*e1997b9aSAndroid Build Coastguard Worker let locked_receiver = confirmation_token_receiver.lock().unwrap();
271*e1997b9aSAndroid Build Coastguard Worker if let Some(ref receiver) = *locked_receiver {
272*e1997b9aSAndroid Build Coastguard Worker loop {
273*e1997b9aSAndroid Build Coastguard Worker match receiver.try_recv() {
274*e1997b9aSAndroid Build Coastguard Worker // As long as we get tokens we loop and discard all but the most
275*e1997b9aSAndroid Build Coastguard Worker // recent one.
276*e1997b9aSAndroid Build Coastguard Worker Ok(t) => confirmation_token = Some(t),
277*e1997b9aSAndroid Build Coastguard Worker Err(TryRecvError::Empty) => break,
278*e1997b9aSAndroid Build Coastguard Worker Err(TryRecvError::Disconnected) => {
279*e1997b9aSAndroid Build Coastguard Worker log::error!(concat!(
280*e1997b9aSAndroid Build Coastguard Worker "We got disconnected from the APC service, ",
281*e1997b9aSAndroid Build Coastguard Worker "this should never happen."
282*e1997b9aSAndroid Build Coastguard Worker ));
283*e1997b9aSAndroid Build Coastguard Worker break;
284*e1997b9aSAndroid Build Coastguard Worker }
285*e1997b9aSAndroid Build Coastguard Worker }
286*e1997b9aSAndroid Build Coastguard Worker }
287*e1997b9aSAndroid Build Coastguard Worker }
288*e1997b9aSAndroid Build Coastguard Worker }
289*e1997b9aSAndroid Build Coastguard Worker self.get_auth_tokens().map(|(hat, tst)| (hat, tst, confirmation_token))
290*e1997b9aSAndroid Build Coastguard Worker }
291*e1997b9aSAndroid Build Coastguard Worker
292*e1997b9aSAndroid Build Coastguard Worker /// This function is the authorization hook called after finish succeeded.
293*e1997b9aSAndroid Build Coastguard Worker /// As of this writing it checks if the key was a limited use key. If so it updates the
294*e1997b9aSAndroid Build Coastguard Worker /// use counter of the key in the database. When the use counter is depleted, the key gets
295*e1997b9aSAndroid Build Coastguard Worker /// marked for deletion and the garbage collector is notified.
after_finish(&self) -> Result<()>296*e1997b9aSAndroid Build Coastguard Worker pub fn after_finish(&self) -> Result<()> {
297*e1997b9aSAndroid Build Coastguard Worker if let Some(key_id) = self.key_usage_limited {
298*e1997b9aSAndroid Build Coastguard Worker // On the last successful use, the key gets deleted. In this case we
299*e1997b9aSAndroid Build Coastguard Worker // have to notify the garbage collector.
300*e1997b9aSAndroid Build Coastguard Worker DB.with(|db| {
301*e1997b9aSAndroid Build Coastguard Worker db.borrow_mut()
302*e1997b9aSAndroid Build Coastguard Worker .check_and_update_key_usage_count(key_id)
303*e1997b9aSAndroid Build Coastguard Worker .context("Trying to update key usage count.")
304*e1997b9aSAndroid Build Coastguard Worker })
305*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!())?;
306*e1997b9aSAndroid Build Coastguard Worker }
307*e1997b9aSAndroid Build Coastguard Worker Ok(())
308*e1997b9aSAndroid Build Coastguard Worker }
309*e1997b9aSAndroid Build Coastguard Worker
310*e1997b9aSAndroid Build Coastguard Worker /// This function returns the auth tokens as needed by the ongoing operation or fails
311*e1997b9aSAndroid Build Coastguard Worker /// with ErrorCode::KEY_USER_NOT_AUTHENTICATED. If this was called for the first time
312*e1997b9aSAndroid Build Coastguard Worker /// after a deferred authorization was requested by finalize_create_authorization, this
313*e1997b9aSAndroid Build Coastguard Worker /// function may block on the generation of a time stamp token. It then moves the
314*e1997b9aSAndroid Build Coastguard Worker /// tokens into the DeferredAuthState::Token state for future use.
get_auth_tokens(&mut self) -> Result<(Option<HardwareAuthToken>, Option<TimeStampToken>)>315*e1997b9aSAndroid Build Coastguard Worker fn get_auth_tokens(&mut self) -> Result<(Option<HardwareAuthToken>, Option<TimeStampToken>)> {
316*e1997b9aSAndroid Build Coastguard Worker let deferred_tokens = if let DeferredAuthState::Waiting(ref auth_request) = self.state {
317*e1997b9aSAndroid Build Coastguard Worker Some(auth_request.get_auth_tokens().context("In AuthInfo::get_auth_tokens.")?)
318*e1997b9aSAndroid Build Coastguard Worker } else {
319*e1997b9aSAndroid Build Coastguard Worker None
320*e1997b9aSAndroid Build Coastguard Worker };
321*e1997b9aSAndroid Build Coastguard Worker
322*e1997b9aSAndroid Build Coastguard Worker if let Some((hat, tst)) = deferred_tokens {
323*e1997b9aSAndroid Build Coastguard Worker self.state = DeferredAuthState::Token(hat, tst);
324*e1997b9aSAndroid Build Coastguard Worker }
325*e1997b9aSAndroid Build Coastguard Worker
326*e1997b9aSAndroid Build Coastguard Worker match &self.state {
327*e1997b9aSAndroid Build Coastguard Worker DeferredAuthState::NoAuthRequired => Ok((None, None)),
328*e1997b9aSAndroid Build Coastguard Worker DeferredAuthState::Token(hat, tst) => Ok((Some((*hat).clone()), (*tst).clone())),
329*e1997b9aSAndroid Build Coastguard Worker DeferredAuthState::OpAuthRequired | DeferredAuthState::TimeStampRequired(_) => {
330*e1997b9aSAndroid Build Coastguard Worker Err(Error::Km(ErrorCode::KEY_USER_NOT_AUTHENTICATED)).context(ks_err!(
331*e1997b9aSAndroid Build Coastguard Worker "No operation auth token requested??? \
332*e1997b9aSAndroid Build Coastguard Worker This should not happen."
333*e1997b9aSAndroid Build Coastguard Worker ))
334*e1997b9aSAndroid Build Coastguard Worker }
335*e1997b9aSAndroid Build Coastguard Worker // This should not be reachable, because it should have been handled above.
336*e1997b9aSAndroid Build Coastguard Worker DeferredAuthState::Waiting(_) => {
337*e1997b9aSAndroid Build Coastguard Worker Err(Error::sys()).context(ks_err!("AuthInfo::get_auth_tokens: Cannot be reached.",))
338*e1997b9aSAndroid Build Coastguard Worker }
339*e1997b9aSAndroid Build Coastguard Worker }
340*e1997b9aSAndroid Build Coastguard Worker }
341*e1997b9aSAndroid Build Coastguard Worker }
342*e1997b9aSAndroid Build Coastguard Worker
343*e1997b9aSAndroid Build Coastguard Worker /// Enforcements data structure
344*e1997b9aSAndroid Build Coastguard Worker #[derive(Default)]
345*e1997b9aSAndroid Build Coastguard Worker pub struct Enforcements {
346*e1997b9aSAndroid Build Coastguard Worker /// This hash set contains the user ids for whom the device is currently unlocked. If a user id
347*e1997b9aSAndroid Build Coastguard Worker /// is not in the set, it implies that the device is locked for the user.
348*e1997b9aSAndroid Build Coastguard Worker device_unlocked_set: Mutex<HashSet<i32>>,
349*e1997b9aSAndroid Build Coastguard Worker /// This field maps outstanding auth challenges to their operations. When an auth token
350*e1997b9aSAndroid Build Coastguard Worker /// with the right challenge is received it is passed to the map using
351*e1997b9aSAndroid Build Coastguard Worker /// TokenReceiverMap::add_auth_token() which removes the entry from the map. If an entry goes
352*e1997b9aSAndroid Build Coastguard Worker /// stale, because the operation gets dropped before an auth token is received, the map
353*e1997b9aSAndroid Build Coastguard Worker /// is cleaned up in regular intervals.
354*e1997b9aSAndroid Build Coastguard Worker op_auth_map: TokenReceiverMap,
355*e1997b9aSAndroid Build Coastguard Worker /// The enforcement module will try to get a confirmation token from this channel whenever
356*e1997b9aSAndroid Build Coastguard Worker /// an operation that requires confirmation finishes.
357*e1997b9aSAndroid Build Coastguard Worker confirmation_token_receiver: Arc<Mutex<Option<Receiver<Vec<u8>>>>>,
358*e1997b9aSAndroid Build Coastguard Worker }
359*e1997b9aSAndroid Build Coastguard Worker
360*e1997b9aSAndroid Build Coastguard Worker impl Enforcements {
361*e1997b9aSAndroid Build Coastguard Worker /// Install the confirmation token receiver. The enforcement module will try to get a
362*e1997b9aSAndroid Build Coastguard Worker /// confirmation token from this channel whenever an operation that requires confirmation
363*e1997b9aSAndroid Build Coastguard Worker /// finishes.
install_confirmation_token_receiver( &self, confirmation_token_receiver: Receiver<Vec<u8>>, )364*e1997b9aSAndroid Build Coastguard Worker pub fn install_confirmation_token_receiver(
365*e1997b9aSAndroid Build Coastguard Worker &self,
366*e1997b9aSAndroid Build Coastguard Worker confirmation_token_receiver: Receiver<Vec<u8>>,
367*e1997b9aSAndroid Build Coastguard Worker ) {
368*e1997b9aSAndroid Build Coastguard Worker *self.confirmation_token_receiver.lock().unwrap() = Some(confirmation_token_receiver);
369*e1997b9aSAndroid Build Coastguard Worker }
370*e1997b9aSAndroid Build Coastguard Worker
371*e1997b9aSAndroid Build Coastguard Worker /// Checks if a create call is authorized, given key parameters and operation parameters.
372*e1997b9aSAndroid Build Coastguard Worker /// It returns an optional immediate auth token which can be presented to begin, and an
373*e1997b9aSAndroid Build Coastguard Worker /// AuthInfo object which stays with the authorized operation and is used to obtain
374*e1997b9aSAndroid Build Coastguard Worker /// auth tokens and timestamp tokens as required by the operation.
375*e1997b9aSAndroid Build Coastguard Worker /// With regard to auth tokens, the following steps are taken:
376*e1997b9aSAndroid Build Coastguard Worker ///
377*e1997b9aSAndroid Build Coastguard Worker /// If no key parameters are given (typically when the client is self managed
378*e1997b9aSAndroid Build Coastguard Worker /// (see Domain.Blob)) nothing is enforced.
379*e1997b9aSAndroid Build Coastguard Worker /// If the key is time-bound, find a matching auth token from the database.
380*e1997b9aSAndroid Build Coastguard Worker /// If the above step is successful, and if requires_timestamp is given, the returned
381*e1997b9aSAndroid Build Coastguard Worker /// AuthInfo will provide a Timestamp token as appropriate.
authorize_create( &self, purpose: KeyPurpose, key_properties: Option<&(i64, Vec<KeyParameter>)>, op_params: &[KmKeyParameter], requires_timestamp: bool, ) -> Result<(Option<HardwareAuthToken>, AuthInfo)>382*e1997b9aSAndroid Build Coastguard Worker pub fn authorize_create(
383*e1997b9aSAndroid Build Coastguard Worker &self,
384*e1997b9aSAndroid Build Coastguard Worker purpose: KeyPurpose,
385*e1997b9aSAndroid Build Coastguard Worker key_properties: Option<&(i64, Vec<KeyParameter>)>,
386*e1997b9aSAndroid Build Coastguard Worker op_params: &[KmKeyParameter],
387*e1997b9aSAndroid Build Coastguard Worker requires_timestamp: bool,
388*e1997b9aSAndroid Build Coastguard Worker ) -> Result<(Option<HardwareAuthToken>, AuthInfo)> {
389*e1997b9aSAndroid Build Coastguard Worker let (key_id, key_params) = match key_properties {
390*e1997b9aSAndroid Build Coastguard Worker Some((key_id, key_params)) => (*key_id, key_params),
391*e1997b9aSAndroid Build Coastguard Worker None => {
392*e1997b9aSAndroid Build Coastguard Worker return Ok((
393*e1997b9aSAndroid Build Coastguard Worker None,
394*e1997b9aSAndroid Build Coastguard Worker AuthInfo {
395*e1997b9aSAndroid Build Coastguard Worker state: DeferredAuthState::NoAuthRequired,
396*e1997b9aSAndroid Build Coastguard Worker key_usage_limited: None,
397*e1997b9aSAndroid Build Coastguard Worker confirmation_token_receiver: None,
398*e1997b9aSAndroid Build Coastguard Worker },
399*e1997b9aSAndroid Build Coastguard Worker ));
400*e1997b9aSAndroid Build Coastguard Worker }
401*e1997b9aSAndroid Build Coastguard Worker };
402*e1997b9aSAndroid Build Coastguard Worker
403*e1997b9aSAndroid Build Coastguard Worker match purpose {
404*e1997b9aSAndroid Build Coastguard Worker // Allow SIGN, DECRYPT for both symmetric and asymmetric keys.
405*e1997b9aSAndroid Build Coastguard Worker KeyPurpose::SIGN | KeyPurpose::DECRYPT => {}
406*e1997b9aSAndroid Build Coastguard Worker // Rule out WRAP_KEY purpose
407*e1997b9aSAndroid Build Coastguard Worker KeyPurpose::WRAP_KEY => {
408*e1997b9aSAndroid Build Coastguard Worker return Err(Error::Km(Ec::INCOMPATIBLE_PURPOSE))
409*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("WRAP_KEY purpose is not allowed here.",));
410*e1997b9aSAndroid Build Coastguard Worker }
411*e1997b9aSAndroid Build Coastguard Worker // Allow AGREE_KEY for EC keys only.
412*e1997b9aSAndroid Build Coastguard Worker KeyPurpose::AGREE_KEY => {
413*e1997b9aSAndroid Build Coastguard Worker for kp in key_params.iter() {
414*e1997b9aSAndroid Build Coastguard Worker if kp.get_tag() == Tag::ALGORITHM
415*e1997b9aSAndroid Build Coastguard Worker && *kp.key_parameter_value() != KeyParameterValue::Algorithm(Algorithm::EC)
416*e1997b9aSAndroid Build Coastguard Worker {
417*e1997b9aSAndroid Build Coastguard Worker return Err(Error::Km(Ec::UNSUPPORTED_PURPOSE))
418*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("key agreement is only supported for EC keys.",));
419*e1997b9aSAndroid Build Coastguard Worker }
420*e1997b9aSAndroid Build Coastguard Worker }
421*e1997b9aSAndroid Build Coastguard Worker }
422*e1997b9aSAndroid Build Coastguard Worker KeyPurpose::VERIFY | KeyPurpose::ENCRYPT => {
423*e1997b9aSAndroid Build Coastguard Worker // We do not support ENCRYPT and VERIFY (the remaining two options of purpose) for
424*e1997b9aSAndroid Build Coastguard Worker // asymmetric keys.
425*e1997b9aSAndroid Build Coastguard Worker for kp in key_params.iter() {
426*e1997b9aSAndroid Build Coastguard Worker match *kp.key_parameter_value() {
427*e1997b9aSAndroid Build Coastguard Worker KeyParameterValue::Algorithm(Algorithm::RSA)
428*e1997b9aSAndroid Build Coastguard Worker | KeyParameterValue::Algorithm(Algorithm::EC) => {
429*e1997b9aSAndroid Build Coastguard Worker return Err(Error::Km(Ec::UNSUPPORTED_PURPOSE)).context(ks_err!(
430*e1997b9aSAndroid Build Coastguard Worker "public operations on asymmetric keys are \
431*e1997b9aSAndroid Build Coastguard Worker not supported."
432*e1997b9aSAndroid Build Coastguard Worker ));
433*e1997b9aSAndroid Build Coastguard Worker }
434*e1997b9aSAndroid Build Coastguard Worker _ => {}
435*e1997b9aSAndroid Build Coastguard Worker }
436*e1997b9aSAndroid Build Coastguard Worker }
437*e1997b9aSAndroid Build Coastguard Worker }
438*e1997b9aSAndroid Build Coastguard Worker _ => {
439*e1997b9aSAndroid Build Coastguard Worker return Err(Error::Km(Ec::UNSUPPORTED_PURPOSE))
440*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("authorize_create: specified purpose is not supported."));
441*e1997b9aSAndroid Build Coastguard Worker }
442*e1997b9aSAndroid Build Coastguard Worker }
443*e1997b9aSAndroid Build Coastguard Worker // The following variables are to record information from key parameters to be used in
444*e1997b9aSAndroid Build Coastguard Worker // enforcements, when two or more such pieces of information are required for enforcements.
445*e1997b9aSAndroid Build Coastguard Worker // There is only one additional variable than what legacy keystore has, but this helps
446*e1997b9aSAndroid Build Coastguard Worker // reduce the number of for loops on key parameters from 3 to 1, compared to legacy keystore
447*e1997b9aSAndroid Build Coastguard Worker let mut key_purpose_authorized: bool = false;
448*e1997b9aSAndroid Build Coastguard Worker let mut user_auth_type: Option<HardwareAuthenticatorType> = None;
449*e1997b9aSAndroid Build Coastguard Worker let mut no_auth_required: bool = false;
450*e1997b9aSAndroid Build Coastguard Worker let mut caller_nonce_allowed = false;
451*e1997b9aSAndroid Build Coastguard Worker let mut user_id: i32 = -1;
452*e1997b9aSAndroid Build Coastguard Worker let mut user_secure_ids = Vec::<i64>::new();
453*e1997b9aSAndroid Build Coastguard Worker let mut key_time_out: Option<i64> = None;
454*e1997b9aSAndroid Build Coastguard Worker let mut unlocked_device_required = false;
455*e1997b9aSAndroid Build Coastguard Worker let mut key_usage_limited: Option<i64> = None;
456*e1997b9aSAndroid Build Coastguard Worker let mut confirmation_token_receiver: Option<Arc<Mutex<Option<Receiver<Vec<u8>>>>>> = None;
457*e1997b9aSAndroid Build Coastguard Worker let mut max_boot_level: Option<i32> = None;
458*e1997b9aSAndroid Build Coastguard Worker
459*e1997b9aSAndroid Build Coastguard Worker // iterate through key parameters, recording information we need for authorization
460*e1997b9aSAndroid Build Coastguard Worker // enforcements later, or enforcing authorizations in place, where applicable
461*e1997b9aSAndroid Build Coastguard Worker for key_param in key_params.iter() {
462*e1997b9aSAndroid Build Coastguard Worker match key_param.key_parameter_value() {
463*e1997b9aSAndroid Build Coastguard Worker KeyParameterValue::NoAuthRequired => {
464*e1997b9aSAndroid Build Coastguard Worker no_auth_required = true;
465*e1997b9aSAndroid Build Coastguard Worker }
466*e1997b9aSAndroid Build Coastguard Worker KeyParameterValue::AuthTimeout(t) => {
467*e1997b9aSAndroid Build Coastguard Worker key_time_out = Some(*t as i64);
468*e1997b9aSAndroid Build Coastguard Worker }
469*e1997b9aSAndroid Build Coastguard Worker KeyParameterValue::HardwareAuthenticatorType(a) => {
470*e1997b9aSAndroid Build Coastguard Worker user_auth_type = Some(*a);
471*e1997b9aSAndroid Build Coastguard Worker }
472*e1997b9aSAndroid Build Coastguard Worker KeyParameterValue::KeyPurpose(p) => {
473*e1997b9aSAndroid Build Coastguard Worker // The following check has the effect of key_params.contains(purpose)
474*e1997b9aSAndroid Build Coastguard Worker // Also, authorizing purpose can not be completed here, if there can be multiple
475*e1997b9aSAndroid Build Coastguard Worker // key parameters for KeyPurpose.
476*e1997b9aSAndroid Build Coastguard Worker key_purpose_authorized = key_purpose_authorized || *p == purpose;
477*e1997b9aSAndroid Build Coastguard Worker }
478*e1997b9aSAndroid Build Coastguard Worker KeyParameterValue::CallerNonce => {
479*e1997b9aSAndroid Build Coastguard Worker caller_nonce_allowed = true;
480*e1997b9aSAndroid Build Coastguard Worker }
481*e1997b9aSAndroid Build Coastguard Worker KeyParameterValue::ActiveDateTime(a) => {
482*e1997b9aSAndroid Build Coastguard Worker if !Enforcements::is_given_time_passed(*a, true) {
483*e1997b9aSAndroid Build Coastguard Worker return Err(Error::Km(Ec::KEY_NOT_YET_VALID))
484*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("key is not yet active."));
485*e1997b9aSAndroid Build Coastguard Worker }
486*e1997b9aSAndroid Build Coastguard Worker }
487*e1997b9aSAndroid Build Coastguard Worker KeyParameterValue::OriginationExpireDateTime(o) => {
488*e1997b9aSAndroid Build Coastguard Worker if (purpose == KeyPurpose::ENCRYPT || purpose == KeyPurpose::SIGN)
489*e1997b9aSAndroid Build Coastguard Worker && Enforcements::is_given_time_passed(*o, false)
490*e1997b9aSAndroid Build Coastguard Worker {
491*e1997b9aSAndroid Build Coastguard Worker return Err(Error::Km(Ec::KEY_EXPIRED)).context(ks_err!("key is expired."));
492*e1997b9aSAndroid Build Coastguard Worker }
493*e1997b9aSAndroid Build Coastguard Worker }
494*e1997b9aSAndroid Build Coastguard Worker KeyParameterValue::UsageExpireDateTime(u) => {
495*e1997b9aSAndroid Build Coastguard Worker if (purpose == KeyPurpose::DECRYPT || purpose == KeyPurpose::VERIFY)
496*e1997b9aSAndroid Build Coastguard Worker && Enforcements::is_given_time_passed(*u, false)
497*e1997b9aSAndroid Build Coastguard Worker {
498*e1997b9aSAndroid Build Coastguard Worker return Err(Error::Km(Ec::KEY_EXPIRED)).context(ks_err!("key is expired."));
499*e1997b9aSAndroid Build Coastguard Worker }
500*e1997b9aSAndroid Build Coastguard Worker }
501*e1997b9aSAndroid Build Coastguard Worker KeyParameterValue::UserSecureID(s) => {
502*e1997b9aSAndroid Build Coastguard Worker user_secure_ids.push(*s);
503*e1997b9aSAndroid Build Coastguard Worker }
504*e1997b9aSAndroid Build Coastguard Worker KeyParameterValue::UserID(u) => {
505*e1997b9aSAndroid Build Coastguard Worker user_id = *u;
506*e1997b9aSAndroid Build Coastguard Worker }
507*e1997b9aSAndroid Build Coastguard Worker KeyParameterValue::UnlockedDeviceRequired => {
508*e1997b9aSAndroid Build Coastguard Worker unlocked_device_required = true;
509*e1997b9aSAndroid Build Coastguard Worker }
510*e1997b9aSAndroid Build Coastguard Worker KeyParameterValue::UsageCountLimit(_) => {
511*e1997b9aSAndroid Build Coastguard Worker // We don't examine the limit here because this is enforced on finish.
512*e1997b9aSAndroid Build Coastguard Worker // Instead, we store the key_id so that finish can look up the key
513*e1997b9aSAndroid Build Coastguard Worker // in the database again and check and update the counter.
514*e1997b9aSAndroid Build Coastguard Worker key_usage_limited = Some(key_id);
515*e1997b9aSAndroid Build Coastguard Worker }
516*e1997b9aSAndroid Build Coastguard Worker KeyParameterValue::TrustedConfirmationRequired => {
517*e1997b9aSAndroid Build Coastguard Worker confirmation_token_receiver = Some(self.confirmation_token_receiver.clone());
518*e1997b9aSAndroid Build Coastguard Worker }
519*e1997b9aSAndroid Build Coastguard Worker KeyParameterValue::MaxBootLevel(level) => {
520*e1997b9aSAndroid Build Coastguard Worker max_boot_level = Some(*level);
521*e1997b9aSAndroid Build Coastguard Worker }
522*e1997b9aSAndroid Build Coastguard Worker // NOTE: as per offline discussion, sanitizing key parameters and rejecting
523*e1997b9aSAndroid Build Coastguard Worker // create operation if any non-allowed tags are present, is not done in
524*e1997b9aSAndroid Build Coastguard Worker // authorize_create (unlike in legacy keystore where AuthorizeBegin is rejected if
525*e1997b9aSAndroid Build Coastguard Worker // a subset of non-allowed tags are present). Because sanitizing key parameters
526*e1997b9aSAndroid Build Coastguard Worker // should have been done during generate/import key, by KeyMint.
527*e1997b9aSAndroid Build Coastguard Worker _ => { /*Do nothing on all the other key parameters, as in legacy keystore*/ }
528*e1997b9aSAndroid Build Coastguard Worker }
529*e1997b9aSAndroid Build Coastguard Worker }
530*e1997b9aSAndroid Build Coastguard Worker
531*e1997b9aSAndroid Build Coastguard Worker // authorize the purpose
532*e1997b9aSAndroid Build Coastguard Worker if !key_purpose_authorized {
533*e1997b9aSAndroid Build Coastguard Worker return Err(Error::Km(Ec::INCOMPATIBLE_PURPOSE))
534*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("the purpose is not authorized."));
535*e1997b9aSAndroid Build Coastguard Worker }
536*e1997b9aSAndroid Build Coastguard Worker
537*e1997b9aSAndroid Build Coastguard Worker // if both NO_AUTH_REQUIRED and USER_SECURE_ID tags are present, return error
538*e1997b9aSAndroid Build Coastguard Worker if !user_secure_ids.is_empty() && no_auth_required {
539*e1997b9aSAndroid Build Coastguard Worker return Err(Error::Km(Ec::INVALID_KEY_BLOB))
540*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("key has both NO_AUTH_REQUIRED and USER_SECURE_ID tags."));
541*e1997b9aSAndroid Build Coastguard Worker }
542*e1997b9aSAndroid Build Coastguard Worker
543*e1997b9aSAndroid Build Coastguard Worker // if either of auth_type or secure_id is present and the other is not present, return error
544*e1997b9aSAndroid Build Coastguard Worker if (user_auth_type.is_some() && user_secure_ids.is_empty())
545*e1997b9aSAndroid Build Coastguard Worker || (user_auth_type.is_none() && !user_secure_ids.is_empty())
546*e1997b9aSAndroid Build Coastguard Worker {
547*e1997b9aSAndroid Build Coastguard Worker return Err(Error::Km(Ec::KEY_USER_NOT_AUTHENTICATED)).context(ks_err!(
548*e1997b9aSAndroid Build Coastguard Worker "Auth required, but auth type {:?} + sids {:?} inconsistently specified",
549*e1997b9aSAndroid Build Coastguard Worker user_auth_type,
550*e1997b9aSAndroid Build Coastguard Worker user_secure_ids,
551*e1997b9aSAndroid Build Coastguard Worker ));
552*e1997b9aSAndroid Build Coastguard Worker }
553*e1997b9aSAndroid Build Coastguard Worker
554*e1997b9aSAndroid Build Coastguard Worker // validate caller nonce for origination purposes
555*e1997b9aSAndroid Build Coastguard Worker if (purpose == KeyPurpose::ENCRYPT || purpose == KeyPurpose::SIGN)
556*e1997b9aSAndroid Build Coastguard Worker && !caller_nonce_allowed
557*e1997b9aSAndroid Build Coastguard Worker && op_params.iter().any(|kp| kp.tag == Tag::NONCE)
558*e1997b9aSAndroid Build Coastguard Worker {
559*e1997b9aSAndroid Build Coastguard Worker return Err(Error::Km(Ec::CALLER_NONCE_PROHIBITED))
560*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("NONCE is present, although CALLER_NONCE is not present"));
561*e1997b9aSAndroid Build Coastguard Worker }
562*e1997b9aSAndroid Build Coastguard Worker
563*e1997b9aSAndroid Build Coastguard Worker if unlocked_device_required {
564*e1997b9aSAndroid Build Coastguard Worker // check the device locked status. If locked, operations on the key are not
565*e1997b9aSAndroid Build Coastguard Worker // allowed.
566*e1997b9aSAndroid Build Coastguard Worker if self.is_device_locked(user_id) {
567*e1997b9aSAndroid Build Coastguard Worker return Err(Error::Km(Ec::DEVICE_LOCKED)).context(ks_err!("device is locked."));
568*e1997b9aSAndroid Build Coastguard Worker }
569*e1997b9aSAndroid Build Coastguard Worker }
570*e1997b9aSAndroid Build Coastguard Worker
571*e1997b9aSAndroid Build Coastguard Worker if let Some(level) = max_boot_level {
572*e1997b9aSAndroid Build Coastguard Worker if !SUPER_KEY.read().unwrap().level_accessible(level) {
573*e1997b9aSAndroid Build Coastguard Worker return Err(Error::Km(Ec::BOOT_LEVEL_EXCEEDED))
574*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("boot level is too late."));
575*e1997b9aSAndroid Build Coastguard Worker }
576*e1997b9aSAndroid Build Coastguard Worker }
577*e1997b9aSAndroid Build Coastguard Worker
578*e1997b9aSAndroid Build Coastguard Worker let (hat, state) = if user_secure_ids.is_empty() {
579*e1997b9aSAndroid Build Coastguard Worker (None, DeferredAuthState::NoAuthRequired)
580*e1997b9aSAndroid Build Coastguard Worker } else if let Some(key_time_out) = key_time_out {
581*e1997b9aSAndroid Build Coastguard Worker let hat = Self::find_auth_token(|hat: &AuthTokenEntry| match user_auth_type {
582*e1997b9aSAndroid Build Coastguard Worker Some(auth_type) => hat.satisfies(&user_secure_ids, auth_type),
583*e1997b9aSAndroid Build Coastguard Worker None => false, // not reachable due to earlier check
584*e1997b9aSAndroid Build Coastguard Worker })
585*e1997b9aSAndroid Build Coastguard Worker .ok_or(Error::Km(Ec::KEY_USER_NOT_AUTHENTICATED))
586*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!(
587*e1997b9aSAndroid Build Coastguard Worker "No suitable auth token for sids {:?} type {:?} received in last {}s found.",
588*e1997b9aSAndroid Build Coastguard Worker user_secure_ids,
589*e1997b9aSAndroid Build Coastguard Worker user_auth_type,
590*e1997b9aSAndroid Build Coastguard Worker key_time_out
591*e1997b9aSAndroid Build Coastguard Worker ))?;
592*e1997b9aSAndroid Build Coastguard Worker let now = BootTime::now();
593*e1997b9aSAndroid Build Coastguard Worker let token_age =
594*e1997b9aSAndroid Build Coastguard Worker now.checked_sub(&hat.time_received()).ok_or_else(Error::sys).context(ks_err!(
595*e1997b9aSAndroid Build Coastguard Worker "Overflow while computing Auth token validity. Validity cannot be established."
596*e1997b9aSAndroid Build Coastguard Worker ))?;
597*e1997b9aSAndroid Build Coastguard Worker
598*e1997b9aSAndroid Build Coastguard Worker if token_age.seconds() > key_time_out {
599*e1997b9aSAndroid Build Coastguard Worker return Err(Error::Km(Ec::KEY_USER_NOT_AUTHENTICATED)).context(ks_err!(
600*e1997b9aSAndroid Build Coastguard Worker concat!(
601*e1997b9aSAndroid Build Coastguard Worker "matching auth token (challenge={}, userId={}, authId={}, ",
602*e1997b9aSAndroid Build Coastguard Worker "authType={:#x}, timestamp={}ms) rcved={:?} ",
603*e1997b9aSAndroid Build Coastguard Worker "for sids {:?} type {:?} is expired ({}s old > timeout={}s)"
604*e1997b9aSAndroid Build Coastguard Worker ),
605*e1997b9aSAndroid Build Coastguard Worker hat.auth_token().challenge,
606*e1997b9aSAndroid Build Coastguard Worker hat.auth_token().userId,
607*e1997b9aSAndroid Build Coastguard Worker hat.auth_token().authenticatorId,
608*e1997b9aSAndroid Build Coastguard Worker hat.auth_token().authenticatorType.0,
609*e1997b9aSAndroid Build Coastguard Worker hat.auth_token().timestamp.milliSeconds,
610*e1997b9aSAndroid Build Coastguard Worker hat.time_received(),
611*e1997b9aSAndroid Build Coastguard Worker user_secure_ids,
612*e1997b9aSAndroid Build Coastguard Worker user_auth_type,
613*e1997b9aSAndroid Build Coastguard Worker token_age.seconds(),
614*e1997b9aSAndroid Build Coastguard Worker key_time_out
615*e1997b9aSAndroid Build Coastguard Worker ));
616*e1997b9aSAndroid Build Coastguard Worker }
617*e1997b9aSAndroid Build Coastguard Worker let state = if requires_timestamp {
618*e1997b9aSAndroid Build Coastguard Worker DeferredAuthState::TimeStampRequired(hat.auth_token().clone())
619*e1997b9aSAndroid Build Coastguard Worker } else {
620*e1997b9aSAndroid Build Coastguard Worker DeferredAuthState::NoAuthRequired
621*e1997b9aSAndroid Build Coastguard Worker };
622*e1997b9aSAndroid Build Coastguard Worker (Some(hat.take_auth_token()), state)
623*e1997b9aSAndroid Build Coastguard Worker } else {
624*e1997b9aSAndroid Build Coastguard Worker (None, DeferredAuthState::OpAuthRequired)
625*e1997b9aSAndroid Build Coastguard Worker };
626*e1997b9aSAndroid Build Coastguard Worker Ok((hat, AuthInfo { state, key_usage_limited, confirmation_token_receiver }))
627*e1997b9aSAndroid Build Coastguard Worker }
628*e1997b9aSAndroid Build Coastguard Worker
find_auth_token<F>(p: F) -> Option<AuthTokenEntry> where F: Fn(&AuthTokenEntry) -> bool,629*e1997b9aSAndroid Build Coastguard Worker fn find_auth_token<F>(p: F) -> Option<AuthTokenEntry>
630*e1997b9aSAndroid Build Coastguard Worker where
631*e1997b9aSAndroid Build Coastguard Worker F: Fn(&AuthTokenEntry) -> bool,
632*e1997b9aSAndroid Build Coastguard Worker {
633*e1997b9aSAndroid Build Coastguard Worker DB.with(|db| db.borrow().find_auth_token_entry(p))
634*e1997b9aSAndroid Build Coastguard Worker }
635*e1997b9aSAndroid Build Coastguard Worker
636*e1997b9aSAndroid Build Coastguard Worker /// Checks if the time now since epoch is greater than (or equal, if is_given_time_inclusive is
637*e1997b9aSAndroid Build Coastguard Worker /// set) the given time (in milliseconds)
is_given_time_passed(given_time: i64, is_given_time_inclusive: bool) -> bool638*e1997b9aSAndroid Build Coastguard Worker fn is_given_time_passed(given_time: i64, is_given_time_inclusive: bool) -> bool {
639*e1997b9aSAndroid Build Coastguard Worker let duration_since_epoch = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH);
640*e1997b9aSAndroid Build Coastguard Worker
641*e1997b9aSAndroid Build Coastguard Worker let time_since_epoch = match duration_since_epoch {
642*e1997b9aSAndroid Build Coastguard Worker Ok(duration) => duration.as_millis(),
643*e1997b9aSAndroid Build Coastguard Worker Err(_) => return false,
644*e1997b9aSAndroid Build Coastguard Worker };
645*e1997b9aSAndroid Build Coastguard Worker
646*e1997b9aSAndroid Build Coastguard Worker if is_given_time_inclusive {
647*e1997b9aSAndroid Build Coastguard Worker time_since_epoch >= (given_time as u128)
648*e1997b9aSAndroid Build Coastguard Worker } else {
649*e1997b9aSAndroid Build Coastguard Worker time_since_epoch > (given_time as u128)
650*e1997b9aSAndroid Build Coastguard Worker }
651*e1997b9aSAndroid Build Coastguard Worker }
652*e1997b9aSAndroid Build Coastguard Worker
653*e1997b9aSAndroid Build Coastguard Worker /// Check if the device is locked for the given user. If there's no entry yet for the user,
654*e1997b9aSAndroid Build Coastguard Worker /// we assume that the device is locked
is_device_locked(&self, user_id: i32) -> bool655*e1997b9aSAndroid Build Coastguard Worker fn is_device_locked(&self, user_id: i32) -> bool {
656*e1997b9aSAndroid Build Coastguard Worker let set = self.device_unlocked_set.lock().unwrap();
657*e1997b9aSAndroid Build Coastguard Worker !set.contains(&user_id)
658*e1997b9aSAndroid Build Coastguard Worker }
659*e1997b9aSAndroid Build Coastguard Worker
660*e1997b9aSAndroid Build Coastguard Worker /// Sets the device locked status for the user. This method is called externally.
set_device_locked(&self, user_id: i32, device_locked_status: bool)661*e1997b9aSAndroid Build Coastguard Worker pub fn set_device_locked(&self, user_id: i32, device_locked_status: bool) {
662*e1997b9aSAndroid Build Coastguard Worker let mut set = self.device_unlocked_set.lock().unwrap();
663*e1997b9aSAndroid Build Coastguard Worker if device_locked_status {
664*e1997b9aSAndroid Build Coastguard Worker set.remove(&user_id);
665*e1997b9aSAndroid Build Coastguard Worker } else {
666*e1997b9aSAndroid Build Coastguard Worker set.insert(user_id);
667*e1997b9aSAndroid Build Coastguard Worker }
668*e1997b9aSAndroid Build Coastguard Worker }
669*e1997b9aSAndroid Build Coastguard Worker
670*e1997b9aSAndroid Build Coastguard Worker /// Add this auth token to the database.
671*e1997b9aSAndroid Build Coastguard Worker /// Then present the auth token to the op auth map. If an operation is waiting for this
672*e1997b9aSAndroid Build Coastguard Worker /// auth token this fulfills the request and removes the receiver from the map.
add_auth_token(&self, hat: HardwareAuthToken)673*e1997b9aSAndroid Build Coastguard Worker pub fn add_auth_token(&self, hat: HardwareAuthToken) {
674*e1997b9aSAndroid Build Coastguard Worker DB.with(|db| db.borrow_mut().insert_auth_token(&hat));
675*e1997b9aSAndroid Build Coastguard Worker self.op_auth_map.add_auth_token(hat);
676*e1997b9aSAndroid Build Coastguard Worker }
677*e1997b9aSAndroid Build Coastguard Worker
678*e1997b9aSAndroid Build Coastguard Worker /// This allows adding an entry to the op_auth_map, indexed by the operation challenge.
679*e1997b9aSAndroid Build Coastguard Worker /// This is to be called by create_operation, once it has received the operation challenge
680*e1997b9aSAndroid Build Coastguard Worker /// from keymint for an operation whose authorization decision is OpAuthRequired, as signalled
681*e1997b9aSAndroid Build Coastguard Worker /// by the DeferredAuthState.
register_op_auth_receiver(&self, challenge: i64, recv: TokenReceiver)682*e1997b9aSAndroid Build Coastguard Worker fn register_op_auth_receiver(&self, challenge: i64, recv: TokenReceiver) {
683*e1997b9aSAndroid Build Coastguard Worker self.op_auth_map.add_receiver(challenge, recv);
684*e1997b9aSAndroid Build Coastguard Worker }
685*e1997b9aSAndroid Build Coastguard Worker
686*e1997b9aSAndroid Build Coastguard Worker /// Given the set of key parameters and flags, check if super encryption is required.
super_encryption_required( domain: &Domain, key_parameters: &[KeyParameter], flags: Option<i32>, ) -> SuperEncryptionType687*e1997b9aSAndroid Build Coastguard Worker pub fn super_encryption_required(
688*e1997b9aSAndroid Build Coastguard Worker domain: &Domain,
689*e1997b9aSAndroid Build Coastguard Worker key_parameters: &[KeyParameter],
690*e1997b9aSAndroid Build Coastguard Worker flags: Option<i32>,
691*e1997b9aSAndroid Build Coastguard Worker ) -> SuperEncryptionType {
692*e1997b9aSAndroid Build Coastguard Worker if let Some(flags) = flags {
693*e1997b9aSAndroid Build Coastguard Worker if (flags & KEY_FLAG_AUTH_BOUND_WITHOUT_CRYPTOGRAPHIC_LSKF_BINDING) != 0 {
694*e1997b9aSAndroid Build Coastguard Worker return SuperEncryptionType::None;
695*e1997b9aSAndroid Build Coastguard Worker }
696*e1997b9aSAndroid Build Coastguard Worker }
697*e1997b9aSAndroid Build Coastguard Worker // Each answer has a priority, numerically largest priority wins.
698*e1997b9aSAndroid Build Coastguard Worker struct Candidate {
699*e1997b9aSAndroid Build Coastguard Worker priority: u32,
700*e1997b9aSAndroid Build Coastguard Worker enc_type: SuperEncryptionType,
701*e1997b9aSAndroid Build Coastguard Worker }
702*e1997b9aSAndroid Build Coastguard Worker let mut result = Candidate { priority: 0, enc_type: SuperEncryptionType::None };
703*e1997b9aSAndroid Build Coastguard Worker for kp in key_parameters {
704*e1997b9aSAndroid Build Coastguard Worker let t = match kp.key_parameter_value() {
705*e1997b9aSAndroid Build Coastguard Worker KeyParameterValue::MaxBootLevel(level) => {
706*e1997b9aSAndroid Build Coastguard Worker Candidate { priority: 3, enc_type: SuperEncryptionType::BootLevel(*level) }
707*e1997b9aSAndroid Build Coastguard Worker }
708*e1997b9aSAndroid Build Coastguard Worker KeyParameterValue::UnlockedDeviceRequired if *domain == Domain::APP => {
709*e1997b9aSAndroid Build Coastguard Worker Candidate { priority: 2, enc_type: SuperEncryptionType::UnlockedDeviceRequired }
710*e1997b9aSAndroid Build Coastguard Worker }
711*e1997b9aSAndroid Build Coastguard Worker KeyParameterValue::UserSecureID(_) if *domain == Domain::APP => {
712*e1997b9aSAndroid Build Coastguard Worker Candidate { priority: 1, enc_type: SuperEncryptionType::AfterFirstUnlock }
713*e1997b9aSAndroid Build Coastguard Worker }
714*e1997b9aSAndroid Build Coastguard Worker _ => Candidate { priority: 0, enc_type: SuperEncryptionType::None },
715*e1997b9aSAndroid Build Coastguard Worker };
716*e1997b9aSAndroid Build Coastguard Worker if t.priority > result.priority {
717*e1997b9aSAndroid Build Coastguard Worker result = t;
718*e1997b9aSAndroid Build Coastguard Worker }
719*e1997b9aSAndroid Build Coastguard Worker }
720*e1997b9aSAndroid Build Coastguard Worker result.enc_type
721*e1997b9aSAndroid Build Coastguard Worker }
722*e1997b9aSAndroid Build Coastguard Worker
723*e1997b9aSAndroid Build Coastguard Worker /// Finds a matching auth token along with a timestamp token.
724*e1997b9aSAndroid Build Coastguard Worker /// This method looks through auth-tokens cached by keystore which satisfy the given
725*e1997b9aSAndroid Build Coastguard Worker /// authentication information (i.e. |secureUserId|).
726*e1997b9aSAndroid Build Coastguard Worker /// The most recent matching auth token which has a |challenge| field which matches
727*e1997b9aSAndroid Build Coastguard Worker /// the passed-in |challenge| parameter is returned.
728*e1997b9aSAndroid Build Coastguard Worker /// In this case the |authTokenMaxAgeMillis| parameter is not used.
729*e1997b9aSAndroid Build Coastguard Worker ///
730*e1997b9aSAndroid Build Coastguard Worker /// Otherwise, the most recent matching auth token which is younger than |authTokenMaxAgeMillis|
731*e1997b9aSAndroid Build Coastguard Worker /// is returned.
get_auth_tokens( &self, challenge: i64, secure_user_id: i64, auth_token_max_age_millis: i64, ) -> Result<(HardwareAuthToken, TimeStampToken)>732*e1997b9aSAndroid Build Coastguard Worker pub fn get_auth_tokens(
733*e1997b9aSAndroid Build Coastguard Worker &self,
734*e1997b9aSAndroid Build Coastguard Worker challenge: i64,
735*e1997b9aSAndroid Build Coastguard Worker secure_user_id: i64,
736*e1997b9aSAndroid Build Coastguard Worker auth_token_max_age_millis: i64,
737*e1997b9aSAndroid Build Coastguard Worker ) -> Result<(HardwareAuthToken, TimeStampToken)> {
738*e1997b9aSAndroid Build Coastguard Worker let auth_type = HardwareAuthenticatorType::ANY;
739*e1997b9aSAndroid Build Coastguard Worker let sids: Vec<i64> = vec![secure_user_id];
740*e1997b9aSAndroid Build Coastguard Worker // Filter the matching auth tokens by challenge
741*e1997b9aSAndroid Build Coastguard Worker let result = Self::find_auth_token(|hat: &AuthTokenEntry| {
742*e1997b9aSAndroid Build Coastguard Worker (challenge == hat.challenge()) && hat.satisfies(&sids, auth_type)
743*e1997b9aSAndroid Build Coastguard Worker });
744*e1997b9aSAndroid Build Coastguard Worker
745*e1997b9aSAndroid Build Coastguard Worker let auth_token = if let Some(auth_token_entry) = result {
746*e1997b9aSAndroid Build Coastguard Worker auth_token_entry.take_auth_token()
747*e1997b9aSAndroid Build Coastguard Worker } else {
748*e1997b9aSAndroid Build Coastguard Worker // Filter the matching auth tokens by age.
749*e1997b9aSAndroid Build Coastguard Worker if auth_token_max_age_millis != 0 {
750*e1997b9aSAndroid Build Coastguard Worker let now_in_millis = BootTime::now();
751*e1997b9aSAndroid Build Coastguard Worker let result = Self::find_auth_token(|auth_token_entry: &AuthTokenEntry| {
752*e1997b9aSAndroid Build Coastguard Worker let token_valid = now_in_millis
753*e1997b9aSAndroid Build Coastguard Worker .checked_sub(&auth_token_entry.time_received())
754*e1997b9aSAndroid Build Coastguard Worker .map_or(false, |token_age_in_millis| {
755*e1997b9aSAndroid Build Coastguard Worker auth_token_max_age_millis > token_age_in_millis.milliseconds()
756*e1997b9aSAndroid Build Coastguard Worker });
757*e1997b9aSAndroid Build Coastguard Worker token_valid && auth_token_entry.satisfies(&sids, auth_type)
758*e1997b9aSAndroid Build Coastguard Worker });
759*e1997b9aSAndroid Build Coastguard Worker
760*e1997b9aSAndroid Build Coastguard Worker if let Some(auth_token_entry) = result {
761*e1997b9aSAndroid Build Coastguard Worker auth_token_entry.take_auth_token()
762*e1997b9aSAndroid Build Coastguard Worker } else {
763*e1997b9aSAndroid Build Coastguard Worker return Err(AuthzError::Rc(AuthzResponseCode::NO_AUTH_TOKEN_FOUND))
764*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("No auth token found."));
765*e1997b9aSAndroid Build Coastguard Worker }
766*e1997b9aSAndroid Build Coastguard Worker } else {
767*e1997b9aSAndroid Build Coastguard Worker return Err(AuthzError::Rc(AuthzResponseCode::NO_AUTH_TOKEN_FOUND)).context(
768*e1997b9aSAndroid Build Coastguard Worker ks_err!(
769*e1997b9aSAndroid Build Coastguard Worker "No auth token found for \
770*e1997b9aSAndroid Build Coastguard Worker the given challenge and passed-in auth token max age is zero."
771*e1997b9aSAndroid Build Coastguard Worker ),
772*e1997b9aSAndroid Build Coastguard Worker );
773*e1997b9aSAndroid Build Coastguard Worker }
774*e1997b9aSAndroid Build Coastguard Worker };
775*e1997b9aSAndroid Build Coastguard Worker // Wait and obtain the timestamp token from secure clock service.
776*e1997b9aSAndroid Build Coastguard Worker let tst =
777*e1997b9aSAndroid Build Coastguard Worker get_timestamp_token(challenge).context(ks_err!("Error in getting timestamp token."))?;
778*e1997b9aSAndroid Build Coastguard Worker Ok((auth_token, tst))
779*e1997b9aSAndroid Build Coastguard Worker }
780*e1997b9aSAndroid Build Coastguard Worker
781*e1997b9aSAndroid Build Coastguard Worker /// Finds the most recent received time for an auth token that matches the given secure user id and authenticator
get_last_auth_time( &self, secure_user_id: i64, auth_type: HardwareAuthenticatorType, ) -> Option<BootTime>782*e1997b9aSAndroid Build Coastguard Worker pub fn get_last_auth_time(
783*e1997b9aSAndroid Build Coastguard Worker &self,
784*e1997b9aSAndroid Build Coastguard Worker secure_user_id: i64,
785*e1997b9aSAndroid Build Coastguard Worker auth_type: HardwareAuthenticatorType,
786*e1997b9aSAndroid Build Coastguard Worker ) -> Option<BootTime> {
787*e1997b9aSAndroid Build Coastguard Worker let sids: Vec<i64> = vec![secure_user_id];
788*e1997b9aSAndroid Build Coastguard Worker
789*e1997b9aSAndroid Build Coastguard Worker let result =
790*e1997b9aSAndroid Build Coastguard Worker Self::find_auth_token(|entry: &AuthTokenEntry| entry.satisfies(&sids, auth_type));
791*e1997b9aSAndroid Build Coastguard Worker
792*e1997b9aSAndroid Build Coastguard Worker result.map(|auth_token_entry| auth_token_entry.time_received())
793*e1997b9aSAndroid Build Coastguard Worker }
794*e1997b9aSAndroid Build Coastguard Worker }
795*e1997b9aSAndroid Build Coastguard Worker
796*e1997b9aSAndroid Build Coastguard Worker // TODO: Add tests to enforcement module (b/175578618).
797