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 crate implements the `IKeystoreOperation` AIDL interface, which represents 16*e1997b9aSAndroid Build Coastguard Worker //! an ongoing key operation, as well as the operation database, which is mainly 17*e1997b9aSAndroid Build Coastguard Worker //! required for tracking operations for the purpose of pruning. 18*e1997b9aSAndroid Build Coastguard Worker //! This crate also implements an operation pruning strategy. 19*e1997b9aSAndroid Build Coastguard Worker //! 20*e1997b9aSAndroid Build Coastguard Worker //! Operations implement the API calls update, finish, and abort. 21*e1997b9aSAndroid Build Coastguard Worker //! Additionally, an operation can be dropped and pruned. The former 22*e1997b9aSAndroid Build Coastguard Worker //! happens if the client deletes a binder to the operation object. 23*e1997b9aSAndroid Build Coastguard Worker //! An existing operation may get pruned when running out of operation 24*e1997b9aSAndroid Build Coastguard Worker //! slots and a new operation takes precedence. 25*e1997b9aSAndroid Build Coastguard Worker //! 26*e1997b9aSAndroid Build Coastguard Worker //! ## Operation Lifecycle 27*e1997b9aSAndroid Build Coastguard Worker //! An operation gets created when the client calls `IKeystoreSecurityLevel::create`. 28*e1997b9aSAndroid Build Coastguard Worker //! It may receive zero or more update request. The lifecycle ends when: 29*e1997b9aSAndroid Build Coastguard Worker //! * `update` yields an error. 30*e1997b9aSAndroid Build Coastguard Worker //! * `finish` is called. 31*e1997b9aSAndroid Build Coastguard Worker //! * `abort` is called. 32*e1997b9aSAndroid Build Coastguard Worker //! * The operation gets dropped. 33*e1997b9aSAndroid Build Coastguard Worker //! * The operation gets pruned. 34*e1997b9aSAndroid Build Coastguard Worker //! 35*e1997b9aSAndroid Build Coastguard Worker //! `Operation` has an `Outcome` member. While the outcome is `Outcome::Unknown`, 36*e1997b9aSAndroid Build Coastguard Worker //! the operation is active and in a good state. Any of the above conditions may 37*e1997b9aSAndroid Build Coastguard Worker //! change the outcome to one of the defined outcomes Success, Abort, Dropped, 38*e1997b9aSAndroid Build Coastguard Worker //! Pruned, or ErrorCode. The latter is chosen in the case of an unexpected error, during 39*e1997b9aSAndroid Build Coastguard Worker //! `update` or `finish`. `Success` is chosen iff `finish` completes without error. 40*e1997b9aSAndroid Build Coastguard Worker //! Note that all operations get dropped eventually in the sense that they lose 41*e1997b9aSAndroid Build Coastguard Worker //! their last reference and get destroyed. At that point, the fate of the operation 42*e1997b9aSAndroid Build Coastguard Worker //! gets logged. However, an operation will transition to `Outcome::Dropped` iff 43*e1997b9aSAndroid Build Coastguard Worker //! the operation was still active (`Outcome::Unknown`) at that time. 44*e1997b9aSAndroid Build Coastguard Worker //! 45*e1997b9aSAndroid Build Coastguard Worker //! ## Operation Dropping 46*e1997b9aSAndroid Build Coastguard Worker //! To observe the dropping of an operation, we have to make sure that there 47*e1997b9aSAndroid Build Coastguard Worker //! are no strong references to the IBinder representing this operation. 48*e1997b9aSAndroid Build Coastguard Worker //! This would be simple enough if the operation object would need to be accessed 49*e1997b9aSAndroid Build Coastguard Worker //! only by transactions. But to perform pruning, we have to retain a reference to the 50*e1997b9aSAndroid Build Coastguard Worker //! original operation object. 51*e1997b9aSAndroid Build Coastguard Worker //! 52*e1997b9aSAndroid Build Coastguard Worker //! ## Operation Pruning 53*e1997b9aSAndroid Build Coastguard Worker //! Pruning an operation happens during the creation of a new operation. 54*e1997b9aSAndroid Build Coastguard Worker //! We have to iterate through the operation database to find a suitable 55*e1997b9aSAndroid Build Coastguard Worker //! candidate. Then we abort and finalize this operation setting its outcome to 56*e1997b9aSAndroid Build Coastguard Worker //! `Outcome::Pruned`. The corresponding KeyMint operation slot will have been freed 57*e1997b9aSAndroid Build Coastguard Worker //! up at this point, but the `Operation` object lingers. When the client 58*e1997b9aSAndroid Build Coastguard Worker //! attempts to use the operation again they will receive 59*e1997b9aSAndroid Build Coastguard Worker //! ErrorCode::INVALID_OPERATION_HANDLE indicating that the operation no longer 60*e1997b9aSAndroid Build Coastguard Worker //! exits. This should be the cue for the client to destroy its binder. 61*e1997b9aSAndroid Build Coastguard Worker //! At that point the operation gets dropped. 62*e1997b9aSAndroid Build Coastguard Worker //! 63*e1997b9aSAndroid Build Coastguard Worker //! ## Architecture 64*e1997b9aSAndroid Build Coastguard Worker //! The `IKeystoreOperation` trait is implemented by `KeystoreOperation`. 65*e1997b9aSAndroid Build Coastguard Worker //! This acts as a proxy object holding a strong reference to actual operation 66*e1997b9aSAndroid Build Coastguard Worker //! implementation `Operation`. 67*e1997b9aSAndroid Build Coastguard Worker //! 68*e1997b9aSAndroid Build Coastguard Worker //! ``` 69*e1997b9aSAndroid Build Coastguard Worker //! struct KeystoreOperation { 70*e1997b9aSAndroid Build Coastguard Worker //! operation: Mutex<Option<Arc<Operation>>>, 71*e1997b9aSAndroid Build Coastguard Worker //! } 72*e1997b9aSAndroid Build Coastguard Worker //! ``` 73*e1997b9aSAndroid Build Coastguard Worker //! 74*e1997b9aSAndroid Build Coastguard Worker //! The `Mutex` serves two purposes. It provides interior mutability allowing 75*e1997b9aSAndroid Build Coastguard Worker //! us to set the Option to None. We do this when the life cycle ends during 76*e1997b9aSAndroid Build Coastguard Worker //! a call to `update`, `finish`, or `abort`. As a result most of the Operation 77*e1997b9aSAndroid Build Coastguard Worker //! related resources are freed. The `KeystoreOperation` proxy object still 78*e1997b9aSAndroid Build Coastguard Worker //! lingers until dropped by the client. 79*e1997b9aSAndroid Build Coastguard Worker //! The second purpose is to protect operations against concurrent usage. 80*e1997b9aSAndroid Build Coastguard Worker //! Failing to lock this mutex yields `ResponseCode::OPERATION_BUSY` and indicates 81*e1997b9aSAndroid Build Coastguard Worker //! a programming error in the client. 82*e1997b9aSAndroid Build Coastguard Worker //! 83*e1997b9aSAndroid Build Coastguard Worker //! Note that the Mutex only protects the operation against concurrent client calls. 84*e1997b9aSAndroid Build Coastguard Worker //! We still retain weak references to the operation in the operation database: 85*e1997b9aSAndroid Build Coastguard Worker //! 86*e1997b9aSAndroid Build Coastguard Worker //! ``` 87*e1997b9aSAndroid Build Coastguard Worker //! struct OperationDb { 88*e1997b9aSAndroid Build Coastguard Worker //! operations: Mutex<Vec<Weak<Operation>>> 89*e1997b9aSAndroid Build Coastguard Worker //! } 90*e1997b9aSAndroid Build Coastguard Worker //! ``` 91*e1997b9aSAndroid Build Coastguard Worker //! 92*e1997b9aSAndroid Build Coastguard Worker //! This allows us to access the operations for the purpose of pruning. 93*e1997b9aSAndroid Build Coastguard Worker //! We do this in three phases. 94*e1997b9aSAndroid Build Coastguard Worker //! 1. We gather the pruning information. Besides non mutable information, 95*e1997b9aSAndroid Build Coastguard Worker //! we access `last_usage` which is protected by a mutex. 96*e1997b9aSAndroid Build Coastguard Worker //! We only lock this mutex for single statements at a time. During 97*e1997b9aSAndroid Build Coastguard Worker //! this phase we hold the operation db lock. 98*e1997b9aSAndroid Build Coastguard Worker //! 2. We choose a pruning candidate by computing the pruning resistance 99*e1997b9aSAndroid Build Coastguard Worker //! of each operation. We do this entirely with information we now 100*e1997b9aSAndroid Build Coastguard Worker //! have on the stack without holding any locks. 101*e1997b9aSAndroid Build Coastguard Worker //! (See `OperationDb::prune` for more details on the pruning strategy.) 102*e1997b9aSAndroid Build Coastguard Worker //! 3. During pruning we briefly lock the operation database again to get the 103*e1997b9aSAndroid Build Coastguard Worker //! the pruning candidate by index. We then attempt to abort the candidate. 104*e1997b9aSAndroid Build Coastguard Worker //! If the candidate was touched in the meantime or is currently fulfilling 105*e1997b9aSAndroid Build Coastguard Worker //! a request (i.e., the client calls update, finish, or abort), 106*e1997b9aSAndroid Build Coastguard Worker //! we go back to 1 and try again. 107*e1997b9aSAndroid Build Coastguard Worker //! 108*e1997b9aSAndroid Build Coastguard Worker //! So the outer Mutex in `KeystoreOperation::operation` only protects 109*e1997b9aSAndroid Build Coastguard Worker //! operations against concurrent client calls but not against concurrent 110*e1997b9aSAndroid Build Coastguard Worker //! pruning attempts. This is what the `Operation::outcome` mutex is used for. 111*e1997b9aSAndroid Build Coastguard Worker //! 112*e1997b9aSAndroid Build Coastguard Worker //! ``` 113*e1997b9aSAndroid Build Coastguard Worker //! struct Operation { 114*e1997b9aSAndroid Build Coastguard Worker //! ... 115*e1997b9aSAndroid Build Coastguard Worker //! outcome: Mutex<Outcome>, 116*e1997b9aSAndroid Build Coastguard Worker //! ... 117*e1997b9aSAndroid Build Coastguard Worker //! } 118*e1997b9aSAndroid Build Coastguard Worker //! ``` 119*e1997b9aSAndroid Build Coastguard Worker //! 120*e1997b9aSAndroid Build Coastguard Worker //! Any request that can change the outcome, i.e., `update`, `finish`, `abort`, 121*e1997b9aSAndroid Build Coastguard Worker //! `drop`, and `prune` has to take the outcome lock and check if the outcome 122*e1997b9aSAndroid Build Coastguard Worker //! is still `Outcome::Unknown` before entering. `prune` is special in that 123*e1997b9aSAndroid Build Coastguard Worker //! it will `try_lock`, because we don't want to be blocked on a potentially 124*e1997b9aSAndroid Build Coastguard Worker //! long running request at another operation. If it fails to get the lock 125*e1997b9aSAndroid Build Coastguard Worker //! the operation is either being touched, which changes its pruning resistance, 126*e1997b9aSAndroid Build Coastguard Worker //! or it transitions to its end-of-life, which means we may get a free slot. 127*e1997b9aSAndroid Build Coastguard Worker //! Either way, we have to revaluate the pruning scores. 128*e1997b9aSAndroid Build Coastguard Worker 129*e1997b9aSAndroid Build Coastguard Worker use crate::enforcements::AuthInfo; 130*e1997b9aSAndroid Build Coastguard Worker use crate::error::{ 131*e1997b9aSAndroid Build Coastguard Worker error_to_serialized_error, into_binder, into_logged_binder, map_km_error, Error, ErrorCode, 132*e1997b9aSAndroid Build Coastguard Worker ResponseCode, SerializedError, 133*e1997b9aSAndroid Build Coastguard Worker }; 134*e1997b9aSAndroid Build Coastguard Worker use crate::ks_err; 135*e1997b9aSAndroid Build Coastguard Worker use crate::metrics_store::log_key_operation_event_stats; 136*e1997b9aSAndroid Build Coastguard Worker use crate::utils::watchdog as wd; 137*e1997b9aSAndroid Build Coastguard Worker use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{ 138*e1997b9aSAndroid Build Coastguard Worker IKeyMintOperation::IKeyMintOperation, KeyParameter::KeyParameter, KeyPurpose::KeyPurpose, 139*e1997b9aSAndroid Build Coastguard Worker SecurityLevel::SecurityLevel, 140*e1997b9aSAndroid Build Coastguard Worker }; 141*e1997b9aSAndroid Build Coastguard Worker use android_hardware_security_keymint::binder::{BinderFeatures, Strong}; 142*e1997b9aSAndroid Build Coastguard Worker use android_system_keystore2::aidl::android::system::keystore2::{ 143*e1997b9aSAndroid Build Coastguard Worker IKeystoreOperation::BnKeystoreOperation, IKeystoreOperation::IKeystoreOperation, 144*e1997b9aSAndroid Build Coastguard Worker }; 145*e1997b9aSAndroid Build Coastguard Worker use anyhow::{anyhow, Context, Result}; 146*e1997b9aSAndroid Build Coastguard Worker use std::{ 147*e1997b9aSAndroid Build Coastguard Worker collections::HashMap, 148*e1997b9aSAndroid Build Coastguard Worker sync::{Arc, Mutex, MutexGuard, Weak}, 149*e1997b9aSAndroid Build Coastguard Worker time::Duration, 150*e1997b9aSAndroid Build Coastguard Worker time::Instant, 151*e1997b9aSAndroid Build Coastguard Worker }; 152*e1997b9aSAndroid Build Coastguard Worker 153*e1997b9aSAndroid Build Coastguard Worker /// Operations have `Outcome::Unknown` as long as they are active. They transition 154*e1997b9aSAndroid Build Coastguard Worker /// to one of the other variants exactly once. The distinction in outcome is mainly 155*e1997b9aSAndroid Build Coastguard Worker /// for the statistic. 156*e1997b9aSAndroid Build Coastguard Worker #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] 157*e1997b9aSAndroid Build Coastguard Worker pub enum Outcome { 158*e1997b9aSAndroid Build Coastguard Worker /// Operations have `Outcome::Unknown` as long as they are active. 159*e1997b9aSAndroid Build Coastguard Worker Unknown, 160*e1997b9aSAndroid Build Coastguard Worker /// Operation is successful. 161*e1997b9aSAndroid Build Coastguard Worker Success, 162*e1997b9aSAndroid Build Coastguard Worker /// Operation is aborted. 163*e1997b9aSAndroid Build Coastguard Worker Abort, 164*e1997b9aSAndroid Build Coastguard Worker /// Operation is dropped. 165*e1997b9aSAndroid Build Coastguard Worker Dropped, 166*e1997b9aSAndroid Build Coastguard Worker /// Operation is pruned. 167*e1997b9aSAndroid Build Coastguard Worker Pruned, 168*e1997b9aSAndroid Build Coastguard Worker /// Operation is failed with the error code. 169*e1997b9aSAndroid Build Coastguard Worker ErrorCode(SerializedError), 170*e1997b9aSAndroid Build Coastguard Worker } 171*e1997b9aSAndroid Build Coastguard Worker 172*e1997b9aSAndroid Build Coastguard Worker /// Operation bundles all of the operation related resources and tracks the operation's 173*e1997b9aSAndroid Build Coastguard Worker /// outcome. 174*e1997b9aSAndroid Build Coastguard Worker #[derive(Debug)] 175*e1997b9aSAndroid Build Coastguard Worker pub struct Operation { 176*e1997b9aSAndroid Build Coastguard Worker // The index of this operation in the OperationDb. 177*e1997b9aSAndroid Build Coastguard Worker index: usize, 178*e1997b9aSAndroid Build Coastguard Worker km_op: Strong<dyn IKeyMintOperation>, 179*e1997b9aSAndroid Build Coastguard Worker last_usage: Mutex<Instant>, 180*e1997b9aSAndroid Build Coastguard Worker outcome: Mutex<Outcome>, 181*e1997b9aSAndroid Build Coastguard Worker owner: u32, // Uid of the operation's owner. 182*e1997b9aSAndroid Build Coastguard Worker auth_info: Mutex<AuthInfo>, 183*e1997b9aSAndroid Build Coastguard Worker forced: bool, 184*e1997b9aSAndroid Build Coastguard Worker logging_info: LoggingInfo, 185*e1997b9aSAndroid Build Coastguard Worker } 186*e1997b9aSAndroid Build Coastguard Worker 187*e1997b9aSAndroid Build Coastguard Worker /// Keeps track of the information required for logging operations. 188*e1997b9aSAndroid Build Coastguard Worker #[derive(Debug)] 189*e1997b9aSAndroid Build Coastguard Worker pub struct LoggingInfo { 190*e1997b9aSAndroid Build Coastguard Worker sec_level: SecurityLevel, 191*e1997b9aSAndroid Build Coastguard Worker purpose: KeyPurpose, 192*e1997b9aSAndroid Build Coastguard Worker op_params: Vec<KeyParameter>, 193*e1997b9aSAndroid Build Coastguard Worker key_upgraded: bool, 194*e1997b9aSAndroid Build Coastguard Worker } 195*e1997b9aSAndroid Build Coastguard Worker 196*e1997b9aSAndroid Build Coastguard Worker impl LoggingInfo { 197*e1997b9aSAndroid Build Coastguard Worker /// Constructor new( sec_level: SecurityLevel, purpose: KeyPurpose, op_params: Vec<KeyParameter>, key_upgraded: bool, ) -> LoggingInfo198*e1997b9aSAndroid Build Coastguard Worker pub fn new( 199*e1997b9aSAndroid Build Coastguard Worker sec_level: SecurityLevel, 200*e1997b9aSAndroid Build Coastguard Worker purpose: KeyPurpose, 201*e1997b9aSAndroid Build Coastguard Worker op_params: Vec<KeyParameter>, 202*e1997b9aSAndroid Build Coastguard Worker key_upgraded: bool, 203*e1997b9aSAndroid Build Coastguard Worker ) -> LoggingInfo { 204*e1997b9aSAndroid Build Coastguard Worker Self { sec_level, purpose, op_params, key_upgraded } 205*e1997b9aSAndroid Build Coastguard Worker } 206*e1997b9aSAndroid Build Coastguard Worker } 207*e1997b9aSAndroid Build Coastguard Worker 208*e1997b9aSAndroid Build Coastguard Worker struct PruningInfo { 209*e1997b9aSAndroid Build Coastguard Worker last_usage: Instant, 210*e1997b9aSAndroid Build Coastguard Worker owner: u32, 211*e1997b9aSAndroid Build Coastguard Worker index: usize, 212*e1997b9aSAndroid Build Coastguard Worker forced: bool, 213*e1997b9aSAndroid Build Coastguard Worker } 214*e1997b9aSAndroid Build Coastguard Worker 215*e1997b9aSAndroid Build Coastguard Worker // We don't except more than 32KiB of data in `update`, `updateAad`, and `finish`. 216*e1997b9aSAndroid Build Coastguard Worker const MAX_RECEIVE_DATA: usize = 0x8000; 217*e1997b9aSAndroid Build Coastguard Worker 218*e1997b9aSAndroid Build Coastguard Worker impl Operation { 219*e1997b9aSAndroid Build Coastguard Worker /// Constructor new( index: usize, km_op: binder::Strong<dyn IKeyMintOperation>, owner: u32, auth_info: AuthInfo, forced: bool, logging_info: LoggingInfo, ) -> Self220*e1997b9aSAndroid Build Coastguard Worker pub fn new( 221*e1997b9aSAndroid Build Coastguard Worker index: usize, 222*e1997b9aSAndroid Build Coastguard Worker km_op: binder::Strong<dyn IKeyMintOperation>, 223*e1997b9aSAndroid Build Coastguard Worker owner: u32, 224*e1997b9aSAndroid Build Coastguard Worker auth_info: AuthInfo, 225*e1997b9aSAndroid Build Coastguard Worker forced: bool, 226*e1997b9aSAndroid Build Coastguard Worker logging_info: LoggingInfo, 227*e1997b9aSAndroid Build Coastguard Worker ) -> Self { 228*e1997b9aSAndroid Build Coastguard Worker Self { 229*e1997b9aSAndroid Build Coastguard Worker index, 230*e1997b9aSAndroid Build Coastguard Worker km_op, 231*e1997b9aSAndroid Build Coastguard Worker last_usage: Mutex::new(Instant::now()), 232*e1997b9aSAndroid Build Coastguard Worker outcome: Mutex::new(Outcome::Unknown), 233*e1997b9aSAndroid Build Coastguard Worker owner, 234*e1997b9aSAndroid Build Coastguard Worker auth_info: Mutex::new(auth_info), 235*e1997b9aSAndroid Build Coastguard Worker forced, 236*e1997b9aSAndroid Build Coastguard Worker logging_info, 237*e1997b9aSAndroid Build Coastguard Worker } 238*e1997b9aSAndroid Build Coastguard Worker } 239*e1997b9aSAndroid Build Coastguard Worker get_pruning_info(&self) -> Option<PruningInfo>240*e1997b9aSAndroid Build Coastguard Worker fn get_pruning_info(&self) -> Option<PruningInfo> { 241*e1997b9aSAndroid Build Coastguard Worker // An operation may be finalized. 242*e1997b9aSAndroid Build Coastguard Worker if let Ok(guard) = self.outcome.try_lock() { 243*e1997b9aSAndroid Build Coastguard Worker match *guard { 244*e1997b9aSAndroid Build Coastguard Worker Outcome::Unknown => {} 245*e1997b9aSAndroid Build Coastguard Worker // If the outcome is any other than unknown, it has been finalized, 246*e1997b9aSAndroid Build Coastguard Worker // and we can no longer consider it for pruning. 247*e1997b9aSAndroid Build Coastguard Worker _ => return None, 248*e1997b9aSAndroid Build Coastguard Worker } 249*e1997b9aSAndroid Build Coastguard Worker } 250*e1997b9aSAndroid Build Coastguard Worker // Else: If we could not grab the lock, this means that the operation is currently 251*e1997b9aSAndroid Build Coastguard Worker // being used and it may be transitioning to finalized or it was simply updated. 252*e1997b9aSAndroid Build Coastguard Worker // In any case it is fair game to consider it for pruning. If the operation 253*e1997b9aSAndroid Build Coastguard Worker // transitioned to a final state, we will notice when we attempt to prune, and 254*e1997b9aSAndroid Build Coastguard Worker // a subsequent attempt to create a new operation will succeed. 255*e1997b9aSAndroid Build Coastguard Worker Some(PruningInfo { 256*e1997b9aSAndroid Build Coastguard Worker // Expect safety: 257*e1997b9aSAndroid Build Coastguard Worker // `last_usage` is locked only for primitive single line statements. 258*e1997b9aSAndroid Build Coastguard Worker // There is no chance to panic and poison the mutex. 259*e1997b9aSAndroid Build Coastguard Worker last_usage: *self.last_usage.lock().expect("In get_pruning_info."), 260*e1997b9aSAndroid Build Coastguard Worker owner: self.owner, 261*e1997b9aSAndroid Build Coastguard Worker index: self.index, 262*e1997b9aSAndroid Build Coastguard Worker forced: self.forced, 263*e1997b9aSAndroid Build Coastguard Worker }) 264*e1997b9aSAndroid Build Coastguard Worker } 265*e1997b9aSAndroid Build Coastguard Worker prune(&self, last_usage: Instant) -> Result<(), Error>266*e1997b9aSAndroid Build Coastguard Worker fn prune(&self, last_usage: Instant) -> Result<(), Error> { 267*e1997b9aSAndroid Build Coastguard Worker let mut locked_outcome = match self.outcome.try_lock() { 268*e1997b9aSAndroid Build Coastguard Worker Ok(guard) => match *guard { 269*e1997b9aSAndroid Build Coastguard Worker Outcome::Unknown => guard, 270*e1997b9aSAndroid Build Coastguard Worker _ => return Err(Error::Km(ErrorCode::INVALID_OPERATION_HANDLE)), 271*e1997b9aSAndroid Build Coastguard Worker }, 272*e1997b9aSAndroid Build Coastguard Worker Err(_) => return Err(Error::Rc(ResponseCode::OPERATION_BUSY)), 273*e1997b9aSAndroid Build Coastguard Worker }; 274*e1997b9aSAndroid Build Coastguard Worker 275*e1997b9aSAndroid Build Coastguard Worker // In `OperationDb::prune`, which is our caller, we first gather the pruning 276*e1997b9aSAndroid Build Coastguard Worker // information including the last usage. When we select a candidate 277*e1997b9aSAndroid Build Coastguard Worker // we call `prune` on that candidate passing the last_usage 278*e1997b9aSAndroid Build Coastguard Worker // that we gathered earlier. If the actual last usage 279*e1997b9aSAndroid Build Coastguard Worker // has changed since than, it means the operation was busy in the 280*e1997b9aSAndroid Build Coastguard Worker // meantime, which means that we have to reevaluate the pruning score. 281*e1997b9aSAndroid Build Coastguard Worker // 282*e1997b9aSAndroid Build Coastguard Worker // Expect safety: 283*e1997b9aSAndroid Build Coastguard Worker // `last_usage` is locked only for primitive single line statements. 284*e1997b9aSAndroid Build Coastguard Worker // There is no chance to panic and poison the mutex. 285*e1997b9aSAndroid Build Coastguard Worker if *self.last_usage.lock().expect("In Operation::prune()") != last_usage { 286*e1997b9aSAndroid Build Coastguard Worker return Err(Error::Rc(ResponseCode::OPERATION_BUSY)); 287*e1997b9aSAndroid Build Coastguard Worker } 288*e1997b9aSAndroid Build Coastguard Worker *locked_outcome = Outcome::Pruned; 289*e1997b9aSAndroid Build Coastguard Worker 290*e1997b9aSAndroid Build Coastguard Worker let _wp = wd::watch("Operation::prune: calling IKeyMintOperation::abort()"); 291*e1997b9aSAndroid Build Coastguard Worker 292*e1997b9aSAndroid Build Coastguard Worker // We abort the operation. If there was an error we log it but ignore it. 293*e1997b9aSAndroid Build Coastguard Worker if let Err(e) = map_km_error(self.km_op.abort()) { 294*e1997b9aSAndroid Build Coastguard Worker log::warn!("In prune: KeyMint::abort failed with {:?}.", e); 295*e1997b9aSAndroid Build Coastguard Worker } 296*e1997b9aSAndroid Build Coastguard Worker 297*e1997b9aSAndroid Build Coastguard Worker Ok(()) 298*e1997b9aSAndroid Build Coastguard Worker } 299*e1997b9aSAndroid Build Coastguard Worker 300*e1997b9aSAndroid Build Coastguard Worker // This function takes a Result from a KeyMint call and inspects it for errors. 301*e1997b9aSAndroid Build Coastguard Worker // If an error was found it updates the given `locked_outcome` accordingly. 302*e1997b9aSAndroid Build Coastguard Worker // It forwards the Result unmodified. 303*e1997b9aSAndroid Build Coastguard Worker // The precondition to this call must be *locked_outcome == Outcome::Unknown. 304*e1997b9aSAndroid Build Coastguard Worker // Ideally the `locked_outcome` came from a successful call to `check_active` 305*e1997b9aSAndroid Build Coastguard Worker // see below. update_outcome<T>( &self, locked_outcome: &mut Outcome, err: Result<T, Error>, ) -> Result<T, Error>306*e1997b9aSAndroid Build Coastguard Worker fn update_outcome<T>( 307*e1997b9aSAndroid Build Coastguard Worker &self, 308*e1997b9aSAndroid Build Coastguard Worker locked_outcome: &mut Outcome, 309*e1997b9aSAndroid Build Coastguard Worker err: Result<T, Error>, 310*e1997b9aSAndroid Build Coastguard Worker ) -> Result<T, Error> { 311*e1997b9aSAndroid Build Coastguard Worker if let Err(e) = &err { 312*e1997b9aSAndroid Build Coastguard Worker *locked_outcome = Outcome::ErrorCode(error_to_serialized_error(e)) 313*e1997b9aSAndroid Build Coastguard Worker } 314*e1997b9aSAndroid Build Coastguard Worker err 315*e1997b9aSAndroid Build Coastguard Worker } 316*e1997b9aSAndroid Build Coastguard Worker 317*e1997b9aSAndroid Build Coastguard Worker // This function grabs the outcome lock and checks the current outcome state. 318*e1997b9aSAndroid Build Coastguard Worker // If the outcome is still `Outcome::Unknown`, this function returns 319*e1997b9aSAndroid Build Coastguard Worker // the locked outcome for further updates. In any other case it returns 320*e1997b9aSAndroid Build Coastguard Worker // ErrorCode::INVALID_OPERATION_HANDLE indicating that this operation has 321*e1997b9aSAndroid Build Coastguard Worker // been finalized and is no longer active. check_active(&self) -> Result<MutexGuard<Outcome>>322*e1997b9aSAndroid Build Coastguard Worker fn check_active(&self) -> Result<MutexGuard<Outcome>> { 323*e1997b9aSAndroid Build Coastguard Worker let guard = self.outcome.lock().expect("In check_active."); 324*e1997b9aSAndroid Build Coastguard Worker match *guard { 325*e1997b9aSAndroid Build Coastguard Worker Outcome::Unknown => Ok(guard), 326*e1997b9aSAndroid Build Coastguard Worker _ => Err(Error::Km(ErrorCode::INVALID_OPERATION_HANDLE)) 327*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("Call on finalized operation with outcome: {:?}.", *guard)), 328*e1997b9aSAndroid Build Coastguard Worker } 329*e1997b9aSAndroid Build Coastguard Worker } 330*e1997b9aSAndroid Build Coastguard Worker 331*e1997b9aSAndroid Build Coastguard Worker // This function checks the amount of input data sent to us. We reject any buffer 332*e1997b9aSAndroid Build Coastguard Worker // exceeding MAX_RECEIVE_DATA bytes as input to `update`, `update_aad`, and `finish` 333*e1997b9aSAndroid Build Coastguard Worker // in order to force clients into using reasonable limits. check_input_length(data: &[u8]) -> Result<()>334*e1997b9aSAndroid Build Coastguard Worker fn check_input_length(data: &[u8]) -> Result<()> { 335*e1997b9aSAndroid Build Coastguard Worker if data.len() > MAX_RECEIVE_DATA { 336*e1997b9aSAndroid Build Coastguard Worker // This error code is unique, no context required here. 337*e1997b9aSAndroid Build Coastguard Worker return Err(anyhow!(Error::Rc(ResponseCode::TOO_MUCH_DATA))); 338*e1997b9aSAndroid Build Coastguard Worker } 339*e1997b9aSAndroid Build Coastguard Worker Ok(()) 340*e1997b9aSAndroid Build Coastguard Worker } 341*e1997b9aSAndroid Build Coastguard Worker 342*e1997b9aSAndroid Build Coastguard Worker // Update the last usage to now. touch(&self)343*e1997b9aSAndroid Build Coastguard Worker fn touch(&self) { 344*e1997b9aSAndroid Build Coastguard Worker // Expect safety: 345*e1997b9aSAndroid Build Coastguard Worker // `last_usage` is locked only for primitive single line statements. 346*e1997b9aSAndroid Build Coastguard Worker // There is no chance to panic and poison the mutex. 347*e1997b9aSAndroid Build Coastguard Worker *self.last_usage.lock().expect("In touch.") = Instant::now(); 348*e1997b9aSAndroid Build Coastguard Worker } 349*e1997b9aSAndroid Build Coastguard Worker 350*e1997b9aSAndroid Build Coastguard Worker /// Implementation of `IKeystoreOperation::updateAad`. 351*e1997b9aSAndroid Build Coastguard Worker /// Refer to the AIDL spec at system/hardware/interfaces/keystore2 for details. update_aad(&self, aad_input: &[u8]) -> Result<()>352*e1997b9aSAndroid Build Coastguard Worker fn update_aad(&self, aad_input: &[u8]) -> Result<()> { 353*e1997b9aSAndroid Build Coastguard Worker let mut outcome = self.check_active().context("In update_aad")?; 354*e1997b9aSAndroid Build Coastguard Worker Self::check_input_length(aad_input).context("In update_aad")?; 355*e1997b9aSAndroid Build Coastguard Worker self.touch(); 356*e1997b9aSAndroid Build Coastguard Worker 357*e1997b9aSAndroid Build Coastguard Worker let (hat, tst) = self 358*e1997b9aSAndroid Build Coastguard Worker .auth_info 359*e1997b9aSAndroid Build Coastguard Worker .lock() 360*e1997b9aSAndroid Build Coastguard Worker .unwrap() 361*e1997b9aSAndroid Build Coastguard Worker .before_update() 362*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("Trying to get auth tokens."))?; 363*e1997b9aSAndroid Build Coastguard Worker 364*e1997b9aSAndroid Build Coastguard Worker self.update_outcome(&mut outcome, { 365*e1997b9aSAndroid Build Coastguard Worker let _wp = wd::watch("Operation::update_aad: calling IKeyMintOperation::updateAad"); 366*e1997b9aSAndroid Build Coastguard Worker map_km_error(self.km_op.updateAad(aad_input, hat.as_ref(), tst.as_ref())) 367*e1997b9aSAndroid Build Coastguard Worker }) 368*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("Update failed."))?; 369*e1997b9aSAndroid Build Coastguard Worker 370*e1997b9aSAndroid Build Coastguard Worker Ok(()) 371*e1997b9aSAndroid Build Coastguard Worker } 372*e1997b9aSAndroid Build Coastguard Worker 373*e1997b9aSAndroid Build Coastguard Worker /// Implementation of `IKeystoreOperation::update`. 374*e1997b9aSAndroid Build Coastguard Worker /// Refer to the AIDL spec at system/hardware/interfaces/keystore2 for details. update(&self, input: &[u8]) -> Result<Option<Vec<u8>>>375*e1997b9aSAndroid Build Coastguard Worker fn update(&self, input: &[u8]) -> Result<Option<Vec<u8>>> { 376*e1997b9aSAndroid Build Coastguard Worker let mut outcome = self.check_active().context("In update")?; 377*e1997b9aSAndroid Build Coastguard Worker Self::check_input_length(input).context("In update")?; 378*e1997b9aSAndroid Build Coastguard Worker self.touch(); 379*e1997b9aSAndroid Build Coastguard Worker 380*e1997b9aSAndroid Build Coastguard Worker let (hat, tst) = self 381*e1997b9aSAndroid Build Coastguard Worker .auth_info 382*e1997b9aSAndroid Build Coastguard Worker .lock() 383*e1997b9aSAndroid Build Coastguard Worker .unwrap() 384*e1997b9aSAndroid Build Coastguard Worker .before_update() 385*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("Trying to get auth tokens."))?; 386*e1997b9aSAndroid Build Coastguard Worker 387*e1997b9aSAndroid Build Coastguard Worker let output = self 388*e1997b9aSAndroid Build Coastguard Worker .update_outcome(&mut outcome, { 389*e1997b9aSAndroid Build Coastguard Worker let _wp = wd::watch("Operation::update: calling IKeyMintOperation::update"); 390*e1997b9aSAndroid Build Coastguard Worker map_km_error(self.km_op.update(input, hat.as_ref(), tst.as_ref())) 391*e1997b9aSAndroid Build Coastguard Worker }) 392*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("Update failed."))?; 393*e1997b9aSAndroid Build Coastguard Worker 394*e1997b9aSAndroid Build Coastguard Worker if output.is_empty() { 395*e1997b9aSAndroid Build Coastguard Worker Ok(None) 396*e1997b9aSAndroid Build Coastguard Worker } else { 397*e1997b9aSAndroid Build Coastguard Worker Ok(Some(output)) 398*e1997b9aSAndroid Build Coastguard Worker } 399*e1997b9aSAndroid Build Coastguard Worker } 400*e1997b9aSAndroid Build Coastguard Worker 401*e1997b9aSAndroid Build Coastguard Worker /// Implementation of `IKeystoreOperation::finish`. 402*e1997b9aSAndroid Build Coastguard Worker /// Refer to the AIDL spec at system/hardware/interfaces/keystore2 for details. finish(&self, input: Option<&[u8]>, signature: Option<&[u8]>) -> Result<Option<Vec<u8>>>403*e1997b9aSAndroid Build Coastguard Worker fn finish(&self, input: Option<&[u8]>, signature: Option<&[u8]>) -> Result<Option<Vec<u8>>> { 404*e1997b9aSAndroid Build Coastguard Worker let mut outcome = self.check_active().context("In finish")?; 405*e1997b9aSAndroid Build Coastguard Worker if let Some(input) = input { 406*e1997b9aSAndroid Build Coastguard Worker Self::check_input_length(input).context("In finish")?; 407*e1997b9aSAndroid Build Coastguard Worker } 408*e1997b9aSAndroid Build Coastguard Worker self.touch(); 409*e1997b9aSAndroid Build Coastguard Worker 410*e1997b9aSAndroid Build Coastguard Worker let (hat, tst, confirmation_token) = self 411*e1997b9aSAndroid Build Coastguard Worker .auth_info 412*e1997b9aSAndroid Build Coastguard Worker .lock() 413*e1997b9aSAndroid Build Coastguard Worker .unwrap() 414*e1997b9aSAndroid Build Coastguard Worker .before_finish() 415*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("Trying to get auth tokens."))?; 416*e1997b9aSAndroid Build Coastguard Worker 417*e1997b9aSAndroid Build Coastguard Worker let output = self 418*e1997b9aSAndroid Build Coastguard Worker .update_outcome(&mut outcome, { 419*e1997b9aSAndroid Build Coastguard Worker let _wp = wd::watch("Operation::finish: calling IKeyMintOperation::finish"); 420*e1997b9aSAndroid Build Coastguard Worker map_km_error(self.km_op.finish( 421*e1997b9aSAndroid Build Coastguard Worker input, 422*e1997b9aSAndroid Build Coastguard Worker signature, 423*e1997b9aSAndroid Build Coastguard Worker hat.as_ref(), 424*e1997b9aSAndroid Build Coastguard Worker tst.as_ref(), 425*e1997b9aSAndroid Build Coastguard Worker confirmation_token.as_deref(), 426*e1997b9aSAndroid Build Coastguard Worker )) 427*e1997b9aSAndroid Build Coastguard Worker }) 428*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("Finish failed."))?; 429*e1997b9aSAndroid Build Coastguard Worker 430*e1997b9aSAndroid Build Coastguard Worker self.auth_info.lock().unwrap().after_finish().context("In finish.")?; 431*e1997b9aSAndroid Build Coastguard Worker 432*e1997b9aSAndroid Build Coastguard Worker // At this point the operation concluded successfully. 433*e1997b9aSAndroid Build Coastguard Worker *outcome = Outcome::Success; 434*e1997b9aSAndroid Build Coastguard Worker 435*e1997b9aSAndroid Build Coastguard Worker if output.is_empty() { 436*e1997b9aSAndroid Build Coastguard Worker Ok(None) 437*e1997b9aSAndroid Build Coastguard Worker } else { 438*e1997b9aSAndroid Build Coastguard Worker Ok(Some(output)) 439*e1997b9aSAndroid Build Coastguard Worker } 440*e1997b9aSAndroid Build Coastguard Worker } 441*e1997b9aSAndroid Build Coastguard Worker 442*e1997b9aSAndroid Build Coastguard Worker /// Aborts the operation if it is active. IFF the operation is aborted the outcome is 443*e1997b9aSAndroid Build Coastguard Worker /// set to `outcome`. `outcome` must reflect the reason for the abort. Since the operation 444*e1997b9aSAndroid Build Coastguard Worker /// gets aborted `outcome` must not be `Operation::Success` or `Operation::Unknown`. abort(&self, outcome: Outcome) -> Result<()>445*e1997b9aSAndroid Build Coastguard Worker fn abort(&self, outcome: Outcome) -> Result<()> { 446*e1997b9aSAndroid Build Coastguard Worker let mut locked_outcome = self.check_active().context("In abort")?; 447*e1997b9aSAndroid Build Coastguard Worker *locked_outcome = outcome; 448*e1997b9aSAndroid Build Coastguard Worker 449*e1997b9aSAndroid Build Coastguard Worker { 450*e1997b9aSAndroid Build Coastguard Worker let _wp = wd::watch("Operation::abort: calling IKeyMintOperation::abort"); 451*e1997b9aSAndroid Build Coastguard Worker map_km_error(self.km_op.abort()).context(ks_err!("KeyMint::abort failed.")) 452*e1997b9aSAndroid Build Coastguard Worker } 453*e1997b9aSAndroid Build Coastguard Worker } 454*e1997b9aSAndroid Build Coastguard Worker } 455*e1997b9aSAndroid Build Coastguard Worker 456*e1997b9aSAndroid Build Coastguard Worker impl Drop for Operation { drop(&mut self)457*e1997b9aSAndroid Build Coastguard Worker fn drop(&mut self) { 458*e1997b9aSAndroid Build Coastguard Worker let guard = self.outcome.lock().expect("In drop."); 459*e1997b9aSAndroid Build Coastguard Worker log_key_operation_event_stats( 460*e1997b9aSAndroid Build Coastguard Worker self.logging_info.sec_level, 461*e1997b9aSAndroid Build Coastguard Worker self.logging_info.purpose, 462*e1997b9aSAndroid Build Coastguard Worker &(self.logging_info.op_params), 463*e1997b9aSAndroid Build Coastguard Worker &guard, 464*e1997b9aSAndroid Build Coastguard Worker self.logging_info.key_upgraded, 465*e1997b9aSAndroid Build Coastguard Worker ); 466*e1997b9aSAndroid Build Coastguard Worker if let Outcome::Unknown = *guard { 467*e1997b9aSAndroid Build Coastguard Worker drop(guard); 468*e1997b9aSAndroid Build Coastguard Worker // If the operation was still active we call abort, setting 469*e1997b9aSAndroid Build Coastguard Worker // the outcome to `Outcome::Dropped` 470*e1997b9aSAndroid Build Coastguard Worker if let Err(e) = self.abort(Outcome::Dropped) { 471*e1997b9aSAndroid Build Coastguard Worker log::error!("While dropping Operation: abort failed:\n {:?}", e); 472*e1997b9aSAndroid Build Coastguard Worker } 473*e1997b9aSAndroid Build Coastguard Worker } 474*e1997b9aSAndroid Build Coastguard Worker } 475*e1997b9aSAndroid Build Coastguard Worker } 476*e1997b9aSAndroid Build Coastguard Worker 477*e1997b9aSAndroid Build Coastguard Worker /// The OperationDb holds weak references to all ongoing operations. 478*e1997b9aSAndroid Build Coastguard Worker /// Its main purpose is to facilitate operation pruning. 479*e1997b9aSAndroid Build Coastguard Worker #[derive(Debug, Default)] 480*e1997b9aSAndroid Build Coastguard Worker pub struct OperationDb { 481*e1997b9aSAndroid Build Coastguard Worker // TODO replace Vec with WeakTable when the weak_table crate becomes 482*e1997b9aSAndroid Build Coastguard Worker // available. 483*e1997b9aSAndroid Build Coastguard Worker operations: Mutex<Vec<Weak<Operation>>>, 484*e1997b9aSAndroid Build Coastguard Worker } 485*e1997b9aSAndroid Build Coastguard Worker 486*e1997b9aSAndroid Build Coastguard Worker impl OperationDb { 487*e1997b9aSAndroid Build Coastguard Worker /// Creates a new OperationDb. new() -> Self488*e1997b9aSAndroid Build Coastguard Worker pub fn new() -> Self { 489*e1997b9aSAndroid Build Coastguard Worker Self { operations: Mutex::new(Vec::new()) } 490*e1997b9aSAndroid Build Coastguard Worker } 491*e1997b9aSAndroid Build Coastguard Worker 492*e1997b9aSAndroid Build Coastguard Worker /// Creates a new operation. 493*e1997b9aSAndroid Build Coastguard Worker /// This function takes a KeyMint operation and an associated 494*e1997b9aSAndroid Build Coastguard Worker /// owner uid and returns a new Operation wrapped in a `std::sync::Arc`. create_operation( &self, km_op: binder::Strong<dyn IKeyMintOperation>, owner: u32, auth_info: AuthInfo, forced: bool, logging_info: LoggingInfo, ) -> Arc<Operation>495*e1997b9aSAndroid Build Coastguard Worker pub fn create_operation( 496*e1997b9aSAndroid Build Coastguard Worker &self, 497*e1997b9aSAndroid Build Coastguard Worker km_op: binder::Strong<dyn IKeyMintOperation>, 498*e1997b9aSAndroid Build Coastguard Worker owner: u32, 499*e1997b9aSAndroid Build Coastguard Worker auth_info: AuthInfo, 500*e1997b9aSAndroid Build Coastguard Worker forced: bool, 501*e1997b9aSAndroid Build Coastguard Worker logging_info: LoggingInfo, 502*e1997b9aSAndroid Build Coastguard Worker ) -> Arc<Operation> { 503*e1997b9aSAndroid Build Coastguard Worker // We use unwrap because we don't allow code that can panic while locked. 504*e1997b9aSAndroid Build Coastguard Worker let mut operations = self.operations.lock().expect("In create_operation."); 505*e1997b9aSAndroid Build Coastguard Worker 506*e1997b9aSAndroid Build Coastguard Worker let mut index: usize = 0; 507*e1997b9aSAndroid Build Coastguard Worker // First we iterate through the operation slots to try and find an unused 508*e1997b9aSAndroid Build Coastguard Worker // slot. If we don't find one, we append the new entry instead. 509*e1997b9aSAndroid Build Coastguard Worker match (*operations).iter_mut().find(|s| { 510*e1997b9aSAndroid Build Coastguard Worker index += 1; 511*e1997b9aSAndroid Build Coastguard Worker s.upgrade().is_none() 512*e1997b9aSAndroid Build Coastguard Worker }) { 513*e1997b9aSAndroid Build Coastguard Worker Some(free_slot) => { 514*e1997b9aSAndroid Build Coastguard Worker let new_op = Arc::new(Operation::new( 515*e1997b9aSAndroid Build Coastguard Worker index - 1, 516*e1997b9aSAndroid Build Coastguard Worker km_op, 517*e1997b9aSAndroid Build Coastguard Worker owner, 518*e1997b9aSAndroid Build Coastguard Worker auth_info, 519*e1997b9aSAndroid Build Coastguard Worker forced, 520*e1997b9aSAndroid Build Coastguard Worker logging_info, 521*e1997b9aSAndroid Build Coastguard Worker )); 522*e1997b9aSAndroid Build Coastguard Worker *free_slot = Arc::downgrade(&new_op); 523*e1997b9aSAndroid Build Coastguard Worker new_op 524*e1997b9aSAndroid Build Coastguard Worker } 525*e1997b9aSAndroid Build Coastguard Worker None => { 526*e1997b9aSAndroid Build Coastguard Worker let new_op = Arc::new(Operation::new( 527*e1997b9aSAndroid Build Coastguard Worker operations.len(), 528*e1997b9aSAndroid Build Coastguard Worker km_op, 529*e1997b9aSAndroid Build Coastguard Worker owner, 530*e1997b9aSAndroid Build Coastguard Worker auth_info, 531*e1997b9aSAndroid Build Coastguard Worker forced, 532*e1997b9aSAndroid Build Coastguard Worker logging_info, 533*e1997b9aSAndroid Build Coastguard Worker )); 534*e1997b9aSAndroid Build Coastguard Worker operations.push(Arc::downgrade(&new_op)); 535*e1997b9aSAndroid Build Coastguard Worker new_op 536*e1997b9aSAndroid Build Coastguard Worker } 537*e1997b9aSAndroid Build Coastguard Worker } 538*e1997b9aSAndroid Build Coastguard Worker } 539*e1997b9aSAndroid Build Coastguard Worker get(&self, index: usize) -> Option<Arc<Operation>>540*e1997b9aSAndroid Build Coastguard Worker fn get(&self, index: usize) -> Option<Arc<Operation>> { 541*e1997b9aSAndroid Build Coastguard Worker self.operations.lock().expect("In OperationDb::get.").get(index).and_then(|op| op.upgrade()) 542*e1997b9aSAndroid Build Coastguard Worker } 543*e1997b9aSAndroid Build Coastguard Worker 544*e1997b9aSAndroid Build Coastguard Worker /// Attempts to prune an operation. 545*e1997b9aSAndroid Build Coastguard Worker /// 546*e1997b9aSAndroid Build Coastguard Worker /// This function is used during operation creation, i.e., by 547*e1997b9aSAndroid Build Coastguard Worker /// `KeystoreSecurityLevel::create_operation`, to try and free up an operation slot 548*e1997b9aSAndroid Build Coastguard Worker /// if it got `ErrorCode::TOO_MANY_OPERATIONS` from the KeyMint backend. It is not 549*e1997b9aSAndroid Build Coastguard Worker /// guaranteed that an operation slot is available after this call successfully 550*e1997b9aSAndroid Build Coastguard Worker /// returned for various reasons. E.g., another thread may have snatched up the newly 551*e1997b9aSAndroid Build Coastguard Worker /// available slot. Callers may have to call prune multiple times before they get a 552*e1997b9aSAndroid Build Coastguard Worker /// free operation slot. Prune may also return `Err(Error::Rc(ResponseCode::BACKEND_BUSY))` 553*e1997b9aSAndroid Build Coastguard Worker /// which indicates that no prunable operation was found. 554*e1997b9aSAndroid Build Coastguard Worker /// 555*e1997b9aSAndroid Build Coastguard Worker /// To find a suitable candidate we compute the malus for the caller and each existing 556*e1997b9aSAndroid Build Coastguard Worker /// operation. The malus is the inverse of the pruning power (caller) or pruning 557*e1997b9aSAndroid Build Coastguard Worker /// resistance (existing operation). 558*e1997b9aSAndroid Build Coastguard Worker /// 559*e1997b9aSAndroid Build Coastguard Worker /// The malus is based on the number of sibling operations and age. Sibling 560*e1997b9aSAndroid Build Coastguard Worker /// operations are operations that have the same owner (UID). 561*e1997b9aSAndroid Build Coastguard Worker /// 562*e1997b9aSAndroid Build Coastguard Worker /// Every operation, existing or new, starts with a malus of 1. Every sibling 563*e1997b9aSAndroid Build Coastguard Worker /// increases the malus by one. The age is the time since an operation was last touched. 564*e1997b9aSAndroid Build Coastguard Worker /// It increases the malus by log6(<age in seconds> + 1) rounded down to the next 565*e1997b9aSAndroid Build Coastguard Worker /// integer. So the malus increases stepwise after 5s, 35s, 215s, ... 566*e1997b9aSAndroid Build Coastguard Worker /// Of two operations with the same malus the least recently used one is considered 567*e1997b9aSAndroid Build Coastguard Worker /// weaker. 568*e1997b9aSAndroid Build Coastguard Worker /// 569*e1997b9aSAndroid Build Coastguard Worker /// For the caller to be able to prune an operation it must find an operation 570*e1997b9aSAndroid Build Coastguard Worker /// with a malus higher than its own. 571*e1997b9aSAndroid Build Coastguard Worker /// 572*e1997b9aSAndroid Build Coastguard Worker /// The malus can be expressed as 573*e1997b9aSAndroid Build Coastguard Worker /// ``` 574*e1997b9aSAndroid Build Coastguard Worker /// malus = 1 + no_of_siblings + floor(log6(age_in_seconds + 1)) 575*e1997b9aSAndroid Build Coastguard Worker /// ``` 576*e1997b9aSAndroid Build Coastguard Worker /// where the constant `1` accounts for the operation under consideration. 577*e1997b9aSAndroid Build Coastguard Worker /// In reality we compute it as 578*e1997b9aSAndroid Build Coastguard Worker /// ``` 579*e1997b9aSAndroid Build Coastguard Worker /// caller_malus = 1 + running_siblings 580*e1997b9aSAndroid Build Coastguard Worker /// ``` 581*e1997b9aSAndroid Build Coastguard Worker /// because the new operation has no age and is not included in the `running_siblings`, 582*e1997b9aSAndroid Build Coastguard Worker /// and 583*e1997b9aSAndroid Build Coastguard Worker /// ``` 584*e1997b9aSAndroid Build Coastguard Worker /// running_malus = running_siblings + floor(log6(age_in_seconds + 1)) 585*e1997b9aSAndroid Build Coastguard Worker /// ``` 586*e1997b9aSAndroid Build Coastguard Worker /// because a running operation is included in the `running_siblings` and it has 587*e1997b9aSAndroid Build Coastguard Worker /// an age. 588*e1997b9aSAndroid Build Coastguard Worker /// 589*e1997b9aSAndroid Build Coastguard Worker /// ## Example 590*e1997b9aSAndroid Build Coastguard Worker /// A caller with no running operations has a malus of 1. Young (age < 5s) operations 591*e1997b9aSAndroid Build Coastguard Worker /// also with no siblings have a malus of one and cannot be pruned by the caller. 592*e1997b9aSAndroid Build Coastguard Worker /// We have to find an operation that has at least one sibling or is older than 5s. 593*e1997b9aSAndroid Build Coastguard Worker /// 594*e1997b9aSAndroid Build Coastguard Worker /// A caller with one running operation has a malus of 2. Now even young siblings 595*e1997b9aSAndroid Build Coastguard Worker /// or single child aging (5s <= age < 35s) operations are off limit. An aging 596*e1997b9aSAndroid Build Coastguard Worker /// sibling of two, however, would have a malus of 3 and would be fair game. 597*e1997b9aSAndroid Build Coastguard Worker /// 598*e1997b9aSAndroid Build Coastguard Worker /// ## Rationale 599*e1997b9aSAndroid Build Coastguard Worker /// Due to the limitation of KeyMint operation slots, we cannot get around pruning or 600*e1997b9aSAndroid Build Coastguard Worker /// a single app could easily DoS KeyMint. 601*e1997b9aSAndroid Build Coastguard Worker /// Keystore 1.0 used to always prune the least recently used operation. This at least 602*e1997b9aSAndroid Build Coastguard Worker /// guaranteed that new operations can always be started. With the increased usage 603*e1997b9aSAndroid Build Coastguard Worker /// of Keystore we saw increased pruning activity which can lead to a livelock 604*e1997b9aSAndroid Build Coastguard Worker /// situation in the worst case. 605*e1997b9aSAndroid Build Coastguard Worker /// 606*e1997b9aSAndroid Build Coastguard Worker /// With the new pruning strategy we want to provide well behaved clients with 607*e1997b9aSAndroid Build Coastguard Worker /// progress assurances while punishing DoS attempts. As a result of this 608*e1997b9aSAndroid Build Coastguard Worker /// strategy we can be in the situation where no operation can be pruned and the 609*e1997b9aSAndroid Build Coastguard Worker /// creation of a new operation fails. This allows single child operations which 610*e1997b9aSAndroid Build Coastguard Worker /// are frequently updated to complete, thereby breaking up livelock situations 611*e1997b9aSAndroid Build Coastguard Worker /// and facilitating system wide progress. 612*e1997b9aSAndroid Build Coastguard Worker /// 613*e1997b9aSAndroid Build Coastguard Worker /// ## Update 614*e1997b9aSAndroid Build Coastguard Worker /// We also allow callers to cannibalize their own sibling operations if no other 615*e1997b9aSAndroid Build Coastguard Worker /// slot can be found. In this case the least recently used sibling is pruned. prune(&self, caller: u32, forced: bool) -> Result<(), Error>616*e1997b9aSAndroid Build Coastguard Worker pub fn prune(&self, caller: u32, forced: bool) -> Result<(), Error> { 617*e1997b9aSAndroid Build Coastguard Worker loop { 618*e1997b9aSAndroid Build Coastguard Worker // Maps the uid of the owner to the number of operations that owner has 619*e1997b9aSAndroid Build Coastguard Worker // (running_siblings). More operations per owner lowers the pruning 620*e1997b9aSAndroid Build Coastguard Worker // resistance of the operations of that owner. Whereas the number of 621*e1997b9aSAndroid Build Coastguard Worker // ongoing operations of the caller lowers the pruning power of the caller. 622*e1997b9aSAndroid Build Coastguard Worker let mut owners: HashMap<u32, u64> = HashMap::new(); 623*e1997b9aSAndroid Build Coastguard Worker let mut pruning_info: Vec<PruningInfo> = Vec::new(); 624*e1997b9aSAndroid Build Coastguard Worker 625*e1997b9aSAndroid Build Coastguard Worker let now = Instant::now(); 626*e1997b9aSAndroid Build Coastguard Worker self.operations 627*e1997b9aSAndroid Build Coastguard Worker .lock() 628*e1997b9aSAndroid Build Coastguard Worker .expect("In OperationDb::prune: Trying to lock self.operations.") 629*e1997b9aSAndroid Build Coastguard Worker .iter() 630*e1997b9aSAndroid Build Coastguard Worker .for_each(|op| { 631*e1997b9aSAndroid Build Coastguard Worker if let Some(op) = op.upgrade() { 632*e1997b9aSAndroid Build Coastguard Worker if let Some(p_info) = op.get_pruning_info() { 633*e1997b9aSAndroid Build Coastguard Worker let owner = p_info.owner; 634*e1997b9aSAndroid Build Coastguard Worker pruning_info.push(p_info); 635*e1997b9aSAndroid Build Coastguard Worker // Count operations per owner. 636*e1997b9aSAndroid Build Coastguard Worker *owners.entry(owner).or_insert(0) += 1; 637*e1997b9aSAndroid Build Coastguard Worker } 638*e1997b9aSAndroid Build Coastguard Worker } 639*e1997b9aSAndroid Build Coastguard Worker }); 640*e1997b9aSAndroid Build Coastguard Worker 641*e1997b9aSAndroid Build Coastguard Worker // If the operation is forced, the caller has a malus of 0. 642*e1997b9aSAndroid Build Coastguard Worker let caller_malus = if forced { 0 } else { 1u64 + *owners.entry(caller).or_default() }; 643*e1997b9aSAndroid Build Coastguard Worker 644*e1997b9aSAndroid Build Coastguard Worker // We iterate through all operations computing the malus and finding 645*e1997b9aSAndroid Build Coastguard Worker // the candidate with the highest malus which must also be higher 646*e1997b9aSAndroid Build Coastguard Worker // than the caller_malus. 647*e1997b9aSAndroid Build Coastguard Worker struct CandidateInfo { 648*e1997b9aSAndroid Build Coastguard Worker index: usize, 649*e1997b9aSAndroid Build Coastguard Worker malus: u64, 650*e1997b9aSAndroid Build Coastguard Worker last_usage: Instant, 651*e1997b9aSAndroid Build Coastguard Worker age: Duration, 652*e1997b9aSAndroid Build Coastguard Worker } 653*e1997b9aSAndroid Build Coastguard Worker let mut oldest_caller_op: Option<CandidateInfo> = None; 654*e1997b9aSAndroid Build Coastguard Worker let candidate = pruning_info.iter().fold( 655*e1997b9aSAndroid Build Coastguard Worker None, 656*e1997b9aSAndroid Build Coastguard Worker |acc: Option<CandidateInfo>, &PruningInfo { last_usage, owner, index, forced }| { 657*e1997b9aSAndroid Build Coastguard Worker // Compute the age of the current operation. 658*e1997b9aSAndroid Build Coastguard Worker let age = now 659*e1997b9aSAndroid Build Coastguard Worker .checked_duration_since(last_usage) 660*e1997b9aSAndroid Build Coastguard Worker .unwrap_or_else(|| Duration::new(0, 0)); 661*e1997b9aSAndroid Build Coastguard Worker 662*e1997b9aSAndroid Build Coastguard Worker // Find the least recently used sibling as an alternative pruning candidate. 663*e1997b9aSAndroid Build Coastguard Worker if owner == caller { 664*e1997b9aSAndroid Build Coastguard Worker if let Some(CandidateInfo { age: a, .. }) = oldest_caller_op { 665*e1997b9aSAndroid Build Coastguard Worker if age > a { 666*e1997b9aSAndroid Build Coastguard Worker oldest_caller_op = 667*e1997b9aSAndroid Build Coastguard Worker Some(CandidateInfo { index, malus: 0, last_usage, age }); 668*e1997b9aSAndroid Build Coastguard Worker } 669*e1997b9aSAndroid Build Coastguard Worker } else { 670*e1997b9aSAndroid Build Coastguard Worker oldest_caller_op = 671*e1997b9aSAndroid Build Coastguard Worker Some(CandidateInfo { index, malus: 0, last_usage, age }); 672*e1997b9aSAndroid Build Coastguard Worker } 673*e1997b9aSAndroid Build Coastguard Worker } 674*e1997b9aSAndroid Build Coastguard Worker 675*e1997b9aSAndroid Build Coastguard Worker // Compute the malus of the current operation. 676*e1997b9aSAndroid Build Coastguard Worker let malus = if forced { 677*e1997b9aSAndroid Build Coastguard Worker // Forced operations have a malus of 0. And cannot even be pruned 678*e1997b9aSAndroid Build Coastguard Worker // by other forced operations. 679*e1997b9aSAndroid Build Coastguard Worker 0 680*e1997b9aSAndroid Build Coastguard Worker } else { 681*e1997b9aSAndroid Build Coastguard Worker // Expect safety: Every owner in pruning_info was counted in 682*e1997b9aSAndroid Build Coastguard Worker // the owners map. So this unwrap cannot panic. 683*e1997b9aSAndroid Build Coastguard Worker *owners.get(&owner).expect( 684*e1997b9aSAndroid Build Coastguard Worker "This is odd. We should have counted every owner in pruning_info.", 685*e1997b9aSAndroid Build Coastguard Worker ) + ((age.as_secs() + 1) as f64).log(6.0).floor() as u64 686*e1997b9aSAndroid Build Coastguard Worker }; 687*e1997b9aSAndroid Build Coastguard Worker 688*e1997b9aSAndroid Build Coastguard Worker // Now check if the current operation is a viable/better candidate 689*e1997b9aSAndroid Build Coastguard Worker // the one currently stored in the accumulator. 690*e1997b9aSAndroid Build Coastguard Worker match acc { 691*e1997b9aSAndroid Build Coastguard Worker // First we have to find any operation that is prunable by the caller. 692*e1997b9aSAndroid Build Coastguard Worker None => { 693*e1997b9aSAndroid Build Coastguard Worker if caller_malus < malus { 694*e1997b9aSAndroid Build Coastguard Worker Some(CandidateInfo { index, malus, last_usage, age }) 695*e1997b9aSAndroid Build Coastguard Worker } else { 696*e1997b9aSAndroid Build Coastguard Worker None 697*e1997b9aSAndroid Build Coastguard Worker } 698*e1997b9aSAndroid Build Coastguard Worker } 699*e1997b9aSAndroid Build Coastguard Worker // If we have found one we look for the operation with the worst score. 700*e1997b9aSAndroid Build Coastguard Worker // If there is a tie, the older operation is considered weaker. 701*e1997b9aSAndroid Build Coastguard Worker Some(CandidateInfo { index: i, malus: m, last_usage: l, age: a }) => { 702*e1997b9aSAndroid Build Coastguard Worker if malus > m || (malus == m && age > a) { 703*e1997b9aSAndroid Build Coastguard Worker Some(CandidateInfo { index, malus, last_usage, age }) 704*e1997b9aSAndroid Build Coastguard Worker } else { 705*e1997b9aSAndroid Build Coastguard Worker Some(CandidateInfo { index: i, malus: m, last_usage: l, age: a }) 706*e1997b9aSAndroid Build Coastguard Worker } 707*e1997b9aSAndroid Build Coastguard Worker } 708*e1997b9aSAndroid Build Coastguard Worker } 709*e1997b9aSAndroid Build Coastguard Worker }, 710*e1997b9aSAndroid Build Coastguard Worker ); 711*e1997b9aSAndroid Build Coastguard Worker 712*e1997b9aSAndroid Build Coastguard Worker // If we did not find a suitable candidate we may cannibalize our oldest sibling. 713*e1997b9aSAndroid Build Coastguard Worker let candidate = candidate.or(oldest_caller_op); 714*e1997b9aSAndroid Build Coastguard Worker 715*e1997b9aSAndroid Build Coastguard Worker match candidate { 716*e1997b9aSAndroid Build Coastguard Worker Some(CandidateInfo { index, malus: _, last_usage, age: _ }) => { 717*e1997b9aSAndroid Build Coastguard Worker match self.get(index) { 718*e1997b9aSAndroid Build Coastguard Worker Some(op) => { 719*e1997b9aSAndroid Build Coastguard Worker match op.prune(last_usage) { 720*e1997b9aSAndroid Build Coastguard Worker // We successfully freed up a slot. 721*e1997b9aSAndroid Build Coastguard Worker Ok(()) => break Ok(()), 722*e1997b9aSAndroid Build Coastguard Worker // This means the operation we tried to prune was on its way 723*e1997b9aSAndroid Build Coastguard Worker // out. It also means that the slot it had occupied was freed up. 724*e1997b9aSAndroid Build Coastguard Worker Err(Error::Km(ErrorCode::INVALID_OPERATION_HANDLE)) => break Ok(()), 725*e1997b9aSAndroid Build Coastguard Worker // This means the operation we tried to prune was currently 726*e1997b9aSAndroid Build Coastguard Worker // servicing a request. There are two options. 727*e1997b9aSAndroid Build Coastguard Worker // * Assume that it was touched, which means that its 728*e1997b9aSAndroid Build Coastguard Worker // pruning resistance increased. In that case we have 729*e1997b9aSAndroid Build Coastguard Worker // to start over and find another candidate. 730*e1997b9aSAndroid Build Coastguard Worker // * Assume that the operation is transitioning to end-of-life. 731*e1997b9aSAndroid Build Coastguard Worker // which means that we got a free slot for free. 732*e1997b9aSAndroid Build Coastguard Worker // If we assume the first but the second is true, we prune 733*e1997b9aSAndroid Build Coastguard Worker // a good operation without need (aggressive approach). 734*e1997b9aSAndroid Build Coastguard Worker // If we assume the second but the first is true, our 735*e1997b9aSAndroid Build Coastguard Worker // caller will attempt to create a new KeyMint operation, 736*e1997b9aSAndroid Build Coastguard Worker // fail with `ErrorCode::TOO_MANY_OPERATIONS`, and call 737*e1997b9aSAndroid Build Coastguard Worker // us again (conservative approach). 738*e1997b9aSAndroid Build Coastguard Worker Err(Error::Rc(ResponseCode::OPERATION_BUSY)) => { 739*e1997b9aSAndroid Build Coastguard Worker // We choose the conservative approach, because 740*e1997b9aSAndroid Build Coastguard Worker // every needlessly pruned operation can impact 741*e1997b9aSAndroid Build Coastguard Worker // the user experience. 742*e1997b9aSAndroid Build Coastguard Worker // To switch to the aggressive approach replace 743*e1997b9aSAndroid Build Coastguard Worker // the following line with `continue`. 744*e1997b9aSAndroid Build Coastguard Worker break Ok(()); 745*e1997b9aSAndroid Build Coastguard Worker } 746*e1997b9aSAndroid Build Coastguard Worker 747*e1997b9aSAndroid Build Coastguard Worker // The candidate may have been touched so the score 748*e1997b9aSAndroid Build Coastguard Worker // has changed since our evaluation. 749*e1997b9aSAndroid Build Coastguard Worker _ => continue, 750*e1997b9aSAndroid Build Coastguard Worker } 751*e1997b9aSAndroid Build Coastguard Worker } 752*e1997b9aSAndroid Build Coastguard Worker // This index does not exist any more. The operation 753*e1997b9aSAndroid Build Coastguard Worker // in this slot was dropped. Good news, a slot 754*e1997b9aSAndroid Build Coastguard Worker // has freed up. 755*e1997b9aSAndroid Build Coastguard Worker None => break Ok(()), 756*e1997b9aSAndroid Build Coastguard Worker } 757*e1997b9aSAndroid Build Coastguard Worker } 758*e1997b9aSAndroid Build Coastguard Worker // We did not get a pruning candidate. 759*e1997b9aSAndroid Build Coastguard Worker None => break Err(Error::Rc(ResponseCode::BACKEND_BUSY)), 760*e1997b9aSAndroid Build Coastguard Worker } 761*e1997b9aSAndroid Build Coastguard Worker } 762*e1997b9aSAndroid Build Coastguard Worker } 763*e1997b9aSAndroid Build Coastguard Worker } 764*e1997b9aSAndroid Build Coastguard Worker 765*e1997b9aSAndroid Build Coastguard Worker /// Implementation of IKeystoreOperation. 766*e1997b9aSAndroid Build Coastguard Worker pub struct KeystoreOperation { 767*e1997b9aSAndroid Build Coastguard Worker operation: Mutex<Option<Arc<Operation>>>, 768*e1997b9aSAndroid Build Coastguard Worker } 769*e1997b9aSAndroid Build Coastguard Worker 770*e1997b9aSAndroid Build Coastguard Worker impl KeystoreOperation { 771*e1997b9aSAndroid Build Coastguard Worker /// Creates a new operation instance wrapped in a 772*e1997b9aSAndroid Build Coastguard Worker /// BnKeystoreOperation proxy object. It also enables 773*e1997b9aSAndroid Build Coastguard Worker /// `BinderFeatures::set_requesting_sid` on the new interface, because 774*e1997b9aSAndroid Build Coastguard Worker /// we need it for checking Keystore permissions. new_native_binder(operation: Arc<Operation>) -> binder::Strong<dyn IKeystoreOperation>775*e1997b9aSAndroid Build Coastguard Worker pub fn new_native_binder(operation: Arc<Operation>) -> binder::Strong<dyn IKeystoreOperation> { 776*e1997b9aSAndroid Build Coastguard Worker BnKeystoreOperation::new_binder( 777*e1997b9aSAndroid Build Coastguard Worker Self { operation: Mutex::new(Some(operation)) }, 778*e1997b9aSAndroid Build Coastguard Worker BinderFeatures { set_requesting_sid: true, ..BinderFeatures::default() }, 779*e1997b9aSAndroid Build Coastguard Worker ) 780*e1997b9aSAndroid Build Coastguard Worker } 781*e1997b9aSAndroid Build Coastguard Worker 782*e1997b9aSAndroid Build Coastguard Worker /// Grabs the outer operation mutex and calls `f` on the locked operation. 783*e1997b9aSAndroid Build Coastguard Worker /// The function also deletes the operation if it returns with an error or if 784*e1997b9aSAndroid Build Coastguard Worker /// `delete_op` is true. with_locked_operation<T, F>(&self, f: F, delete_op: bool) -> Result<T> where for<'a> F: FnOnce(&'a Operation) -> Result<T>,785*e1997b9aSAndroid Build Coastguard Worker fn with_locked_operation<T, F>(&self, f: F, delete_op: bool) -> Result<T> 786*e1997b9aSAndroid Build Coastguard Worker where 787*e1997b9aSAndroid Build Coastguard Worker for<'a> F: FnOnce(&'a Operation) -> Result<T>, 788*e1997b9aSAndroid Build Coastguard Worker { 789*e1997b9aSAndroid Build Coastguard Worker let mut delete_op: bool = delete_op; 790*e1997b9aSAndroid Build Coastguard Worker match self.operation.try_lock() { 791*e1997b9aSAndroid Build Coastguard Worker Ok(mut mutex_guard) => { 792*e1997b9aSAndroid Build Coastguard Worker let result = match &*mutex_guard { 793*e1997b9aSAndroid Build Coastguard Worker Some(op) => { 794*e1997b9aSAndroid Build Coastguard Worker let result = f(op); 795*e1997b9aSAndroid Build Coastguard Worker // Any error here means we can discard the operation. 796*e1997b9aSAndroid Build Coastguard Worker if result.is_err() { 797*e1997b9aSAndroid Build Coastguard Worker delete_op = true; 798*e1997b9aSAndroid Build Coastguard Worker } 799*e1997b9aSAndroid Build Coastguard Worker result 800*e1997b9aSAndroid Build Coastguard Worker } 801*e1997b9aSAndroid Build Coastguard Worker None => Err(Error::Km(ErrorCode::INVALID_OPERATION_HANDLE)) 802*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("KeystoreOperation::with_locked_operation")), 803*e1997b9aSAndroid Build Coastguard Worker }; 804*e1997b9aSAndroid Build Coastguard Worker 805*e1997b9aSAndroid Build Coastguard Worker if delete_op { 806*e1997b9aSAndroid Build Coastguard Worker // We give up our reference to the Operation, thereby freeing up our 807*e1997b9aSAndroid Build Coastguard Worker // internal resources and ending the wrapped KeyMint operation. 808*e1997b9aSAndroid Build Coastguard Worker // This KeystoreOperation object will still be owned by an SpIBinder 809*e1997b9aSAndroid Build Coastguard Worker // until the client drops its remote reference. 810*e1997b9aSAndroid Build Coastguard Worker *mutex_guard = None; 811*e1997b9aSAndroid Build Coastguard Worker } 812*e1997b9aSAndroid Build Coastguard Worker result 813*e1997b9aSAndroid Build Coastguard Worker } 814*e1997b9aSAndroid Build Coastguard Worker Err(_) => Err(Error::Rc(ResponseCode::OPERATION_BUSY)) 815*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("KeystoreOperation::with_locked_operation")), 816*e1997b9aSAndroid Build Coastguard Worker } 817*e1997b9aSAndroid Build Coastguard Worker } 818*e1997b9aSAndroid Build Coastguard Worker } 819*e1997b9aSAndroid Build Coastguard Worker 820*e1997b9aSAndroid Build Coastguard Worker impl binder::Interface for KeystoreOperation {} 821*e1997b9aSAndroid Build Coastguard Worker 822*e1997b9aSAndroid Build Coastguard Worker impl IKeystoreOperation for KeystoreOperation { updateAad(&self, aad_input: &[u8]) -> binder::Result<()>823*e1997b9aSAndroid Build Coastguard Worker fn updateAad(&self, aad_input: &[u8]) -> binder::Result<()> { 824*e1997b9aSAndroid Build Coastguard Worker let _wp = wd::watch("IKeystoreOperation::updateAad"); 825*e1997b9aSAndroid Build Coastguard Worker self.with_locked_operation( 826*e1997b9aSAndroid Build Coastguard Worker |op| op.update_aad(aad_input).context(ks_err!("KeystoreOperation::updateAad")), 827*e1997b9aSAndroid Build Coastguard Worker false, 828*e1997b9aSAndroid Build Coastguard Worker ) 829*e1997b9aSAndroid Build Coastguard Worker .map_err(into_logged_binder) 830*e1997b9aSAndroid Build Coastguard Worker } 831*e1997b9aSAndroid Build Coastguard Worker update(&self, input: &[u8]) -> binder::Result<Option<Vec<u8>>>832*e1997b9aSAndroid Build Coastguard Worker fn update(&self, input: &[u8]) -> binder::Result<Option<Vec<u8>>> { 833*e1997b9aSAndroid Build Coastguard Worker let _wp = wd::watch("IKeystoreOperation::update"); 834*e1997b9aSAndroid Build Coastguard Worker self.with_locked_operation( 835*e1997b9aSAndroid Build Coastguard Worker |op| op.update(input).context(ks_err!("KeystoreOperation::update")), 836*e1997b9aSAndroid Build Coastguard Worker false, 837*e1997b9aSAndroid Build Coastguard Worker ) 838*e1997b9aSAndroid Build Coastguard Worker .map_err(into_logged_binder) 839*e1997b9aSAndroid Build Coastguard Worker } finish( &self, input: Option<&[u8]>, signature: Option<&[u8]>, ) -> binder::Result<Option<Vec<u8>>>840*e1997b9aSAndroid Build Coastguard Worker fn finish( 841*e1997b9aSAndroid Build Coastguard Worker &self, 842*e1997b9aSAndroid Build Coastguard Worker input: Option<&[u8]>, 843*e1997b9aSAndroid Build Coastguard Worker signature: Option<&[u8]>, 844*e1997b9aSAndroid Build Coastguard Worker ) -> binder::Result<Option<Vec<u8>>> { 845*e1997b9aSAndroid Build Coastguard Worker let _wp = wd::watch("IKeystoreOperation::finish"); 846*e1997b9aSAndroid Build Coastguard Worker self.with_locked_operation( 847*e1997b9aSAndroid Build Coastguard Worker |op| op.finish(input, signature).context(ks_err!("KeystoreOperation::finish")), 848*e1997b9aSAndroid Build Coastguard Worker true, 849*e1997b9aSAndroid Build Coastguard Worker ) 850*e1997b9aSAndroid Build Coastguard Worker .map_err(into_logged_binder) 851*e1997b9aSAndroid Build Coastguard Worker } 852*e1997b9aSAndroid Build Coastguard Worker abort(&self) -> binder::Result<()>853*e1997b9aSAndroid Build Coastguard Worker fn abort(&self) -> binder::Result<()> { 854*e1997b9aSAndroid Build Coastguard Worker let _wp = wd::watch("IKeystoreOperation::abort"); 855*e1997b9aSAndroid Build Coastguard Worker let result = self.with_locked_operation( 856*e1997b9aSAndroid Build Coastguard Worker |op| op.abort(Outcome::Abort).context(ks_err!("KeystoreOperation::abort")), 857*e1997b9aSAndroid Build Coastguard Worker true, 858*e1997b9aSAndroid Build Coastguard Worker ); 859*e1997b9aSAndroid Build Coastguard Worker result.map_err(|e| { 860*e1997b9aSAndroid Build Coastguard Worker match e.root_cause().downcast_ref::<Error>() { 861*e1997b9aSAndroid Build Coastguard Worker // Calling abort on expired operations is something very common. 862*e1997b9aSAndroid Build Coastguard Worker // There is no reason to clutter the log with it. It is never the cause 863*e1997b9aSAndroid Build Coastguard Worker // for a true problem. 864*e1997b9aSAndroid Build Coastguard Worker Some(Error::Km(ErrorCode::INVALID_OPERATION_HANDLE)) => {} 865*e1997b9aSAndroid Build Coastguard Worker _ => log::error!("{:?}", e), 866*e1997b9aSAndroid Build Coastguard Worker }; 867*e1997b9aSAndroid Build Coastguard Worker into_binder(e) 868*e1997b9aSAndroid Build Coastguard Worker }) 869*e1997b9aSAndroid Build Coastguard Worker } 870*e1997b9aSAndroid Build Coastguard Worker } 871