blob: 287d626996ff97be227f69978f7e215b3f138806 [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
19use android_hardware_keymint::aidl::android::hardware::keymint::{
20 Algorithm::Algorithm, Certificate::Certificate as KmCertificate,
21 IKeyMintDevice::IKeyMintDevice, KeyCharacteristics::KeyCharacteristics, KeyFormat::KeyFormat,
22 KeyParameter::KeyParameter as KmParam, KeyPurpose::KeyPurpose, Tag::Tag,
23};
24use android_system_keystore2::aidl::android::system::keystore2::{
25 AuthenticatorSpec::AuthenticatorSpec, AuthenticatorType::AuthenticatorType,
26 Certificate::Certificate, CertificateChain::CertificateChain, Domain::Domain,
27 IKeystoreOperation::IKeystoreOperation, IKeystoreSecurityLevel::BnKeystoreSecurityLevel,
28 IKeystoreSecurityLevel::IKeystoreSecurityLevel, KeyDescriptor::KeyDescriptor,
29 KeyParameter::KeyParameter, OperationChallenge::OperationChallenge,
30 SecurityLevel::SecurityLevel,
31};
32
33use crate::error::{self, map_km_error, map_or_log_err, Error, ErrorCode};
34use crate::globals::DB;
35use crate::permission::KeyPerm;
36use crate::utils::{check_key_permission, keyparam_ks_to_km, Asp};
37use crate::{
38 database::{KeyEntry, KeyEntryLoadBits, SubComponentType},
39 operation::KeystoreOperation,
40 operation::OperationDb,
41};
42use anyhow::{anyhow, Context, Result};
43use binder::{IBinder, Interface, ThreadState};
44
45/// Implementation of the IKeystoreSecurityLevel Interface.
46pub struct KeystoreSecurityLevel {
47 security_level: SecurityLevel,
48 keymint: Asp,
49 operation_db: OperationDb,
50}
51
52static KEYMINT_SERVICE_NAME: &str = "android.hardware.keymint.IKeyMintDevice";
53
54// Blob of 32 zeroes used as empty masking key.
55static ZERO_BLOB_32: &[u8] = &[0; 32];
56
57impl KeystoreSecurityLevel {
58 /// Creates a new security level instance wrapped in a
59 /// BnKeystoreSecurityLevel proxy object. It also
60 /// calls `IBinder::set_requesting_sid` on the new interface, because
61 /// we need it for checking keystore permissions.
62 pub fn new_native_binder(
63 security_level: SecurityLevel,
64 ) -> Result<impl IKeystoreSecurityLevel + Send> {
65 let service_name = format!("{}/default", KEYMINT_SERVICE_NAME);
66 let keymint: Box<dyn IKeyMintDevice> =
67 binder::get_interface(&service_name).map_err(|e| {
68 anyhow!(format!(
69 "Could not get KeyMint instance: {} failed with error code {:?}",
70 service_name, e
71 ))
72 })?;
73
74 let result = BnKeystoreSecurityLevel::new_binder(Self {
75 security_level,
76 keymint: Asp::new(keymint.as_binder()),
77 operation_db: OperationDb::new(),
78 });
79 result.as_binder().set_requesting_sid(true);
80 Ok(result)
81 }
82
83 fn store_new_key(
84 &self,
85 key: KeyDescriptor,
86 km_cert_chain: Option<Vec<KmCertificate>>,
87 blob: Vec<u8>,
88 ) -> Result<(KeyDescriptor, Option<Certificate>, Option<CertificateChain>)> {
89 let (cert, cert_chain) = match km_cert_chain {
90 Some(mut chain) => (
91 match chain.len() {
92 0 => None,
93 _ => Some(Certificate { data: chain.remove(0).encodedCertificate }),
94 },
95 match chain.len() {
96 0 => None,
97 _ => Some(CertificateChain {
98 data: chain
99 .iter()
100 .map(|c| c.encodedCertificate.iter())
101 .flatten()
102 .copied()
103 .collect(),
104 }),
105 },
106 ),
107 None => (None, None),
108 };
109
110 let key = match key.domain {
111 Domain::BLOB => {
112 KeyDescriptor { domain: Domain::BLOB, blob: Some(blob), ..Default::default() }
113 }
114 _ => DB
115 .with(|db| {
116 let mut db = db.borrow_mut();
117 let key_id = db
118 .create_key_entry(key.domain, key.nspace)
119 .context("Trying to create a key entry.")?;
120 db.insert_blob(key_id, SubComponentType::KM_BLOB, &blob, self.security_level)
121 .context("Trying to insert km blob.")?;
122 if let Some(c) = &cert {
123 db.insert_blob(
124 key_id,
125 SubComponentType::CERT,
126 &c.data,
127 self.security_level,
128 )
129 .context("Trying to insert cert blob.")?;
130 }
131 if let Some(c) = &cert_chain {
132 db.insert_blob(
133 key_id,
134 SubComponentType::CERT_CHAIN,
135 &c.data,
136 self.security_level,
137 )
138 .context("Trying to insert cert chain blob.")?;
139 }
140 match &key.alias {
141 Some(alias) => db
142 .rebind_alias(key_id, alias, key.domain, key.nspace)
143 .context("Failed to rebind alias.")?,
144 None => {
145 return Err(error::Error::sys()).context(
146 "Alias must be specified. (This should have been checked earlier.)",
147 )
148 }
149 }
150 Ok(KeyDescriptor {
151 domain: Domain::KEY_ID,
152 nspace: key_id,
153 ..Default::default()
154 })
155 })
156 .context("In store_new_key.")?,
157 };
158
159 Ok((key, cert, cert_chain))
160 }
161
162 fn create(
163 &self,
164 key: &KeyDescriptor,
165 operation_parameters: &[KeyParameter],
166 forced: bool,
167 ) -> Result<(Box<dyn IKeystoreOperation>, Option<OperationChallenge>)> {
168 let caller_uid = ThreadState::get_calling_uid();
169 // We use `scoping_blob` to extend the life cycle of the blob loaded from the database,
170 // so that we can use it by reference like the blob provided by the key descriptor.
171 // Otherwise, we would have to clone the blob from the key descriptor.
172 let scoping_blob: Vec<u8>;
173 let (km_blob, key_id) =
174 match key.domain {
175 Domain::BLOB => {
176 check_key_permission(KeyPerm::use_(), key, &None)
177 .context("In create: checking use permission for Domain::BLOB.")?;
178 (
179 match &key.blob {
180 Some(blob) => blob,
181 None => return Err(Error::sys()).context(
182 "In create: Key blob must be specified when using Domain::BLOB.",
183 ),
184 },
185 None,
186 )
187 }
188 _ => {
189 let mut key_entry = DB
190 .with::<_, Result<KeyEntry>>(|db| {
191 db.borrow_mut().load_key_entry(
192 key.clone(),
193 KeyEntryLoadBits::KM,
194 caller_uid,
195 |k, av| check_key_permission(KeyPerm::use_(), k, &av),
196 )
197 })
198 .context("In create: Failed to load key blob.")?;
199 scoping_blob = match key_entry.take_km_blob() {
200 Some(blob) => blob,
201 None => return Err(Error::sys()).context(
202 "In create: Successfully loaded key entry, but KM blob was missing.",
203 ),
204 };
205 (&scoping_blob, Some(key_entry.id()))
206 }
207 };
208
209 // TODO Authorize begin operation.
210 // Check if we need an authorization token.
211 // Lookup authorization token and request VerificationToken if required.
212
213 let purpose = operation_parameters.iter().find(|p| p.tag == Tag::PURPOSE.0).map_or(
214 Err(Error::Km(ErrorCode::INVALID_ARGUMENT))
215 .context("In create: No operation purpose specified."),
216 |kp| Ok(KeyPurpose(kp.integer)),
217 )?;
218
219 let km_params =
220 operation_parameters.iter().map(|p| keyparam_ks_to_km(p)).collect::<Vec<KmParam>>();
221
222 let km_dev: Box<dyn IKeyMintDevice> =
223 self.keymint.get_interface().context("In create: Failed to get KeyMint device")?;
224
225 let (begin_result, upgraded_blob) = loop {
226 match map_km_error(km_dev.begin(purpose, &km_blob, &km_params, &Default::default())) {
227 Ok(result) => break (result, None),
228 Err(Error::Km(ErrorCode::TOO_MANY_OPERATIONS)) => {
229 self.operation_db.prune(caller_uid).context("In create: Outer loop.")?;
230 continue;
231 }
232 Err(Error::Km(ErrorCode::KEY_REQUIRES_UPGRADE)) => {
233 let upgraded_blob = map_km_error(km_dev.upgradeKey(&km_blob, &km_params))
234 .context("In create: Upgrade failed.")?;
235 break loop {
236 match map_km_error(km_dev.begin(
237 purpose,
238 &upgraded_blob,
239 &km_params,
240 &Default::default(),
241 )) {
242 Ok(result) => break (result, Some(upgraded_blob)),
243 // If Keystore 2.0 is multi threaded another request may have
244 // snatched up our previously pruned operation slot. So we might
245 // need to prune again.
246 Err(Error::Km(ErrorCode::TOO_MANY_OPERATIONS)) => {
247 self.operation_db
248 .prune(caller_uid)
249 .context("In create: Inner loop.")?;
250 continue;
251 }
252 Err(e) => {
253 return Err(e)
254 .context("In create: Begin operation failed after upgrade.")
255 }
256 }
257 };
258 }
259 Err(e) => return Err(e).context("In create: Begin operation failed."),
260 };
261 };
262
263 if let Some(upgraded_blob) = upgraded_blob {
264 if let Some(key_id) = key_id {
265 DB.with(|db| {
266 db.borrow_mut().insert_blob(
267 key_id,
268 SubComponentType::KM_BLOB,
269 &upgraded_blob,
270 self.security_level,
271 )
272 })
273 .context("In create: Failed to insert upgraded blob into the database.")?;
274 }
275 }
276
277 let operation = match begin_result.operation {
278 Some(km_op) => self.operation_db.create_operation(km_op, caller_uid),
279 None => return Err(Error::sys()).context("In create: Begin operation returned successfully, but did not return a valid operation."),
280 };
281
282 let op_binder: Box<dyn IKeystoreOperation> =
283 KeystoreOperation::new_native_binder(operation)
284 .as_binder()
285 .into_interface()
286 .context("In create: Failed to create IKeystoreOperation.")?;
287
288 // TODO find out what to do with the returned parameters.
289
290 // TODO we need to the enforcement module to determine if we need to return the challenge.
291 // We return None for now because we don't support auth bound keys yet.
292 Ok((op_binder, None))
293 }
294
295 fn generate_key(
296 &self,
297 key: &KeyDescriptor,
298 params: &[KeyParameter],
299 entropy: &[u8],
300 ) -> Result<(KeyDescriptor, Option<Certificate>, Option<CertificateChain>)> {
301 if key.domain != Domain::BLOB && key.alias.is_none() {
302 return Err(error::Error::Km(ErrorCode::INVALID_ARGUMENT))
303 .context("In generate_key: Alias must be specified");
304 }
305
306 let key = match key.domain {
307 Domain::APP => KeyDescriptor {
308 domain: key.domain,
309 nspace: ThreadState::get_calling_uid() as i64,
310 alias: key.alias.clone(),
311 blob: None,
312 },
313 _ => key.clone(),
314 };
315
316 // generate_key requires the rebind permission.
317 check_key_permission(KeyPerm::rebind(), &key, &None).context("In generate_key.")?;
318
319 let km_dev: Box<dyn IKeyMintDevice> = self.keymint.get_interface()?;
320 map_km_error(km_dev.addRngEntropy(entropy))?;
321 let mut blob: Vec<u8> = Default::default();
322 let mut key_characteristics: KeyCharacteristics = Default::default();
323 let mut certificate_chain: Vec<KmCertificate> = Default::default();
324 map_km_error(km_dev.generateKey(
325 &params.iter().map(|p| keyparam_ks_to_km(p)).collect::<Vec<KmParam>>(),
326 &mut blob,
327 &mut key_characteristics,
328 &mut certificate_chain,
329 ))?;
330
331 self.store_new_key(key, Some(certificate_chain), blob).context("In generate_key.")
332 }
333
334 fn import_key(
335 &self,
336 key: &KeyDescriptor,
337 params: &[KeyParameter],
338 key_data: &[u8],
339 ) -> Result<(KeyDescriptor, Option<Certificate>, Option<CertificateChain>)> {
340 if key.domain != Domain::BLOB && key.alias.is_none() {
341 return Err(error::Error::Km(ErrorCode::INVALID_ARGUMENT))
342 .context("In import_key: Alias must be specified");
343 }
344
345 let key = match key.domain {
346 Domain::APP => KeyDescriptor {
347 domain: key.domain,
348 nspace: ThreadState::get_calling_uid() as i64,
349 alias: key.alias.clone(),
350 blob: None,
351 },
352 _ => key.clone(),
353 };
354
355 // import_key requires the rebind permission.
356 check_key_permission(KeyPerm::rebind(), &key, &None).context("In import_key.")?;
357
358 let mut blob: Vec<u8> = Default::default();
359 let mut key_characteristics: KeyCharacteristics = Default::default();
360 let mut certificate_chain: Vec<KmCertificate> = Default::default();
361
362 let format = params
363 .iter()
364 .find(|p| p.tag == Tag::ALGORITHM.0)
365 .ok_or(error::Error::Km(ErrorCode::INVALID_ARGUMENT))
366 .context("No KeyParameter 'Algorithm'.")
367 .and_then(|p| match Algorithm(p.integer) {
368 Algorithm::AES | Algorithm::HMAC | Algorithm::TRIPLE_DES => Ok(KeyFormat::RAW),
369 Algorithm::RSA | Algorithm::EC => Ok(KeyFormat::PKCS8),
370 algorithm => Err(error::Error::Km(ErrorCode::INVALID_ARGUMENT))
371 .context(format!("Unknown Algorithm {:?}.", algorithm)),
372 })
373 .context("In import_key.")?;
374
375 let km_dev: Box<dyn IKeyMintDevice> = self.keymint.get_interface()?;
376 map_km_error(km_dev.importKey(
377 &params.iter().map(|p| keyparam_ks_to_km(p)).collect::<Vec<KmParam>>(),
378 format,
379 key_data,
380 &mut blob,
381 &mut key_characteristics,
382 &mut certificate_chain,
383 ))?;
384
385 self.store_new_key(key, Some(certificate_chain), blob).context("In import_key.")
386 }
387
388 fn import_wrapped_key(
389 &self,
390 key: &KeyDescriptor,
391 wrapping_key: &KeyDescriptor,
392 masking_key: Option<&[u8]>,
393 params: &[KeyParameter],
394 authenticators: &[AuthenticatorSpec],
395 ) -> Result<(KeyDescriptor, Option<Certificate>, Option<CertificateChain>)> {
396 if key.domain != Domain::BLOB && key.alias.is_none() {
397 return Err(error::Error::Km(ErrorCode::INVALID_ARGUMENT))
398 .context("In import_wrapped_key: Alias must be specified.");
399 }
400
401 let wrapped_data = match &key.blob {
402 Some(d) => d,
403 None => {
404 return Err(error::Error::Km(ErrorCode::INVALID_ARGUMENT)).context(
405 "In import_wrapped_key: Blob must be specified and hold wrapped key data.",
406 )
407 }
408 };
409
410 let key = match key.domain {
411 Domain::APP => KeyDescriptor {
412 domain: key.domain,
413 nspace: ThreadState::get_calling_uid() as i64,
414 alias: key.alias.clone(),
415 blob: None,
416 },
417 _ => key.clone(),
418 };
419
420 // import_wrapped_key requires the rebind permission for the new key.
421 check_key_permission(KeyPerm::rebind(), &key, &None).context("In import_wrapped_key.")?;
422
423 let wrapping_key_entry = DB
424 .with(|db| {
425 db.borrow_mut().load_key_entry(
426 wrapping_key.clone(),
427 KeyEntryLoadBits::KM,
428 ThreadState::get_calling_uid(),
429 |k, av| check_key_permission(KeyPerm::use_(), k, &av),
430 )
431 })
432 .context("Failed to load wrapping key.")?;
433 let wrapping_key_blob = match wrapping_key_entry.km_blob() {
434 Some(blob) => blob,
435 None => {
436 return Err(error::Error::sys()).context(concat!(
437 "No km_blob after successfully loading key.",
438 " This should never happen."
439 ))
440 }
441 };
442
443 let mut blob: Vec<u8> = Default::default();
444 let mut key_characteristics: KeyCharacteristics = Default::default();
445 // km_dev.importWrappedKey does not return a certificate chain.
446 // TODO Do we assume that all wrapped keys are symmetric?
447 // let certificate_chain: Vec<KmCertificate> = Default::default();
448
449 let pw_sid = authenticators
450 .iter()
451 .find_map(|a| match a.authenticatorType {
452 AuthenticatorType::PASSWORD => Some(a.authenticatorId),
453 _ => None,
454 })
455 .ok_or(error::Error::Km(ErrorCode::INVALID_ARGUMENT))
456 .context("A password authenticator SID must be specified.")?;
457
458 let fp_sid = authenticators
459 .iter()
460 .find_map(|a| match a.authenticatorType {
461 AuthenticatorType::FINGERPRINT => Some(a.authenticatorId),
462 _ => None,
463 })
464 .ok_or(error::Error::Km(ErrorCode::INVALID_ARGUMENT))
465 .context("A fingerprint authenticator SID must be specified.")?;
466
467 let masking_key = masking_key.unwrap_or(ZERO_BLOB_32);
468
469 let km_dev: Box<dyn IKeyMintDevice> = self.keymint.get_interface()?;
470 map_km_error(km_dev.importWrappedKey(
471 wrapped_data,
472 wrapping_key_blob,
473 masking_key,
474 &params.iter().map(|p| keyparam_ks_to_km(p)).collect::<Vec<KmParam>>(),
475 pw_sid,
476 fp_sid,
477 &mut blob,
478 &mut key_characteristics,
479 ))?;
480
481 self.store_new_key(key, None, blob).context("In import_wrapped_key.")
482 }
483}
484
485impl binder::Interface for KeystoreSecurityLevel {}
486
487impl IKeystoreSecurityLevel for KeystoreSecurityLevel {
488 fn create(
489 &self,
490 key: &KeyDescriptor,
491 operation_parameters: &[KeyParameter],
492 forced: bool,
493 challenge: &mut Option<OperationChallenge>,
494 ) -> binder::public_api::Result<Box<dyn IKeystoreOperation>> {
495 map_or_log_err(self.create(key, operation_parameters, forced), |v| {
496 *challenge = v.1;
497 Ok(v.0)
498 })
499 }
500 fn generateKey(
501 &self,
502 key: &KeyDescriptor,
503 params: &[KeyParameter],
504 entropy: &[u8],
505 result_key: &mut KeyDescriptor,
506 public_cert: &mut Option<Certificate>,
507 certificate_chain: &mut Option<CertificateChain>,
508 ) -> binder::public_api::Result<()> {
509 map_or_log_err(self.generate_key(key, params, entropy), |v| {
510 *result_key = v.0;
511 *public_cert = v.1;
512 *certificate_chain = v.2;
513 Ok(())
514 })
515 }
516 fn importKey(
517 &self,
518 key: &KeyDescriptor,
519 params: &[KeyParameter],
520 key_data: &[u8],
521 result_key: &mut KeyDescriptor,
522 public_cert: &mut Option<Certificate>,
523 certificate_chain: &mut Option<CertificateChain>,
524 ) -> binder::public_api::Result<()> {
525 map_or_log_err(self.import_key(key, params, key_data), |v| {
526 *result_key = v.0;
527 *public_cert = v.1;
528 *certificate_chain = v.2;
529 Ok(())
530 })
531 }
532 fn importWrappedKey(
533 &self,
534 key: &KeyDescriptor,
535 wrapping_key: &KeyDescriptor,
536 masking_key: Option<&[u8]>,
537 params: &[KeyParameter],
538 authenticators: &[AuthenticatorSpec],
539 result_key: &mut KeyDescriptor,
540 public_cert: &mut Option<Certificate>,
541 certificate_chain: &mut Option<CertificateChain>,
542 ) -> binder::public_api::Result<()> {
543 map_or_log_err(
544 self.import_wrapped_key(key, wrapping_key, masking_key, params, authenticators),
545 |v| {
546 *result_key = v.0;
547 *public_cert = v.1;
548 *certificate_chain = v.2;
549 Ok(())
550 },
551 )
552 }
553}