blob: 3657a43c0c45ecc8adbdcee09961b7c1aa9b5ce1 [file] [log] [blame]
Janis Danisevskis1af91262020-08-10 14:58:08 -07001// Copyright 2020, 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#![allow(unused_variables)]
16
17//! This crate implements the IKeystoreSecurityLevel interface.
18
Shawn Willden708744a2020-12-11 13:05:27 +000019use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
Janis Danisevskis85d47932020-10-23 16:12:59 -070020 Algorithm::Algorithm, ByteArray::ByteArray, Certificate::Certificate as KmCertificate,
Janis Danisevskisa53c9cf2020-10-26 11:52:33 -070021 HardwareAuthenticatorType::HardwareAuthenticatorType, IKeyMintDevice::IKeyMintDevice,
22 KeyCharacteristics::KeyCharacteristics, KeyFormat::KeyFormat, KeyParameter::KeyParameter,
Janis Danisevskis398e6be2020-12-17 09:29:25 -080023 KeyParameterValue::KeyParameterValue, SecurityLevel::SecurityLevel, Tag::Tag,
Janis Danisevskis1af91262020-08-10 14:58:08 -070024};
25use android_system_keystore2::aidl::android::system::keystore2::{
Janis Danisevskisa53c9cf2020-10-26 11:52:33 -070026 AuthenticatorSpec::AuthenticatorSpec, CreateOperationResponse::CreateOperationResponse,
27 Domain::Domain, IKeystoreOperation::IKeystoreOperation,
28 IKeystoreSecurityLevel::BnKeystoreSecurityLevel,
Janis Danisevskis1af91262020-08-10 14:58:08 -070029 IKeystoreSecurityLevel::IKeystoreSecurityLevel, KeyDescriptor::KeyDescriptor,
Janis Danisevskisa53c9cf2020-10-26 11:52:33 -070030 KeyMetadata::KeyMetadata, KeyParameters::KeyParameters,
Janis Danisevskis1af91262020-08-10 14:58:08 -070031};
32
Janis Danisevskis1af91262020-08-10 14:58:08 -070033use crate::permission::KeyPerm;
Janis Danisevskisa53c9cf2020-10-26 11:52:33 -070034use crate::utils::{check_key_permission, Asp};
Janis Danisevskisaec14592020-11-12 09:41:49 -080035use crate::{database::KeyIdGuard, globals::DB};
Janis Danisevskis1af91262020-08-10 14:58:08 -070036use crate::{
37 database::{KeyEntry, KeyEntryLoadBits, SubComponentType},
38 operation::KeystoreOperation,
39 operation::OperationDb,
40};
Janis Danisevskis04b02832020-10-26 09:21:40 -070041use crate::{
42 error::{self, map_km_error, map_or_log_err, Error, ErrorCode},
43 utils::key_characteristics_to_internal,
44};
Janis Danisevskis1af91262020-08-10 14:58:08 -070045use anyhow::{anyhow, Context, Result};
46use binder::{IBinder, Interface, ThreadState};
47
48/// Implementation of the IKeystoreSecurityLevel Interface.
49pub struct KeystoreSecurityLevel {
50 security_level: SecurityLevel,
51 keymint: Asp,
52 operation_db: OperationDb,
53}
54
Janis Danisevskise04f7a72020-12-15 14:53:21 -080055static KEYMINT_SERVICE_NAME: &str = "android.hardware.security.keymint.IKeyMintDevice";
Janis Danisevskis1af91262020-08-10 14:58:08 -070056
57// Blob of 32 zeroes used as empty masking key.
58static ZERO_BLOB_32: &[u8] = &[0; 32];
59
60impl KeystoreSecurityLevel {
61 /// Creates a new security level instance wrapped in a
62 /// BnKeystoreSecurityLevel proxy object. It also
63 /// calls `IBinder::set_requesting_sid` on the new interface, because
64 /// we need it for checking keystore permissions.
65 pub fn new_native_binder(
66 security_level: SecurityLevel,
67 ) -> Result<impl IKeystoreSecurityLevel + Send> {
68 let service_name = format!("{}/default", KEYMINT_SERVICE_NAME);
69 let keymint: Box<dyn IKeyMintDevice> =
70 binder::get_interface(&service_name).map_err(|e| {
71 anyhow!(format!(
72 "Could not get KeyMint instance: {} failed with error code {:?}",
73 service_name, e
74 ))
75 })?;
76
77 let result = BnKeystoreSecurityLevel::new_binder(Self {
78 security_level,
79 keymint: Asp::new(keymint.as_binder()),
80 operation_db: OperationDb::new(),
81 });
82 result.as_binder().set_requesting_sid(true);
83 Ok(result)
84 }
85
86 fn store_new_key(
87 &self,
88 key: KeyDescriptor,
Janis Danisevskis04b02832020-10-26 09:21:40 -070089 key_characteristics: KeyCharacteristics,
Janis Danisevskis1af91262020-08-10 14:58:08 -070090 km_cert_chain: Option<Vec<KmCertificate>>,
Janis Danisevskis85d47932020-10-23 16:12:59 -070091 blob: ByteArray,
Janis Danisevskis2c7f9622020-09-30 16:30:31 -070092 ) -> Result<KeyMetadata> {
93 let (cert, cert_chain): (Option<Vec<u8>>, Option<Vec<u8>>) = match km_cert_chain {
Janis Danisevskis1af91262020-08-10 14:58:08 -070094 Some(mut chain) => (
95 match chain.len() {
96 0 => None,
Janis Danisevskis2c7f9622020-09-30 16:30:31 -070097 _ => Some(chain.remove(0).encodedCertificate),
Janis Danisevskis1af91262020-08-10 14:58:08 -070098 },
99 match chain.len() {
100 0 => None,
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700101 _ => Some(
102 chain
Janis Danisevskis1af91262020-08-10 14:58:08 -0700103 .iter()
104 .map(|c| c.encodedCertificate.iter())
105 .flatten()
106 .copied()
107 .collect(),
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700108 ),
Janis Danisevskis1af91262020-08-10 14:58:08 -0700109 },
110 ),
111 None => (None, None),
112 };
113
Janis Danisevskis04b02832020-10-26 09:21:40 -0700114 let key_parameters =
115 key_characteristics_to_internal(key_characteristics, self.security_level);
116
Janis Danisevskis1af91262020-08-10 14:58:08 -0700117 let key = match key.domain {
118 Domain::BLOB => {
Janis Danisevskis85d47932020-10-23 16:12:59 -0700119 KeyDescriptor { domain: Domain::BLOB, blob: Some(blob.data), ..Default::default() }
Janis Danisevskis1af91262020-08-10 14:58:08 -0700120 }
121 _ => DB
122 .with(|db| {
123 let mut db = db.borrow_mut();
124 let key_id = db
125 .create_key_entry(key.domain, key.nspace)
126 .context("Trying to create a key entry.")?;
Janis Danisevskis85d47932020-10-23 16:12:59 -0700127 db.insert_blob(
Janis Danisevskisaec14592020-11-12 09:41:49 -0800128 &key_id,
Janis Danisevskis85d47932020-10-23 16:12:59 -0700129 SubComponentType::KM_BLOB,
130 &blob.data,
131 self.security_level,
132 )
133 .context("Trying to insert km blob.")?;
Janis Danisevskis1af91262020-08-10 14:58:08 -0700134 if let Some(c) = &cert {
Janis Danisevskisaec14592020-11-12 09:41:49 -0800135 db.insert_blob(&key_id, SubComponentType::CERT, c, self.security_level)
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700136 .context("Trying to insert cert blob.")?;
Janis Danisevskis1af91262020-08-10 14:58:08 -0700137 }
138 if let Some(c) = &cert_chain {
139 db.insert_blob(
Janis Danisevskisaec14592020-11-12 09:41:49 -0800140 &key_id,
Janis Danisevskis1af91262020-08-10 14:58:08 -0700141 SubComponentType::CERT_CHAIN,
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700142 c,
Janis Danisevskis1af91262020-08-10 14:58:08 -0700143 self.security_level,
144 )
145 .context("Trying to insert cert chain blob.")?;
146 }
Janis Danisevskisaec14592020-11-12 09:41:49 -0800147 db.insert_keyparameter(&key_id, &key_parameters)
Janis Danisevskis04b02832020-10-26 09:21:40 -0700148 .context("Trying to insert key parameters.")?;
Janis Danisevskis1af91262020-08-10 14:58:08 -0700149 match &key.alias {
150 Some(alias) => db
Janis Danisevskisaec14592020-11-12 09:41:49 -0800151 .rebind_alias(&key_id, alias, key.domain, key.nspace)
Janis Danisevskis1af91262020-08-10 14:58:08 -0700152 .context("Failed to rebind alias.")?,
153 None => {
154 return Err(error::Error::sys()).context(
155 "Alias must be specified. (This should have been checked earlier.)",
156 )
157 }
158 }
159 Ok(KeyDescriptor {
160 domain: Domain::KEY_ID,
Janis Danisevskisaec14592020-11-12 09:41:49 -0800161 nspace: key_id.id(),
Janis Danisevskis1af91262020-08-10 14:58:08 -0700162 ..Default::default()
163 })
164 })
165 .context("In store_new_key.")?,
166 };
167
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700168 Ok(KeyMetadata {
169 key,
Janis Danisevskisa53c9cf2020-10-26 11:52:33 -0700170 keySecurityLevel: self.security_level,
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700171 certificate: cert,
172 certificateChain: cert_chain,
Janis Danisevskis04b02832020-10-26 09:21:40 -0700173 authorizations: crate::utils::key_parameters_to_authorizations(key_parameters),
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700174 ..Default::default()
175 })
Janis Danisevskis1af91262020-08-10 14:58:08 -0700176 }
177
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700178 fn create_operation(
Janis Danisevskis1af91262020-08-10 14:58:08 -0700179 &self,
180 key: &KeyDescriptor,
181 operation_parameters: &[KeyParameter],
182 forced: bool,
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700183 ) -> Result<CreateOperationResponse> {
Janis Danisevskis1af91262020-08-10 14:58:08 -0700184 let caller_uid = ThreadState::get_calling_uid();
185 // We use `scoping_blob` to extend the life cycle of the blob loaded from the database,
186 // so that we can use it by reference like the blob provided by the key descriptor.
187 // Otherwise, we would have to clone the blob from the key descriptor.
188 let scoping_blob: Vec<u8>;
Janis Danisevskisaec14592020-11-12 09:41:49 -0800189 let (km_blob, key_id_guard) = match key.domain {
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700190 Domain::BLOB => {
191 check_key_permission(KeyPerm::use_(), key, &None)
192 .context("In create_operation: checking use permission for Domain::BLOB.")?;
193 (
194 match &key.blob {
Janis Danisevskis1af91262020-08-10 14:58:08 -0700195 Some(blob) => blob,
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700196 None => {
197 return Err(Error::sys()).context(concat!(
198 "In create_operation: Key blob must be specified when",
199 " using Domain::BLOB."
200 ))
201 }
202 },
203 None,
204 )
205 }
206 _ => {
Janis Danisevskisaec14592020-11-12 09:41:49 -0800207 let (key_id_guard, mut key_entry) = DB
208 .with::<_, Result<(KeyIdGuard, KeyEntry)>>(|db| {
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700209 db.borrow_mut().load_key_entry(
210 key.clone(),
211 KeyEntryLoadBits::KM,
212 caller_uid,
213 |k, av| check_key_permission(KeyPerm::use_(), k, &av),
214 )
215 })
216 .context("In create_operation: Failed to load key blob.")?;
217 scoping_blob = match key_entry.take_km_blob() {
218 Some(blob) => blob,
219 None => {
220 return Err(Error::sys()).context(concat!(
221 "In create_operation: Successfully loaded key entry,",
222 " but KM blob was missing."
223 ))
224 }
225 };
Janis Danisevskisaec14592020-11-12 09:41:49 -0800226 (&scoping_blob, Some(key_id_guard))
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700227 }
228 };
Janis Danisevskis1af91262020-08-10 14:58:08 -0700229
230 // TODO Authorize begin operation.
231 // Check if we need an authorization token.
232 // Lookup authorization token and request VerificationToken if required.
233
Janis Danisevskisa53c9cf2020-10-26 11:52:33 -0700234 let purpose = operation_parameters.iter().find(|p| p.tag == Tag::PURPOSE).map_or(
Janis Danisevskis1af91262020-08-10 14:58:08 -0700235 Err(Error::Km(ErrorCode::INVALID_ARGUMENT))
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700236 .context("In create_operation: No operation purpose specified."),
Janis Danisevskis398e6be2020-12-17 09:29:25 -0800237 |kp| match kp.value {
238 KeyParameterValue::KeyPurpose(p) => Ok(p),
239 _ => Err(Error::Km(ErrorCode::INVALID_ARGUMENT))
240 .context("In create_operation: Malformed KeyParameter."),
241 },
Janis Danisevskis1af91262020-08-10 14:58:08 -0700242 )?;
243
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700244 let km_dev: Box<dyn IKeyMintDevice> = self
245 .keymint
246 .get_interface()
247 .context("In create_operation: Failed to get KeyMint device")?;
Janis Danisevskis1af91262020-08-10 14:58:08 -0700248
Janis Danisevskisaec14592020-11-12 09:41:49 -0800249 let (begin_result, upgraded_blob) = self
250 .upgrade_keyblob_if_required_with(
251 &*km_dev,
252 key_id_guard,
Janis Danisevskisa53c9cf2020-10-26 11:52:33 -0700253 &km_blob,
254 &operation_parameters,
Janis Danisevskisaec14592020-11-12 09:41:49 -0800255 |blob| loop {
256 match map_km_error(km_dev.begin(
257 purpose,
258 blob,
259 &operation_parameters,
260 &Default::default(),
261 )) {
262 Err(Error::Km(ErrorCode::TOO_MANY_OPERATIONS)) => {
263 self.operation_db.prune(caller_uid)?;
264 continue;
Janis Danisevskis1af91262020-08-10 14:58:08 -0700265 }
Janis Danisevskisaec14592020-11-12 09:41:49 -0800266 v => return v,
267 }
268 },
269 )
270 .context("In create_operation: Failed to begin operation.")?;
Janis Danisevskis1af91262020-08-10 14:58:08 -0700271
272 let operation = match begin_result.operation {
273 Some(km_op) => self.operation_db.create_operation(km_op, caller_uid),
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700274 None => return Err(Error::sys()).context("In create_operation: Begin operation returned successfully, but did not return a valid operation."),
Janis Danisevskis1af91262020-08-10 14:58:08 -0700275 };
276
277 let op_binder: Box<dyn IKeystoreOperation> =
278 KeystoreOperation::new_native_binder(operation)
279 .as_binder()
280 .into_interface()
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700281 .context("In create_operation: Failed to create IKeystoreOperation.")?;
Janis Danisevskis1af91262020-08-10 14:58:08 -0700282
283 // TODO we need to the enforcement module to determine if we need to return the challenge.
284 // We return None for now because we don't support auth bound keys yet.
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700285 Ok(CreateOperationResponse {
286 iOperation: Some(op_binder),
287 operationChallenge: None,
288 parameters: match begin_result.params.len() {
289 0 => None,
Janis Danisevskisa53c9cf2020-10-26 11:52:33 -0700290 _ => Some(KeyParameters { keyParameter: begin_result.params }),
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700291 },
292 })
Janis Danisevskis1af91262020-08-10 14:58:08 -0700293 }
294
295 fn generate_key(
296 &self,
297 key: &KeyDescriptor,
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700298 attestation_key: Option<&KeyDescriptor>,
Janis Danisevskis1af91262020-08-10 14:58:08 -0700299 params: &[KeyParameter],
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700300 flags: i32,
Janis Danisevskis1af91262020-08-10 14:58:08 -0700301 entropy: &[u8],
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700302 ) -> Result<KeyMetadata> {
Janis Danisevskis1af91262020-08-10 14:58:08 -0700303 if key.domain != Domain::BLOB && key.alias.is_none() {
304 return Err(error::Error::Km(ErrorCode::INVALID_ARGUMENT))
305 .context("In generate_key: Alias must be specified");
306 }
307
308 let key = match key.domain {
309 Domain::APP => KeyDescriptor {
310 domain: key.domain,
311 nspace: ThreadState::get_calling_uid() as i64,
312 alias: key.alias.clone(),
313 blob: None,
314 },
315 _ => key.clone(),
316 };
317
318 // generate_key requires the rebind permission.
319 check_key_permission(KeyPerm::rebind(), &key, &None).context("In generate_key.")?;
320
321 let km_dev: Box<dyn IKeyMintDevice> = self.keymint.get_interface()?;
322 map_km_error(km_dev.addRngEntropy(entropy))?;
Janis Danisevskis85d47932020-10-23 16:12:59 -0700323 let mut blob: ByteArray = Default::default();
Janis Danisevskis1af91262020-08-10 14:58:08 -0700324 let mut key_characteristics: KeyCharacteristics = Default::default();
325 let mut certificate_chain: Vec<KmCertificate> = Default::default();
326 map_km_error(km_dev.generateKey(
Janis Danisevskisa53c9cf2020-10-26 11:52:33 -0700327 &params,
Janis Danisevskis1af91262020-08-10 14:58:08 -0700328 &mut blob,
329 &mut key_characteristics,
330 &mut certificate_chain,
331 ))?;
332
Janis Danisevskis04b02832020-10-26 09:21:40 -0700333 self.store_new_key(key, key_characteristics, Some(certificate_chain), blob)
334 .context("In generate_key.")
Janis Danisevskis1af91262020-08-10 14:58:08 -0700335 }
336
337 fn import_key(
338 &self,
339 key: &KeyDescriptor,
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700340 attestation_key: Option<&KeyDescriptor>,
Janis Danisevskis1af91262020-08-10 14:58:08 -0700341 params: &[KeyParameter],
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700342 flags: i32,
Janis Danisevskis1af91262020-08-10 14:58:08 -0700343 key_data: &[u8],
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700344 ) -> Result<KeyMetadata> {
Janis Danisevskis1af91262020-08-10 14:58:08 -0700345 if key.domain != Domain::BLOB && key.alias.is_none() {
346 return Err(error::Error::Km(ErrorCode::INVALID_ARGUMENT))
347 .context("In import_key: Alias must be specified");
348 }
349
350 let key = match key.domain {
351 Domain::APP => KeyDescriptor {
352 domain: key.domain,
353 nspace: ThreadState::get_calling_uid() as i64,
354 alias: key.alias.clone(),
355 blob: None,
356 },
357 _ => key.clone(),
358 };
359
360 // import_key requires the rebind permission.
361 check_key_permission(KeyPerm::rebind(), &key, &None).context("In import_key.")?;
362
Janis Danisevskis85d47932020-10-23 16:12:59 -0700363 let mut blob: ByteArray = Default::default();
Janis Danisevskis1af91262020-08-10 14:58:08 -0700364 let mut key_characteristics: KeyCharacteristics = Default::default();
365 let mut certificate_chain: Vec<KmCertificate> = Default::default();
366
367 let format = params
368 .iter()
Janis Danisevskisa53c9cf2020-10-26 11:52:33 -0700369 .find(|p| p.tag == Tag::ALGORITHM)
Janis Danisevskis1af91262020-08-10 14:58:08 -0700370 .ok_or(error::Error::Km(ErrorCode::INVALID_ARGUMENT))
371 .context("No KeyParameter 'Algorithm'.")
Janis Danisevskis398e6be2020-12-17 09:29:25 -0800372 .and_then(|p| match &p.value {
373 KeyParameterValue::Algorithm(Algorithm::AES)
374 | KeyParameterValue::Algorithm(Algorithm::HMAC)
375 | KeyParameterValue::Algorithm(Algorithm::TRIPLE_DES) => Ok(KeyFormat::RAW),
376 KeyParameterValue::Algorithm(Algorithm::RSA)
377 | KeyParameterValue::Algorithm(Algorithm::EC) => Ok(KeyFormat::PKCS8),
378 v => Err(error::Error::Km(ErrorCode::INVALID_ARGUMENT))
379 .context(format!("Unknown Algorithm {:?}.", v)),
Janis Danisevskis1af91262020-08-10 14:58:08 -0700380 })
381 .context("In import_key.")?;
382
383 let km_dev: Box<dyn IKeyMintDevice> = self.keymint.get_interface()?;
384 map_km_error(km_dev.importKey(
Janis Danisevskisa53c9cf2020-10-26 11:52:33 -0700385 &params,
Janis Danisevskis1af91262020-08-10 14:58:08 -0700386 format,
387 key_data,
388 &mut blob,
389 &mut key_characteristics,
390 &mut certificate_chain,
391 ))?;
392
Janis Danisevskis04b02832020-10-26 09:21:40 -0700393 self.store_new_key(key, key_characteristics, Some(certificate_chain), blob)
394 .context("In import_key.")
Janis Danisevskis1af91262020-08-10 14:58:08 -0700395 }
396
397 fn import_wrapped_key(
398 &self,
399 key: &KeyDescriptor,
400 wrapping_key: &KeyDescriptor,
401 masking_key: Option<&[u8]>,
402 params: &[KeyParameter],
403 authenticators: &[AuthenticatorSpec],
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700404 ) -> Result<KeyMetadata> {
Janis Danisevskis1af91262020-08-10 14:58:08 -0700405 if key.domain != Domain::BLOB && key.alias.is_none() {
406 return Err(error::Error::Km(ErrorCode::INVALID_ARGUMENT))
407 .context("In import_wrapped_key: Alias must be specified.");
408 }
409
Janis Danisevskisaec14592020-11-12 09:41:49 -0800410 if wrapping_key.domain == Domain::BLOB {
411 return Err(error::Error::Km(ErrorCode::INVALID_ARGUMENT)).context(
412 "In import_wrapped_key: Import wrapped key not supported for self managed blobs.",
413 );
414 }
415
Janis Danisevskis1af91262020-08-10 14:58:08 -0700416 let wrapped_data = match &key.blob {
417 Some(d) => d,
418 None => {
419 return Err(error::Error::Km(ErrorCode::INVALID_ARGUMENT)).context(
420 "In import_wrapped_key: Blob must be specified and hold wrapped key data.",
421 )
422 }
423 };
424
425 let key = match key.domain {
426 Domain::APP => KeyDescriptor {
427 domain: key.domain,
428 nspace: ThreadState::get_calling_uid() as i64,
429 alias: key.alias.clone(),
430 blob: None,
431 },
432 _ => key.clone(),
433 };
434
435 // import_wrapped_key requires the rebind permission for the new key.
436 check_key_permission(KeyPerm::rebind(), &key, &None).context("In import_wrapped_key.")?;
437
Janis Danisevskisaec14592020-11-12 09:41:49 -0800438 let (wrapping_key_id_guard, wrapping_key_entry) = DB
Janis Danisevskis1af91262020-08-10 14:58:08 -0700439 .with(|db| {
440 db.borrow_mut().load_key_entry(
441 wrapping_key.clone(),
442 KeyEntryLoadBits::KM,
443 ThreadState::get_calling_uid(),
444 |k, av| check_key_permission(KeyPerm::use_(), k, &av),
445 )
446 })
447 .context("Failed to load wrapping key.")?;
448 let wrapping_key_blob = match wrapping_key_entry.km_blob() {
449 Some(blob) => blob,
450 None => {
451 return Err(error::Error::sys()).context(concat!(
452 "No km_blob after successfully loading key.",
453 " This should never happen."
454 ))
455 }
456 };
457
Janis Danisevskis1af91262020-08-10 14:58:08 -0700458 // km_dev.importWrappedKey does not return a certificate chain.
459 // TODO Do we assume that all wrapped keys are symmetric?
460 // let certificate_chain: Vec<KmCertificate> = Default::default();
461
462 let pw_sid = authenticators
463 .iter()
464 .find_map(|a| match a.authenticatorType {
Janis Danisevskisa53c9cf2020-10-26 11:52:33 -0700465 HardwareAuthenticatorType::PASSWORD => Some(a.authenticatorId),
Janis Danisevskis1af91262020-08-10 14:58:08 -0700466 _ => None,
467 })
468 .ok_or(error::Error::Km(ErrorCode::INVALID_ARGUMENT))
469 .context("A password authenticator SID must be specified.")?;
470
471 let fp_sid = authenticators
472 .iter()
473 .find_map(|a| match a.authenticatorType {
Janis Danisevskisa53c9cf2020-10-26 11:52:33 -0700474 HardwareAuthenticatorType::FINGERPRINT => Some(a.authenticatorId),
Janis Danisevskis1af91262020-08-10 14:58:08 -0700475 _ => None,
476 })
477 .ok_or(error::Error::Km(ErrorCode::INVALID_ARGUMENT))
478 .context("A fingerprint authenticator SID must be specified.")?;
479
480 let masking_key = masking_key.unwrap_or(ZERO_BLOB_32);
481
482 let km_dev: Box<dyn IKeyMintDevice> = self.keymint.get_interface()?;
Janis Danisevskisaec14592020-11-12 09:41:49 -0800483 let ((blob, key_characteristics), _) = self.upgrade_keyblob_if_required_with(
484 &*km_dev,
485 Some(wrapping_key_id_guard),
Janis Danisevskis1af91262020-08-10 14:58:08 -0700486 wrapping_key_blob,
Janis Danisevskisaec14592020-11-12 09:41:49 -0800487 &[],
488 |wrapping_blob| {
489 let mut blob: ByteArray = Default::default();
490 let mut key_characteristics: KeyCharacteristics = Default::default();
491 map_km_error(km_dev.importWrappedKey(
492 wrapped_data,
493 wrapping_key_blob,
494 masking_key,
495 &params,
496 pw_sid,
497 fp_sid,
498 &mut blob,
499 &mut key_characteristics,
500 ))?;
501 Ok((blob, key_characteristics))
502 },
503 )?;
Janis Danisevskis1af91262020-08-10 14:58:08 -0700504
Janis Danisevskis04b02832020-10-26 09:21:40 -0700505 self.store_new_key(key, key_characteristics, None, blob).context("In import_wrapped_key.")
Janis Danisevskis1af91262020-08-10 14:58:08 -0700506 }
Janis Danisevskisaec14592020-11-12 09:41:49 -0800507
508 fn upgrade_keyblob_if_required_with<T, F>(
509 &self,
510 km_dev: &dyn IKeyMintDevice,
511 key_id_guard: Option<KeyIdGuard>,
512 blob: &[u8],
513 params: &[KeyParameter],
514 f: F,
515 ) -> Result<(T, Option<Vec<u8>>)>
516 where
517 F: Fn(&[u8]) -> Result<T, Error>,
518 {
519 match f(blob) {
520 Err(Error::Km(ErrorCode::KEY_REQUIRES_UPGRADE)) => {
521 let upgraded_blob = map_km_error(km_dev.upgradeKey(blob, params))
522 .context("In upgrade_keyblob_if_required_with: Upgrade failed.")?;
523 key_id_guard.map_or(Ok(()), |key_id_guard| {
524 DB.with(|db| {
525 db.borrow_mut().insert_blob(
526 &key_id_guard,
527 SubComponentType::KM_BLOB,
528 &upgraded_blob,
529 self.security_level,
530 )
531 })
532 .context(concat!(
533 "In upgrade_keyblob_if_required_with: ",
534 "Failed to insert upgraded blob into the database.",
535 ))
536 })?;
537 match f(&upgraded_blob) {
538 Ok(v) => Ok((v, Some(upgraded_blob))),
539 Err(e) => Err(e).context(concat!(
540 "In upgrade_keyblob_if_required_with: ",
541 "Failed to perform operation on second try."
542 )),
543 }
544 }
545 Err(e) => {
546 Err(e).context("In upgrade_keyblob_if_required_with: Failed perform operation.")
547 }
548 Ok(v) => Ok((v, None)),
549 }
550 }
Janis Danisevskis1af91262020-08-10 14:58:08 -0700551}
552
553impl binder::Interface for KeystoreSecurityLevel {}
554
555impl IKeystoreSecurityLevel for KeystoreSecurityLevel {
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700556 fn createOperation(
Janis Danisevskis1af91262020-08-10 14:58:08 -0700557 &self,
558 key: &KeyDescriptor,
559 operation_parameters: &[KeyParameter],
560 forced: bool,
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700561 ) -> binder::public_api::Result<CreateOperationResponse> {
562 map_or_log_err(self.create_operation(key, operation_parameters, forced), Ok)
Janis Danisevskis1af91262020-08-10 14:58:08 -0700563 }
564 fn generateKey(
565 &self,
566 key: &KeyDescriptor,
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700567 attestation_key: Option<&KeyDescriptor>,
Janis Danisevskis1af91262020-08-10 14:58:08 -0700568 params: &[KeyParameter],
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700569 flags: i32,
Janis Danisevskis1af91262020-08-10 14:58:08 -0700570 entropy: &[u8],
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700571 ) -> binder::public_api::Result<KeyMetadata> {
572 map_or_log_err(self.generate_key(key, attestation_key, params, flags, entropy), Ok)
Janis Danisevskis1af91262020-08-10 14:58:08 -0700573 }
574 fn importKey(
575 &self,
576 key: &KeyDescriptor,
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700577 attestation_key: Option<&KeyDescriptor>,
Janis Danisevskis1af91262020-08-10 14:58:08 -0700578 params: &[KeyParameter],
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700579 flags: i32,
Janis Danisevskis1af91262020-08-10 14:58:08 -0700580 key_data: &[u8],
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700581 ) -> binder::public_api::Result<KeyMetadata> {
582 map_or_log_err(self.import_key(key, attestation_key, params, flags, key_data), Ok)
Janis Danisevskis1af91262020-08-10 14:58:08 -0700583 }
584 fn importWrappedKey(
585 &self,
586 key: &KeyDescriptor,
587 wrapping_key: &KeyDescriptor,
588 masking_key: Option<&[u8]>,
589 params: &[KeyParameter],
590 authenticators: &[AuthenticatorSpec],
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700591 ) -> binder::public_api::Result<KeyMetadata> {
Janis Danisevskis1af91262020-08-10 14:58:08 -0700592 map_or_log_err(
593 self.import_wrapped_key(key, wrapping_key, masking_key, params, authenticators),
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700594 Ok,
Janis Danisevskis1af91262020-08-10 14:58:08 -0700595 )
596 }
597}