Skip to content

Verify TAs - #1399

Open
Angelina Vu (athvu) wants to merge 8 commits into
mainfrom
avu/verify_ta
Open

Angelina Vu (athvu) wants to merge 8 commits into
mainfrom
avu/verify_ta

Conversation

@athvu

@athvu Angelina Vu (athvu) commented Sep 21, 2026 •

Copy link
Copy Markdown
Contributor

Allow for TA signature verification. A verification key can be embedded through the LITEBOX_TA_VERIFY_KEY build variable.
Built-in TAs can either be unsigned .elf or signed .ta files. Dynamic TAs must be signed.

@praveen-pk

Copy link
Copy Markdown
Contributor

Why make this a compile time feature: signed-ta-rsa? Why not determine the binary type dynamically, by checking the MAGIC value and take appropriate steps?

} else {
let ta_bin = Self::rpc_get_ta_bin(ta_uuid)?;
if !self.store_ta_bin(ta_uuid, &ta_bin) {
if !self.store_ta_bin(ta_uuid, &ta_bin, TaSource::Dynamic) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fyi, the place to store_ta_bin changed with the open Dynamic TA Support PR (#1213).

So, this should be revisited later

Angelina Vu added 3 commits September 29, 2026 16:10
Signed-off-by: Angelina Vu <angelinavu@microsoft.com>
Signed-off-by: Angelina Vu <angelinavu@microsoft.com>
Signed-off-by: Angelina Vu <angelinavu@microsoft.com>
@athvu
Angelina Vu (athvu) force-pushed the avu/verify_ta branch 2 times, most recently from b259c1e to 96b466b Compare September 29, 2026 17:04
@athvu
Angelina Vu (athvu) marked this pull request as ready for review September 29, 2026 17:15
Angelina Vu added 4 commits September 30, 2026 06:05
Dynamic TAs must be signed and verified.

Signed-off-by: Angelina Vu <angelinavu@microsoft.com>
… is not given.

Signed-off-by: Angelina Vu <angelinavu@microsoft.com>
Signed-off-by: Angelina Vu <angelinavu@microsoft.com>
Signed-off-by: Angelina Vu <angelinavu@microsoft.com>
Signed-off-by: Angelina Vu <angelinavu@microsoft.com>
@github-actions

Copy link
Copy Markdown

🤖 SemverChecks 🤖 ⚠️ Potential breaking API changes detected ⚠️

Click for details
--- failure method_parameter_count_changed: pub method parameter count changed ---

Description:
A publicly-visible method now takes a different number of parameters, not counting the receiver (self) parameter.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#fn-change-arity
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.50.0/src/lints/method_parameter_count_changed.ron

Failed in:
  litebox_shim_optee::OpteeShim::store_ta_bin takes 2 parameters in /home/runner/work/litebox/litebox/target/semver-checks/git-main/76da2f2c93619305727f9255644e6e055b5c1c7d/litebox_shim_optee/src/lib.rs:423, but now takes 3 parameters in /home/runner/work/litebox/litebox/litebox_shim_optee/src/lib.rs:476

@sangho2 Sangho Lee (sangho2) left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two things should be considered:

  1. this PR is not yet wired with ta_signing_cert, ta_svn, ta_digest, and ta_dynamic. ta_dynamic is still debatable because it is related to not only this PR but also #1213. However, the former three should be wired here.
  2. It doesn't have an end-to-end test. We can implement one using litebox_runner_optee_on_linux_userland, which sign_encrypt.py one of the example TAs using a randomly generated RSA key pair and checks whether the userland runner can verify/run it.

const SHDR_VERSION_LEN: usize = 4;

/// An RSA public key used to verify signed `.ta` files
pub struct TaVerifyKey(rsa::RsaPublicKey);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All these implementations (TaVerifyKey, parse_and_verify_ta, ...) should be moved to litebox_shim_optee. We are trying to avoid having actual implementation in common crates. This would also allow us to revert the changes in ci.yml and Cargo.toml.

pub fn parse_and_verify_ta<'a>(
ta_data: &'a [u8],
verify_key: &TaVerifyKey,
) -> Result<(TaHead, &'a [u8]), &'static str> {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nits: using thiserror should be better. returning error strings is a bit fragile.

signed_message.extend_from_slice(uuid_and_version);
signed_message.extend_from_slice(img);
verify_shdr_signature(&signed_message, sig, shdr.algo, &verify_key.0)?;
let ta_head = parse_ta_head(img).ok_or("Invalid TA ELF binary")?;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should check whether UUIDs in uuid_and_version and ta_head are equal.

verify_shdr_signature(&signed_message, sig, shdr.algo, &verify_key.0)?;
let ta_head = parse_ta_head(img).ok_or("Invalid TA ELF binary")?;

Ok((ta_head, img))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should return version as well because a raw TA image doesn't contain version info. assign it to ta_svn.

Comment on lines +2715 to +2716
}
let hash_size = shdr.hash_size as usize;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nits: Better to check whether other fields (e.g., img_type) is valid and whether hash_size is correct (SHA256).

/// UUID (from `.ta_head` section) doesn't match the provided UUID or parsing failed.
pub(crate) fn store_ta_bin(&self, ta_uuid: &TeeUuid, ta_bin: &[u8]) -> bool {
self.ta_uuid_map.insert(*ta_uuid, ta_bin.into())
pub(crate) fn store_ta_bin(&self, ta_uuid: &TeeUuid, ta_bin: &[u8], source: TaSource) -> bool {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nits: Rather than relying on the source argument, we could check ta_bin itself to identify whether it is signed or not.

Comment on lines 181 to +182
ta_signing_cert: &'static [u8],
ta_verify_key: &'static [u8],

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two are the same one.

Comment on lines +2674 to +2681
/// and from `optee_os/core/include/tee_api_types.h`
/// ```c
/// typedef struct {
/// uint32_t timeLow;
/// uint16_t timeMid;
/// uint16_t timeHiAndVersion;
/// uint8_t clockSeqAndNode[8];
/// } TEE_UUID;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not needed. this UUID thing is already in the same file.

signature: &[u8],
algo: u32,
rsa_pub_key: &rsa::RsaPublicKey,
) -> Result<(), &'static str> {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same. thiserror is preferred.

Comment on lines +1540 to +1541
/// How the TA binary was loaded
source: TaSource,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

take a look at ta_dynamic.

let end = img_offset
.checked_add(img_size)
.ok_or("Invalid signed TA file")?;
if end > ta_data.len() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not end != ta_data.len()? do we need to accept trailing bytes?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants