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