Skip to content

Commit a266932

Browse files
committed
Improved FapiContext::create_seal() to accept either a non-empty '&[u8]' slice or a 'NonZeroUsize' value.
1 parent c359832 commit a266932

File tree

10 files changed

+227
-92
lines changed

10 files changed

+227
-92
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file.
44

55
The format is based on [Keep a Changelog](http://keepachangelog.com/).
66

7+
## [0.12.0] - 2026-01-22
8+
9+
### Changed
10+
11+
- Improved `FapiContext::create_seal()` to accept either a non-empty `&[u8]` slice or a `NonZeroUsize` value.
12+
- Various improvements to internal memory handling.
13+
714
## [0.11.0] - 2026-01-21
815

916
### Changed

Cargo.lock

Lines changed: 3 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "tss2-fapi-rs"
3-
version = "0.11.0"
3+
version = "0.12.0"
44
edition = "2024"
55
rust-version = "1.85"
66
description = "Provides a Rust interface to the TSS2.0 Feature API (FAPI)"
@@ -16,7 +16,6 @@ full_locking = ["locking"]
1616

1717
[dependencies]
1818
json = "0.12.4"
19-
libc = "0.2.180"
2019
log = "0.4.29"
2120

2221
[build-dependencies]

src/callback.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
use super::{
88
HashAlgorithm,
99
fapi_sys::TPM2_ALG_ID,
10-
memory::{CDataHolder, CStringHolder, CStringPointer, RawSlice},
10+
memory::{CBinaryHolder, CStringHolder, CStringPointer, RawSlice},
1111
};
1212
use log::trace;
1313
use std::{any::Any, borrow::Cow, ffi::CStr, fmt::Debug, sync::Mutex};
@@ -322,7 +322,7 @@ enum TemporaryData {
322322
#[default]
323323
Empty,
324324
String(CStringHolder),
325-
Data(CDataHolder),
325+
Data(CBinaryHolder),
326326
}
327327

328328
impl TemporaryData {
@@ -334,10 +334,10 @@ impl TemporaryData {
334334
}
335335
}
336336

337-
fn set_data(&mut self, data: CDataHolder) -> RawSlice {
337+
fn set_data(&mut self, data: CBinaryHolder) -> RawSlice {
338338
*self = Self::Data(data);
339339
match self {
340-
TemporaryData::Data(data_ref) => data_ref.as_ptr(),
340+
TemporaryData::Data(data_ref) => data_ref.as_slice(),
341341
_ => unreachable!(),
342342
}
343343
}
@@ -414,7 +414,7 @@ impl CallbackManager {
414414
let mut lock = self.0.lock().unwrap();
415415
let param = SignCbParam::new(object_path, description, public_key, key_hint, hash_algo, challenge);
416416
trace!("Callbacks::sign_cb({:?})", &param);
417-
lock.callbacks.sign_cb(param).and_then(|data| CDataHolder::try_from(data).ok()).map(|value| lock.temp.set_data(value))
417+
lock.callbacks.sign_cb(param).and_then(|data| CBinaryHolder::try_from(data).ok()).map(|value| lock.temp.set_data(value))
418418
}
419419

420420
fn branch_cb(&self, object_path: &CStr, description: Option<&CStr>, branches: &[&CStr]) -> Option<usize> {

src/context.rs

Lines changed: 46 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,24 @@
77
use std::{ffi::c_char, fmt::Display, num::NonZeroUsize, os::raw::c_void, ptr, sync::RwLock};
88

99
use crate::{
10-
BaseErrorCode, BlobType, ErrorCode, FapiCallbacks, ImportData, InternalError, KeyFlags, NvFlags, PaddingFlags, QuoteFlags, QuoteResult, SealFlags,
11-
SignResult, TpmBlobs,
10+
BaseErrorCode, BlobType, ErrorCode, FapiCallbacks, ImportData, InternalError, KeyFlags, NvFlags, PaddingFlags, QuoteFlags, QuoteResult, SealData,
11+
SealFlags, SignResult, TpmBlobs,
1212
callback::{CallbackManager, entry_point},
1313
fapi_sys::{self, FAPI_CONTEXT, TPM2_RC, TSS2_RC, constants::TSS2_RC_SUCCESS},
1414
flags::Flags,
1515
json::{self, JsonValue},
1616
locking::LockGuard,
1717
marshal::u64_from_be,
18-
memory::{CStringHolder, FapiMemoryHolder, cond_out, cond_ptr, opt_to_len, opt_to_ptr},
18+
memory::{CBinaryHolder, CStringHolder, FapiMemoryHolder, cond_out, cond_ptr},
1919
};
2020

2121
/* Const */
2222
const ERR_NO_RESULT_DATA: ErrorCode = ErrorCode::InternalError(InternalError::NoResultData);
2323
const ERR_INVALID_ARGUMENTS: ErrorCode = ErrorCode::InternalError(InternalError::InvalidArguments);
2424

25-
/* Opaque type */
26-
type TctiOpaqueContextBlob = *mut [u8; 0];
25+
/* Opaque ContextBlob type */
26+
#[derive(Debug)]
27+
pub struct TctiOpaqueContextBlob(pub *mut c_void);
2728

2829
/// Wraps the native `FAPI_CONTEXT` and exposes the related FAPI functions.
2930
///
@@ -402,8 +403,9 @@ impl FapiContext {
402403
pub fn nv_write(&mut self, nv_path: &str, data: &[u8]) -> Result<(), ErrorCode> {
403404
fail_if_empty!(data);
404405
let cstr_path = CStringHolder::try_from(nv_path)?;
406+
let cstr_data = CBinaryHolder::try_from(data)?;
405407

406-
self.fapi_call(false, |context| unsafe { fapi_sys::Fapi_NvWrite(context, cstr_path.as_ptr(), data.as_ptr(), data.len()) })
408+
self.fapi_call(false, |context| unsafe { fapi_sys::Fapi_NvWrite(context, cstr_path.as_ptr(), cstr_data.as_ptr(), cstr_data.len()) })
407409
}
408410

409411
/// Convenience function to [`nv_write()`](FapiContext::nv_write) an **`u64`** value. Assumes "big endian" byte order.
@@ -439,8 +441,11 @@ impl FapiContext {
439441

440442
let cstr_path = CStringHolder::try_from(nv_path)?;
441443
let cstr_logs = CStringHolder::try_from(log_data)?;
444+
let cstr_data = CBinaryHolder::try_from(data)?;
442445

443-
self.fapi_call(false, |context| unsafe { fapi_sys::Fapi_NvExtend(context, cstr_path.as_ptr(), data.as_ptr(), data.len(), cstr_logs.as_ptr()) })
446+
self.fapi_call(false, |context| unsafe {
447+
fapi_sys::Fapi_NvExtend(context, cstr_path.as_ptr(), cstr_data.as_ptr(), cstr_data.len(), cstr_logs.as_ptr())
448+
})
444449
}
445450

446451
/// Write the policyDigest of a policy to an NV index so it can be used in policies containing PolicyAuthorizeNV elements.
@@ -463,9 +468,10 @@ impl FapiContext {
463468
pub fn pcr_extend(&mut self, pcr_no: u32, data: &[u8], log_data: Option<&str>) -> Result<(), ErrorCode> {
464469
fail_if_empty!(data);
465470

471+
let cstr_data = CBinaryHolder::try_from(data)?;
466472
let cstr_logs = CStringHolder::try_from(log_data)?;
467473

468-
self.fapi_call(false, |context| unsafe { fapi_sys::Fapi_PcrExtend(context, pcr_no, data.as_ptr(), data.len(), cstr_logs.as_ptr()) })
474+
self.fapi_call(false, |context| unsafe { fapi_sys::Fapi_PcrExtend(context, pcr_no, cstr_data.as_ptr(), cstr_data.len(), cstr_logs.as_ptr()) })
469475
}
470476

471477
/// Reads from a given PCR and returns the value and the event log.
@@ -508,6 +514,7 @@ impl FapiContext {
508514

509515
let cstr_path = CStringHolder::try_from(key_path)?;
510516
let cstr_type = CStringHolder::try_from(Flags::as_string(quote_type)?)?;
517+
let cstr_qual = CBinaryHolder::try_from(qualifying_data)?;
511518

512519
let mut quote_info: *mut c_char = ptr::null_mut();
513520
let mut signature_data: *mut u8 = ptr::null_mut();
@@ -522,8 +529,8 @@ impl FapiContext {
522529
pcr_no.len(),
523530
cstr_path.as_ptr(),
524531
cstr_type.as_ptr(),
525-
opt_to_ptr(qualifying_data),
526-
opt_to_len(qualifying_data),
532+
cstr_qual.as_ptr(),
533+
cstr_qual.len(),
527534
&mut quote_info,
528535
&mut signature_data,
529536
&mut signature_size,
@@ -557,16 +564,18 @@ impl FapiContext {
557564
let cstr_path = CStringHolder::try_from(key_path)?;
558565
let cstr_info = CStringHolder::try_from(quote_info)?;
559566
let cstr_logs = CStringHolder::try_from(prc_log)?;
567+
let cstr_qual = CBinaryHolder::try_from(qualifying_data)?;
568+
let cstr_sign = CBinaryHolder::try_from(signature)?;
560569

561570
self.fapi_call(false, |context| unsafe {
562571
fapi_sys::Fapi_VerifyQuote(
563572
context,
564573
cstr_path.as_ptr(),
565-
opt_to_ptr(qualifying_data),
566-
opt_to_len(qualifying_data),
574+
cstr_qual.as_ptr(),
575+
cstr_qual.len(),
567576
cstr_info.as_ptr(),
568-
signature.as_ptr(),
569-
signature.len(),
577+
cstr_sign.as_ptr(),
578+
cstr_sign.len(),
570579
cstr_logs.as_ptr(),
571580
)
572581
})
@@ -589,12 +598,13 @@ impl FapiContext {
589598
fail_if_empty!(plaintext);
590599

591600
let cstr_path = CStringHolder::try_from(key_path)?;
601+
let cstr_plaintext = CBinaryHolder::try_from(plaintext)?;
592602

593603
let mut ciphertext_data: *mut u8 = ptr::null_mut();
594604
let mut ciphertext_size: usize = 0;
595605

596606
self.fapi_call(false, |context| unsafe {
597-
fapi_sys::Fapi_Encrypt(context, cstr_path.as_ptr(), plaintext.as_ptr(), plaintext.len(), &mut ciphertext_data, &mut ciphertext_size)
607+
fapi_sys::Fapi_Encrypt(context, cstr_path.as_ptr(), cstr_plaintext.as_ptr(), cstr_plaintext.len(), &mut ciphertext_data, &mut ciphertext_size)
598608
})
599609
.and_then(|_| FapiMemoryHolder::from_raw(ciphertext_data, ciphertext_size).to_vec().ok_or(ERR_NO_RESULT_DATA))
600610
}
@@ -606,12 +616,13 @@ impl FapiContext {
606616
fail_if_empty!(ciphertext);
607617

608618
let cstr_path = CStringHolder::try_from(key_path)?;
619+
let cstr_ciphertext = CBinaryHolder::try_from(ciphertext)?;
609620

610621
let mut plaintext_data: *mut u8 = ptr::null_mut();
611622
let mut plaintext_size: usize = 0;
612623

613624
self.fapi_call(false, |context| unsafe {
614-
fapi_sys::Fapi_Decrypt(context, cstr_path.as_ptr(), ciphertext.as_ptr(), ciphertext.len(), &mut plaintext_data, &mut plaintext_size)
625+
fapi_sys::Fapi_Decrypt(context, cstr_path.as_ptr(), cstr_ciphertext.as_ptr(), cstr_ciphertext.len(), &mut plaintext_data, &mut plaintext_size)
615626
})
616627
.and_then(|_| FapiMemoryHolder::from_raw(plaintext_data, plaintext_size).to_vec().ok_or(ERR_NO_RESULT_DATA))
617628
}
@@ -639,6 +650,7 @@ impl FapiContext {
639650

640651
let cstr_path = CStringHolder::try_from(key_path)?;
641652
let cstr_algo = CStringHolder::try_from(Flags::as_string(pad_algo)?)?;
653+
let cstr_hash = CBinaryHolder::try_from(digest)?;
642654

643655
let mut signature_data: *mut u8 = ptr::null_mut();
644656
let mut signature_size: usize = 0;
@@ -650,8 +662,8 @@ impl FapiContext {
650662
context,
651663
cstr_path.as_ptr(),
652664
cstr_algo.as_ptr(),
653-
digest.as_ptr(),
654-
digest.len(),
665+
cstr_hash.as_ptr(),
666+
cstr_hash.len(),
655667
&mut signature_data,
656668
&mut signature_size,
657669
cond_out(&mut public_key_pem, get_pubkey),
@@ -673,9 +685,11 @@ impl FapiContext {
673685
fail_if_empty!(digest, signature);
674686

675687
let cstr_path = CStringHolder::try_from(key_path)?;
688+
let cstr_hash = CBinaryHolder::try_from(digest)?;
689+
let cstr_sign = CBinaryHolder::try_from(signature)?;
676690

677691
self.fapi_call(false, |context| unsafe {
678-
fapi_sys::Fapi_VerifySignature(context, cstr_path.as_ptr(), digest.as_ptr(), digest.len(), signature.as_ptr(), signature.len())
692+
fapi_sys::Fapi_VerifySignature(context, cstr_path.as_ptr(), cstr_hash.as_ptr(), cstr_hash.len(), cstr_sign.as_ptr(), cstr_sign.len())
679693
})
680694
.map(|_| true)
681695
.or_else(|error| match error {
@@ -689,25 +703,28 @@ impl FapiContext {
689703
// [ Sealing functions ]
690704
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
691705

692-
/// Creates a sealed object and stores it in the FAPI metadata store. If no data is provided, the TPM generates random data to fill the sealed object.
706+
/// Creates a sealed object and stores it in the FAPI metadata store.
707+
///
708+
/// The [`data`](crate::SealData) to be sealed can be given as a *non-empty* `&[u8]` slice. Alternatively, a [`NoneZeroUsize`](std::num::NonZeroUsize) size can be specified.
709+
///
710+
/// If **no** explicit data is provided (i.e., only the size), the TPM generates random data to fill the sealed object.
693711
///
694712
/// *See also:* [`Fapi_CreateSeal()`](https://tpm2-tss.readthedocs.io/en/stable/group___fapi___create_seal.html)
695713
pub fn create_seal(
696714
&mut self,
697715
path: &str,
698716
seal_type: Option<&[SealFlags]>,
699-
seal_size: NonZeroUsize,
700717
pol_path: Option<&str>,
701718
auth_val: Option<&str>,
702-
data: Option<&[u8]>,
719+
data: SealData,
703720
) -> Result<(), ErrorCode> {
704721
fail_if_opt_empty!(seal_type);
705-
fail_if_opt_empty!(data);
706722

707723
let cstr_path = CStringHolder::try_from(path)?;
708724
let cstr_type = CStringHolder::try_from(Flags::as_string(seal_type)?)?;
709725
let cstr_poli = CStringHolder::try_from(pol_path)?;
710726
let cstr_auth = CStringHolder::try_from(auth_val)?;
727+
let (seal_size, seal_data) = data.into_raw_data()?;
711728

712729
self.fapi_call(false, |context| unsafe {
713730
fapi_sys::Fapi_CreateSeal(
@@ -717,7 +734,7 @@ impl FapiContext {
717734
seal_size.get(),
718735
cstr_poli.as_ptr(),
719736
cstr_auth.as_ptr(),
720-
opt_to_ptr(data),
737+
seal_data.as_ptr(),
721738
)
722739
})
723740
}
@@ -827,8 +844,9 @@ impl FapiContext {
827844
pub fn set_app_data(&mut self, path: &str, app_data: Option<&[u8]>) -> Result<(), ErrorCode> {
828845
fail_if_opt_empty!(app_data);
829846
let cstr_path = CStringHolder::try_from(path)?;
847+
let cstr_data = CBinaryHolder::try_from(app_data)?;
830848

831-
self.fapi_call(false, |context| unsafe { fapi_sys::Fapi_SetAppData(context, cstr_path.as_ptr(), opt_to_ptr(app_data), opt_to_len(app_data)) })
849+
self.fapi_call(false, |context| unsafe { fapi_sys::Fapi_SetAppData(context, cstr_path.as_ptr(), cstr_data.as_ptr(), cstr_data.len()) })
832850
}
833851

834852
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -879,9 +897,10 @@ impl FapiContext {
879897

880898
let cstr_path_pol = CStringHolder::try_from(pol_path)?;
881899
let cstr_path_key = CStringHolder::try_from(key_path)?;
900+
let cstr_ref_data = CBinaryHolder::try_from(ref_data)?;
882901

883902
self.fapi_call(false, |context| unsafe {
884-
fapi_sys::Fapi_AuthorizePolicy(context, cstr_path_pol.as_ptr(), cstr_path_key.as_ptr(), opt_to_ptr(ref_data), opt_to_len(ref_data))
903+
fapi_sys::Fapi_AuthorizePolicy(context, cstr_path_pol.as_ptr(), cstr_path_key.as_ptr(), cstr_ref_data.as_ptr(), cstr_ref_data.len())
885904
})
886905
}
887906

@@ -895,7 +914,7 @@ impl FapiContext {
895914
pub fn get_tcti(&mut self) -> Result<TctiOpaqueContextBlob, ErrorCode> {
896915
let mut tcti: *mut fapi_sys::TSS2_TCTI_CONTEXT = ptr::null_mut();
897916

898-
self.fapi_call(false, |context| unsafe { fapi_sys::Fapi_GetTcti(context, &mut tcti) }).map(|_| tcti as TctiOpaqueContextBlob)
917+
self.fapi_call(false, |context| unsafe { fapi_sys::Fapi_GetTcti(context, &mut tcti) }).map(|_| TctiOpaqueContextBlob(tcti as *mut c_void))
899918
}
900919

901920
/// Returns an array of handles that can be polled on to get notified when data from the TPM or from a disk operation is available.

src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* All rights reserved.
55
**********************************************************************************************/
66

7-
//! [![Rust](https://img.shields.io/badge/rust-1.82.0+-orchid?logo=rust)](https://www.rust-lang.org/)
7+
//! [![Rust](https://img.shields.io/badge/rust-1.85.0+-orchid?logo=rust)](https://www.rust-lang.org/)
88
//! [![Crates.io](https://img.shields.io/crates/v/tss2-fapi-rs.svg)](https://crates.io/crates/tss2-fapi-rs)
99
//! [![Docs.rs](https://img.shields.io/docsrs/tss2-fapi-rs.svg)](https://docs.rs/tss2-fapi-rs/latest/tss2_fapi_rs/)
1010
//! [![License](https://img.shields.io/crates/l/tss2-fapi-rs)](https://opensource.org/licenses/BSD-3-Clause)
@@ -88,7 +88,7 @@
8888
//!
8989
//! ```toml
9090
//! [dependencies]
91-
//! tss2-fapi-rs = "0.11.0"
91+
//! tss2-fapi-rs = "0.12.0"
9292
//! ```
9393
//!
9494
//! **Note:** Please also consider the [prerequisites](#prerequisites) that are required to use the `tss2-fapi-rs` library!
@@ -443,7 +443,7 @@ pub use callback::{AuthCbParam, BranchCbParam, Callbacks, FapiCallbacks, PolicyA
443443
pub use context::FapiContext;
444444
pub use error::{BaseErrorCode, ErrorCode, InternalError, Tpm2ErrFmt0, Tpm2ErrFmt1, Tpm2ErrorCode, Tpm2Warning};
445445
pub use flags::{BlobType, KeyFlags, NvFlags, PaddingFlags, QuoteFlags, SealFlags};
446-
pub use types::{ImportData, QuoteResult, SignResult, TpmBlobs};
446+
pub use types::{ImportData, QuoteResult, SealData, SignResult, TpmBlobs};
447447
pub use version::{FapiVersion, VersionInfo, get_version};
448448

449449
// Re-export JSON module

0 commit comments

Comments
 (0)