|
4 | 4 | //! Implementation of pseudo TAs (PTAs) which export system services as |
5 | 5 | //! the functions of built-in TAs. |
6 | 6 |
|
| 7 | +use crate::syscalls::Cleanup; |
7 | 8 | use crate::{Task, UserConstPtr, UserMutPtr}; |
8 | 9 | use alloc::vec; |
9 | 10 | use alloc::vec::Vec; |
10 | 11 | use hmac::{Hmac, Mac}; |
| 12 | +use litebox::mm::linux::PAGE_SIZE; |
11 | 13 | use litebox::platform::{ |
12 | 14 | DerivedKeyError, DerivedKeyProvider, KDFParams, RawConstPointer as _, RawMutPointer as _, |
13 | 15 | }; |
14 | 16 | use litebox::utils::TruncateExt; |
15 | 17 | use litebox_common_optee::{ |
16 | | - HUK_SUBKEY_MAX_LEN, HukSubkeyUsage, TaFlags, TeeParamType, TeeResult, TeeUuid, UteeParams, |
| 18 | + HUK_SUBKEY_MAX_LEN, HukSubkeyUsage, LdelfMapFlags, TaFlags, TeeParamType, TeeResult, TeeUuid, |
| 19 | + UteeParams, |
17 | 20 | }; |
18 | 21 | use num_enum::TryFromPrimitive; |
19 | 22 | use sha2::Sha256; |
@@ -48,8 +51,8 @@ impl PseudoTa { |
48 | 51 | self, |
49 | 52 | task: &Task, |
50 | 53 | cmd_id: u32, |
51 | | - params: &UteeParams, |
52 | | - ) -> Result<(), TeeResult> { |
| 54 | + params: &mut UteeParams, |
| 55 | + ) -> Result<Cleanup, TeeResult> { |
53 | 56 | let _busy = task.try_set_busy(self)?; |
54 | 57 | match self { |
55 | 58 | Self::System => SystemPta::invoke_command(task, cmd_id, params), |
@@ -235,10 +238,19 @@ impl SystemPta { |
235 | 238 | } |
236 | 239 |
|
237 | 240 | /// Handle a command of the system PTA. |
238 | | - fn invoke_command(task: &Task, cmd_id: u32, params: &UteeParams) -> Result<(), TeeResult> { |
239 | | - #[allow(clippy::single_match_else)] |
| 241 | + /// |
| 242 | + /// See `Cleanup` for the returned rollback; most commands have no cleanup. |
| 243 | + fn invoke_command( |
| 244 | + task: &Task, |
| 245 | + cmd_id: u32, |
| 246 | + params: &mut UteeParams, |
| 247 | + ) -> Result<Cleanup, TeeResult> { |
240 | 248 | match PtaSystemCommandId::try_from(cmd_id).map_err(|_| TeeResult::BadParameters)? { |
241 | | - PtaSystemCommandId::DeriveTaUniqueKey => Self::derive_ta_unique_key(task, params), |
| 249 | + PtaSystemCommandId::DeriveTaUniqueKey => { |
| 250 | + Self::derive_ta_unique_key(task, params).map(|()| Cleanup::None) |
| 251 | + } |
| 252 | + PtaSystemCommandId::MapZi => Self::map_zi(task, params), |
| 253 | + PtaSystemCommandId::Unmap => Self::unmap(task, params).map(|()| Cleanup::None), |
242 | 254 | _ => { |
243 | 255 | #[cfg(debug_assertions)] |
244 | 256 | todo!("support other system PTA commands {cmd_id}"); |
@@ -346,6 +358,81 @@ impl SystemPta { |
346 | 358 |
|
347 | 359 | Ok(()) |
348 | 360 | } |
| 361 | + |
| 362 | + fn map_zi(task: &Task, params: &mut UteeParams) -> Result<Cleanup, TeeResult> { |
| 363 | + use TeeParamType::{None, ValueInout, ValueInput}; |
| 364 | + |
| 365 | + if !params.has_types([ValueInput, ValueInout, ValueInput, None]) { |
| 366 | + return Err(TeeResult::BadParameters); |
| 367 | + } |
| 368 | + |
| 369 | + let (num_bytes, flags) = params |
| 370 | + .get_values(0) |
| 371 | + .map_err(|_| TeeResult::BadParameters)? |
| 372 | + .ok_or(TeeResult::BadParameters)?; |
| 373 | + if num_bytes == 0 { |
| 374 | + return Err(TeeResult::BadParameters); |
| 375 | + } |
| 376 | + let (addr_high, addr_low) = params |
| 377 | + .get_values(1) |
| 378 | + .map_err(|_| TeeResult::BadParameters)? |
| 379 | + .ok_or(TeeResult::BadParameters)?; |
| 380 | + let (pad_begin, pad_end) = params |
| 381 | + .get_values(2) |
| 382 | + .map_err(|_| TeeResult::BadParameters)? |
| 383 | + .ok_or(TeeResult::BadParameters)?; |
| 384 | + |
| 385 | + if addr_high & 0xffff_ffff_0000_0000 != 0 || addr_low & 0xffff_ffff_0000_0000 != 0 { |
| 386 | + return Err(TeeResult::BadParameters); |
| 387 | + } |
| 388 | + let addr: usize = ((addr_high << 32) | addr_low).trunc(); |
| 389 | + let (mapped, cleanup) = task.sys_map_zi( |
| 390 | + addr, |
| 391 | + num_bytes.trunc(), |
| 392 | + pad_begin.trunc(), |
| 393 | + pad_end.trunc(), |
| 394 | + LdelfMapFlags::from_bits_retain(flags.trunc()), |
| 395 | + )?; |
| 396 | + |
| 397 | + // Return the mapped address to the caller via the inout value param. |
| 398 | + // This `set_values` cannot fail because the index is fixed/known. |
| 399 | + let _ = params.set_values(1, (mapped as u64) >> 32, (mapped as u64) & 0xffff_ffff); |
| 400 | + |
| 401 | + // The caller runs `cleanup` (unmap) if it encounters an error. |
| 402 | + Ok(cleanup) |
| 403 | + } |
| 404 | + |
| 405 | + fn unmap(task: &Task, params: &UteeParams) -> Result<(), TeeResult> { |
| 406 | + use TeeParamType::{None, ValueInput}; |
| 407 | + |
| 408 | + if !params.has_types([ValueInput, ValueInput, None, None]) { |
| 409 | + return Err(TeeResult::BadParameters); |
| 410 | + } |
| 411 | + |
| 412 | + let (size, must_be_zero) = params |
| 413 | + .get_values(0) |
| 414 | + .map_err(|_| TeeResult::BadParameters)? |
| 415 | + .ok_or(TeeResult::BadParameters)?; |
| 416 | + if must_be_zero != 0 { |
| 417 | + return Err(TeeResult::BadParameters); |
| 418 | + } |
| 419 | + let (addr_high, addr_low) = params |
| 420 | + .get_values(1) |
| 421 | + .map_err(|_| TeeResult::BadParameters)? |
| 422 | + .ok_or(TeeResult::BadParameters)?; |
| 423 | + |
| 424 | + if addr_high & 0xffff_ffff_0000_0000 != 0 || addr_low & 0xffff_ffff_0000_0000 != 0 { |
| 425 | + return Err(TeeResult::BadParameters); |
| 426 | + } |
| 427 | + let addr: usize = ((addr_high << 32) | addr_low).trunc(); |
| 428 | + let size: usize = size.trunc(); |
| 429 | + let size = size |
| 430 | + .checked_next_multiple_of(PAGE_SIZE) |
| 431 | + .ok_or(TeeResult::BadParameters)?; |
| 432 | + |
| 433 | + task.sys_munmap(UserMutPtr::<u8>::from_usize(addr), size) |
| 434 | + .map_err(|_| TeeResult::BadParameters) |
| 435 | + } |
349 | 436 | } |
350 | 437 |
|
351 | 438 | /// A KDF callback that derives a subkey from `huk` and `params.context` to be passed to |
|
0 commit comments