xref: /aosp_15_r20/system/security/keystore2/src/operation.rs (revision e1997b9af69e3155ead6e072d106a0077849ffba)
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