xref: /aosp_15_r20/system/security/keystore2/src/raw_device.rs (revision e1997b9af69e3155ead6e072d106a0077849ffba)
1*e1997b9aSAndroid Build Coastguard Worker // Copyright 2021, 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 //! Provide the [`KeyMintDevice`] wrapper for operating directly on a KeyMint device.
16*e1997b9aSAndroid Build Coastguard Worker 
17*e1997b9aSAndroid Build Coastguard Worker use crate::{
18*e1997b9aSAndroid Build Coastguard Worker     database::{
19*e1997b9aSAndroid Build Coastguard Worker         BlobInfo, BlobMetaData, BlobMetaEntry, CertificateInfo, DateTime, KeyEntry,
20*e1997b9aSAndroid Build Coastguard Worker         KeyEntryLoadBits, KeyIdGuard, KeyMetaData, KeyMetaEntry, KeyType, KeystoreDB,
21*e1997b9aSAndroid Build Coastguard Worker         SubComponentType, Uuid,
22*e1997b9aSAndroid Build Coastguard Worker     },
23*e1997b9aSAndroid Build Coastguard Worker     error::{map_km_error, Error, ErrorCode},
24*e1997b9aSAndroid Build Coastguard Worker     globals::get_keymint_device,
25*e1997b9aSAndroid Build Coastguard Worker     ks_err,
26*e1997b9aSAndroid Build Coastguard Worker     super_key::KeyBlob,
27*e1997b9aSAndroid Build Coastguard Worker     utils::{key_characteristics_to_internal, watchdog as wd, AID_KEYSTORE},
28*e1997b9aSAndroid Build Coastguard Worker };
29*e1997b9aSAndroid Build Coastguard Worker use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
30*e1997b9aSAndroid Build Coastguard Worker     HardwareAuthToken::HardwareAuthToken, IKeyMintDevice::IKeyMintDevice,
31*e1997b9aSAndroid Build Coastguard Worker     IKeyMintOperation::IKeyMintOperation, KeyCharacteristics::KeyCharacteristics,
32*e1997b9aSAndroid Build Coastguard Worker     KeyCreationResult::KeyCreationResult, KeyParameter::KeyParameter, KeyPurpose::KeyPurpose,
33*e1997b9aSAndroid Build Coastguard Worker     SecurityLevel::SecurityLevel,
34*e1997b9aSAndroid Build Coastguard Worker };
35*e1997b9aSAndroid Build Coastguard Worker use android_system_keystore2::aidl::android::system::keystore2::{
36*e1997b9aSAndroid Build Coastguard Worker     Domain::Domain, KeyDescriptor::KeyDescriptor, ResponseCode::ResponseCode,
37*e1997b9aSAndroid Build Coastguard Worker };
38*e1997b9aSAndroid Build Coastguard Worker use anyhow::{Context, Result};
39*e1997b9aSAndroid Build Coastguard Worker use binder::Strong;
40*e1997b9aSAndroid Build Coastguard Worker 
41*e1997b9aSAndroid Build Coastguard Worker /// Wrapper for operating directly on a KeyMint device.
42*e1997b9aSAndroid Build Coastguard Worker /// These methods often mirror methods in [`crate::security_level`]. However
43*e1997b9aSAndroid Build Coastguard Worker /// the functions in [`crate::security_level`] make assumptions that hold, and has side effects
44*e1997b9aSAndroid Build Coastguard Worker /// that make sense, only if called by an external client through binder.
45*e1997b9aSAndroid Build Coastguard Worker /// In addition we are trying to maintain a separation between interface services
46*e1997b9aSAndroid Build Coastguard Worker /// so that the architecture is compatible with a future move to multiple thread pools.
47*e1997b9aSAndroid Build Coastguard Worker /// So the simplest approach today is to write new implementations of them for internal use.
48*e1997b9aSAndroid Build Coastguard Worker /// Because these methods run very early, we don't even try to cooperate with
49*e1997b9aSAndroid Build Coastguard Worker /// the operation slot database; we assume there will be plenty of slots.
50*e1997b9aSAndroid Build Coastguard Worker pub struct KeyMintDevice {
51*e1997b9aSAndroid Build Coastguard Worker     km_dev: Strong<dyn IKeyMintDevice>,
52*e1997b9aSAndroid Build Coastguard Worker     km_uuid: Uuid,
53*e1997b9aSAndroid Build Coastguard Worker     version: i32,
54*e1997b9aSAndroid Build Coastguard Worker     security_level: SecurityLevel,
55*e1997b9aSAndroid Build Coastguard Worker }
56*e1997b9aSAndroid Build Coastguard Worker 
57*e1997b9aSAndroid Build Coastguard Worker impl KeyMintDevice {
58*e1997b9aSAndroid Build Coastguard Worker     /// Version number of KeyMasterDevice@V4_0
59*e1997b9aSAndroid Build Coastguard Worker     pub const KEY_MASTER_V4_0: i32 = 40;
60*e1997b9aSAndroid Build Coastguard Worker     /// Version number of KeyMasterDevice@V4_1
61*e1997b9aSAndroid Build Coastguard Worker     pub const KEY_MASTER_V4_1: i32 = 41;
62*e1997b9aSAndroid Build Coastguard Worker     /// Version number of KeyMintDevice@V1
63*e1997b9aSAndroid Build Coastguard Worker     pub const KEY_MINT_V1: i32 = 100;
64*e1997b9aSAndroid Build Coastguard Worker     /// Version number of KeyMintDevice@V2
65*e1997b9aSAndroid Build Coastguard Worker     pub const KEY_MINT_V2: i32 = 200;
66*e1997b9aSAndroid Build Coastguard Worker     /// Version number of KeyMintDevice@V3
67*e1997b9aSAndroid Build Coastguard Worker     pub const KEY_MINT_V3: i32 = 300;
68*e1997b9aSAndroid Build Coastguard Worker 
69*e1997b9aSAndroid Build Coastguard Worker     /// Get a [`KeyMintDevice`] for the given [`SecurityLevel`]
get(security_level: SecurityLevel) -> Result<KeyMintDevice>70*e1997b9aSAndroid Build Coastguard Worker     pub fn get(security_level: SecurityLevel) -> Result<KeyMintDevice> {
71*e1997b9aSAndroid Build Coastguard Worker         let (km_dev, hw_info, km_uuid) =
72*e1997b9aSAndroid Build Coastguard Worker             get_keymint_device(&security_level).context(ks_err!("get_keymint_device failed"))?;
73*e1997b9aSAndroid Build Coastguard Worker 
74*e1997b9aSAndroid Build Coastguard Worker         Ok(KeyMintDevice {
75*e1997b9aSAndroid Build Coastguard Worker             km_dev,
76*e1997b9aSAndroid Build Coastguard Worker             km_uuid,
77*e1997b9aSAndroid Build Coastguard Worker             version: hw_info.versionNumber,
78*e1997b9aSAndroid Build Coastguard Worker             security_level: hw_info.securityLevel,
79*e1997b9aSAndroid Build Coastguard Worker         })
80*e1997b9aSAndroid Build Coastguard Worker     }
81*e1997b9aSAndroid Build Coastguard Worker 
82*e1997b9aSAndroid Build Coastguard Worker     /// Get a [`KeyMintDevice`] for the given [`SecurityLevel`], return
83*e1997b9aSAndroid Build Coastguard Worker     /// [`None`] if the error `HARDWARE_TYPE_UNAVAILABLE` is returned
get_or_none(security_level: SecurityLevel) -> Result<Option<KeyMintDevice>>84*e1997b9aSAndroid Build Coastguard Worker     pub fn get_or_none(security_level: SecurityLevel) -> Result<Option<KeyMintDevice>> {
85*e1997b9aSAndroid Build Coastguard Worker         KeyMintDevice::get(security_level).map(Some).or_else(|e| {
86*e1997b9aSAndroid Build Coastguard Worker             match e.root_cause().downcast_ref::<Error>() {
87*e1997b9aSAndroid Build Coastguard Worker                 Some(Error::Km(ErrorCode::HARDWARE_TYPE_UNAVAILABLE)) => Ok(None),
88*e1997b9aSAndroid Build Coastguard Worker                 _ => Err(e),
89*e1997b9aSAndroid Build Coastguard Worker             }
90*e1997b9aSAndroid Build Coastguard Worker         })
91*e1997b9aSAndroid Build Coastguard Worker     }
92*e1997b9aSAndroid Build Coastguard Worker 
93*e1997b9aSAndroid Build Coastguard Worker     /// Returns the version of the underlying KeyMint/KeyMaster device.
version(&self) -> i3294*e1997b9aSAndroid Build Coastguard Worker     pub fn version(&self) -> i32 {
95*e1997b9aSAndroid Build Coastguard Worker         self.version
96*e1997b9aSAndroid Build Coastguard Worker     }
97*e1997b9aSAndroid Build Coastguard Worker 
98*e1997b9aSAndroid Build Coastguard Worker     /// Returns the self advertised security level of the KeyMint device.
99*e1997b9aSAndroid Build Coastguard Worker     /// This may differ from the requested security level if the best security level
100*e1997b9aSAndroid Build Coastguard Worker     /// on the device is Software.
security_level(&self) -> SecurityLevel101*e1997b9aSAndroid Build Coastguard Worker     pub fn security_level(&self) -> SecurityLevel {
102*e1997b9aSAndroid Build Coastguard Worker         self.security_level
103*e1997b9aSAndroid Build Coastguard Worker     }
104*e1997b9aSAndroid Build Coastguard Worker 
105*e1997b9aSAndroid Build Coastguard Worker     /// Create a KM key and store in the database.
create_and_store_key<F>( &self, db: &mut KeystoreDB, key_desc: &KeyDescriptor, key_type: KeyType, creator: F, ) -> Result<()> where F: FnOnce(&Strong<dyn IKeyMintDevice>) -> Result<KeyCreationResult, binder::Status>,106*e1997b9aSAndroid Build Coastguard Worker     pub fn create_and_store_key<F>(
107*e1997b9aSAndroid Build Coastguard Worker         &self,
108*e1997b9aSAndroid Build Coastguard Worker         db: &mut KeystoreDB,
109*e1997b9aSAndroid Build Coastguard Worker         key_desc: &KeyDescriptor,
110*e1997b9aSAndroid Build Coastguard Worker         key_type: KeyType,
111*e1997b9aSAndroid Build Coastguard Worker         creator: F,
112*e1997b9aSAndroid Build Coastguard Worker     ) -> Result<()>
113*e1997b9aSAndroid Build Coastguard Worker     where
114*e1997b9aSAndroid Build Coastguard Worker         F: FnOnce(&Strong<dyn IKeyMintDevice>) -> Result<KeyCreationResult, binder::Status>,
115*e1997b9aSAndroid Build Coastguard Worker     {
116*e1997b9aSAndroid Build Coastguard Worker         let creation_result =
117*e1997b9aSAndroid Build Coastguard Worker             map_km_error(creator(&self.km_dev)).context(ks_err!("creator failed"))?;
118*e1997b9aSAndroid Build Coastguard Worker         let key_parameters = key_characteristics_to_internal(creation_result.keyCharacteristics);
119*e1997b9aSAndroid Build Coastguard Worker 
120*e1997b9aSAndroid Build Coastguard Worker         let creation_date = DateTime::now().context(ks_err!("DateTime::now() failed"))?;
121*e1997b9aSAndroid Build Coastguard Worker 
122*e1997b9aSAndroid Build Coastguard Worker         let mut key_metadata = KeyMetaData::new();
123*e1997b9aSAndroid Build Coastguard Worker         key_metadata.add(KeyMetaEntry::CreationDate(creation_date));
124*e1997b9aSAndroid Build Coastguard Worker         let mut blob_metadata = BlobMetaData::new();
125*e1997b9aSAndroid Build Coastguard Worker         blob_metadata.add(BlobMetaEntry::KmUuid(self.km_uuid));
126*e1997b9aSAndroid Build Coastguard Worker 
127*e1997b9aSAndroid Build Coastguard Worker         db.store_new_key(
128*e1997b9aSAndroid Build Coastguard Worker             key_desc,
129*e1997b9aSAndroid Build Coastguard Worker             key_type,
130*e1997b9aSAndroid Build Coastguard Worker             &key_parameters,
131*e1997b9aSAndroid Build Coastguard Worker             &BlobInfo::new(&creation_result.keyBlob, &blob_metadata),
132*e1997b9aSAndroid Build Coastguard Worker             &CertificateInfo::new(None, None),
133*e1997b9aSAndroid Build Coastguard Worker             &key_metadata,
134*e1997b9aSAndroid Build Coastguard Worker             &self.km_uuid,
135*e1997b9aSAndroid Build Coastguard Worker         )
136*e1997b9aSAndroid Build Coastguard Worker         .context(ks_err!("store_new_key failed"))?;
137*e1997b9aSAndroid Build Coastguard Worker         Ok(())
138*e1997b9aSAndroid Build Coastguard Worker     }
139*e1997b9aSAndroid Build Coastguard Worker 
140*e1997b9aSAndroid Build Coastguard Worker     /// Generate a KeyDescriptor for internal-use keys.
internal_descriptor(alias: String) -> KeyDescriptor141*e1997b9aSAndroid Build Coastguard Worker     pub fn internal_descriptor(alias: String) -> KeyDescriptor {
142*e1997b9aSAndroid Build Coastguard Worker         KeyDescriptor {
143*e1997b9aSAndroid Build Coastguard Worker             domain: Domain::APP,
144*e1997b9aSAndroid Build Coastguard Worker             nspace: AID_KEYSTORE as i64,
145*e1997b9aSAndroid Build Coastguard Worker             alias: Some(alias),
146*e1997b9aSAndroid Build Coastguard Worker             blob: None,
147*e1997b9aSAndroid Build Coastguard Worker         }
148*e1997b9aSAndroid Build Coastguard Worker     }
149*e1997b9aSAndroid Build Coastguard Worker 
150*e1997b9aSAndroid Build Coastguard Worker     /// Look up an internal-use key in the database given a key descriptor.
lookup_from_desc( db: &mut KeystoreDB, key_desc: &KeyDescriptor, key_type: KeyType, ) -> Result<(KeyIdGuard, KeyEntry)>151*e1997b9aSAndroid Build Coastguard Worker     fn lookup_from_desc(
152*e1997b9aSAndroid Build Coastguard Worker         db: &mut KeystoreDB,
153*e1997b9aSAndroid Build Coastguard Worker         key_desc: &KeyDescriptor,
154*e1997b9aSAndroid Build Coastguard Worker         key_type: KeyType,
155*e1997b9aSAndroid Build Coastguard Worker     ) -> Result<(KeyIdGuard, KeyEntry)> {
156*e1997b9aSAndroid Build Coastguard Worker         db.load_key_entry(key_desc, key_type, KeyEntryLoadBits::KM, AID_KEYSTORE, |_, _| Ok(()))
157*e1997b9aSAndroid Build Coastguard Worker             .context(ks_err!("load_key_entry failed."))
158*e1997b9aSAndroid Build Coastguard Worker     }
159*e1997b9aSAndroid Build Coastguard Worker 
160*e1997b9aSAndroid Build Coastguard Worker     /// Look up the key in the database, and return None if it is absent.
not_found_is_none( lookup: Result<(KeyIdGuard, KeyEntry)>, ) -> Result<Option<(KeyIdGuard, KeyEntry)>>161*e1997b9aSAndroid Build Coastguard Worker     fn not_found_is_none(
162*e1997b9aSAndroid Build Coastguard Worker         lookup: Result<(KeyIdGuard, KeyEntry)>,
163*e1997b9aSAndroid Build Coastguard Worker     ) -> Result<Option<(KeyIdGuard, KeyEntry)>> {
164*e1997b9aSAndroid Build Coastguard Worker         match lookup {
165*e1997b9aSAndroid Build Coastguard Worker             Ok(result) => Ok(Some(result)),
166*e1997b9aSAndroid Build Coastguard Worker             Err(e) => match e.root_cause().downcast_ref::<Error>() {
167*e1997b9aSAndroid Build Coastguard Worker                 Some(&Error::Rc(ResponseCode::KEY_NOT_FOUND)) => Ok(None),
168*e1997b9aSAndroid Build Coastguard Worker                 _ => Err(e),
169*e1997b9aSAndroid Build Coastguard Worker             },
170*e1997b9aSAndroid Build Coastguard Worker         }
171*e1997b9aSAndroid Build Coastguard Worker     }
172*e1997b9aSAndroid Build Coastguard Worker 
173*e1997b9aSAndroid Build Coastguard Worker     /// This does the lookup and store in separate transactions; caller must
174*e1997b9aSAndroid Build Coastguard Worker     /// hold a lock before calling.
lookup_or_generate_key<F>( &self, db: &mut KeystoreDB, key_desc: &KeyDescriptor, key_type: KeyType, params: &[KeyParameter], validate_characteristics: F, ) -> Result<(KeyIdGuard, KeyBlob)> where F: FnOnce(&[KeyCharacteristics]) -> bool,175*e1997b9aSAndroid Build Coastguard Worker     pub fn lookup_or_generate_key<F>(
176*e1997b9aSAndroid Build Coastguard Worker         &self,
177*e1997b9aSAndroid Build Coastguard Worker         db: &mut KeystoreDB,
178*e1997b9aSAndroid Build Coastguard Worker         key_desc: &KeyDescriptor,
179*e1997b9aSAndroid Build Coastguard Worker         key_type: KeyType,
180*e1997b9aSAndroid Build Coastguard Worker         params: &[KeyParameter],
181*e1997b9aSAndroid Build Coastguard Worker         validate_characteristics: F,
182*e1997b9aSAndroid Build Coastguard Worker     ) -> Result<(KeyIdGuard, KeyBlob)>
183*e1997b9aSAndroid Build Coastguard Worker     where
184*e1997b9aSAndroid Build Coastguard Worker         F: FnOnce(&[KeyCharacteristics]) -> bool,
185*e1997b9aSAndroid Build Coastguard Worker     {
186*e1997b9aSAndroid Build Coastguard Worker         // We use a separate transaction for the lookup than for the store
187*e1997b9aSAndroid Build Coastguard Worker         // - to keep the code simple
188*e1997b9aSAndroid Build Coastguard Worker         // - because the caller needs to hold a lock in any case
189*e1997b9aSAndroid Build Coastguard Worker         // - because it avoids holding database locks during slow
190*e1997b9aSAndroid Build Coastguard Worker         //   KeyMint operations
191*e1997b9aSAndroid Build Coastguard Worker         let lookup = Self::not_found_is_none(Self::lookup_from_desc(db, key_desc, key_type))
192*e1997b9aSAndroid Build Coastguard Worker             .context(ks_err!("first lookup failed"))?;
193*e1997b9aSAndroid Build Coastguard Worker 
194*e1997b9aSAndroid Build Coastguard Worker         if let Some((key_id_guard, mut key_entry)) = lookup {
195*e1997b9aSAndroid Build Coastguard Worker             // If the key is associated with a different km instance
196*e1997b9aSAndroid Build Coastguard Worker             // or if there is no blob metadata for some reason the key entry
197*e1997b9aSAndroid Build Coastguard Worker             // is considered corrupted and needs to be replaced with a new one.
198*e1997b9aSAndroid Build Coastguard Worker             let key_blob = key_entry.take_key_blob_info().and_then(|(key_blob, blob_metadata)| {
199*e1997b9aSAndroid Build Coastguard Worker                 if Some(&self.km_uuid) == blob_metadata.km_uuid() {
200*e1997b9aSAndroid Build Coastguard Worker                     Some(key_blob)
201*e1997b9aSAndroid Build Coastguard Worker                 } else {
202*e1997b9aSAndroid Build Coastguard Worker                     None
203*e1997b9aSAndroid Build Coastguard Worker                 }
204*e1997b9aSAndroid Build Coastguard Worker             });
205*e1997b9aSAndroid Build Coastguard Worker 
206*e1997b9aSAndroid Build Coastguard Worker             if let Some(key_blob_vec) = key_blob {
207*e1997b9aSAndroid Build Coastguard Worker                 let (key_characteristics, key_blob) = self
208*e1997b9aSAndroid Build Coastguard Worker                     .upgrade_keyblob_if_required_with(
209*e1997b9aSAndroid Build Coastguard Worker                         db,
210*e1997b9aSAndroid Build Coastguard Worker                         &key_id_guard,
211*e1997b9aSAndroid Build Coastguard Worker                         KeyBlob::NonSensitive(key_blob_vec),
212*e1997b9aSAndroid Build Coastguard Worker                         |key_blob| {
213*e1997b9aSAndroid Build Coastguard Worker                             map_km_error({
214*e1997b9aSAndroid Build Coastguard Worker                                 let _wp = wd::watch(concat!(
215*e1997b9aSAndroid Build Coastguard Worker                                     "KeyMintDevice::lookup_or_generate_key: ",
216*e1997b9aSAndroid Build Coastguard Worker                                     "calling IKeyMintDevice::getKeyCharacteristics."
217*e1997b9aSAndroid Build Coastguard Worker                                 ));
218*e1997b9aSAndroid Build Coastguard Worker                                 self.km_dev.getKeyCharacteristics(key_blob, &[], &[])
219*e1997b9aSAndroid Build Coastguard Worker                             })
220*e1997b9aSAndroid Build Coastguard Worker                         },
221*e1997b9aSAndroid Build Coastguard Worker                     )
222*e1997b9aSAndroid Build Coastguard Worker                     .context(ks_err!("calling getKeyCharacteristics"))?;
223*e1997b9aSAndroid Build Coastguard Worker 
224*e1997b9aSAndroid Build Coastguard Worker                 if validate_characteristics(&key_characteristics) {
225*e1997b9aSAndroid Build Coastguard Worker                     return Ok((key_id_guard, key_blob));
226*e1997b9aSAndroid Build Coastguard Worker                 }
227*e1997b9aSAndroid Build Coastguard Worker 
228*e1997b9aSAndroid Build Coastguard Worker                 // If this point is reached the existing key is considered outdated or corrupted
229*e1997b9aSAndroid Build Coastguard Worker                 // in some way. It will be replaced with a new key below.
230*e1997b9aSAndroid Build Coastguard Worker             };
231*e1997b9aSAndroid Build Coastguard Worker         }
232*e1997b9aSAndroid Build Coastguard Worker 
233*e1997b9aSAndroid Build Coastguard Worker         self.create_and_store_key(db, key_desc, key_type, |km_dev| {
234*e1997b9aSAndroid Build Coastguard Worker             km_dev.generateKey(params, None)
235*e1997b9aSAndroid Build Coastguard Worker         })
236*e1997b9aSAndroid Build Coastguard Worker         .context(ks_err!("generate_and_store_key failed"))?;
237*e1997b9aSAndroid Build Coastguard Worker         Self::lookup_from_desc(db, key_desc, key_type)
238*e1997b9aSAndroid Build Coastguard Worker             .and_then(|(key_id_guard, mut key_entry)| {
239*e1997b9aSAndroid Build Coastguard Worker                 Ok((
240*e1997b9aSAndroid Build Coastguard Worker                     key_id_guard,
241*e1997b9aSAndroid Build Coastguard Worker                     key_entry
242*e1997b9aSAndroid Build Coastguard Worker                         .take_key_blob_info()
243*e1997b9aSAndroid Build Coastguard Worker                         .ok_or(Error::Rc(ResponseCode::KEY_NOT_FOUND))
244*e1997b9aSAndroid Build Coastguard Worker                         .map(|(key_blob, _)| KeyBlob::NonSensitive(key_blob))
245*e1997b9aSAndroid Build Coastguard Worker                         .context(ks_err!("Missing key blob info."))?,
246*e1997b9aSAndroid Build Coastguard Worker                 ))
247*e1997b9aSAndroid Build Coastguard Worker             })
248*e1997b9aSAndroid Build Coastguard Worker             .context(ks_err!("second lookup failed"))
249*e1997b9aSAndroid Build Coastguard Worker     }
250*e1997b9aSAndroid Build Coastguard Worker 
251*e1997b9aSAndroid Build Coastguard Worker     /// Call the passed closure; if it returns `KEY_REQUIRES_UPGRADE`, call upgradeKey, and
252*e1997b9aSAndroid Build Coastguard Worker     /// write the upgraded key to the database.
upgrade_keyblob_if_required_with<'a, T, F>( &self, db: &mut KeystoreDB, key_id_guard: &KeyIdGuard, key_blob: KeyBlob<'a>, f: F, ) -> Result<(T, KeyBlob<'a>)> where F: Fn(&[u8]) -> Result<T, Error>,253*e1997b9aSAndroid Build Coastguard Worker     fn upgrade_keyblob_if_required_with<'a, T, F>(
254*e1997b9aSAndroid Build Coastguard Worker         &self,
255*e1997b9aSAndroid Build Coastguard Worker         db: &mut KeystoreDB,
256*e1997b9aSAndroid Build Coastguard Worker         key_id_guard: &KeyIdGuard,
257*e1997b9aSAndroid Build Coastguard Worker         key_blob: KeyBlob<'a>,
258*e1997b9aSAndroid Build Coastguard Worker         f: F,
259*e1997b9aSAndroid Build Coastguard Worker     ) -> Result<(T, KeyBlob<'a>)>
260*e1997b9aSAndroid Build Coastguard Worker     where
261*e1997b9aSAndroid Build Coastguard Worker         F: Fn(&[u8]) -> Result<T, Error>,
262*e1997b9aSAndroid Build Coastguard Worker     {
263*e1997b9aSAndroid Build Coastguard Worker         let (f_result, upgraded_blob) = crate::utils::upgrade_keyblob_if_required_with(
264*e1997b9aSAndroid Build Coastguard Worker             &*self.km_dev,
265*e1997b9aSAndroid Build Coastguard Worker             self.version(),
266*e1997b9aSAndroid Build Coastguard Worker             &key_blob,
267*e1997b9aSAndroid Build Coastguard Worker             &[],
268*e1997b9aSAndroid Build Coastguard Worker             f,
269*e1997b9aSAndroid Build Coastguard Worker             |upgraded_blob| {
270*e1997b9aSAndroid Build Coastguard Worker                 let mut new_blob_metadata = BlobMetaData::new();
271*e1997b9aSAndroid Build Coastguard Worker                 new_blob_metadata.add(BlobMetaEntry::KmUuid(self.km_uuid));
272*e1997b9aSAndroid Build Coastguard Worker 
273*e1997b9aSAndroid Build Coastguard Worker                 db.set_blob(
274*e1997b9aSAndroid Build Coastguard Worker                     key_id_guard,
275*e1997b9aSAndroid Build Coastguard Worker                     SubComponentType::KEY_BLOB,
276*e1997b9aSAndroid Build Coastguard Worker                     Some(upgraded_blob),
277*e1997b9aSAndroid Build Coastguard Worker                     Some(&new_blob_metadata),
278*e1997b9aSAndroid Build Coastguard Worker                 )
279*e1997b9aSAndroid Build Coastguard Worker                 .context(ks_err!("Failed to insert upgraded blob into the database"))?;
280*e1997b9aSAndroid Build Coastguard Worker                 Ok(())
281*e1997b9aSAndroid Build Coastguard Worker             },
282*e1997b9aSAndroid Build Coastguard Worker         )?;
283*e1997b9aSAndroid Build Coastguard Worker         let returned_blob = match upgraded_blob {
284*e1997b9aSAndroid Build Coastguard Worker             None => key_blob,
285*e1997b9aSAndroid Build Coastguard Worker             Some(upgraded_blob) => KeyBlob::NonSensitive(upgraded_blob),
286*e1997b9aSAndroid Build Coastguard Worker         };
287*e1997b9aSAndroid Build Coastguard Worker         Ok((f_result, returned_blob))
288*e1997b9aSAndroid Build Coastguard Worker     }
289*e1997b9aSAndroid Build Coastguard Worker 
290*e1997b9aSAndroid Build Coastguard Worker     /// Use the created key in an operation that can be done with
291*e1997b9aSAndroid Build Coastguard Worker     /// a call to begin followed by a call to finish.
292*e1997b9aSAndroid Build Coastguard Worker     #[allow(clippy::too_many_arguments)]
use_key_in_one_step( &self, db: &mut KeystoreDB, key_id_guard: &KeyIdGuard, key_blob: &[u8], purpose: KeyPurpose, operation_parameters: &[KeyParameter], auth_token: Option<&HardwareAuthToken>, input: &[u8], ) -> Result<Vec<u8>>293*e1997b9aSAndroid Build Coastguard Worker     pub fn use_key_in_one_step(
294*e1997b9aSAndroid Build Coastguard Worker         &self,
295*e1997b9aSAndroid Build Coastguard Worker         db: &mut KeystoreDB,
296*e1997b9aSAndroid Build Coastguard Worker         key_id_guard: &KeyIdGuard,
297*e1997b9aSAndroid Build Coastguard Worker         key_blob: &[u8],
298*e1997b9aSAndroid Build Coastguard Worker         purpose: KeyPurpose,
299*e1997b9aSAndroid Build Coastguard Worker         operation_parameters: &[KeyParameter],
300*e1997b9aSAndroid Build Coastguard Worker         auth_token: Option<&HardwareAuthToken>,
301*e1997b9aSAndroid Build Coastguard Worker         input: &[u8],
302*e1997b9aSAndroid Build Coastguard Worker     ) -> Result<Vec<u8>> {
303*e1997b9aSAndroid Build Coastguard Worker         let key_blob = KeyBlob::Ref(key_blob);
304*e1997b9aSAndroid Build Coastguard Worker 
305*e1997b9aSAndroid Build Coastguard Worker         let (begin_result, _) = self
306*e1997b9aSAndroid Build Coastguard Worker             .upgrade_keyblob_if_required_with(db, key_id_guard, key_blob, |blob| {
307*e1997b9aSAndroid Build Coastguard Worker                 map_km_error({
308*e1997b9aSAndroid Build Coastguard Worker                     let _wp = wd::watch(
309*e1997b9aSAndroid Build Coastguard Worker                         "KeyMintDevice::use_key_in_one_step: calling IKeyMintDevice::begin",
310*e1997b9aSAndroid Build Coastguard Worker                     );
311*e1997b9aSAndroid Build Coastguard Worker                     self.km_dev.begin(purpose, blob, operation_parameters, auth_token)
312*e1997b9aSAndroid Build Coastguard Worker                 })
313*e1997b9aSAndroid Build Coastguard Worker             })
314*e1997b9aSAndroid Build Coastguard Worker             .context(ks_err!("Failed to begin operation."))?;
315*e1997b9aSAndroid Build Coastguard Worker         let operation: Strong<dyn IKeyMintOperation> =
316*e1997b9aSAndroid Build Coastguard Worker             begin_result.operation.ok_or_else(Error::sys).context(ks_err!("Operation missing"))?;
317*e1997b9aSAndroid Build Coastguard Worker         map_km_error({
318*e1997b9aSAndroid Build Coastguard Worker             let _wp =
319*e1997b9aSAndroid Build Coastguard Worker                 wd::watch("KeyMintDevice::use_key_in_one_step: calling IKeyMintDevice::finish");
320*e1997b9aSAndroid Build Coastguard Worker             operation.finish(Some(input), None, None, None, None)
321*e1997b9aSAndroid Build Coastguard Worker         })
322*e1997b9aSAndroid Build Coastguard Worker         .context(ks_err!("Failed to finish operation."))
323*e1997b9aSAndroid Build Coastguard Worker     }
324*e1997b9aSAndroid Build Coastguard Worker }
325