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