1 //! TA functionality related to in-progress crypto operations. 2 3 use crate::LockState; 4 use alloc::{boxed::Box, vec::Vec}; 5 use kmr_common::{ 6 crypto, 7 crypto::{aes, AadOperation, AccumulatingOperation, EmittingOperation, KeyMaterial}, 8 get_bool_tag_value, get_opt_tag_value, get_tag_value, keyblob, km_err, tag, try_to_vec, Error, 9 FallibleAllocExt, 10 }; 11 use kmr_wire::{ 12 keymint::{ErrorCode, HardwareAuthToken, HardwareAuthenticatorType, KeyParam, KeyPurpose}, 13 secureclock, 14 secureclock::{TimeStampToken, Timestamp}, 15 InternalBeginResult, 16 }; 17 use log::{error, info, warn}; 18 19 /// A trusted confirmation token should be the size of HMAC-SHA256 output. 20 const CONFIRMATION_TOKEN_SIZE: usize = 32; 21 22 /// Trusted confirmation data prefix, from IConfirmationResultCallback.hal. 23 const CONFIRMATION_DATA_PREFIX: &[u8] = b"confirmation token"; 24 25 /// Maximum size of messages with `Tag::TrustedConfirmationRequired` set. 26 /// See <https://source.android.com/security/protected-confirmation/implementation> 27 const CONFIRMATION_MESSAGE_MAX_LEN: usize = 6144; 28 29 /// Union holder for in-progress cryptographic operations, each of which is an instance 30 /// of the relevant trait. 31 pub(crate) enum CryptoOperation { 32 Aes(Box<dyn EmittingOperation>), 33 AesGcm(Box<dyn AadOperation>), 34 Des(Box<dyn EmittingOperation>), 35 HmacSign(Box<dyn AccumulatingOperation>, usize), // tag length 36 HmacVerify(Box<dyn AccumulatingOperation>, core::ops::Range<usize>), 37 RsaDecrypt(Box<dyn AccumulatingOperation>), 38 RsaSign(Box<dyn AccumulatingOperation>), 39 EcAgree(Box<dyn AccumulatingOperation>), 40 EcSign(Box<dyn AccumulatingOperation>), 41 } 42 43 /// Current state of an operation. 44 pub(crate) struct Operation { 45 /// Random handle used to identify the operation, also used as a challenge. 46 pub handle: OpHandle, 47 48 /// Whether update_aad() is allowed (only ever true for AEADs before data has arrived). 49 pub aad_allowed: bool, 50 51 /// Secure deletion slot to delete on successful completion of the operation. 52 pub slot_to_delete: Option<keyblob::SecureDeletionSlot>, 53 54 /// Buffer to accumulate data being signed that must have a trusted confirmation. This 55 /// data matches what was been fed into `crypto_op`'s `update` method (but has a size 56 /// limit so will not grow unboundedly). 57 pub trusted_conf_data: Option<Vec<u8>>, 58 59 /// Authentication data to check. 60 pub auth_info: Option<AuthInfo>, 61 62 pub crypto_op: CryptoOperation, 63 64 /// Accumulated input size. 65 pub input_size: usize, 66 } 67 68 impl Operation { 69 /// Check whether `len` additional bytes of data can be accommodated by the `Operation`. check_size(&mut self, len: usize) -> Result<(), Error>70 fn check_size(&mut self, len: usize) -> Result<(), Error> { 71 self.input_size += len; 72 let max_size = match &self.crypto_op { 73 CryptoOperation::HmacSign(op, _) 74 | CryptoOperation::HmacVerify(op, _) 75 | CryptoOperation::RsaDecrypt(op) 76 | CryptoOperation::RsaSign(op) 77 | CryptoOperation::EcAgree(op) 78 | CryptoOperation::EcSign(op) => op.max_input_size(), 79 _ => None, 80 }; 81 if let Some(max_size) = max_size { 82 if self.input_size > max_size { 83 return Err(km_err!( 84 InvalidInputLength, 85 "too much input accumulated for operation" 86 )); 87 } 88 } 89 Ok(()) 90 } 91 } 92 93 /// Newtype for operation handles. 94 #[derive(Debug, Clone, Copy, PartialEq, Eq)] 95 pub(crate) struct OpHandle(pub i64); 96 97 /// Authentication requirements associated with an operation. 98 pub(crate) struct AuthInfo { 99 secure_ids: Vec<u64>, 100 auth_type: u32, 101 timeout_secs: Option<u32>, 102 } 103 104 impl AuthInfo { 105 /// Optionally build an `AuthInfo` from key characteristics. If no authentication is needed on 106 /// `update()`/`update_aad()`/`finish()`, return `None`. new(key_chars: &[KeyParam]) -> Result<Option<AuthInfo>, Error>107 fn new(key_chars: &[KeyParam]) -> Result<Option<AuthInfo>, Error> { 108 let mut secure_ids = Vec::new(); 109 let mut auth_type = None; 110 let mut timeout_secs = None; 111 let mut no_auth_required = false; 112 113 for param in key_chars { 114 match param { 115 KeyParam::UserSecureId(sid) => secure_ids.try_push(*sid)?, 116 KeyParam::UserAuthType(atype) => { 117 if auth_type.is_none() { 118 auth_type = Some(*atype); 119 } else { 120 return Err(km_err!(InvalidKeyBlob, "duplicate UserAuthType tag found")); 121 } 122 } 123 KeyParam::AuthTimeout(secs) => { 124 if timeout_secs.is_none() { 125 timeout_secs = Some(*secs) 126 } else { 127 return Err(km_err!(InvalidKeyBlob, "duplicate AuthTimeout tag found")); 128 } 129 } 130 KeyParam::NoAuthRequired => no_auth_required = true, 131 _ => {} 132 } 133 } 134 135 if secure_ids.is_empty() { 136 Ok(None) 137 } else if let Some(auth_type) = auth_type { 138 if no_auth_required { 139 Err(km_err!(InvalidKeyBlob, "found both NO_AUTH_REQUIRED and USER_SECURE_ID")) 140 } else { 141 Ok(Some(AuthInfo { secure_ids, auth_type, timeout_secs })) 142 } 143 } else { 144 Err(km_err!(KeyUserNotAuthenticated, "found USER_SECURE_ID but no USER_AUTH_TYPE")) 145 } 146 } 147 } 148 149 /// Newtype holding a [`keymint::HardwareAuthToken`] that has already been authenticated. 150 #[derive(Debug, Clone)] 151 struct HardwareAuthenticatedToken(pub HardwareAuthToken); 152 153 impl<'a> crate::KeyMintTa<'a> { begin_operation( &mut self, purpose: KeyPurpose, key_blob: &[u8], params: Vec<KeyParam>, auth_token: Option<HardwareAuthToken>, ) -> Result<InternalBeginResult, Error>154 pub(crate) fn begin_operation( 155 &mut self, 156 purpose: KeyPurpose, 157 key_blob: &[u8], 158 params: Vec<KeyParam>, 159 auth_token: Option<HardwareAuthToken>, 160 ) -> Result<InternalBeginResult, Error> { 161 let op_idx = self.new_operation_index()?; 162 163 // Parse and decrypt the keyblob, which requires extra hidden params. 164 let (keyblob, sdd_slot) = self.keyblob_parse_decrypt(key_blob, ¶ms)?; 165 let keyblob::PlaintextKeyBlob { characteristics, key_material } = keyblob; 166 167 // Validate parameters. 168 let key_chars = 169 kmr_common::tag::characteristics_at(&characteristics, self.hw_info.security_level)?; 170 tag::check_begin_params(key_chars, purpose, ¶ms)?; 171 self.check_begin_auths(key_chars, key_blob)?; 172 173 let trusted_conf_data = if purpose == KeyPurpose::Sign 174 && get_bool_tag_value!(key_chars, TrustedConfirmationRequired)? 175 { 176 // Trusted confirmation is required; accumulate the signed data in an extra buffer, 177 // starting with a prefix. 178 Some(try_to_vec(CONFIRMATION_DATA_PREFIX)?) 179 } else { 180 None 181 }; 182 183 let slot_to_delete = if let Some(&1) = get_opt_tag_value!(key_chars, UsageCountLimit)? { 184 warn!("single-use key will be deleted on operation completion"); 185 sdd_slot 186 } else { 187 None 188 }; 189 190 // At most one operation involving proof of user presence can be in-flight at a time. 191 let presence_required = get_bool_tag_value!(key_chars, TrustedUserPresenceRequired)?; 192 if presence_required && self.presence_required_op.is_some() { 193 return Err(km_err!( 194 ConcurrentProofOfPresenceRequested, 195 "additional op with proof-of-presence requested" 196 )); 197 } 198 199 let mut op_auth_info = AuthInfo::new(key_chars)?; 200 if let Some(auth_info) = &op_auth_info { 201 // Authentication checks are required on begin() if there's a timeout that 202 // we can check. 203 if let Some(timeout_secs) = auth_info.timeout_secs { 204 if let Some(clock) = &self.imp.clock { 205 let now: Timestamp = clock.now().into(); 206 let auth_token = auth_token.ok_or_else(|| { 207 km_err!(KeyUserNotAuthenticated, "no auth token on begin()") 208 })?; 209 self.check_auth_token( 210 auth_token, 211 auth_info, 212 Some(now), 213 Some(timeout_secs), 214 None, 215 )?; 216 217 // Auth already checked, nothing needed on subsequent calls 218 op_auth_info = None; 219 } else if let Some(auth_token) = auth_token { 220 self.check_auth_token(auth_token, auth_info, None, None, None)?; 221 } 222 } 223 } 224 225 // Re-use the same random value for both: 226 // - op_handle: the way to identify which operation is involved 227 // - challenge: the value used as part of the input for authentication tokens 228 let op_handle = self.new_op_handle(); 229 let challenge = op_handle.0; 230 let mut ret_params = Vec::new(); 231 let op = match key_material { 232 KeyMaterial::Aes(key) => { 233 let caller_nonce = get_opt_tag_value!(¶ms, Nonce)?; 234 let mode = aes::Mode::new(¶ms, caller_nonce, &mut *self.imp.rng)?; 235 let dir = match purpose { 236 KeyPurpose::Encrypt => crypto::SymmetricOperation::Encrypt, 237 KeyPurpose::Decrypt => crypto::SymmetricOperation::Decrypt, 238 _ => { 239 return Err(km_err!( 240 IncompatiblePurpose, 241 "invalid purpose {:?} for AES key", 242 purpose 243 )) 244 } 245 }; 246 if caller_nonce.is_none() { 247 // Need to return any randomly-generated nonce to the caller. 248 match &mode { 249 aes::Mode::Cipher(aes::CipherMode::EcbNoPadding) 250 | aes::Mode::Cipher(aes::CipherMode::EcbPkcs7Padding) => {} 251 aes::Mode::Cipher(aes::CipherMode::CbcNoPadding { nonce: n }) 252 | aes::Mode::Cipher(aes::CipherMode::CbcPkcs7Padding { nonce: n }) => { 253 ret_params.try_push(KeyParam::Nonce(try_to_vec(n)?))? 254 } 255 aes::Mode::Cipher(aes::CipherMode::Ctr { nonce: n }) => { 256 ret_params.try_push(KeyParam::Nonce(try_to_vec(n)?))? 257 } 258 aes::Mode::Aead(aes::GcmMode::GcmTag12 { nonce: n }) 259 | aes::Mode::Aead(aes::GcmMode::GcmTag13 { nonce: n }) 260 | aes::Mode::Aead(aes::GcmMode::GcmTag14 { nonce: n }) 261 | aes::Mode::Aead(aes::GcmMode::GcmTag15 { nonce: n }) 262 | aes::Mode::Aead(aes::GcmMode::GcmTag16 { nonce: n }) => { 263 ret_params.try_push(KeyParam::Nonce(try_to_vec(n)?))? 264 } 265 } 266 } 267 match &mode { 268 aes::Mode::Cipher(mode) => Operation { 269 handle: op_handle, 270 aad_allowed: false, 271 input_size: 0, 272 slot_to_delete, 273 trusted_conf_data, 274 auth_info: op_auth_info, 275 crypto_op: CryptoOperation::Aes(self.imp.aes.begin(key, *mode, dir)?), 276 }, 277 aes::Mode::Aead(mode) => Operation { 278 handle: op_handle, 279 aad_allowed: true, 280 input_size: 0, 281 slot_to_delete, 282 trusted_conf_data, 283 auth_info: op_auth_info, 284 crypto_op: CryptoOperation::AesGcm( 285 self.imp.aes.begin_aead(key, *mode, dir)?, 286 ), 287 }, 288 } 289 } 290 KeyMaterial::TripleDes(key) => { 291 let caller_nonce = get_opt_tag_value!(¶ms, Nonce)?; 292 let mode = crypto::des::Mode::new(¶ms, caller_nonce, &mut *self.imp.rng)?; 293 let dir = match purpose { 294 KeyPurpose::Encrypt => crypto::SymmetricOperation::Encrypt, 295 KeyPurpose::Decrypt => crypto::SymmetricOperation::Decrypt, 296 _ => { 297 return Err(km_err!( 298 IncompatiblePurpose, 299 "invalid purpose {:?} for DES key", 300 purpose 301 )) 302 } 303 }; 304 if caller_nonce.is_none() { 305 // Need to return any randomly-generated nonce to the caller. 306 match &mode { 307 crypto::des::Mode::EcbNoPadding | crypto::des::Mode::EcbPkcs7Padding => {} 308 crypto::des::Mode::CbcNoPadding { nonce: n } 309 | crypto::des::Mode::CbcPkcs7Padding { nonce: n } => { 310 ret_params.try_push(KeyParam::Nonce(try_to_vec(n)?))? 311 } 312 } 313 } 314 Operation { 315 handle: op_handle, 316 aad_allowed: false, 317 input_size: 0, 318 slot_to_delete, 319 trusted_conf_data, 320 auth_info: op_auth_info, 321 crypto_op: CryptoOperation::Des(self.imp.des.begin(key, mode, dir)?), 322 } 323 } 324 KeyMaterial::Hmac(key) => { 325 let digest = tag::get_digest(¶ms)?; 326 327 Operation { 328 handle: op_handle, 329 aad_allowed: false, 330 input_size: 0, 331 slot_to_delete, 332 trusted_conf_data, 333 auth_info: op_auth_info, 334 crypto_op: match purpose { 335 KeyPurpose::Sign => { 336 let tag_len = 337 get_tag_value!(¶ms, MacLength, ErrorCode::MissingMacLength)? 338 as usize 339 / 8; 340 CryptoOperation::HmacSign(self.imp.hmac.begin(key, digest)?, tag_len) 341 } 342 KeyPurpose::Verify => { 343 // Remember the acceptable tag lengths. 344 let min_tag_len = get_tag_value!( 345 key_chars, 346 MinMacLength, 347 ErrorCode::MissingMinMacLength 348 )? as usize 349 / 8; 350 let max_tag_len = kmr_common::tag::digest_len(digest)? as usize; 351 CryptoOperation::HmacVerify( 352 self.imp.hmac.begin(key, digest)?, 353 min_tag_len..max_tag_len, 354 ) 355 } 356 _ => { 357 return Err(km_err!( 358 IncompatiblePurpose, 359 "invalid purpose {:?} for HMAC key", 360 purpose 361 )) 362 } 363 }, 364 } 365 } 366 KeyMaterial::Rsa(key) => Operation { 367 handle: op_handle, 368 aad_allowed: false, 369 input_size: 0, 370 slot_to_delete, 371 trusted_conf_data, 372 auth_info: op_auth_info, 373 crypto_op: match purpose { 374 KeyPurpose::Decrypt => { 375 let mode = crypto::rsa::DecryptionMode::new(¶ms)?; 376 CryptoOperation::RsaDecrypt(self.imp.rsa.begin_decrypt(key, mode)?) 377 } 378 KeyPurpose::Sign => { 379 let mode = crypto::rsa::SignMode::new(¶ms)?; 380 CryptoOperation::RsaSign(self.imp.rsa.begin_sign(key, mode)?) 381 } 382 _ => { 383 return Err(km_err!( 384 IncompatiblePurpose, 385 "invalid purpose {:?} for RSA key", 386 purpose 387 )) 388 } 389 }, 390 }, 391 KeyMaterial::Ec(_, _, key) => Operation { 392 handle: op_handle, 393 aad_allowed: false, 394 input_size: 0, 395 slot_to_delete, 396 trusted_conf_data, 397 auth_info: op_auth_info, 398 crypto_op: match purpose { 399 KeyPurpose::AgreeKey => CryptoOperation::EcAgree(self.imp.ec.begin_agree(key)?), 400 KeyPurpose::Sign => { 401 let digest = tag::get_digest(¶ms)?; 402 CryptoOperation::EcSign(self.imp.ec.begin_sign(key, digest)?) 403 } 404 _ => { 405 return Err(km_err!( 406 IncompatiblePurpose, 407 "invalid purpose {:?} for EC key", 408 purpose 409 )) 410 } 411 }, 412 }, 413 }; 414 self.operations[op_idx] = Some(op); 415 if presence_required { 416 info!("this operation requires proof-of-presence"); 417 self.presence_required_op = Some(op_handle); 418 } 419 Ok(InternalBeginResult { challenge, params: ret_params, op_handle: op_handle.0 }) 420 } 421 op_update_aad( &mut self, op_handle: OpHandle, data: &[u8], auth_token: Option<HardwareAuthToken>, timestamp_token: Option<TimeStampToken>, ) -> Result<(), Error>422 pub(crate) fn op_update_aad( 423 &mut self, 424 op_handle: OpHandle, 425 data: &[u8], 426 auth_token: Option<HardwareAuthToken>, 427 timestamp_token: Option<TimeStampToken>, 428 ) -> Result<(), Error> { 429 self.with_authed_operation(op_handle, auth_token, timestamp_token, |op| { 430 if !op.aad_allowed { 431 return Err(km_err!(InvalidTag, "update-aad not allowed")); 432 } 433 match &mut op.crypto_op { 434 CryptoOperation::AesGcm(op) => op.update_aad(data), 435 _ => Err(km_err!(InvalidOperation, "operation does not support update_aad")), 436 } 437 }) 438 } 439 op_update( &mut self, op_handle: OpHandle, data: &[u8], auth_token: Option<HardwareAuthToken>, timestamp_token: Option<TimeStampToken>, ) -> Result<Vec<u8>, Error>440 pub(crate) fn op_update( 441 &mut self, 442 op_handle: OpHandle, 443 data: &[u8], 444 auth_token: Option<HardwareAuthToken>, 445 timestamp_token: Option<TimeStampToken>, 446 ) -> Result<Vec<u8>, Error> { 447 let check_presence = if self.presence_required_op == Some(op_handle) { 448 self.presence_required_op = None; 449 true 450 } else { 451 false 452 }; 453 self.with_authed_operation(op_handle, auth_token, timestamp_token, |op| { 454 if check_presence && !self.dev.tup.available() { 455 return Err(km_err!( 456 ProofOfPresenceRequired, 457 "trusted proof of presence required but not available" 458 )); 459 } 460 if let Some(trusted_conf_data) = &mut op.trusted_conf_data { 461 if trusted_conf_data.len() + data.len() 462 > CONFIRMATION_DATA_PREFIX.len() + CONFIRMATION_MESSAGE_MAX_LEN 463 { 464 return Err(km_err!( 465 InvalidArgument, 466 "trusted confirmation data of size {} + {} too big", 467 trusted_conf_data.len(), 468 data.len() 469 )); 470 } 471 trusted_conf_data.try_extend_from_slice(data)?; 472 } 473 op.aad_allowed = false; 474 op.check_size(data.len())?; 475 match &mut op.crypto_op { 476 CryptoOperation::Aes(op) => op.update(data), 477 CryptoOperation::AesGcm(op) => op.update(data), 478 CryptoOperation::Des(op) => op.update(data), 479 CryptoOperation::HmacSign(op, _) | CryptoOperation::HmacVerify(op, _) => { 480 op.update(data)?; 481 Ok(Vec::new()) 482 } 483 CryptoOperation::RsaDecrypt(op) => { 484 op.update(data)?; 485 Ok(Vec::new()) 486 } 487 CryptoOperation::RsaSign(op) => { 488 op.update(data)?; 489 Ok(Vec::new()) 490 } 491 CryptoOperation::EcAgree(op) => { 492 op.update(data)?; 493 Ok(Vec::new()) 494 } 495 CryptoOperation::EcSign(op) => { 496 op.update(data)?; 497 Ok(Vec::new()) 498 } 499 } 500 }) 501 } 502 op_finish( &mut self, op_handle: OpHandle, data: Option<&[u8]>, signature: Option<&[u8]>, auth_token: Option<HardwareAuthToken>, timestamp_token: Option<TimeStampToken>, confirmation_token: Option<&[u8]>, ) -> Result<Vec<u8>, Error>503 pub(crate) fn op_finish( 504 &mut self, 505 op_handle: OpHandle, 506 data: Option<&[u8]>, 507 signature: Option<&[u8]>, 508 auth_token: Option<HardwareAuthToken>, 509 timestamp_token: Option<TimeStampToken>, 510 confirmation_token: Option<&[u8]>, 511 ) -> Result<Vec<u8>, Error> { 512 let mut op = self.take_operation(op_handle)?; 513 self.check_subsequent_auth(&op, auth_token, timestamp_token)?; 514 515 if self.presence_required_op == Some(op_handle) { 516 self.presence_required_op = None; 517 if !self.dev.tup.available() { 518 return Err(km_err!( 519 ProofOfPresenceRequired, 520 "trusted proof of presence required but not available" 521 )); 522 } 523 } 524 if let (Some(trusted_conf_data), Some(data)) = (&mut op.trusted_conf_data, data) { 525 if trusted_conf_data.len() + data.len() 526 > CONFIRMATION_DATA_PREFIX.len() + CONFIRMATION_MESSAGE_MAX_LEN 527 { 528 return Err(km_err!( 529 InvalidArgument, 530 "data of size {} + {} too big", 531 trusted_conf_data.len(), 532 data.len() 533 )); 534 } 535 trusted_conf_data.try_extend_from_slice(data)?; 536 } 537 538 op.check_size(data.map_or(0, |v| v.len()))?; 539 let result = match op.crypto_op { 540 CryptoOperation::Aes(mut op) => { 541 let mut result = if let Some(data) = data { op.update(data)? } else { Vec::new() }; 542 result.try_extend_from_slice(&op.finish()?)?; 543 Ok(result) 544 } 545 CryptoOperation::AesGcm(mut op) => { 546 let mut result = if let Some(data) = data { op.update(data)? } else { Vec::new() }; 547 result.try_extend_from_slice(&op.finish()?)?; 548 Ok(result) 549 } 550 CryptoOperation::Des(mut op) => { 551 let mut result = if let Some(data) = data { op.update(data)? } else { Vec::new() }; 552 result.try_extend_from_slice(&op.finish()?)?; 553 Ok(result) 554 } 555 CryptoOperation::HmacSign(mut op, tag_len) => { 556 if let Some(data) = data { 557 op.update(data)?; 558 }; 559 let mut tag = op.finish()?; 560 tag.truncate(tag_len); 561 Ok(tag) 562 } 563 CryptoOperation::HmacVerify(mut op, tag_len_range) => { 564 let sig = signature 565 .ok_or_else(|| km_err!(InvalidArgument, "signature missing for HMAC verify"))?; 566 if !tag_len_range.contains(&sig.len()) { 567 return Err(km_err!( 568 InvalidArgument, 569 "signature length invalid: {} not in {:?}", 570 sig.len(), 571 tag_len_range 572 )); 573 } 574 575 if let Some(data) = data { 576 op.update(data)?; 577 }; 578 let got = op.finish()?; 579 580 if self.imp.compare.eq(&got[..sig.len()], sig) { 581 Ok(Vec::new()) 582 } else { 583 Err(km_err!(VerificationFailed, "HMAC verify failed")) 584 } 585 } 586 CryptoOperation::RsaDecrypt(mut op) => { 587 if let Some(data) = data { 588 op.update(data)?; 589 }; 590 op.finish() 591 } 592 CryptoOperation::RsaSign(mut op) => { 593 if let Some(data) = data { 594 op.update(data)?; 595 }; 596 op.finish() 597 } 598 CryptoOperation::EcAgree(mut op) => { 599 if let Some(data) = data { 600 op.update(data)?; 601 }; 602 op.finish() 603 } 604 CryptoOperation::EcSign(mut op) => { 605 if let Some(data) = data { 606 op.update(data)?; 607 }; 608 op.finish() 609 } 610 }; 611 if result.is_ok() { 612 if let Some(trusted_conf_data) = op.trusted_conf_data { 613 // Accumulated input must be checked against the trusted confirmation token. 614 self.verify_confirmation_token(&trusted_conf_data, confirmation_token)?; 615 } 616 if let (Some(slot), Some(sdd_mgr)) = (op.slot_to_delete, &mut self.dev.sdd_mgr) { 617 // A successful use of a key with UsageCountLimit(1) triggers deletion. 618 warn!("Deleting single-use key after use"); 619 if let Err(e) = sdd_mgr.delete_secret(slot) { 620 error!("Failed to delete single-use key after use: {:?}", e); 621 } 622 } 623 } 624 result 625 } 626 op_abort(&mut self, op_handle: OpHandle) -> Result<(), Error>627 pub(crate) fn op_abort(&mut self, op_handle: OpHandle) -> Result<(), Error> { 628 if self.presence_required_op == Some(op_handle) { 629 self.presence_required_op = None; 630 } 631 let _op = self.take_operation(op_handle)?; 632 Ok(()) 633 } 634 635 /// Check TA-specific key authorizations on `begin()`. check_begin_auths(&mut self, key_chars: &[KeyParam], key_blob: &[u8]) -> Result<(), Error>636 fn check_begin_auths(&mut self, key_chars: &[KeyParam], key_blob: &[u8]) -> Result<(), Error> { 637 if self.dev.bootloader.done() && get_bool_tag_value!(key_chars, BootloaderOnly)? { 638 return Err(km_err!( 639 InvalidKeyBlob, 640 "attempt to use bootloader-only key after bootloader done" 641 )); 642 } 643 if !self.in_early_boot && get_bool_tag_value!(key_chars, EarlyBootOnly)? { 644 return Err(km_err!(EarlyBootEnded, "attempt to use EARLY_BOOT key after early boot")); 645 } 646 647 if let Some(max_uses) = get_opt_tag_value!(key_chars, MaxUsesPerBoot)? { 648 // Track the use count for this key. 649 let key_id = self.key_id(key_blob)?; 650 self.update_use_count(key_id, *max_uses)?; 651 } 652 Ok(()) 653 } 654 655 /// Validate a `[keymint::HardwareAuthToken`]. check_auth_token( &self, auth_token: HardwareAuthToken, auth_info: &AuthInfo, now: Option<Timestamp>, timeout_secs: Option<u32>, challenge: Option<i64>, ) -> Result<HardwareAuthenticatedToken, Error>656 fn check_auth_token( 657 &self, 658 auth_token: HardwareAuthToken, 659 auth_info: &AuthInfo, 660 now: Option<Timestamp>, 661 timeout_secs: Option<u32>, 662 challenge: Option<i64>, 663 ) -> Result<HardwareAuthenticatedToken, Error> { 664 // Common check: confirm the HMAC tag in the token is valid. 665 let mac_input = crate::hardware_auth_token_mac_input(&auth_token)?; 666 if !self.verify_device_hmac(&mac_input, &auth_token.mac)? { 667 return Err(km_err!(KeyUserNotAuthenticated, "failed to authenticate auth_token")); 668 } 669 // Common check: token's auth type should match key's USER_AUTH_TYPE. 670 if (auth_token.authenticator_type as u32 & auth_info.auth_type) == 0 { 671 return Err(km_err!( 672 KeyUserNotAuthenticated, 673 "token auth type {:?} doesn't overlap with key auth type {:?}", 674 auth_token.authenticator_type, 675 auth_info.auth_type, 676 )); 677 } 678 679 // Common check: token's authenticator or user ID should match key's USER_SECURE_ID. 680 if !auth_info.secure_ids.iter().any(|sid| { 681 auth_token.user_id == *sid as i64 || auth_token.authenticator_id == *sid as i64 682 }) { 683 return Err(km_err!( 684 KeyUserNotAuthenticated, 685 "neither user id {:?} nor authenticator id {:?} matches key", 686 auth_token.user_id, 687 auth_token.authenticator_id 688 )); 689 } 690 691 // Optional check: token is in time range. 692 if let (Some(now), Some(timeout_secs)) = (now, timeout_secs) { 693 if now.milliseconds > auth_token.timestamp.milliseconds + 1000 * timeout_secs as i64 { 694 return Err(km_err!( 695 KeyUserNotAuthenticated, 696 "now {:?} is later than auth token time {:?} + {} seconds", 697 now, 698 auth_token.timestamp, 699 timeout_secs, 700 )); 701 } 702 } 703 704 // Optional check: challenge matches. 705 if let Some(challenge) = challenge { 706 if auth_token.challenge != challenge { 707 return Err(km_err!(KeyUserNotAuthenticated, "challenge mismatch")); 708 } 709 } 710 let auth_token = HardwareAuthenticatedToken(auth_token); 711 712 // The accompanying auth token may trigger an unlock, regardless of whether the operation 713 // succeeds. 714 self.maybe_unlock(&auth_token); 715 Ok(auth_token) 716 } 717 718 /// Update the device unlock state based on a possible hardware auth token. maybe_unlock(&self, auth_token: &HardwareAuthenticatedToken)719 fn maybe_unlock(&self, auth_token: &HardwareAuthenticatedToken) { 720 // This auth token may or may not indicate an unlock. It's not an error if 721 // it doesn't, though. 722 let (locked, lock_time, need_password) = match *self.device_locked.borrow() { 723 LockState::Unlocked => (false, secureclock::Timestamp { milliseconds: 0 }, false), 724 LockState::LockedSince(t) => (true, t, false), 725 LockState::PasswordLockedSince(t) => (true, t, true), 726 }; 727 728 if locked 729 && auth_token.0.timestamp.milliseconds >= lock_time.milliseconds 730 && (!need_password 731 || ((auth_token.0.authenticator_type as u32) 732 & (HardwareAuthenticatorType::Password as u32) 733 != 0)) 734 { 735 info!("auth token indicates device unlocked"); 736 *self.device_locked.borrow_mut() = LockState::Unlocked; 737 } 738 } 739 740 /// Verify that an optional confirmation token matches the provided `data`. verify_confirmation_token(&self, data: &[u8], token: Option<&[u8]>) -> Result<(), Error>741 fn verify_confirmation_token(&self, data: &[u8], token: Option<&[u8]>) -> Result<(), Error> { 742 if let Some(token) = token { 743 if token.len() != CONFIRMATION_TOKEN_SIZE { 744 return Err(km_err!( 745 InvalidArgument, 746 "confirmation token wrong length {}", 747 token.len() 748 )); 749 } 750 if self.verify_device_hmac(data, token).map_err(|e| { 751 km_err!(UnknownError, "failed to perform HMAC on confirmation token: {:?}", e) 752 })? { 753 Ok(()) 754 } else { 755 Err(km_err!(NoUserConfirmation, "trusted confirmation token did not match")) 756 } 757 } else { 758 Err(km_err!(NoUserConfirmation, "no trusted confirmation token provided")) 759 } 760 } 761 762 /// Return the index of a free slot in the operations table. new_operation_index(&mut self) -> Result<usize, Error>763 fn new_operation_index(&mut self) -> Result<usize, Error> { 764 self.operations.iter().position(Option::is_none).ok_or_else(|| { 765 km_err!(TooManyOperations, "current op count {} >= limit", self.operations.len()) 766 }) 767 } 768 769 /// Return a new operation handle value that is not currently in use in the 770 /// operations table. new_op_handle(&mut self) -> OpHandle771 fn new_op_handle(&mut self) -> OpHandle { 772 loop { 773 let op_handle = OpHandle(self.imp.rng.next_u64() as i64); 774 if self.op_index(op_handle).is_err() { 775 return op_handle; 776 } 777 // op_handle already in use, go around again. 778 } 779 } 780 781 /// Return the index into the operations table of an operation identified by `op_handle`. op_index(&self, op_handle: OpHandle) -> Result<usize, Error>782 fn op_index(&self, op_handle: OpHandle) -> Result<usize, Error> { 783 self.operations 784 .iter() 785 .position(|op| match op { 786 Some(op) if op.handle == op_handle => true, 787 Some(_op) => false, 788 None => false, 789 }) 790 .ok_or_else(|| km_err!(InvalidOperation, "operation handle {:?} not found", op_handle)) 791 } 792 793 /// Execute the provided lambda over the associated [`Operation`], handling 794 /// errors. with_authed_operation<F, T>( &mut self, op_handle: OpHandle, auth_token: Option<HardwareAuthToken>, timestamp_token: Option<TimeStampToken>, f: F, ) -> Result<T, Error> where F: FnOnce(&mut Operation) -> Result<T, Error>,795 fn with_authed_operation<F, T>( 796 &mut self, 797 op_handle: OpHandle, 798 auth_token: Option<HardwareAuthToken>, 799 timestamp_token: Option<TimeStampToken>, 800 f: F, 801 ) -> Result<T, Error> 802 where 803 F: FnOnce(&mut Operation) -> Result<T, Error>, 804 { 805 let op_idx = self.op_index(op_handle)?; 806 let check_again = self.check_subsequent_auth( 807 self.operations[op_idx].as_ref().unwrap(/* safe: op_index() checks */ ), 808 auth_token, 809 timestamp_token, 810 )?; 811 let op = self.operations[op_idx].as_mut().unwrap(/* safe: op_index() checks */); 812 if !check_again { 813 op.auth_info = None; 814 } 815 let result = f(op); 816 if result.is_err() { 817 // A failure destroys the operation. 818 if self.presence_required_op == Some(op_handle) { 819 self.presence_required_op = None; 820 } 821 self.operations[op_idx] = None; 822 } 823 result 824 } 825 826 /// Return the associated [`Operation`], removing it. take_operation(&mut self, op_handle: OpHandle) -> Result<Operation, Error>827 fn take_operation(&mut self, op_handle: OpHandle) -> Result<Operation, Error> { 828 let op_idx = self.op_index(op_handle)?; 829 Ok(self.operations[op_idx].take().unwrap(/* safe: op_index() checks */)) 830 } 831 832 /// Check authentication for an operation that has already begun. Returns an indication as to 833 /// whether future invocations also need to check authentication. check_subsequent_auth( &self, op: &Operation, auth_token: Option<HardwareAuthToken>, timestamp_token: Option<TimeStampToken>, ) -> Result<bool, Error>834 fn check_subsequent_auth( 835 &self, 836 op: &Operation, 837 auth_token: Option<HardwareAuthToken>, 838 timestamp_token: Option<TimeStampToken>, 839 ) -> Result<bool, Error> { 840 if let Some(auth_info) = &op.auth_info { 841 let auth_token = auth_token.ok_or_else(|| { 842 km_err!(KeyUserNotAuthenticated, "no auth token on subsequent op") 843 })?; 844 845 // Most auth checks happen on begin(), but there are two exceptions. 846 // a) There is no AUTH_TIMEOUT: there should be a valid auth token on every invocation. 847 // b) There is an AUTH_TIMEOUT but we have no clock: the first invocation on the 848 // operation (after `begin()`) should check the timeout, based on a provided 849 // timestamp token. 850 if let Some(timeout_secs) = auth_info.timeout_secs { 851 if self.imp.clock.is_some() { 852 return Err(km_err!( 853 UnknownError, 854 "attempt to check auth timeout after begin() on device with clock!" 855 )); 856 } 857 858 // Check that the timestamp token is valid. 859 let timestamp_token = timestamp_token 860 .ok_or_else(|| km_err!(InvalidArgument, "no timestamp token provided"))?; 861 if timestamp_token.challenge != op.handle.0 { 862 return Err(km_err!(InvalidArgument, "timestamp challenge mismatch")); 863 } 864 let mac_input = crate::clock::timestamp_token_mac_input(×tamp_token)?; 865 if !self.verify_device_hmac(&mac_input, ×tamp_token.mac)? { 866 return Err(km_err!(InvalidArgument, "timestamp MAC not verified")); 867 } 868 869 self.check_auth_token( 870 auth_token, 871 auth_info, 872 Some(timestamp_token.timestamp), 873 Some(timeout_secs), 874 Some(op.handle.0), 875 )?; 876 877 // No need to check again. 878 Ok(false) 879 } else { 880 self.check_auth_token(auth_token, auth_info, None, None, Some(op.handle.0))?; 881 // Check on every invocation 882 Ok(true) 883 } 884 } else { 885 Ok(false) 886 } 887 } 888 } 889