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