blob: c5b5da0033c591ba929fef505bdf1194255e39a3 [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::{
Hasini Gunasinghe888dd352020-11-17 23:08:39 +000020 Algorithm::Algorithm, HardwareAuthToken::HardwareAuthToken,
21 HardwareAuthenticatorType::HardwareAuthenticatorType, IKeyMintDevice::IKeyMintDevice,
22 KeyCreationResult::KeyCreationResult, KeyFormat::KeyFormat, KeyParameter::KeyParameter,
23 KeyParameterValue::KeyParameterValue, SecurityLevel::SecurityLevel, Tag::Tag,
24 VerificationToken::VerificationToken,
Janis Danisevskis1af91262020-08-10 14:58:08 -070025};
26use android_system_keystore2::aidl::android::system::keystore2::{
Janis Danisevskisa53c9cf2020-10-26 11:52:33 -070027 AuthenticatorSpec::AuthenticatorSpec, CreateOperationResponse::CreateOperationResponse,
28 Domain::Domain, IKeystoreOperation::IKeystoreOperation,
29 IKeystoreSecurityLevel::BnKeystoreSecurityLevel,
Janis Danisevskis1af91262020-08-10 14:58:08 -070030 IKeystoreSecurityLevel::IKeystoreSecurityLevel, KeyDescriptor::KeyDescriptor,
Hasini Gunasinghe888dd352020-11-17 23:08:39 +000031 KeyMetadata::KeyMetadata, KeyParameters::KeyParameters, OperationChallenge::OperationChallenge,
Janis Danisevskis1af91262020-08-10 14:58:08 -070032};
33
Hasini Gunasinghe888dd352020-11-17 23:08:39 +000034use crate::auth_token_handler::AuthTokenHandler;
35use crate::globals::ENFORCEMENTS;
36use crate::key_parameter::KeyParameter as KsKeyParam;
Janis Danisevskisa53c9cf2020-10-26 11:52:33 -070037use crate::utils::{check_key_permission, Asp};
Janis Danisevskisaec14592020-11-12 09:41:49 -080038use crate::{database::KeyIdGuard, globals::DB};
Janis Danisevskis1af91262020-08-10 14:58:08 -070039use crate::{
Janis Danisevskisb42fc182020-12-15 08:41:27 -080040 database::{DateTime, KeyMetaData, KeyMetaEntry, KeyType},
41 permission::KeyPerm,
42};
43use crate::{
Janis Danisevskis1af91262020-08-10 14:58:08 -070044 database::{KeyEntry, KeyEntryLoadBits, SubComponentType},
45 operation::KeystoreOperation,
46 operation::OperationDb,
47};
Janis Danisevskis04b02832020-10-26 09:21:40 -070048use crate::{
49 error::{self, map_km_error, map_or_log_err, Error, ErrorCode},
50 utils::key_characteristics_to_internal,
51};
Janis Danisevskisba998992020-12-29 16:08:40 -080052use anyhow::{Context, Result};
Janis Danisevskis1af91262020-08-10 14:58:08 -070053use binder::{IBinder, Interface, ThreadState};
Hasini Gunasinghe888dd352020-11-17 23:08:39 +000054use std::sync::mpsc::channel;
Janis Danisevskis1af91262020-08-10 14:58:08 -070055
56/// Implementation of the IKeystoreSecurityLevel Interface.
57pub struct KeystoreSecurityLevel {
58 security_level: SecurityLevel,
59 keymint: Asp,
60 operation_db: OperationDb,
61}
62
Janis Danisevskis1af91262020-08-10 14:58:08 -070063// Blob of 32 zeroes used as empty masking key.
64static ZERO_BLOB_32: &[u8] = &[0; 32];
65
66impl KeystoreSecurityLevel {
67 /// Creates a new security level instance wrapped in a
68 /// BnKeystoreSecurityLevel proxy object. It also
69 /// calls `IBinder::set_requesting_sid` on the new interface, because
70 /// we need it for checking keystore permissions.
71 pub fn new_native_binder(
72 security_level: SecurityLevel,
73 ) -> Result<impl IKeystoreSecurityLevel + Send> {
Janis Danisevskis1af91262020-08-10 14:58:08 -070074 let result = BnKeystoreSecurityLevel::new_binder(Self {
75 security_level,
Janis Danisevskisba998992020-12-29 16:08:40 -080076 keymint: crate::globals::get_keymint_device(security_level)
77 .context("In KeystoreSecurityLevel::new_native_binder.")?,
Janis Danisevskis1af91262020-08-10 14:58:08 -070078 operation_db: OperationDb::new(),
79 });
80 result.as_binder().set_requesting_sid(true);
81 Ok(result)
82 }
83
84 fn store_new_key(
85 &self,
86 key: KeyDescriptor,
Shawn Willdendbdac602021-01-12 22:35:16 -070087 creation_result: KeyCreationResult,
Janis Danisevskis2c7f9622020-09-30 16:30:31 -070088 ) -> Result<KeyMetadata> {
Shawn Willdendbdac602021-01-12 22:35:16 -070089 let KeyCreationResult {
90 keyBlob: key_blob,
91 keyCharacteristics: key_characteristics,
92 certificateChain: mut certificate_chain,
93 } = creation_result;
Janis Danisevskis1af91262020-08-10 14:58:08 -070094
Shawn Willdendbdac602021-01-12 22:35:16 -070095 let (cert, cert_chain): (Option<Vec<u8>>, Option<Vec<u8>>) = (
96 match certificate_chain.len() {
97 0 => None,
98 _ => Some(certificate_chain.remove(0).encodedCertificate),
99 },
100 match certificate_chain.len() {
101 0 => None,
102 _ => Some(
103 certificate_chain
104 .iter()
105 .map(|c| c.encodedCertificate.iter())
106 .flatten()
107 .copied()
108 .collect(),
109 ),
110 },
111 );
112
113 let key_parameters = key_characteristics_to_internal(key_characteristics);
Janis Danisevskis04b02832020-10-26 09:21:40 -0700114
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800115 let creation_date = DateTime::now().context("Trying to make creation time.")?;
116
Janis Danisevskis1af91262020-08-10 14:58:08 -0700117 let key = match key.domain {
118 Domain::BLOB => {
Shawn Willdendbdac602021-01-12 22:35:16 -0700119 KeyDescriptor { domain: Domain::BLOB, blob: Some(key_blob), ..Default::default() }
Janis Danisevskis1af91262020-08-10 14:58:08 -0700120 }
121 _ => DB
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800122 .with::<_, Result<KeyDescriptor>>(|db| {
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800123 let mut metadata = KeyMetaData::new();
124 metadata.add(KeyMetaEntry::CreationDate(creation_date));
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800125
126 let mut db = db.borrow_mut();
127 let key_id = db
128 .store_new_key(
129 key,
130 &key_parameters,
Shawn Willdendbdac602021-01-12 22:35:16 -0700131 &key_blob,
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800132 cert.as_deref(),
133 cert_chain.as_deref(),
134 &metadata,
135 )
136 .context("In store_new_key.")?;
Janis Danisevskis1af91262020-08-10 14:58:08 -0700137 Ok(KeyDescriptor {
138 domain: Domain::KEY_ID,
Janis Danisevskisaec14592020-11-12 09:41:49 -0800139 nspace: key_id.id(),
Janis Danisevskis1af91262020-08-10 14:58:08 -0700140 ..Default::default()
141 })
142 })
143 .context("In store_new_key.")?,
144 };
145
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700146 Ok(KeyMetadata {
147 key,
Janis Danisevskisa53c9cf2020-10-26 11:52:33 -0700148 keySecurityLevel: self.security_level,
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700149 certificate: cert,
150 certificateChain: cert_chain,
Janis Danisevskis04b02832020-10-26 09:21:40 -0700151 authorizations: crate::utils::key_parameters_to_authorizations(key_parameters),
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800152 modificationTimeMs: creation_date.to_millis_epoch(),
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700153 })
Janis Danisevskis1af91262020-08-10 14:58:08 -0700154 }
155
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700156 fn create_operation(
Janis Danisevskis1af91262020-08-10 14:58:08 -0700157 &self,
158 key: &KeyDescriptor,
159 operation_parameters: &[KeyParameter],
160 forced: bool,
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700161 ) -> Result<CreateOperationResponse> {
Janis Danisevskis1af91262020-08-10 14:58:08 -0700162 let caller_uid = ThreadState::get_calling_uid();
163 // We use `scoping_blob` to extend the life cycle of the blob loaded from the database,
164 // so that we can use it by reference like the blob provided by the key descriptor.
165 // Otherwise, we would have to clone the blob from the key descriptor.
166 let scoping_blob: Vec<u8>;
Hasini Gunasinghe888dd352020-11-17 23:08:39 +0000167 let (km_blob, key_id_guard, key_parameters) = match key.domain {
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700168 Domain::BLOB => {
169 check_key_permission(KeyPerm::use_(), key, &None)
170 .context("In create_operation: checking use permission for Domain::BLOB.")?;
171 (
172 match &key.blob {
Janis Danisevskis1af91262020-08-10 14:58:08 -0700173 Some(blob) => blob,
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700174 None => {
175 return Err(Error::sys()).context(concat!(
176 "In create_operation: Key blob must be specified when",
177 " using Domain::BLOB."
178 ))
179 }
180 },
181 None,
Hasini Gunasinghe888dd352020-11-17 23:08:39 +0000182 None,
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700183 )
184 }
185 _ => {
Janis Danisevskisaec14592020-11-12 09:41:49 -0800186 let (key_id_guard, mut key_entry) = DB
187 .with::<_, Result<(KeyIdGuard, KeyEntry)>>(|db| {
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700188 db.borrow_mut().load_key_entry(
189 key.clone(),
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800190 KeyType::Client,
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700191 KeyEntryLoadBits::KM,
192 caller_uid,
193 |k, av| check_key_permission(KeyPerm::use_(), k, &av),
194 )
195 })
196 .context("In create_operation: Failed to load key blob.")?;
197 scoping_blob = match key_entry.take_km_blob() {
198 Some(blob) => blob,
199 None => {
200 return Err(Error::sys()).context(concat!(
201 "In create_operation: Successfully loaded key entry,",
202 " but KM blob was missing."
203 ))
204 }
205 };
Hasini Gunasinghe888dd352020-11-17 23:08:39 +0000206 (&scoping_blob, Some(key_id_guard), Some(key_entry.into_key_parameters()))
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700207 }
208 };
Janis Danisevskis1af91262020-08-10 14:58:08 -0700209
Janis Danisevskisa53c9cf2020-10-26 11:52:33 -0700210 let purpose = operation_parameters.iter().find(|p| p.tag == Tag::PURPOSE).map_or(
Janis Danisevskis1af91262020-08-10 14:58:08 -0700211 Err(Error::Km(ErrorCode::INVALID_ARGUMENT))
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700212 .context("In create_operation: No operation purpose specified."),
Janis Danisevskis398e6be2020-12-17 09:29:25 -0800213 |kp| match kp.value {
214 KeyParameterValue::KeyPurpose(p) => Ok(p),
215 _ => Err(Error::Km(ErrorCode::INVALID_ARGUMENT))
216 .context("In create_operation: Malformed KeyParameter."),
217 },
Janis Danisevskis1af91262020-08-10 14:58:08 -0700218 )?;
219
Hasini Gunasinghe888dd352020-11-17 23:08:39 +0000220 let mut auth_token_for_km: &HardwareAuthToken = &Default::default();
221 let mut auth_token_handler = AuthTokenHandler::NoAuthRequired;
222
223 // keystore performs authorizations only if the key parameters are loaded above
224 if let Some(ref key_params) = key_parameters {
225 // Note: although currently only one operation parameter is checked in authorizing the
226 // operation, the whole operation_parameter vector is converted into the internal
227 // representation of key parameter because we might need to sanitize operation
228 // parameters (b/175792701)
229 let mut op_params: Vec<KsKeyParam> = Vec::new();
230 for op_param in operation_parameters.iter() {
231 op_params.push(KsKeyParam::new(op_param.into(), self.security_level));
232 }
233 // authorize the operation, and receive an AuthTokenHandler, if authorized, else
234 // propagate the error
235 auth_token_handler = ENFORCEMENTS
236 .authorize_create(
237 purpose,
238 key_params.as_slice(),
239 op_params.as_slice(),
240 self.security_level,
241 )
242 .context("In create_operation.")?;
243 // if an auth token was found, pass it to keymint
244 if let Some(auth_token) = auth_token_handler.get_auth_token() {
245 auth_token_for_km = auth_token;
246 }
247 }
248
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700249 let km_dev: Box<dyn IKeyMintDevice> = self
250 .keymint
251 .get_interface()
252 .context("In create_operation: Failed to get KeyMint device")?;
Janis Danisevskis1af91262020-08-10 14:58:08 -0700253
Janis Danisevskisaec14592020-11-12 09:41:49 -0800254 let (begin_result, upgraded_blob) = self
255 .upgrade_keyblob_if_required_with(
256 &*km_dev,
257 key_id_guard,
Janis Danisevskisa53c9cf2020-10-26 11:52:33 -0700258 &km_blob,
259 &operation_parameters,
Janis Danisevskisaec14592020-11-12 09:41:49 -0800260 |blob| loop {
261 match map_km_error(km_dev.begin(
262 purpose,
263 blob,
264 &operation_parameters,
Hasini Gunasinghe888dd352020-11-17 23:08:39 +0000265 auth_token_for_km,
Janis Danisevskisaec14592020-11-12 09:41:49 -0800266 )) {
267 Err(Error::Km(ErrorCode::TOO_MANY_OPERATIONS)) => {
268 self.operation_db.prune(caller_uid)?;
269 continue;
Janis Danisevskis1af91262020-08-10 14:58:08 -0700270 }
Janis Danisevskisaec14592020-11-12 09:41:49 -0800271 v => return v,
272 }
273 },
274 )
275 .context("In create_operation: Failed to begin operation.")?;
Janis Danisevskis1af91262020-08-10 14:58:08 -0700276
Hasini Gunasinghe888dd352020-11-17 23:08:39 +0000277 let mut operation_challenge: Option<OperationChallenge> = None;
278
279 // take actions based on the authorization decision (if any) received via auth token handler
280 match auth_token_handler {
281 AuthTokenHandler::OpAuthRequired => {
282 operation_challenge =
283 Some(OperationChallenge { challenge: begin_result.challenge });
284 ENFORCEMENTS.insert_to_op_auth_map(begin_result.challenge);
285 }
286 AuthTokenHandler::VerificationRequired(auth_token) => {
287 let (_sender, receiver) = channel::<(HardwareAuthToken, VerificationToken)>();
288 //TODO: call the worker thread and hand over the sender, auth token and challenge
289 auth_token_handler = AuthTokenHandler::Channel(receiver);
290 }
291 _ => {}
292 }
293
Janis Danisevskis1af91262020-08-10 14:58:08 -0700294 let operation = match begin_result.operation {
Hasini Gunasinghe888dd352020-11-17 23:08:39 +0000295 Some(km_op) => {
296 let mut op_challenge_copy: Option<OperationChallenge> = None;
297 if let Some(ref op_challenge) = operation_challenge {
298 op_challenge_copy = Some(OperationChallenge{challenge: op_challenge.challenge});
299 }
300 self.operation_db.create_operation(km_op, caller_uid,
301 auth_token_handler, key_parameters, op_challenge_copy)
302 },
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700303 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 -0700304 };
305
306 let op_binder: Box<dyn IKeystoreOperation> =
307 KeystoreOperation::new_native_binder(operation)
308 .as_binder()
309 .into_interface()
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700310 .context("In create_operation: Failed to create IKeystoreOperation.")?;
Janis Danisevskis1af91262020-08-10 14:58:08 -0700311
312 // TODO we need to the enforcement module to determine if we need to return the challenge.
313 // We return None for now because we don't support auth bound keys yet.
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700314 Ok(CreateOperationResponse {
315 iOperation: Some(op_binder),
Hasini Gunasinghe888dd352020-11-17 23:08:39 +0000316 operationChallenge: operation_challenge,
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700317 parameters: match begin_result.params.len() {
318 0 => None,
Janis Danisevskisa53c9cf2020-10-26 11:52:33 -0700319 _ => Some(KeyParameters { keyParameter: begin_result.params }),
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700320 },
321 })
Janis Danisevskis1af91262020-08-10 14:58:08 -0700322 }
323
324 fn generate_key(
325 &self,
326 key: &KeyDescriptor,
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700327 attestation_key: Option<&KeyDescriptor>,
Janis Danisevskis1af91262020-08-10 14:58:08 -0700328 params: &[KeyParameter],
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700329 flags: i32,
Janis Danisevskis1af91262020-08-10 14:58:08 -0700330 entropy: &[u8],
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700331 ) -> Result<KeyMetadata> {
Janis Danisevskis1af91262020-08-10 14:58:08 -0700332 if key.domain != Domain::BLOB && key.alias.is_none() {
333 return Err(error::Error::Km(ErrorCode::INVALID_ARGUMENT))
334 .context("In generate_key: Alias must be specified");
335 }
336
337 let key = match key.domain {
338 Domain::APP => KeyDescriptor {
339 domain: key.domain,
340 nspace: ThreadState::get_calling_uid() as i64,
341 alias: key.alias.clone(),
342 blob: None,
343 },
344 _ => key.clone(),
345 };
346
347 // generate_key requires the rebind permission.
348 check_key_permission(KeyPerm::rebind(), &key, &None).context("In generate_key.")?;
349
350 let km_dev: Box<dyn IKeyMintDevice> = self.keymint.get_interface()?;
351 map_km_error(km_dev.addRngEntropy(entropy))?;
Shawn Willdendbdac602021-01-12 22:35:16 -0700352 let creation_result = map_km_error(km_dev.generateKey(&params))?;
Janis Danisevskis1af91262020-08-10 14:58:08 -0700353
Shawn Willdendbdac602021-01-12 22:35:16 -0700354 self.store_new_key(key, creation_result).context("In generate_key.")
Janis Danisevskis1af91262020-08-10 14:58:08 -0700355 }
356
357 fn import_key(
358 &self,
359 key: &KeyDescriptor,
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700360 attestation_key: Option<&KeyDescriptor>,
Janis Danisevskis1af91262020-08-10 14:58:08 -0700361 params: &[KeyParameter],
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700362 flags: i32,
Janis Danisevskis1af91262020-08-10 14:58:08 -0700363 key_data: &[u8],
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700364 ) -> Result<KeyMetadata> {
Janis Danisevskis1af91262020-08-10 14:58:08 -0700365 if key.domain != Domain::BLOB && key.alias.is_none() {
366 return Err(error::Error::Km(ErrorCode::INVALID_ARGUMENT))
367 .context("In import_key: Alias must be specified");
368 }
369
370 let key = match key.domain {
371 Domain::APP => KeyDescriptor {
372 domain: key.domain,
373 nspace: ThreadState::get_calling_uid() as i64,
374 alias: key.alias.clone(),
375 blob: None,
376 },
377 _ => key.clone(),
378 };
379
380 // import_key requires the rebind permission.
381 check_key_permission(KeyPerm::rebind(), &key, &None).context("In import_key.")?;
382
Janis Danisevskis1af91262020-08-10 14:58:08 -0700383 let format = params
384 .iter()
Janis Danisevskisa53c9cf2020-10-26 11:52:33 -0700385 .find(|p| p.tag == Tag::ALGORITHM)
Janis Danisevskis1af91262020-08-10 14:58:08 -0700386 .ok_or(error::Error::Km(ErrorCode::INVALID_ARGUMENT))
387 .context("No KeyParameter 'Algorithm'.")
Janis Danisevskis398e6be2020-12-17 09:29:25 -0800388 .and_then(|p| match &p.value {
389 KeyParameterValue::Algorithm(Algorithm::AES)
390 | KeyParameterValue::Algorithm(Algorithm::HMAC)
391 | KeyParameterValue::Algorithm(Algorithm::TRIPLE_DES) => Ok(KeyFormat::RAW),
392 KeyParameterValue::Algorithm(Algorithm::RSA)
393 | KeyParameterValue::Algorithm(Algorithm::EC) => Ok(KeyFormat::PKCS8),
394 v => Err(error::Error::Km(ErrorCode::INVALID_ARGUMENT))
395 .context(format!("Unknown Algorithm {:?}.", v)),
Janis Danisevskis1af91262020-08-10 14:58:08 -0700396 })
397 .context("In import_key.")?;
398
399 let km_dev: Box<dyn IKeyMintDevice> = self.keymint.get_interface()?;
Shawn Willdendbdac602021-01-12 22:35:16 -0700400 let creation_result = map_km_error(km_dev.importKey(&params, format, key_data))?;
Janis Danisevskis1af91262020-08-10 14:58:08 -0700401
Shawn Willdendbdac602021-01-12 22:35:16 -0700402 self.store_new_key(key, creation_result).context("In import_key.")
Janis Danisevskis1af91262020-08-10 14:58:08 -0700403 }
404
405 fn import_wrapped_key(
406 &self,
407 key: &KeyDescriptor,
408 wrapping_key: &KeyDescriptor,
409 masking_key: Option<&[u8]>,
410 params: &[KeyParameter],
411 authenticators: &[AuthenticatorSpec],
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700412 ) -> Result<KeyMetadata> {
Janis Danisevskis1af91262020-08-10 14:58:08 -0700413 if key.domain != Domain::BLOB && key.alias.is_none() {
414 return Err(error::Error::Km(ErrorCode::INVALID_ARGUMENT))
415 .context("In import_wrapped_key: Alias must be specified.");
416 }
417
Janis Danisevskisaec14592020-11-12 09:41:49 -0800418 if wrapping_key.domain == Domain::BLOB {
419 return Err(error::Error::Km(ErrorCode::INVALID_ARGUMENT)).context(
420 "In import_wrapped_key: Import wrapped key not supported for self managed blobs.",
421 );
422 }
423
Janis Danisevskis1af91262020-08-10 14:58:08 -0700424 let wrapped_data = match &key.blob {
425 Some(d) => d,
426 None => {
427 return Err(error::Error::Km(ErrorCode::INVALID_ARGUMENT)).context(
428 "In import_wrapped_key: Blob must be specified and hold wrapped key data.",
429 )
430 }
431 };
432
433 let key = match key.domain {
434 Domain::APP => KeyDescriptor {
435 domain: key.domain,
436 nspace: ThreadState::get_calling_uid() as i64,
437 alias: key.alias.clone(),
438 blob: None,
439 },
440 _ => key.clone(),
441 };
442
443 // import_wrapped_key requires the rebind permission for the new key.
444 check_key_permission(KeyPerm::rebind(), &key, &None).context("In import_wrapped_key.")?;
445
Janis Danisevskisaec14592020-11-12 09:41:49 -0800446 let (wrapping_key_id_guard, wrapping_key_entry) = DB
Janis Danisevskis1af91262020-08-10 14:58:08 -0700447 .with(|db| {
448 db.borrow_mut().load_key_entry(
449 wrapping_key.clone(),
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800450 KeyType::Client,
Janis Danisevskis1af91262020-08-10 14:58:08 -0700451 KeyEntryLoadBits::KM,
452 ThreadState::get_calling_uid(),
453 |k, av| check_key_permission(KeyPerm::use_(), k, &av),
454 )
455 })
456 .context("Failed to load wrapping key.")?;
457 let wrapping_key_blob = match wrapping_key_entry.km_blob() {
458 Some(blob) => blob,
459 None => {
460 return Err(error::Error::sys()).context(concat!(
461 "No km_blob after successfully loading key.",
462 " This should never happen."
463 ))
464 }
465 };
466
Janis Danisevskis1af91262020-08-10 14:58:08 -0700467 // km_dev.importWrappedKey does not return a certificate chain.
468 // TODO Do we assume that all wrapped keys are symmetric?
469 // let certificate_chain: Vec<KmCertificate> = Default::default();
470
471 let pw_sid = authenticators
472 .iter()
473 .find_map(|a| match a.authenticatorType {
Janis Danisevskisa53c9cf2020-10-26 11:52:33 -0700474 HardwareAuthenticatorType::PASSWORD => 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 password authenticator SID must be specified.")?;
479
480 let fp_sid = authenticators
481 .iter()
482 .find_map(|a| match a.authenticatorType {
Janis Danisevskisa53c9cf2020-10-26 11:52:33 -0700483 HardwareAuthenticatorType::FINGERPRINT => Some(a.authenticatorId),
Janis Danisevskis1af91262020-08-10 14:58:08 -0700484 _ => None,
485 })
486 .ok_or(error::Error::Km(ErrorCode::INVALID_ARGUMENT))
487 .context("A fingerprint authenticator SID must be specified.")?;
488
489 let masking_key = masking_key.unwrap_or(ZERO_BLOB_32);
490
491 let km_dev: Box<dyn IKeyMintDevice> = self.keymint.get_interface()?;
Shawn Willdendbdac602021-01-12 22:35:16 -0700492 let (creation_result, _) = self.upgrade_keyblob_if_required_with(
Janis Danisevskisaec14592020-11-12 09:41:49 -0800493 &*km_dev,
494 Some(wrapping_key_id_guard),
Janis Danisevskis1af91262020-08-10 14:58:08 -0700495 wrapping_key_blob,
Janis Danisevskisaec14592020-11-12 09:41:49 -0800496 &[],
497 |wrapping_blob| {
Shawn Willdendbdac602021-01-12 22:35:16 -0700498 let creation_result = map_km_error(km_dev.importWrappedKey(
Janis Danisevskisaec14592020-11-12 09:41:49 -0800499 wrapped_data,
500 wrapping_key_blob,
501 masking_key,
502 &params,
503 pw_sid,
504 fp_sid,
Janis Danisevskisaec14592020-11-12 09:41:49 -0800505 ))?;
Shawn Willdendbdac602021-01-12 22:35:16 -0700506 Ok(creation_result)
Janis Danisevskisaec14592020-11-12 09:41:49 -0800507 },
508 )?;
Janis Danisevskis1af91262020-08-10 14:58:08 -0700509
Shawn Willdendbdac602021-01-12 22:35:16 -0700510 self.store_new_key(key, creation_result).context("In import_wrapped_key.")
Janis Danisevskis1af91262020-08-10 14:58:08 -0700511 }
Janis Danisevskisaec14592020-11-12 09:41:49 -0800512
513 fn upgrade_keyblob_if_required_with<T, F>(
514 &self,
515 km_dev: &dyn IKeyMintDevice,
516 key_id_guard: Option<KeyIdGuard>,
517 blob: &[u8],
518 params: &[KeyParameter],
519 f: F,
520 ) -> Result<(T, Option<Vec<u8>>)>
521 where
522 F: Fn(&[u8]) -> Result<T, Error>,
523 {
524 match f(blob) {
525 Err(Error::Km(ErrorCode::KEY_REQUIRES_UPGRADE)) => {
526 let upgraded_blob = map_km_error(km_dev.upgradeKey(blob, params))
527 .context("In upgrade_keyblob_if_required_with: Upgrade failed.")?;
528 key_id_guard.map_or(Ok(()), |key_id_guard| {
529 DB.with(|db| {
530 db.borrow_mut().insert_blob(
531 &key_id_guard,
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800532 SubComponentType::KEY_BLOB,
Janis Danisevskisaec14592020-11-12 09:41:49 -0800533 &upgraded_blob,
Janis Danisevskisaec14592020-11-12 09:41:49 -0800534 )
535 })
536 .context(concat!(
537 "In upgrade_keyblob_if_required_with: ",
538 "Failed to insert upgraded blob into the database.",
539 ))
540 })?;
541 match f(&upgraded_blob) {
542 Ok(v) => Ok((v, Some(upgraded_blob))),
543 Err(e) => Err(e).context(concat!(
544 "In upgrade_keyblob_if_required_with: ",
545 "Failed to perform operation on second try."
546 )),
547 }
548 }
549 Err(e) => {
550 Err(e).context("In upgrade_keyblob_if_required_with: Failed perform operation.")
551 }
552 Ok(v) => Ok((v, None)),
553 }
554 }
Janis Danisevskis1af91262020-08-10 14:58:08 -0700555}
556
557impl binder::Interface for KeystoreSecurityLevel {}
558
559impl IKeystoreSecurityLevel for KeystoreSecurityLevel {
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700560 fn createOperation(
Janis Danisevskis1af91262020-08-10 14:58:08 -0700561 &self,
562 key: &KeyDescriptor,
563 operation_parameters: &[KeyParameter],
564 forced: bool,
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700565 ) -> binder::public_api::Result<CreateOperationResponse> {
566 map_or_log_err(self.create_operation(key, operation_parameters, forced), Ok)
Janis Danisevskis1af91262020-08-10 14:58:08 -0700567 }
568 fn generateKey(
569 &self,
570 key: &KeyDescriptor,
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700571 attestation_key: Option<&KeyDescriptor>,
Janis Danisevskis1af91262020-08-10 14:58:08 -0700572 params: &[KeyParameter],
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700573 flags: i32,
Janis Danisevskis1af91262020-08-10 14:58:08 -0700574 entropy: &[u8],
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700575 ) -> binder::public_api::Result<KeyMetadata> {
576 map_or_log_err(self.generate_key(key, attestation_key, params, flags, entropy), Ok)
Janis Danisevskis1af91262020-08-10 14:58:08 -0700577 }
578 fn importKey(
579 &self,
580 key: &KeyDescriptor,
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700581 attestation_key: Option<&KeyDescriptor>,
Janis Danisevskis1af91262020-08-10 14:58:08 -0700582 params: &[KeyParameter],
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700583 flags: i32,
Janis Danisevskis1af91262020-08-10 14:58:08 -0700584 key_data: &[u8],
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700585 ) -> binder::public_api::Result<KeyMetadata> {
586 map_or_log_err(self.import_key(key, attestation_key, params, flags, key_data), Ok)
Janis Danisevskis1af91262020-08-10 14:58:08 -0700587 }
588 fn importWrappedKey(
589 &self,
590 key: &KeyDescriptor,
591 wrapping_key: &KeyDescriptor,
592 masking_key: Option<&[u8]>,
593 params: &[KeyParameter],
594 authenticators: &[AuthenticatorSpec],
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700595 ) -> binder::public_api::Result<KeyMetadata> {
Janis Danisevskis1af91262020-08-10 14:58:08 -0700596 map_or_log_err(
597 self.import_wrapped_key(key, wrapping_key, masking_key, params, authenticators),
Janis Danisevskis2c7f9622020-09-30 16:30:31 -0700598 Ok,
Janis Danisevskis1af91262020-08-10 14:58:08 -0700599 )
600 }
601}