diff --git a/keystore2/src/keystore2_main.rs b/keystore2/src/keystore2_main.rs
new file mode 100644
index 0000000..dea0a93
--- /dev/null
+++ b/keystore2/src/keystore2_main.rs
@@ -0,0 +1,59 @@
+// Copyright 2020, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! This crate implements Keystore 2.0.
+
+use binder::Interface;
+use keystore2::service::KeystoreService;
+use log::{error, info};
+use std::panic;
+
+static KS2_SERVICE_NAME: &str = "android.system.keystore2";
+
+/// Keystore 2.0 takes one argument which is a path indicating its designated working directory.
+fn main() {
+    // Initialize android logging.
+    android_logger::init_once(
+        android_logger::Config::default().with_tag("keystore2").with_min_level(log::Level::Debug),
+    );
+    // Redirect panic messages to logcat.
+    panic::set_hook(Box::new(|panic_info| {
+        error!("{}", panic_info);
+    }));
+
+    // Saying hi.
+    info!("Keystore2 is starting.");
+
+    let mut args = std::env::args();
+    args.next().expect("That's odd. How is there not even a first argument?");
+    if let Some(dir) = args.next() {
+        if std::env::set_current_dir(dir.clone()).is_err() {
+            panic!("Failed to set working directory {}.", dir)
+        }
+    } else {
+        panic!("Must specify a working directory.");
+    }
+
+    let ks_service = KeystoreService::new_native_binder().unwrap_or_else(|e| {
+        panic!("Failed to create service {} because of {:?}.", KS2_SERVICE_NAME, e);
+    });
+    binder::add_service(KS2_SERVICE_NAME, ks_service.as_binder()).unwrap_or_else(|e| {
+        panic!("Failed to register service {} because of {:?}.", KS2_SERVICE_NAME, e);
+    });
+
+    info!("Successfully registered Keystore 2.0 service.");
+    info!("Joining threadpool now.");
+
+    binder::ProcessState::join_thread_pool();
+}
diff --git a/keystore2/src/lib.rs b/keystore2/src/lib.rs
index 7439a5b..067399e 100644
--- a/keystore2/src/lib.rs
+++ b/keystore2/src/lib.rs
@@ -19,5 +19,8 @@
 pub mod globals;
 /// Internal Representation of Key Parameter and convenience functions.
 pub mod key_parameter;
+pub mod operation;
 pub mod permission;
+pub mod security_level;
+pub mod service;
 pub mod utils;
