blob: a8a88d256e92134d23744f56642e6fbaf004f4f9 [file] [log] [blame]
Paul Crowleyef611e52021-04-20 14:43:04 -07001// Copyright 2021, The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Provide the [`KeyMintDevice`] wrapper for operating directly on a KeyMint device.
16
17use crate::{
18 database::{
Janis Danisevskisf84d0b02022-01-26 14:11:14 -080019 BlobInfo, BlobMetaData, BlobMetaEntry, CertificateInfo, DateTime, KeyEntry,
20 KeyEntryLoadBits, KeyIdGuard, KeyMetaData, KeyMetaEntry, KeyType, KeystoreDB,
21 SubComponentType, Uuid,
Paul Crowleyef611e52021-04-20 14:43:04 -070022 },
Janis Danisevskis5c748212021-05-17 17:13:56 -070023 error::{map_km_error, Error, ErrorCode},
Paul Crowleyef611e52021-04-20 14:43:04 -070024 globals::get_keymint_device,
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +000025 ks_err,
Paul Crowleyef611e52021-04-20 14:43:04 -070026 super_key::KeyBlob,
Janis Danisevskisacebfa22021-05-25 10:56:10 -070027 utils::{key_characteristics_to_internal, watchdog as wd, AID_KEYSTORE},
Paul Crowleyef611e52021-04-20 14:43:04 -070028};
29use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
Janis Danisevskisacebfa22021-05-25 10:56:10 -070030 HardwareAuthToken::HardwareAuthToken, IKeyMintDevice::IKeyMintDevice,
31 IKeyMintOperation::IKeyMintOperation, KeyCharacteristics::KeyCharacteristics,
32 KeyCreationResult::KeyCreationResult, KeyParameter::KeyParameter, KeyPurpose::KeyPurpose,
33 SecurityLevel::SecurityLevel,
Paul Crowleyef611e52021-04-20 14:43:04 -070034};
35use android_system_keystore2::aidl::android::system::keystore2::{
Paul Crowley618869e2021-04-08 20:30:54 -070036 Domain::Domain, KeyDescriptor::KeyDescriptor, ResponseCode::ResponseCode,
Paul Crowleyef611e52021-04-20 14:43:04 -070037};
38use anyhow::{Context, Result};
39use binder::Strong;
40
41/// Wrapper for operating directly on a KeyMint device.
42/// These methods often mirror methods in [`crate::security_level`]. However
43/// the functions in [`crate::security_level`] make assumptions that hold, and has side effects
44/// that make sense, only if called by an external client through binder.
45/// In addition we are trying to maintain a separation between interface services
46/// so that the architecture is compatible with a future move to multiple thread pools.
47/// So the simplest approach today is to write new implementations of them for internal use.
48/// Because these methods run very early, we don't even try to cooperate with
49/// the operation slot database; we assume there will be plenty of slots.
50pub struct KeyMintDevice {
Janis Danisevskisacebfa22021-05-25 10:56:10 -070051 km_dev: Strong<dyn IKeyMintDevice>,
Paul Crowleyef611e52021-04-20 14:43:04 -070052 km_uuid: Uuid,
Janis Danisevskis5c748212021-05-17 17:13:56 -070053 version: i32,
Janis Danisevskisacebfa22021-05-25 10:56:10 -070054 security_level: SecurityLevel,
Paul Crowleyef611e52021-04-20 14:43:04 -070055}
56
57impl KeyMintDevice {
Janis Danisevskis5c748212021-05-17 17:13:56 -070058 /// Version number of KeyMasterDevice@V4_0
59 pub const KEY_MASTER_V4_0: i32 = 40;
60 /// Version number of KeyMasterDevice@V4_1
61 pub const KEY_MASTER_V4_1: i32 = 41;
62 /// Version number of KeyMintDevice@V1
63 pub const KEY_MINT_V1: i32 = 100;
David Drysdalea6c82a92021-12-06 11:24:26 +000064 /// Version number of KeyMintDevice@V2
65 pub const KEY_MINT_V2: i32 = 200;
Eran Messeri637259c2022-10-31 12:23:36 +000066 /// Version number of KeyMintDevice@V3
67 pub const KEY_MINT_V3: i32 = 300;
Janis Danisevskis5c748212021-05-17 17:13:56 -070068
Paul Crowleyef611e52021-04-20 14:43:04 -070069 /// Get a [`KeyMintDevice`] for the given [`SecurityLevel`]
70 pub fn get(security_level: SecurityLevel) -> Result<KeyMintDevice> {
Shaquille Johnsonaec2eca2022-11-30 17:08:05 +000071 let (km_dev, hw_info, km_uuid) =
72 get_keymint_device(&security_level).context(ks_err!("get_keymint_device failed"))?;
Janis Danisevskis5c748212021-05-17 17:13:56 -070073
Janis Danisevskisacebfa22021-05-25 10:56:10 -070074 Ok(KeyMintDevice {
Janis Danisevskis5f3a0572021-06-18 11:26:42 -070075 km_dev,
Janis Danisevskisacebfa22021-05-25 10:56:10 -070076 km_uuid,
77 version: hw_info.versionNumber,
78 security_level: hw_info.securityLevel,
79 })
Janis Danisevskis5c748212021-05-17 17:13:56 -070080 }
81
82 /// Get a [`KeyMintDevice`] for the given [`SecurityLevel`], return
83 /// [`None`] if the error `HARDWARE_TYPE_UNAVAILABLE` is returned
84 pub fn get_or_none(security_level: SecurityLevel) -> Result<Option<KeyMintDevice>> {
85 KeyMintDevice::get(security_level).map(Some).or_else(|e| {
86 match e.root_cause().downcast_ref::<Error>() {
87 Some(Error::Km(ErrorCode::HARDWARE_TYPE_UNAVAILABLE)) => Ok(None),
88 _ => Err(e),
89 }
90 })
91 }
92
93 /// Returns the version of the underlying KeyMint/KeyMaster device.
94 pub fn version(&self) -> i32 {
95 self.version
Paul Crowleyef611e52021-04-20 14:43:04 -070096 }
97
Janis Danisevskisacebfa22021-05-25 10:56:10 -070098 /// Returns the self advertised security level of the KeyMint device.
99 /// This may differ from the requested security level if the best security level
100 /// on the device is Software.
101 pub fn security_level(&self) -> SecurityLevel {
102 self.security_level
103 }
104
Paul Crowley618869e2021-04-08 20:30:54 -0700105 /// Create a KM key and store in the database.
106 pub fn create_and_store_key<F>(
Paul Crowleyef611e52021-04-20 14:43:04 -0700107 &self,
108 db: &mut KeystoreDB,
109 key_desc: &KeyDescriptor,
Janis Danisevskis0cabd712021-05-25 11:07:10 -0700110 key_type: KeyType,
Paul Crowley618869e2021-04-08 20:30:54 -0700111 creator: F,
112 ) -> Result<()>
113 where
Janis Danisevskisacebfa22021-05-25 10:56:10 -0700114 F: FnOnce(&Strong<dyn IKeyMintDevice>) -> Result<KeyCreationResult, binder::Status>,
Paul Crowley618869e2021-04-08 20:30:54 -0700115 {
Shaquille Johnsonaec2eca2022-11-30 17:08:05 +0000116 let creation_result =
117 map_km_error(creator(&self.km_dev)).context(ks_err!("creator failed"))?;
Paul Crowleyef611e52021-04-20 14:43:04 -0700118 let key_parameters = key_characteristics_to_internal(creation_result.keyCharacteristics);
119
Shaquille Johnsonaec2eca2022-11-30 17:08:05 +0000120 let creation_date = DateTime::now().context(ks_err!("DateTime::now() failed"))?;
Paul Crowleyef611e52021-04-20 14:43:04 -0700121
122 let mut key_metadata = KeyMetaData::new();
123 key_metadata.add(KeyMetaEntry::CreationDate(creation_date));
124 let mut blob_metadata = BlobMetaData::new();
125 blob_metadata.add(BlobMetaEntry::KmUuid(self.km_uuid));
126
127 db.store_new_key(
Chris Wailesd5aaaef2021-07-27 16:04:33 -0700128 key_desc,
Janis Danisevskis0cabd712021-05-25 11:07:10 -0700129 key_type,
Paul Crowleyef611e52021-04-20 14:43:04 -0700130 &key_parameters,
Janis Danisevskisf84d0b02022-01-26 14:11:14 -0800131 &BlobInfo::new(&creation_result.keyBlob, &blob_metadata),
Paul Crowleyef611e52021-04-20 14:43:04 -0700132 &CertificateInfo::new(None, None),
133 &key_metadata,
134 &self.km_uuid,
135 )
Shaquille Johnsonaec2eca2022-11-30 17:08:05 +0000136 .context(ks_err!("store_new_key failed"))?;
Paul Crowleyef611e52021-04-20 14:43:04 -0700137 Ok(())
138 }
139
Paul Crowley618869e2021-04-08 20:30:54 -0700140 /// Generate a KeyDescriptor for internal-use keys.
141 pub fn internal_descriptor(alias: String) -> KeyDescriptor {
142 KeyDescriptor {
143 domain: Domain::APP,
144 nspace: AID_KEYSTORE as i64,
145 alias: Some(alias),
146 blob: None,
147 }
148 }
149
150 /// Look up an internal-use key in the database given a key descriptor.
Janis Danisevskisacebfa22021-05-25 10:56:10 -0700151 fn lookup_from_desc(
Paul Crowley618869e2021-04-08 20:30:54 -0700152 db: &mut KeystoreDB,
153 key_desc: &KeyDescriptor,
Janis Danisevskis0cabd712021-05-25 11:07:10 -0700154 key_type: KeyType,
Paul Crowley618869e2021-04-08 20:30:54 -0700155 ) -> Result<(KeyIdGuard, KeyEntry)> {
Chris Wailesd5aaaef2021-07-27 16:04:33 -0700156 db.load_key_entry(key_desc, key_type, KeyEntryLoadBits::KM, AID_KEYSTORE, |_, _| Ok(()))
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000157 .context(ks_err!("load_key_entry failed."))
Paul Crowley618869e2021-04-08 20:30:54 -0700158 }
159
160 /// Look up the key in the database, and return None if it is absent.
Janis Danisevskisacebfa22021-05-25 10:56:10 -0700161 fn not_found_is_none(
Paul Crowley618869e2021-04-08 20:30:54 -0700162 lookup: Result<(KeyIdGuard, KeyEntry)>,
163 ) -> Result<Option<(KeyIdGuard, KeyEntry)>> {
164 match lookup {
165 Ok(result) => Ok(Some(result)),
166 Err(e) => match e.root_cause().downcast_ref::<Error>() {
167 Some(&Error::Rc(ResponseCode::KEY_NOT_FOUND)) => Ok(None),
168 _ => Err(e),
169 },
170 }
171 }
172
Paul Crowleyef611e52021-04-20 14:43:04 -0700173 /// This does the lookup and store in separate transactions; caller must
174 /// hold a lock before calling.
Janis Danisevskisacebfa22021-05-25 10:56:10 -0700175 pub fn lookup_or_generate_key<F>(
Paul Crowleyef611e52021-04-20 14:43:04 -0700176 &self,
177 db: &mut KeystoreDB,
178 key_desc: &KeyDescriptor,
Janis Danisevskis0cabd712021-05-25 11:07:10 -0700179 key_type: KeyType,
Paul Crowleyef611e52021-04-20 14:43:04 -0700180 params: &[KeyParameter],
Janis Danisevskisacebfa22021-05-25 10:56:10 -0700181 validate_characteristics: F,
182 ) -> Result<(KeyIdGuard, KeyBlob)>
183 where
184 F: FnOnce(&[KeyCharacteristics]) -> bool,
185 {
Paul Crowleyef611e52021-04-20 14:43:04 -0700186 // We use a separate transaction for the lookup than for the store
187 // - to keep the code simple
188 // - because the caller needs to hold a lock in any case
189 // - because it avoids holding database locks during slow
190 // KeyMint operations
Janis Danisevskis0cabd712021-05-25 11:07:10 -0700191 let lookup = Self::not_found_is_none(Self::lookup_from_desc(db, key_desc, key_type))
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000192 .context(ks_err!("first lookup failed"))?;
Janis Danisevskis5c748212021-05-17 17:13:56 -0700193
Janis Danisevskisacebfa22021-05-25 10:56:10 -0700194 if let Some((key_id_guard, mut key_entry)) = lookup {
Janis Danisevskis5c748212021-05-17 17:13:56 -0700195 // If the key is associated with a different km instance
196 // or if there is no blob metadata for some reason the key entry
197 // is considered corrupted and needs to be replaced with a new one.
Janis Danisevskisacebfa22021-05-25 10:56:10 -0700198 let key_blob = key_entry.take_key_blob_info().and_then(|(key_blob, blob_metadata)| {
199 if Some(&self.km_uuid) == blob_metadata.km_uuid() {
200 Some(key_blob)
201 } else {
202 None
203 }
204 });
205
206 if let Some(key_blob_vec) = key_blob {
207 let (key_characteristics, key_blob) = self
208 .upgrade_keyblob_if_required_with(
209 db,
210 &key_id_guard,
211 KeyBlob::NonSensitive(key_blob_vec),
212 |key_blob| {
213 map_km_error({
David Drysdale541846b2024-05-23 13:16:07 +0100214 let _wp = wd::watch(concat!(
215 "In KeyMintDevice::lookup_or_generate_key: ",
216 "calling getKeyCharacteristics."
217 ));
Janis Danisevskisacebfa22021-05-25 10:56:10 -0700218 self.km_dev.getKeyCharacteristics(key_blob, &[], &[])
219 })
220 },
221 )
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000222 .context(ks_err!("calling getKeyCharacteristics"))?;
Janis Danisevskisacebfa22021-05-25 10:56:10 -0700223
224 if validate_characteristics(&key_characteristics) {
225 return Ok((key_id_guard, key_blob));
226 }
227
228 // If this point is reached the existing key is considered outdated or corrupted
229 // in some way. It will be replaced with a new key below.
230 };
Paul Crowleyef611e52021-04-20 14:43:04 -0700231 }
Janis Danisevskisacebfa22021-05-25 10:56:10 -0700232
Chris Wailesd5aaaef2021-07-27 16:04:33 -0700233 self.create_and_store_key(db, key_desc, key_type, |km_dev| {
234 km_dev.generateKey(params, None)
Janis Danisevskis0cabd712021-05-25 11:07:10 -0700235 })
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000236 .context(ks_err!("generate_and_store_key failed"))?;
Janis Danisevskis0cabd712021-05-25 11:07:10 -0700237 Self::lookup_from_desc(db, key_desc, key_type)
Janis Danisevskisacebfa22021-05-25 10:56:10 -0700238 .and_then(|(key_id_guard, mut key_entry)| {
239 Ok((
240 key_id_guard,
241 key_entry
242 .take_key_blob_info()
243 .ok_or(Error::Rc(ResponseCode::KEY_NOT_FOUND))
244 .map(|(key_blob, _)| KeyBlob::NonSensitive(key_blob))
Shaquille Johnsonaec2eca2022-11-30 17:08:05 +0000245 .context(ks_err!("Missing key blob info."))?,
Janis Danisevskisacebfa22021-05-25 10:56:10 -0700246 ))
247 })
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000248 .context(ks_err!("second lookup failed"))
Paul Crowleyef611e52021-04-20 14:43:04 -0700249 }
250
251 /// Call the passed closure; if it returns `KEY_REQUIRES_UPGRADE`, call upgradeKey, and
252 /// write the upgraded key to the database.
Janis Danisevskisacebfa22021-05-25 10:56:10 -0700253 fn upgrade_keyblob_if_required_with<'a, T, F>(
Paul Crowleyef611e52021-04-20 14:43:04 -0700254 &self,
255 db: &mut KeystoreDB,
Paul Crowley618869e2021-04-08 20:30:54 -0700256 key_id_guard: &KeyIdGuard,
Janis Danisevskisacebfa22021-05-25 10:56:10 -0700257 key_blob: KeyBlob<'a>,
Paul Crowleyef611e52021-04-20 14:43:04 -0700258 f: F,
Janis Danisevskisacebfa22021-05-25 10:56:10 -0700259 ) -> Result<(T, KeyBlob<'a>)>
Paul Crowleyef611e52021-04-20 14:43:04 -0700260 where
261 F: Fn(&[u8]) -> Result<T, Error>,
262 {
David Drysdale96db4252023-07-05 16:55:00 +0100263 let (f_result, upgraded_blob) = crate::utils::upgrade_keyblob_if_required_with(
264 &*self.km_dev,
David Drysdale5accbaa2023-04-12 18:47:10 +0100265 self.version(),
David Drysdale96db4252023-07-05 16:55:00 +0100266 &key_blob,
267 &[],
268 f,
269 |upgraded_blob| {
Paul Crowleyef611e52021-04-20 14:43:04 -0700270 let mut new_blob_metadata = BlobMetaData::new();
271 new_blob_metadata.add(BlobMetaEntry::KmUuid(self.km_uuid));
272
273 db.set_blob(
Paul Crowley618869e2021-04-08 20:30:54 -0700274 key_id_guard,
Paul Crowleyef611e52021-04-20 14:43:04 -0700275 SubComponentType::KEY_BLOB,
David Drysdale96db4252023-07-05 16:55:00 +0100276 Some(upgraded_blob),
Paul Crowleyef611e52021-04-20 14:43:04 -0700277 Some(&new_blob_metadata),
278 )
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000279 .context(ks_err!("Failed to insert upgraded blob into the database"))?;
David Drysdale96db4252023-07-05 16:55:00 +0100280 Ok(())
281 },
282 )?;
283 let returned_blob = match upgraded_blob {
284 None => key_blob,
285 Some(upgraded_blob) => KeyBlob::NonSensitive(upgraded_blob),
286 };
287 Ok((f_result, returned_blob))
Paul Crowleyef611e52021-04-20 14:43:04 -0700288 }
289
290 /// Use the created key in an operation that can be done with
291 /// a call to begin followed by a call to finish.
Paul Crowley618869e2021-04-08 20:30:54 -0700292 #[allow(clippy::too_many_arguments)]
Paul Crowleyef611e52021-04-20 14:43:04 -0700293 pub fn use_key_in_one_step(
294 &self,
295 db: &mut KeystoreDB,
Paul Crowley618869e2021-04-08 20:30:54 -0700296 key_id_guard: &KeyIdGuard,
Janis Danisevskisacebfa22021-05-25 10:56:10 -0700297 key_blob: &[u8],
Paul Crowleyef611e52021-04-20 14:43:04 -0700298 purpose: KeyPurpose,
299 operation_parameters: &[KeyParameter],
Paul Crowley618869e2021-04-08 20:30:54 -0700300 auth_token: Option<&HardwareAuthToken>,
Paul Crowleyef611e52021-04-20 14:43:04 -0700301 input: &[u8],
302 ) -> Result<Vec<u8>> {
Janis Danisevskisacebfa22021-05-25 10:56:10 -0700303 let key_blob = KeyBlob::Ref(key_blob);
Paul Crowleyef611e52021-04-20 14:43:04 -0700304
Janis Danisevskisacebfa22021-05-25 10:56:10 -0700305 let (begin_result, _) = self
306 .upgrade_keyblob_if_required_with(db, key_id_guard, key_blob, |blob| {
Janis Danisevskis2ee014b2021-05-05 14:29:08 -0700307 map_km_error({
David Drysdale541846b2024-05-23 13:16:07 +0100308 let _wp = wd::watch("In use_key_in_one_step: calling: begin");
Janis Danisevskisacebfa22021-05-25 10:56:10 -0700309 self.km_dev.begin(purpose, blob, operation_parameters, auth_token)
Janis Danisevskis2ee014b2021-05-05 14:29:08 -0700310 })
Paul Crowleyef611e52021-04-20 14:43:04 -0700311 })
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000312 .context(ks_err!("Failed to begin operation."))?;
313 let operation: Strong<dyn IKeyMintOperation> =
314 begin_result.operation.ok_or_else(Error::sys).context(ks_err!("Operation missing"))?;
Janis Danisevskis2ee014b2021-05-05 14:29:08 -0700315 map_km_error({
David Drysdale541846b2024-05-23 13:16:07 +0100316 let _wp = wd::watch("In use_key_in_one_step: calling: finish");
Janis Danisevskis2ee014b2021-05-05 14:29:08 -0700317 operation.finish(Some(input), None, None, None, None)
318 })
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000319 .context(ks_err!("Failed to finish operation."))
Paul Crowleyef611e52021-04-20 14:43:04 -0700320 }
321}