diff --git a/keystore2/src/operation.rs b/keystore2/src/operation.rs
new file mode 100644
index 0000000..f987188
--- /dev/null
+++ b/keystore2/src/operation.rs
@@ -0,0 +1,768 @@
+// Copyright 2020, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! This crate implements the `IKeystoreOperation` AIDL interface, which represents
+//! an ongoing key operation, as well as the operation database, which is mainly
+//! required for tracking operations for the purpose of pruning.
+//! This crate also implements an operation pruning strategy.
+//!
+//! Operations implement the API calls update, finish, and abort.
+//! Additionally, an operation can be dropped and pruned. The former
+//! happens if the client deletes a binder to the operation object.
+//! An existing operation may get pruned when running out of operation
+//! slots and a new operation takes precedence.
+//!
+//! ## Operation Lifecycle
+//! An operation gets created when the client calls `IKeystoreSecurityLevel::create`.
+//! It may receive zero or more update request. The lifecycle ends when:
+//!  * `update` yields an error.
+//!  * `finish` is called.
+//!  * `abort` is called.
+//!  * The operation gets dropped.
+//!  * The operation gets pruned.
+//! `Operation` has an `Outcome` member. While the outcome is `Outcome::Unknown`,
+//! the operation is active and in a good state. Any of the above conditions may
+//! change the outcome to one of the defined outcomes Success, Abort, Dropped,
+//! Pruned, or ErrorCode. The latter is chosen in the case of an unexpected error, during
+//! `update` or `finish`. `Success` is chosen iff `finish` completes without error.
+//! Note that all operations get dropped eventually in the sense that they lose
+//! their last reference and get destroyed. At that point, the fate of the operation
+//! gets logged. However, an operation will transition to `Outcome::Dropped` iff
+//! the operation was still active (`Outcome::Unknown`) at that time.
+//!
+//! ## Operation Dropping
+//! To observe the dropping of an operation, we have to make sure that there
+//! are no strong references to the IBinder representing this operation.
+//! This would be simple enough if the operation object would need to be accessed
+//! only by transactions. But to perform pruning, we have to retain a reference to the
+//! original operation object.
+//!
+//! ## Operation Pruning
+//! Pruning an operation happens during the creation of a new operation.
+//! We have to iterate through the operation database to find a suitable
+//! candidate. Then we abort and finalize this operation setting its outcome to
+//! `Outcome::Pruned`. The corresponding KeyMint operation slot will have been freed
+//! up at this point, but the `Operation` object lingers. When the client
+//! attempts to use the operation again they will receive
+//! ErrorCode::INVALID_OPERATION_HANDLE indicating that the operation no longer
+//! exits. This should be the cue for the client to destroy its binder.
+//! At that point the operation gets dropped.
+//!
+//! ## Architecture
+//! The `IKeystoreOperation` trait is implemented by `KeystoreOperation`.
+//! This acts as a proxy object holding a strong reference to actual operation
+//! implementation `Operation`.
+//!
+//! ```
+//! struct KeystoreOperation {
+//!     operation: Mutex<Option<Arc<Operation>>>,
+//! }
+//! ```
+//!
+//! The `Mutex` serves two purposes. It provides interior mutability allowing
+//! us to set the Option to None. We do this when the life cycle ends during
+//! a call to `update`, `finish`, or `abort`. As a result most of the Operation
+//! related resources are freed. The `KeystoreOperation` proxy object still
+//! lingers until dropped by the client.
+//! The second purpose is to protect operations against concurrent usage.
+//! Failing to lock this mutex yields `ResponseCode::OPERATION_BUSY` and indicates
+//! a programming error in the client.
+//!
+//! Note that the Mutex only protects the operation against concurrent client calls.
+//! We still retain weak references to the operation in the operation database:
+//!
+//! ```
+//! struct OperationDb {
+//!     operations: Mutex<Vec<Weak<Operation>>>
+//! }
+//! ```
+//!
+//! This allows us to access the operations for the purpose of pruning.
+//! We do this in three phases.
+//!  1. We gather the pruning information. Besides non mutable information,
+//!     we access `last_usage` which is protected by a mutex.
+//!     We only lock this mutex for single statements at a time. During
+//!     this phase we hold the operation db lock.
+//!  2. We choose a pruning candidate by computing the pruning resistance
+//!     of each operation. We do this entirely with information we now
+//!     have on the stack without holding any locks.
+//!     (See `OperationDb::prune` for more details on the pruning strategy.)
+//!  3. During pruning we briefly lock the operation database again to get the
+//!     the pruning candidate by index. We then attempt to abort the candidate.
+//!     If the candidate was touched in the meantime or is currently fulfilling
+//!     a request (i.e., the client calls update, finish, or abort),
+//!     we go back to 1 and try again.
+//!
+//! So the outer Mutex in `KeystoreOperation::operation` only protects
+//! operations against concurrent client calls but not against concurrent
+//! pruning attempts. This is what the `Operation::outcome` mutex is used for.
+//!
+//! ```
+//! struct Operation {
+//!     ...
+//!     outcome: Mutex<Outcome>,
+//!     ...
+//! }
+//! ```
+//!
+//! Any request that can change the outcome, i.e., `update`, `finish`, `abort`,
+//! `drop`, and `prune` has to take the outcome lock and check if the outcome
+//! is still `Outcome::Unknown` before entering. `prune` is special in that
+//! it will `try_lock`, because we don't want to be blocked on a potentially
+//! long running request at another operation. If it fails to get the lock
+//! the operation is either being touched, which changes its pruning resistance,
+//! or it transitions to its end-of-life, which means we may get a free slot.
+//! Either way, we have to revaluate the pruning scores.
+
+use std::{
+    collections::HashMap,
+    sync::{Arc, Mutex, MutexGuard, Weak},
+    time::Duration,
+    time::Instant,
+};
+
+use crate::error::{map_km_error, map_or_log_err, Error, ErrorCode, ResponseCode};
+use crate::utils::Asp;
+use android_hardware_keymint::aidl::android::hardware::keymint::{
+    IKeyMintOperation::IKeyMintOperation, KeyParameter::KeyParameter as KmParam, Tag::Tag,
+};
+use android_system_keystore2::aidl::android::system::keystore2::{
+    IKeystoreOperation::BnKeystoreOperation, IKeystoreOperation::IKeystoreOperation,
+};
+use anyhow::{anyhow, Context, Result};
+use binder::{IBinder, Interface};
+
+/// Operations have `Outcome::Unknown` as long as they are active. They transition
+/// to one of the other variants exactly once. The distinction in outcome is mainly
+/// for the statistic.
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
+enum Outcome {
+    Unknown,
+    Success,
+    Abort,
+    Dropped,
+    Pruned,
+    ErrorCode(ErrorCode),
+}
+
+/// Operation bundles all of the operation related resources and tracks the operation's
+/// outcome.
+#[derive(Debug)]
+pub struct Operation {
+    // The index of this operation in the OperationDb.
+    index: usize,
+    km_op: Asp,
+    last_usage: Mutex<Instant>,
+    outcome: Mutex<Outcome>,
+    owner: u32, // Uid of the operation's owner.
+}
+
+struct PruningInfo {
+    last_usage: Instant,
+    owner: u32,
+    index: usize,
+}
+
+static EMPTY_BLOB: &[u8] = &[];
+// We don't except more than 32KiB of data in `update`, `updateAad`, and `finish`.
+const MAX_RECEIVE_DATA: usize = 0x8000;
+
+impl Operation {
+    /// Constructor
+    pub fn new(index: usize, km_op: Box<dyn IKeyMintOperation>, owner: u32) -> Self {
+        Self {
+            index,
+            km_op: Asp::new(km_op.as_binder()),
+            last_usage: Mutex::new(Instant::now()),
+            outcome: Mutex::new(Outcome::Unknown),
+            owner,
+        }
+    }
+
+    fn get_pruning_info(&self) -> PruningInfo {
+        // Expect safety:
+        // `last_usage` is locked only for primitive single line statements.
+        // There is no chance to panic and poison the mutex.
+        PruningInfo {
+            last_usage: *self.last_usage.lock().expect("In get_pruning_info."),
+            owner: self.owner,
+            index: self.index,
+        }
+    }
+
+    fn prune(&self, last_usage: Instant) -> Result<(), Error> {
+        let mut locked_outcome = match self.outcome.try_lock() {
+            Ok(guard) => match *guard {
+                Outcome::Unknown => guard,
+                _ => return Err(Error::Km(ErrorCode::INVALID_OPERATION_HANDLE)),
+            },
+            Err(_) => return Err(Error::Rc(ResponseCode::OPERATION_BUSY)),
+        };
+
+        // In `OperationDb::prune`, which is our caller, we first gather the pruning
+        // information including the last usage. When we select a candidate
+        // we call `prune` on that candidate passing the last_usage
+        // that we gathered earlier. If the actual last usage
+        // has changed since than, it means the operation was busy in the
+        // meantime, which means that we have to reevaluate the pruning score.
+        //
+        // Expect safety:
+        // `last_usage` is locked only for primitive single line statements.
+        // There is no chance to panic and poison the mutex.
+        if *self.last_usage.lock().expect("In Operation::prune()") != last_usage {
+            return Err(Error::Rc(ResponseCode::OPERATION_BUSY));
+        }
+        *locked_outcome = Outcome::Pruned;
+
+        let km_op: Box<dyn IKeyMintOperation> = match self.km_op.get_interface() {
+            Ok(km_op) => km_op,
+            Err(e) => {
+                log::error!("In prune: Failed to get KeyMintOperation interface.\n    {:?}", e);
+                return Err(Error::sys());
+            }
+        };
+
+        // We abort the operation. If there was an error we log it but ignore it.
+        if let Err(e) = map_km_error(km_op.abort()) {
+            log::error!("In prune: KeyMint::abort failed with {:?}.", e);
+        }
+
+        Ok(())
+    }
+
+    // This function takes a Result from a KeyMint call and inspects it for errors.
+    // If an error was found it updates the given `locked_outcome` accordingly.
+    // It forwards the Result unmodified.
+    // The precondition to this call must be *locked_outcome == Outcome::Unknown.
+    // Ideally the `locked_outcome` came from a successful call to `check_active`
+    // see below.
+    fn update_outcome<T>(
+        &self,
+        locked_outcome: &mut Outcome,
+        err: Result<T, Error>,
+    ) -> Result<T, Error> {
+        match &err {
+            Err(Error::Km(e)) => *locked_outcome = Outcome::ErrorCode(*e),
+            Err(_) => *locked_outcome = Outcome::ErrorCode(ErrorCode::UNKNOWN_ERROR),
+            Ok(_) => (),
+        }
+        err
+    }
+
+    // This function grabs the outcome lock and checks the current outcome state.
+    // If the outcome is still `Outcome::Unknown`, this function returns
+    // the locked outcome for further updates. In any other case it returns
+    // ErrorCode::INVALID_OPERATION_HANDLE indicating that this operation has
+    // been finalized and is no longer active.
+    fn check_active(&self) -> Result<MutexGuard<Outcome>> {
+        let guard = self.outcome.lock().expect("In check_active.");
+        match *guard {
+            Outcome::Unknown => Ok(guard),
+            _ => Err(Error::Km(ErrorCode::INVALID_OPERATION_HANDLE)).context(format!(
+                "In check_active: Call on finalized operation with outcome: {:?}.",
+                *guard
+            )),
+        }
+    }
+
+    // This function checks the amount of input data sent to us. We reject any buffer
+    // exceeding MAX_RECEIVE_DATA bytes as input to `update`, `update_aad`, and `finish`
+    // in order to force clients into using reasonable limits.
+    fn check_input_length(data: &[u8]) -> Result<()> {
+        if data.len() > MAX_RECEIVE_DATA {
+            // This error code is unique, no context required here.
+            return Err(anyhow!(Error::Rc(ResponseCode::TOO_MUCH_DATA)));
+        }
+        Ok(())
+    }
+
+    // Update the last usage to now.
+    fn touch(&self) {
+        // Expect safety:
+        // `last_usage` is locked only for primitive single line statements.
+        // There is no chance to panic and poison the mutex.
+        *self.last_usage.lock().expect("In touch.") = Instant::now();
+    }
+
+    /// Implementation of `IKeystoreOperation::updateAad`.
+    /// Refer to the AIDL spec at system/hardware/interfaces/keystore2 for details.
+    fn update_aad(&self, aad_input: &[u8]) -> Result<()> {
+        let mut outcome = self.check_active().context("In update_aad")?;
+        Self::check_input_length(aad_input).context("In update_aad")?;
+        self.touch();
+
+        let params =
+            [KmParam { tag: Tag::ASSOCIATED_DATA, blob: aad_input.into(), ..Default::default() }];
+
+        let mut out_params: Vec<KmParam> = Vec::new();
+        let mut output: Vec<u8> = Vec::new();
+
+        let km_op: Box<dyn IKeyMintOperation> =
+            self.km_op.get_interface().context("In update: Failed to get KeyMintOperation.")?;
+
+        self.update_outcome(
+            &mut *outcome,
+            map_km_error(km_op.update(
+                &params,
+                &[],
+                // TODO HardwareAuthtoken missing
+                &Default::default(),
+                &mut out_params,
+                &mut output,
+            )),
+        )
+        .context("In update_aad: KeyMint::update failed.")?;
+
+        Ok(())
+    }
+
+    /// Implementation of `IKeystoreOperation::update`.
+    /// Refer to the AIDL spec at system/hardware/interfaces/keystore2 for details.
+    fn update(&self, input: &[u8]) -> Result<Option<Vec<u8>>> {
+        let mut outcome = self.check_active().context("In update")?;
+        Self::check_input_length(input).context("In update")?;
+        self.touch();
+
+        let mut out_params: Vec<KmParam> = Vec::new();
+        let mut output: Vec<u8> = Vec::new();
+
+        let km_op: Box<dyn IKeyMintOperation> =
+            self.km_op.get_interface().context("In update: Failed to get KeyMintOperation.")?;
+
+        self.update_outcome(
+            &mut *outcome,
+            map_km_error(km_op.update(
+                &[],
+                input,
+                // TODO HardwareAuthtoken missing
+                &Default::default(),
+                &mut out_params,
+                &mut output,
+            )),
+        )
+        .context("In update: KeyMint::update failed.")?;
+
+        if output.is_empty() {
+            Ok(None)
+        } else {
+            Ok(Some(output))
+        }
+    }
+
+    /// Implementation of `IKeystoreOperation::finish`.
+    /// Refer to the AIDL spec at system/hardware/interfaces/keystore2 for details.
+    fn finish(&self, input: Option<&[u8]>, signature: Option<&[u8]>) -> Result<Option<Vec<u8>>> {
+        let mut outcome = self.check_active().context("In finish")?;
+        if let Some(input) = input {
+            Self::check_input_length(input).context("In finish")?;
+        }
+        self.touch();
+        let input = input.unwrap_or(EMPTY_BLOB);
+        let signature = signature.unwrap_or(EMPTY_BLOB);
+
+        let mut out_params: Vec<KmParam> = Vec::new();
+        let mut output: Vec<u8> = Vec::new();
+
+        let km_op: Box<dyn IKeyMintOperation> =
+            self.km_op.get_interface().context("In finish: Failed to get KeyMintOperation.")?;
+
+        self.update_outcome(
+            &mut *outcome,
+            map_km_error(km_op.finish(
+                &[],
+                &input,
+                &signature,
+                &Default::default(),
+                &Default::default(),
+                &mut out_params,
+                &mut output,
+            )),
+        )
+        .context("In finish: KeyMint::finish failed.")?;
+
+        // At this point the operation concluded successfully.
+        *outcome = Outcome::Success;
+
+        if output.is_empty() {
+            Ok(None)
+        } else {
+            Ok(Some(output))
+        }
+    }
+
+    /// Aborts the operation if it is active. IFF the operation is aborted the outcome is
+    /// set to `outcome`. `outcome` must reflect the reason for the abort. Since the operation
+    /// gets aborted `outcome` must not be `Operation::Success` or `Operation::Unknown`.
+    fn abort(&self, outcome: Outcome) -> Result<()> {
+        let mut locked_outcome = self.check_active().context("In abort")?;
+        *locked_outcome = outcome;
+        let km_op: Box<dyn IKeyMintOperation> =
+            self.km_op.get_interface().context("In abort: Failed to get KeyMintOperation.")?;
+
+        map_km_error(km_op.abort()).context("In abort: KeyMint::abort failed.")
+    }
+}
+
+impl Drop for Operation {
+    fn drop(&mut self) {
+        if let Ok(Outcome::Unknown) = self.outcome.get_mut() {
+            // If the operation was still active we call abort, setting
+            // the outcome to `Outcome::Dropped`
+            if let Err(e) = self.abort(Outcome::Dropped) {
+                log::error!("While dropping Operation: abort failed:\n    {:?}", e);
+            }
+        }
+    }
+}
+
+/// The OperationDb holds weak references to all ongoing operations.
+/// Its main purpose is to facilitate operation pruning.
+#[derive(Debug, Default)]
+pub struct OperationDb {
+    // TODO replace Vec with WeakTable when the weak_table crate becomes
+    // available.
+    operations: Mutex<Vec<Weak<Operation>>>,
+}
+
+impl OperationDb {
+    /// Creates a new OperationDb.
+    pub fn new() -> Self {
+        Self { operations: Mutex::new(Vec::new()) }
+    }
+
+    /// Creates a new operation.
+    /// This function takes a KeyMint operation and an associated
+    /// owner uid and returns a new Operation wrapped in a `std::sync::Arc`.
+    pub fn create_operation(
+        &self,
+        km_op: Box<dyn IKeyMintOperation>,
+        owner: u32,
+    ) -> Arc<Operation> {
+        // We use unwrap because we don't allow code that can panic while locked.
+        let mut operations = self.operations.lock().expect("In create_operation.");
+
+        let mut index: usize = 0;
+        // First we iterate through the operation slots to try and find an unused
+        // slot. If we don't find one, we append the new entry instead.
+        match (*operations).iter_mut().find(|s| {
+            index += 1;
+            s.upgrade().is_none()
+        }) {
+            Some(free_slot) => {
+                let new_op = Arc::new(Operation::new(index - 1, km_op, owner));
+                *free_slot = Arc::downgrade(&new_op);
+                new_op
+            }
+            None => {
+                let new_op = Arc::new(Operation::new(operations.len(), km_op, owner));
+                operations.push(Arc::downgrade(&new_op));
+                new_op
+            }
+        }
+    }
+
+    fn get(&self, index: usize) -> Option<Arc<Operation>> {
+        self.operations.lock().expect("In OperationDb::get.").get(index).and_then(|op| op.upgrade())
+    }
+
+    /// Attempts to prune an operation.
+    ///
+    /// This function is used during operation creation, i.e., by
+    /// `KeystoreSecurityLevel::create_operation`, to try and free up an operation slot
+    /// if it got `ErrorCode::TOO_MANY_OPERATIONS` from the KeyMint backend. It is not
+    /// guaranteed that an operation slot is available after this call successfully
+    /// returned for various reasons. E.g., another thread may have snatched up the newly
+    /// available slot. Callers may have to call prune multiple times before they get a
+    /// free operation slot. Prune may also return `Err(Error::Rc(ResponseCode::BACKEND_BUSY))`
+    /// which indicates that no prunable operation was found.
+    ///
+    /// To find a suitable candidate we compute the malus for the caller and each existing
+    /// operation. The malus is the inverse of the pruning power (caller) or pruning
+    /// resistance (existing operation).
+    /// The malus is based on the number of sibling operations and age. Sibling
+    /// operations are operations that have the same owner (UID).
+    /// Every operation, existing or new, starts with a malus of 1. Every sibling
+    /// increases the malus by one. The age is the time since an operation was last touched.
+    /// It increases the malus by log6(<age in seconds> + 1) rounded down to the next
+    /// integer. So the malus increases stepwise after 5s, 35s, 215s, ...
+    /// Of two operations with the same malus the least recently used one is considered
+    /// weaker.
+    /// For the caller to be able to prune an operation it must find an operation
+    /// with a malus higher than its own.
+    ///
+    /// The malus can be expressed as
+    /// ```
+    /// malus = 1 + no_of_siblings + floor(log6(age_in_seconds + 1))
+    /// ```
+    /// where the constant `1` accounts for the operation under consideration.
+    /// In reality we compute it as
+    /// ```
+    /// caller_malus = 1 + running_siblings
+    /// ```
+    /// because the new operation has no age and is not included in the `running_siblings`,
+    /// and
+    /// ```
+    /// running_malus = running_siblings + floor(log6(age_in_seconds + 1))
+    /// ```
+    /// because a running operation is included in the `running_siblings` and it has
+    /// an age.
+    ///
+    /// ## Example
+    /// A caller with no running operations has a malus of 1. Young (age < 5s) operations
+    /// also with no siblings have a malus of one and cannot be pruned by the caller.
+    /// We have to find an operation that has at least one sibling or is older than 5s.
+    ///
+    /// A caller with one running operation has a malus of 2. Now even young siblings
+    /// or single child aging (5s <= age < 35s) operations are off limit. An aging
+    /// sibling of two, however, would have a malus of 3 and would be fair game.
+    ///
+    /// ## Rationale
+    /// Due to the limitation of KeyMint operation slots, we cannot get around pruning or
+    /// a single app could easily DoS KeyMint.
+    /// Keystore 1.0 used to always prune the least recently used operation. This at least
+    /// guaranteed that new operations can always be started. With the increased usage
+    /// of Keystore we saw increased pruning activity which can lead to a livelock
+    /// situation in the worst case.
+    /// With the new pruning strategy we want to provide well behaved clients with
+    /// progress assurances while punishing DoS attempts. As a result of this
+    /// strategy we can be in the situation where no operation can be pruned and the
+    /// creation of a new operation fails. This allows single child operations which
+    /// are frequently updated to complete, thereby breaking up livelock situations
+    /// and facilitating system wide progress.
+    pub fn prune(&self, caller: u32) -> Result<(), Error> {
+        loop {
+            // Maps the uid of the owner to the number of operations that owner has
+            // (running_siblings). More operations per owner lowers the pruning
+            // resistance of the operations of that owner. Whereas the number of
+            // ongoing operations of the caller lowers the pruning power of the caller.
+            let mut owners: HashMap<u32, u64> = HashMap::new();
+            let mut pruning_info: Vec<PruningInfo> = Vec::new();
+
+            let now = Instant::now();
+            self.operations
+                .lock()
+                .expect("In OperationDb::prune: Trying to lock self.operations.")
+                .iter()
+                .for_each(|op| {
+                    if let Some(op) = op.upgrade() {
+                        let p_info = op.get_pruning_info();
+                        let owner = p_info.owner;
+                        pruning_info.push(p_info);
+                        // Count operations per owner.
+                        *owners.entry(owner).or_insert(0) += 1;
+                    }
+                });
+
+            let caller_malus = 1u64 + *owners.entry(caller).or_default();
+
+            // We iterate through all operations computing the malus and finding
+            // the candidate with the highest malus which must also be higher
+            // than the caller_malus.
+            struct CandidateInfo {
+                index: usize,
+                malus: u64,
+                last_usage: Instant,
+                age: Duration,
+            }
+            let candidate = pruning_info.iter().fold(
+                None,
+                |acc: Option<CandidateInfo>, &PruningInfo { last_usage, owner, index }| {
+                    // Compute the age of the current operation.
+                    let age = now
+                        .checked_duration_since(last_usage)
+                        .unwrap_or_else(|| Duration::new(0, 0));
+
+                    // Compute the malus of the current operation.
+                    // Expect safety: Every owner in pruning_info was counted in
+                    // the owners map. So this unwrap cannot panic.
+                    let malus = *owners
+                        .get(&owner)
+                        .expect("This is odd. We should have counted every owner in pruning_info.")
+                        + ((age.as_secs() + 1) as f64).log(6.0).floor() as u64;
+
+                    // Now check if the current operation is a viable/better candidate
+                    // the one currently stored in the accumulator.
+                    match acc {
+                        // First we have to find any operation that is prunable by the caller.
+                        None => {
+                            if caller_malus < malus {
+                                Some(CandidateInfo { index, malus, last_usage, age })
+                            } else {
+                                None
+                            }
+                        }
+                        // If we have found one we look for the operation with the worst score.
+                        // If there is a tie, the older operation is considered weaker.
+                        Some(CandidateInfo { index: i, malus: m, last_usage: l, age: a }) => {
+                            if malus > m || (malus == m && age > a) {
+                                Some(CandidateInfo { index, malus, last_usage, age })
+                            } else {
+                                Some(CandidateInfo { index: i, malus: m, last_usage: l, age: a })
+                            }
+                        }
+                    }
+                },
+            );
+
+            match candidate {
+                Some(CandidateInfo { index, malus: _, last_usage, age: _ }) => {
+                    match self.get(index) {
+                        Some(op) => {
+                            match op.prune(last_usage) {
+                                // We successfully freed up a slot.
+                                Ok(()) => break Ok(()),
+                                // This means the operation we tried to prune was on its way
+                                // out. It also means that the slot it had occupied was freed up.
+                                Err(Error::Km(ErrorCode::INVALID_OPERATION_HANDLE)) => break Ok(()),
+                                // This means the operation we tried to prune was currently
+                                // servicing a request. There are two options.
+                                // * Assume that it was touched, which means that its
+                                //   pruning resistance increased. In that case we have
+                                //   to start over and find another candidate.
+                                // * Assume that the operation is transitioning to end-of-life.
+                                //   which means that we got a free slot for free.
+                                // If we assume the first but the second is true, we prune
+                                // a good operation without need (aggressive approach).
+                                // If we assume the second but the first is true, our
+                                // caller will attempt to create a new KeyMint operation,
+                                // fail with `ErrorCode::TOO_MANY_OPERATIONS`, and call
+                                // us again (conservative approach).
+                                Err(Error::Rc(ResponseCode::OPERATION_BUSY)) => {
+                                    // We choose the conservative approach, because
+                                    // every needlessly pruned operation can impact
+                                    // the user experience.
+                                    // To switch to the aggressive approach replace
+                                    // the following line with `continue`.
+                                    break Ok(());
+                                }
+
+                                // The candidate may have been touched so the score
+                                // has changed since our evaluation.
+                                _ => continue,
+                            }
+                        }
+                        // This index does not exist any more. The operation
+                        // in this slot was dropped. Good news, a slot
+                        // has freed up.
+                        None => break Ok(()),
+                    }
+                }
+                // We did not get a pruning candidate.
+                None => break Err(Error::Rc(ResponseCode::BACKEND_BUSY)),
+            }
+        }
+    }
+}
+
+/// Implementation of IKeystoreOperation.
+pub struct KeystoreOperation {
+    operation: Mutex<Option<Arc<Operation>>>,
+}
+
+impl KeystoreOperation {
+    /// Creates a new operation instance wrapped in a
+    /// BnKeystoreOperation proxy object. It also
+    /// calls `IBinder::set_requesting_sid` on the new interface, because
+    /// we need it for checking Keystore permissions.
+    pub fn new_native_binder(operation: Arc<Operation>) -> impl IKeystoreOperation + Send {
+        let result =
+            BnKeystoreOperation::new_binder(Self { operation: Mutex::new(Some(operation)) });
+        result.as_binder().set_requesting_sid(true);
+        result
+    }
+
+    /// Grabs the outer operation mutex and calls `f` on the locked operation.
+    /// The function also deletes the operation if it returns with an error or if
+    /// `delete_op` is true.
+    fn with_locked_operation<T, F>(&self, f: F, delete_op: bool) -> Result<T>
+    where
+        for<'a> F: FnOnce(&'a Operation) -> Result<T>,
+    {
+        let mut delete_op: bool = delete_op;
+        match self.operation.try_lock() {
+            Ok(mut mutex_guard) => {
+                let result = match &*mutex_guard {
+                    Some(op) => {
+                        let result = f(&*op);
+                        // Any error here means we can discard the operation.
+                        if result.is_err() {
+                            delete_op = true;
+                        }
+                        result
+                    }
+                    None => Err(Error::Km(ErrorCode::INVALID_OPERATION_HANDLE))
+                        .context("In KeystoreOperation::with_locked_operation"),
+                };
+
+                if delete_op {
+                    // We give up our reference to the Operation, thereby freeing up our
+                    // internal resources and ending the wrapped KeyMint operation.
+                    // This KeystoreOperation object will still be owned by an SpIBinder
+                    // until the client drops its remote reference.
+                    *mutex_guard = None;
+                }
+                result
+            }
+            Err(_) => Err(Error::Rc(ResponseCode::OPERATION_BUSY))
+                .context("In KeystoreOperation::with_locked_operation"),
+        }
+    }
+}
+
+impl binder::Interface for KeystoreOperation {}
+
+impl IKeystoreOperation for KeystoreOperation {
+    fn updateAad(&self, aad_input: &[u8]) -> binder::public_api::Result<()> {
+        map_or_log_err(
+            self.with_locked_operation(
+                |op| op.update_aad(aad_input).context("In KeystoreOperation::updateAad"),
+                false,
+            ),
+            Ok,
+        )
+    }
+
+    fn update(&self, input: &[u8]) -> binder::public_api::Result<Option<Vec<u8>>> {
+        map_or_log_err(
+            self.with_locked_operation(
+                |op| op.update(input).context("In KeystoreOperation::update"),
+                false,
+            ),
+            Ok,
+        )
+    }
+    fn finish(
+        &self,
+        input: Option<&[u8]>,
+        signature: Option<&[u8]>,
+    ) -> binder::public_api::Result<Option<Vec<u8>>> {
+        map_or_log_err(
+            self.with_locked_operation(
+                |op| op.finish(input, signature).context("In KeystoreOperation::finish"),
+                true,
+            ),
+            Ok,
+        )
+    }
+
+    fn abort(&self) -> binder::public_api::Result<()> {
+        map_or_log_err(
+            self.with_locked_operation(
+                |op| op.abort(Outcome::Abort).context("In KeystoreOperation::abort"),
+                true,
+            ),
+            Ok,
+        )
+    }
+}
diff --git a/keystore2/src/security_level.rs b/keystore2/src/security_level.rs
new file mode 100644
index 0000000..287d626
--- /dev/null
+++ b/keystore2/src/security_level.rs
@@ -0,0 +1,553 @@
+// Copyright 2020, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#![allow(unused_variables)]
+
+//! This crate implements the IKeystoreSecurityLevel interface.
+
+use android_hardware_keymint::aidl::android::hardware::keymint::{
+    Algorithm::Algorithm, Certificate::Certificate as KmCertificate,
+    IKeyMintDevice::IKeyMintDevice, KeyCharacteristics::KeyCharacteristics, KeyFormat::KeyFormat,
+    KeyParameter::KeyParameter as KmParam, KeyPurpose::KeyPurpose, Tag::Tag,
+};
+use android_system_keystore2::aidl::android::system::keystore2::{
+    AuthenticatorSpec::AuthenticatorSpec, AuthenticatorType::AuthenticatorType,
+    Certificate::Certificate, CertificateChain::CertificateChain, Domain::Domain,
+    IKeystoreOperation::IKeystoreOperation, IKeystoreSecurityLevel::BnKeystoreSecurityLevel,
+    IKeystoreSecurityLevel::IKeystoreSecurityLevel, KeyDescriptor::KeyDescriptor,
+    KeyParameter::KeyParameter, OperationChallenge::OperationChallenge,
+    SecurityLevel::SecurityLevel,
+};
+
+use crate::error::{self, map_km_error, map_or_log_err, Error, ErrorCode};
+use crate::globals::DB;
+use crate::permission::KeyPerm;
+use crate::utils::{check_key_permission, keyparam_ks_to_km, Asp};
+use crate::{
+    database::{KeyEntry, KeyEntryLoadBits, SubComponentType},
+    operation::KeystoreOperation,
+    operation::OperationDb,
+};
+use anyhow::{anyhow, Context, Result};
+use binder::{IBinder, Interface, ThreadState};
+
+/// Implementation of the IKeystoreSecurityLevel Interface.
+pub struct KeystoreSecurityLevel {
+    security_level: SecurityLevel,
+    keymint: Asp,
+    operation_db: OperationDb,
+}
+
+static KEYMINT_SERVICE_NAME: &str = "android.hardware.keymint.IKeyMintDevice";
+
+// Blob of 32 zeroes used as empty masking key.
+static ZERO_BLOB_32: &[u8] = &[0; 32];
+
+impl KeystoreSecurityLevel {
+    /// Creates a new security level instance wrapped in a
+    /// BnKeystoreSecurityLevel proxy object. It also
+    /// calls `IBinder::set_requesting_sid` on the new interface, because
+    /// we need it for checking keystore permissions.
+    pub fn new_native_binder(
+        security_level: SecurityLevel,
+    ) -> Result<impl IKeystoreSecurityLevel + Send> {
+        let service_name = format!("{}/default", KEYMINT_SERVICE_NAME);
+        let keymint: Box<dyn IKeyMintDevice> =
+            binder::get_interface(&service_name).map_err(|e| {
+                anyhow!(format!(
+                    "Could not get KeyMint instance: {} failed with error code {:?}",
+                    service_name, e
+                ))
+            })?;
+
+        let result = BnKeystoreSecurityLevel::new_binder(Self {
+            security_level,
+            keymint: Asp::new(keymint.as_binder()),
+            operation_db: OperationDb::new(),
+        });
+        result.as_binder().set_requesting_sid(true);
+        Ok(result)
+    }
+
+    fn store_new_key(
+        &self,
+        key: KeyDescriptor,
+        km_cert_chain: Option<Vec<KmCertificate>>,
+        blob: Vec<u8>,
+    ) -> Result<(KeyDescriptor, Option<Certificate>, Option<CertificateChain>)> {
+        let (cert, cert_chain) = match km_cert_chain {
+            Some(mut chain) => (
+                match chain.len() {
+                    0 => None,
+                    _ => Some(Certificate { data: chain.remove(0).encodedCertificate }),
+                },
+                match chain.len() {
+                    0 => None,
+                    _ => Some(CertificateChain {
+                        data: chain
+                            .iter()
+                            .map(|c| c.encodedCertificate.iter())
+                            .flatten()
+                            .copied()
+                            .collect(),
+                    }),
+                },
+            ),
+            None => (None, None),
+        };
+
+        let key = match key.domain {
+            Domain::BLOB => {
+                KeyDescriptor { domain: Domain::BLOB, blob: Some(blob), ..Default::default() }
+            }
+            _ => DB
+                .with(|db| {
+                    let mut db = db.borrow_mut();
+                    let key_id = db
+                        .create_key_entry(key.domain, key.nspace)
+                        .context("Trying to create a key entry.")?;
+                    db.insert_blob(key_id, SubComponentType::KM_BLOB, &blob, self.security_level)
+                        .context("Trying to insert km blob.")?;
+                    if let Some(c) = &cert {
+                        db.insert_blob(
+                            key_id,
+                            SubComponentType::CERT,
+                            &c.data,
+                            self.security_level,
+                        )
+                        .context("Trying to insert cert blob.")?;
+                    }
+                    if let Some(c) = &cert_chain {
+                        db.insert_blob(
+                            key_id,
+                            SubComponentType::CERT_CHAIN,
+                            &c.data,
+                            self.security_level,
+                        )
+                        .context("Trying to insert cert chain blob.")?;
+                    }
+                    match &key.alias {
+                        Some(alias) => db
+                            .rebind_alias(key_id, alias, key.domain, key.nspace)
+                            .context("Failed to rebind alias.")?,
+                        None => {
+                            return Err(error::Error::sys()).context(
+                                "Alias must be specified. (This should have been checked earlier.)",
+                            )
+                        }
+                    }
+                    Ok(KeyDescriptor {
+                        domain: Domain::KEY_ID,
+                        nspace: key_id,
+                        ..Default::default()
+                    })
+                })
+                .context("In store_new_key.")?,
+        };
+
+        Ok((key, cert, cert_chain))
+    }
+
+    fn create(
+        &self,
+        key: &KeyDescriptor,
+        operation_parameters: &[KeyParameter],
+        forced: bool,
+    ) -> Result<(Box<dyn IKeystoreOperation>, Option<OperationChallenge>)> {
+        let caller_uid = ThreadState::get_calling_uid();
+        // We use `scoping_blob` to extend the life cycle of the blob loaded from the database,
+        // so that we can use it by reference like the blob provided by the key descriptor.
+        // Otherwise, we would have to clone the blob from the key descriptor.
+        let scoping_blob: Vec<u8>;
+        let (km_blob, key_id) =
+            match key.domain {
+                Domain::BLOB => {
+                    check_key_permission(KeyPerm::use_(), key, &None)
+                        .context("In create: checking use permission for Domain::BLOB.")?;
+                    (
+                        match &key.blob {
+                            Some(blob) => blob,
+                            None => return Err(Error::sys()).context(
+                                "In create: Key blob must be specified when using Domain::BLOB.",
+                            ),
+                        },
+                        None,
+                    )
+                }
+                _ => {
+                    let mut key_entry = DB
+                        .with::<_, Result<KeyEntry>>(|db| {
+                            db.borrow_mut().load_key_entry(
+                                key.clone(),
+                                KeyEntryLoadBits::KM,
+                                caller_uid,
+                                |k, av| check_key_permission(KeyPerm::use_(), k, &av),
+                            )
+                        })
+                        .context("In create: Failed to load key blob.")?;
+                    scoping_blob = match key_entry.take_km_blob() {
+                        Some(blob) => blob,
+                        None => return Err(Error::sys()).context(
+                            "In create: Successfully loaded key entry, but KM blob was missing.",
+                        ),
+                    };
+                    (&scoping_blob, Some(key_entry.id()))
+                }
+            };
+
+        // TODO Authorize begin operation.
+        // Check if we need an authorization token.
+        // Lookup authorization token and request VerificationToken if required.
+
+        let purpose = operation_parameters.iter().find(|p| p.tag == Tag::PURPOSE.0).map_or(
+            Err(Error::Km(ErrorCode::INVALID_ARGUMENT))
+                .context("In create: No operation purpose specified."),
+            |kp| Ok(KeyPurpose(kp.integer)),
+        )?;
+
+        let km_params =
+            operation_parameters.iter().map(|p| keyparam_ks_to_km(p)).collect::<Vec<KmParam>>();
+
+        let km_dev: Box<dyn IKeyMintDevice> =
+            self.keymint.get_interface().context("In create: Failed to get KeyMint device")?;
+
+        let (begin_result, upgraded_blob) = loop {
+            match map_km_error(km_dev.begin(purpose, &km_blob, &km_params, &Default::default())) {
+                Ok(result) => break (result, None),
+                Err(Error::Km(ErrorCode::TOO_MANY_OPERATIONS)) => {
+                    self.operation_db.prune(caller_uid).context("In create: Outer loop.")?;
+                    continue;
+                }
+                Err(Error::Km(ErrorCode::KEY_REQUIRES_UPGRADE)) => {
+                    let upgraded_blob = map_km_error(km_dev.upgradeKey(&km_blob, &km_params))
+                        .context("In create: Upgrade failed.")?;
+                    break loop {
+                        match map_km_error(km_dev.begin(
+                            purpose,
+                            &upgraded_blob,
+                            &km_params,
+                            &Default::default(),
+                        )) {
+                            Ok(result) => break (result, Some(upgraded_blob)),
+                            // If Keystore 2.0 is multi threaded another request may have
+                            // snatched up our previously pruned operation slot. So we might
+                            // need to prune again.
+                            Err(Error::Km(ErrorCode::TOO_MANY_OPERATIONS)) => {
+                                self.operation_db
+                                    .prune(caller_uid)
+                                    .context("In create: Inner loop.")?;
+                                continue;
+                            }
+                            Err(e) => {
+                                return Err(e)
+                                    .context("In create: Begin operation failed after upgrade.")
+                            }
+                        }
+                    };
+                }
+                Err(e) => return Err(e).context("In create: Begin operation failed."),
+            };
+        };
+
+        if let Some(upgraded_blob) = upgraded_blob {
+            if let Some(key_id) = key_id {
+                DB.with(|db| {
+                    db.borrow_mut().insert_blob(
+                        key_id,
+                        SubComponentType::KM_BLOB,
+                        &upgraded_blob,
+                        self.security_level,
+                    )
+                })
+                .context("In create: Failed to insert upgraded blob into the database.")?;
+            }
+        }
+
+        let operation = match begin_result.operation {
+            Some(km_op) => self.operation_db.create_operation(km_op, caller_uid),
+            None => return Err(Error::sys()).context("In create: Begin operation returned successfully, but did not return a valid operation."),
+        };
+
+        let op_binder: Box<dyn IKeystoreOperation> =
+            KeystoreOperation::new_native_binder(operation)
+                .as_binder()
+                .into_interface()
+                .context("In create: Failed to create IKeystoreOperation.")?;
+
+        // TODO find out what to do with the returned parameters.
+
+        // TODO we need to the enforcement module to determine if we need to return the challenge.
+        // We return None for now because we don't support auth bound keys yet.
+        Ok((op_binder, None))
+    }
+
+    fn generate_key(
+        &self,
+        key: &KeyDescriptor,
+        params: &[KeyParameter],
+        entropy: &[u8],
+    ) -> Result<(KeyDescriptor, Option<Certificate>, Option<CertificateChain>)> {
+        if key.domain != Domain::BLOB && key.alias.is_none() {
+            return Err(error::Error::Km(ErrorCode::INVALID_ARGUMENT))
+                .context("In generate_key: Alias must be specified");
+        }
+
+        let key = match key.domain {
+            Domain::APP => KeyDescriptor {
+                domain: key.domain,
+                nspace: ThreadState::get_calling_uid() as i64,
+                alias: key.alias.clone(),
+                blob: None,
+            },
+            _ => key.clone(),
+        };
+
+        // generate_key requires the rebind permission.
+        check_key_permission(KeyPerm::rebind(), &key, &None).context("In generate_key.")?;
+
+        let km_dev: Box<dyn IKeyMintDevice> = self.keymint.get_interface()?;
+        map_km_error(km_dev.addRngEntropy(entropy))?;
+        let mut blob: Vec<u8> = Default::default();
+        let mut key_characteristics: KeyCharacteristics = Default::default();
+        let mut certificate_chain: Vec<KmCertificate> = Default::default();
+        map_km_error(km_dev.generateKey(
+            &params.iter().map(|p| keyparam_ks_to_km(p)).collect::<Vec<KmParam>>(),
+            &mut blob,
+            &mut key_characteristics,
+            &mut certificate_chain,
+        ))?;
+
+        self.store_new_key(key, Some(certificate_chain), blob).context("In generate_key.")
+    }
+
+    fn import_key(
+        &self,
+        key: &KeyDescriptor,
+        params: &[KeyParameter],
+        key_data: &[u8],
+    ) -> Result<(KeyDescriptor, Option<Certificate>, Option<CertificateChain>)> {
+        if key.domain != Domain::BLOB && key.alias.is_none() {
+            return Err(error::Error::Km(ErrorCode::INVALID_ARGUMENT))
+                .context("In import_key: Alias must be specified");
+        }
+
+        let key = match key.domain {
+            Domain::APP => KeyDescriptor {
+                domain: key.domain,
+                nspace: ThreadState::get_calling_uid() as i64,
+                alias: key.alias.clone(),
+                blob: None,
+            },
+            _ => key.clone(),
+        };
+
+        // import_key requires the rebind permission.
+        check_key_permission(KeyPerm::rebind(), &key, &None).context("In import_key.")?;
+
+        let mut blob: Vec<u8> = Default::default();
+        let mut key_characteristics: KeyCharacteristics = Default::default();
+        let mut certificate_chain: Vec<KmCertificate> = Default::default();
+
+        let format = params
+            .iter()
+            .find(|p| p.tag == Tag::ALGORITHM.0)
+            .ok_or(error::Error::Km(ErrorCode::INVALID_ARGUMENT))
+            .context("No KeyParameter 'Algorithm'.")
+            .and_then(|p| match Algorithm(p.integer) {
+                Algorithm::AES | Algorithm::HMAC | Algorithm::TRIPLE_DES => Ok(KeyFormat::RAW),
+                Algorithm::RSA | Algorithm::EC => Ok(KeyFormat::PKCS8),
+                algorithm => Err(error::Error::Km(ErrorCode::INVALID_ARGUMENT))
+                    .context(format!("Unknown Algorithm {:?}.", algorithm)),
+            })
+            .context("In import_key.")?;
+
+        let km_dev: Box<dyn IKeyMintDevice> = self.keymint.get_interface()?;
+        map_km_error(km_dev.importKey(
+            &params.iter().map(|p| keyparam_ks_to_km(p)).collect::<Vec<KmParam>>(),
+            format,
+            key_data,
+            &mut blob,
+            &mut key_characteristics,
+            &mut certificate_chain,
+        ))?;
+
+        self.store_new_key(key, Some(certificate_chain), blob).context("In import_key.")
+    }
+
+    fn import_wrapped_key(
+        &self,
+        key: &KeyDescriptor,
+        wrapping_key: &KeyDescriptor,
+        masking_key: Option<&[u8]>,
+        params: &[KeyParameter],
+        authenticators: &[AuthenticatorSpec],
+    ) -> Result<(KeyDescriptor, Option<Certificate>, Option<CertificateChain>)> {
+        if key.domain != Domain::BLOB && key.alias.is_none() {
+            return Err(error::Error::Km(ErrorCode::INVALID_ARGUMENT))
+                .context("In import_wrapped_key: Alias must be specified.");
+        }
+
+        let wrapped_data = match &key.blob {
+            Some(d) => d,
+            None => {
+                return Err(error::Error::Km(ErrorCode::INVALID_ARGUMENT)).context(
+                    "In import_wrapped_key: Blob must be specified and hold wrapped key data.",
+                )
+            }
+        };
+
+        let key = match key.domain {
+            Domain::APP => KeyDescriptor {
+                domain: key.domain,
+                nspace: ThreadState::get_calling_uid() as i64,
+                alias: key.alias.clone(),
+                blob: None,
+            },
+            _ => key.clone(),
+        };
+
+        // import_wrapped_key requires the rebind permission for the new key.
+        check_key_permission(KeyPerm::rebind(), &key, &None).context("In import_wrapped_key.")?;
+
+        let wrapping_key_entry = DB
+            .with(|db| {
+                db.borrow_mut().load_key_entry(
+                    wrapping_key.clone(),
+                    KeyEntryLoadBits::KM,
+                    ThreadState::get_calling_uid(),
+                    |k, av| check_key_permission(KeyPerm::use_(), k, &av),
+                )
+            })
+            .context("Failed to load wrapping key.")?;
+        let wrapping_key_blob = match wrapping_key_entry.km_blob() {
+            Some(blob) => blob,
+            None => {
+                return Err(error::Error::sys()).context(concat!(
+                    "No km_blob after successfully loading key.",
+                    " This should never happen."
+                ))
+            }
+        };
+
+        let mut blob: Vec<u8> = Default::default();
+        let mut key_characteristics: KeyCharacteristics = Default::default();
+        // km_dev.importWrappedKey does not return a certificate chain.
+        // TODO Do we assume that all wrapped keys are symmetric?
+        // let certificate_chain: Vec<KmCertificate> = Default::default();
+
+        let pw_sid = authenticators
+            .iter()
+            .find_map(|a| match a.authenticatorType {
+                AuthenticatorType::PASSWORD => Some(a.authenticatorId),
+                _ => None,
+            })
+            .ok_or(error::Error::Km(ErrorCode::INVALID_ARGUMENT))
+            .context("A password authenticator SID must be specified.")?;
+
+        let fp_sid = authenticators
+            .iter()
+            .find_map(|a| match a.authenticatorType {
+                AuthenticatorType::FINGERPRINT => Some(a.authenticatorId),
+                _ => None,
+            })
+            .ok_or(error::Error::Km(ErrorCode::INVALID_ARGUMENT))
+            .context("A fingerprint authenticator SID must be specified.")?;
+
+        let masking_key = masking_key.unwrap_or(ZERO_BLOB_32);
+
+        let km_dev: Box<dyn IKeyMintDevice> = self.keymint.get_interface()?;
+        map_km_error(km_dev.importWrappedKey(
+            wrapped_data,
+            wrapping_key_blob,
+            masking_key,
+            &params.iter().map(|p| keyparam_ks_to_km(p)).collect::<Vec<KmParam>>(),
+            pw_sid,
+            fp_sid,
+            &mut blob,
+            &mut key_characteristics,
+        ))?;
+
+        self.store_new_key(key, None, blob).context("In import_wrapped_key.")
+    }
+}
+
+impl binder::Interface for KeystoreSecurityLevel {}
+
+impl IKeystoreSecurityLevel for KeystoreSecurityLevel {
+    fn create(
+        &self,
+        key: &KeyDescriptor,
+        operation_parameters: &[KeyParameter],
+        forced: bool,
+        challenge: &mut Option<OperationChallenge>,
+    ) -> binder::public_api::Result<Box<dyn IKeystoreOperation>> {
+        map_or_log_err(self.create(key, operation_parameters, forced), |v| {
+            *challenge = v.1;
+            Ok(v.0)
+        })
+    }
+    fn generateKey(
+        &self,
+        key: &KeyDescriptor,
+        params: &[KeyParameter],
+        entropy: &[u8],
+        result_key: &mut KeyDescriptor,
+        public_cert: &mut Option<Certificate>,
+        certificate_chain: &mut Option<CertificateChain>,
+    ) -> binder::public_api::Result<()> {
+        map_or_log_err(self.generate_key(key, params, entropy), |v| {
+            *result_key = v.0;
+            *public_cert = v.1;
+            *certificate_chain = v.2;
+            Ok(())
+        })
+    }
+    fn importKey(
+        &self,
+        key: &KeyDescriptor,
+        params: &[KeyParameter],
+        key_data: &[u8],
+        result_key: &mut KeyDescriptor,
+        public_cert: &mut Option<Certificate>,
+        certificate_chain: &mut Option<CertificateChain>,
+    ) -> binder::public_api::Result<()> {
+        map_or_log_err(self.import_key(key, params, key_data), |v| {
+            *result_key = v.0;
+            *public_cert = v.1;
+            *certificate_chain = v.2;
+            Ok(())
+        })
+    }
+    fn importWrappedKey(
+        &self,
+        key: &KeyDescriptor,
+        wrapping_key: &KeyDescriptor,
+        masking_key: Option<&[u8]>,
+        params: &[KeyParameter],
+        authenticators: &[AuthenticatorSpec],
+        result_key: &mut KeyDescriptor,
+        public_cert: &mut Option<Certificate>,
+        certificate_chain: &mut Option<CertificateChain>,
+    ) -> binder::public_api::Result<()> {
+        map_or_log_err(
+            self.import_wrapped_key(key, wrapping_key, masking_key, params, authenticators),
+            |v| {
+                *result_key = v.0;
+                *public_cert = v.1;
+                *certificate_chain = v.2;
+                Ok(())
+            },
+        )
+    }
+}
diff --git a/keystore2/src/service.rs b/keystore2/src/service.rs
new file mode 100644
index 0000000..ea17766
--- /dev/null
+++ b/keystore2/src/service.rs
@@ -0,0 +1,254 @@
+// Copyright 2020, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// TODO remove when fully implemented.
+#![allow(unused_variables)]
+
+//! This crate implement the core Keystore 2.0 service API as defined by the Keystore 2.0
+//! AIDL spec.
+
+use crate::database::{KeyEntry, KeyEntryLoadBits, SubComponentType};
+use crate::error::{self, map_or_log_err, ErrorCode};
+use crate::globals::DB;
+use crate::permission;
+use crate::permission::KeyPerm;
+use crate::security_level::KeystoreSecurityLevel;
+use crate::utils::{check_grant_permission, check_key_permission, Asp};
+use android_system_keystore2::aidl::android::system::keystore2::{
+    Certificate::Certificate, CertificateChain::CertificateChain, Domain::Domain,
+    IKeystoreSecurityLevel::IKeystoreSecurityLevel, IKeystoreService::BnKeystoreService,
+    IKeystoreService::IKeystoreService, KeyDescriptor::KeyDescriptor, KeyMetadata::KeyMetadata,
+    SecurityLevel::SecurityLevel,
+};
+use anyhow::{anyhow, Context, Result};
+use binder::{IBinder, Interface, ThreadState};
+
+/// Implementation of the IKeystoreService.
+pub struct KeystoreService {
+    sec_level: Asp,
+}
+
+impl KeystoreService {
+    /// Create a new instance of the Keystore 2.0 service.
+    pub fn new_native_binder() -> Result<impl IKeystoreService> {
+        let result = BnKeystoreService::new_binder(Self {
+            sec_level: Asp::new({
+                let sec_level =
+                    KeystoreSecurityLevel::new_native_binder(SecurityLevel::TRUSTED_ENVIRONMENT)
+                        .context("While trying to create IKeystoreSecurityLevel")?;
+                sec_level.as_binder()
+            }),
+        });
+        result.as_binder().set_requesting_sid(true);
+        Ok(result)
+    }
+
+    fn get_security_level(
+        &self,
+        security_level: SecurityLevel,
+    ) -> Result<Box<dyn IKeystoreSecurityLevel>> {
+        match security_level {
+            SecurityLevel::TRUSTED_ENVIRONMENT => self
+                .sec_level
+                .get_interface()
+                .context("In get_security_level: Failed to get IKeystoreSecurityLevel."),
+            _ => Err(anyhow!(error::Error::Km(ErrorCode::HARDWARE_TYPE_UNAVAILABLE))),
+        }
+    }
+
+    fn get_key_entry(
+        &self,
+        key: &KeyDescriptor,
+    ) -> Result<(
+        KeyMetadata,
+        Option<Certificate>,
+        Option<CertificateChain>,
+        Box<dyn IKeystoreSecurityLevel>,
+    )> {
+        let mut key_entry: KeyEntry = DB
+            .with(|db| {
+                db.borrow_mut().load_key_entry(
+                    key.clone(),
+                    KeyEntryLoadBits::PUBLIC,
+                    ThreadState::get_calling_uid(),
+                    |k, av| check_key_permission(KeyPerm::get_info(), k, &av),
+                )
+            })
+            .context("In get_key_entry, while trying to load key info.")?;
+
+        let i_sec_level = match key_entry.sec_level() {
+            SecurityLevel::TRUSTED_ENVIRONMENT => self
+                .sec_level
+                .get_interface()
+                .context("In get_key_entry: Failed to get IKeystoreSecurityLevel.")?,
+            _ => return Err(anyhow!(error::Error::Km(ErrorCode::HARDWARE_TYPE_UNAVAILABLE))),
+        };
+
+        Ok((
+            KeyMetadata {
+                key: KeyDescriptor {
+                    domain: Domain::KEY_ID,
+                    nspace: key_entry.id(),
+                    ..Default::default()
+                },
+                securityLevel: key_entry.sec_level(),
+                // TODO add key characteristics here.
+                ..Default::default()
+            },
+            key_entry.take_cert().map(|v| Certificate { data: v }),
+            key_entry.take_cert_chain().map(|v| CertificateChain { data: v }),
+            i_sec_level,
+        ))
+    }
+
+    fn update_subcomponent(
+        &self,
+        key: &KeyDescriptor,
+        public_cert: Option<&Certificate>,
+        certificate_chain: Option<&CertificateChain>,
+    ) -> Result<()> {
+        DB.with::<_, Result<()>>(|db| {
+            let mut db = db.borrow_mut();
+            let key_entry = db
+                .load_key_entry(
+                    key.clone(),
+                    KeyEntryLoadBits::NONE,
+                    ThreadState::get_calling_uid(),
+                    |k, av| {
+                        check_key_permission(KeyPerm::update(), k, &av)
+                            .context("In update_subcomponent.")
+                    },
+                )
+                .context("Failed to load key_entry.")?;
+
+            if let Some(cert) = public_cert {
+                db.insert_blob(
+                    key_entry.id(),
+                    SubComponentType::CERT,
+                    &cert.data,
+                    key_entry.sec_level(),
+                )
+                .context("Failed to update cert subcomponent.")?;
+            }
+
+            if let Some(cert_chain) = certificate_chain {
+                db.insert_blob(
+                    key_entry.id(),
+                    SubComponentType::CERT_CHAIN,
+                    &cert_chain.data,
+                    key_entry.sec_level(),
+                )
+                .context("Failed to update cert chain subcomponent.")?;
+            }
+            Ok(())
+        })
+        .context("In update_subcomponent.")
+    }
+
+    fn list_entries(&self, domain: Domain, namespace: i64) -> Result<Vec<KeyDescriptor>> {
+        // TODO implement.
+        Err(anyhow!(error::Error::sys()))
+    }
+
+    fn delete_key(&self, key: &KeyDescriptor) -> Result<()> {
+        // TODO implement.
+        Err(anyhow!(error::Error::sys()))
+    }
+
+    fn grant(
+        &self,
+        key: &KeyDescriptor,
+        grantee_uid: i32,
+        access_vector: permission::KeyPermSet,
+    ) -> Result<KeyDescriptor> {
+        DB.with(|db| {
+            db.borrow_mut().grant(
+                key.clone(),
+                ThreadState::get_calling_uid(),
+                grantee_uid as u32,
+                access_vector,
+                |k, av| check_grant_permission(*av, k).context("During grant."),
+            )
+        })
+        .context("In KeystoreService::grant.")
+    }
+
+    fn ungrant(&self, key: &KeyDescriptor, grantee_uid: i32) -> Result<()> {
+        DB.with(|db| {
+            db.borrow_mut().ungrant(
+                key.clone(),
+                ThreadState::get_calling_uid(),
+                grantee_uid as u32,
+                |k| check_key_permission(KeyPerm::grant(), k, &None),
+            )
+        })
+        .context("In KeystoreService::ungrant.")
+    }
+}
+
+impl binder::Interface for KeystoreService {}
+
+// Implementation of IKeystoreService. See AIDL spec at
+// system/security/keystore2/binder/android/security/keystore2/IKeystoreService.aidl
+impl IKeystoreService for KeystoreService {
+    fn getSecurityLevel(
+        &self,
+        security_level: SecurityLevel,
+    ) -> binder::public_api::Result<Box<dyn IKeystoreSecurityLevel>> {
+        map_or_log_err(self.get_security_level(security_level), Ok)
+    }
+    fn getKeyEntry(
+        &self,
+        key: &KeyDescriptor,
+        metadata: &mut KeyMetadata,
+        public_cert: &mut Option<Certificate>,
+        certificate_chain: &mut Option<CertificateChain>,
+    ) -> binder::public_api::Result<Box<dyn IKeystoreSecurityLevel>> {
+        map_or_log_err(self.get_key_entry(key), |v| {
+            *metadata = v.0;
+            *public_cert = v.1;
+            *certificate_chain = v.2;
+            Ok(v.3)
+        })
+    }
+    fn updateSubcomponent(
+        &self,
+        key: &KeyDescriptor,
+        public_cert: Option<&Certificate>,
+        certificate_chain: Option<&CertificateChain>,
+    ) -> binder::public_api::Result<()> {
+        map_or_log_err(self.update_subcomponent(key, public_cert, certificate_chain), Ok)
+    }
+    fn listEntries(
+        &self,
+        domain: Domain,
+        namespace: i64,
+    ) -> binder::public_api::Result<Vec<KeyDescriptor>> {
+        map_or_log_err(self.list_entries(domain, namespace), Ok)
+    }
+    fn deleteKey(&self, key: &KeyDescriptor) -> binder::public_api::Result<()> {
+        map_or_log_err(self.delete_key(key), Ok)
+    }
+    fn grant(
+        &self,
+        key: &KeyDescriptor,
+        grantee_uid: i32,
+        access_vector: i32,
+    ) -> binder::public_api::Result<KeyDescriptor> {
+        map_or_log_err(self.grant(key, grantee_uid, access_vector.into()), Ok)
+    }
+    fn ungrant(&self, key: &KeyDescriptor, grantee_uid: i32) -> binder::public_api::Result<()> {
+        map_or_log_err(self.ungrant(key, grantee_uid), Ok)
+    }
+}
