You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@teaclave.apache.org by iv...@apache.org on 2026/10/12 09:58:18 UTC

(teaclave-trustzone-sdk) 01/03: optee-utee: represent unknown login types instead of panicking

This is an automated email from the ASF dual-hosted git repository.

ivila pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/teaclave-trustzone-sdk.git

commit 96f2b5b9a5fba894fba1eadf49e69d32b07b80b7
Author: ivila <iv...@apache.org>
AuthorDate: Mon Oct 12 15:45:45 2026 +0800

    optee-utee: represent unknown login types instead of panicking
    
    Derive `LoginType` with num_enum's `FromPrimitive`/`IntoPrimitive`
    and an `Unknown(u32)` catch-all, as `ErrorKind` does, so
    `Identity::login_type` maps an unnamed login to data instead of
    reaching the `panic!` for the seven named `TEE_LOGIN_*` constants. In
    a TA that panic calls `TEE_Panic`, killing the instance and every
    session on it. The raw value still round-trips through `Into<u32>`.
---
 crates/optee-utee/src/identity.rs | 77 +++++++++++++++++++++++++++++++++------
 1 file changed, 66 insertions(+), 11 deletions(-)

diff --git a/crates/optee-utee/src/identity.rs b/crates/optee-utee/src/identity.rs
index 1a3ea65..2c2138b 100644
--- a/crates/optee-utee/src/identity.rs
+++ b/crates/optee-utee/src/identity.rs
@@ -16,6 +16,7 @@
 // under the License.
 
 use crate::Uuid;
+use num_enum::{FromPrimitive, IntoPrimitive};
 use optee_utee_sys as raw;
 
 #[derive(Copy, Clone)]
@@ -24,17 +25,15 @@ pub struct Identity {
 }
 
 impl Identity {
+    /// Returns the login type of this client identity.
+    ///
+    /// The GlobalPlatform specification reserves implementation-defined login ranges,
+    /// so a login value outside the set named below is possible in principle. Such a
+    /// value is returned as [`LoginType::Unknown`] carrying the raw code instead of
+    /// aborting the TA, so a TA inspecting its callers must decide explicitly what to
+    /// do with a login it does not recognize — normally by rejecting the caller.
     pub fn login_type(&self) -> LoginType {
-        match self.raw.login {
-            raw::TEE_LOGIN_PUBLIC => LoginType::Public,
-            raw::TEE_LOGIN_USER => LoginType::User,
-            raw::TEE_LOGIN_GROUP => LoginType::Group,
-            raw::TEE_LOGIN_APPLICATION => LoginType::Application,
-            raw::TEE_LOGIN_APPLICATION_USER => LoginType::ApplicationUser,
-            raw::TEE_LOGIN_APPLICATION_GROUP => LoginType::ApplicationGroup,
-            raw::TEE_LOGIN_TRUSTED_APP => LoginType::TrustedApp,
-            _ => panic!("Invalid login type"),
-        }
+        LoginType::from(self.raw.login)
     }
 
     pub fn uuid(&self) -> Uuid {
@@ -48,7 +47,12 @@ impl From<raw::TEE_Identity> for Identity {
     }
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, strum::Display)]
+/// The login type of a client, as stamped by OP-TEE into `TEE_Identity::login`.
+///
+/// This is the Rust-side mirror of the `TEE_LOGIN_*` constants defined in the C
+/// header. The `Unknown(u32)` variant catches any login value this crate does not
+/// name, so the value always round-trips back through [`IntoPrimitive`].
+#[derive(Clone, Copy, Debug, Eq, PartialEq, FromPrimitive, IntoPrimitive, strum::Display)]
 #[repr(u32)]
 pub enum LoginType {
     Public = raw::TEE_LOGIN_PUBLIC,
@@ -58,4 +62,55 @@ pub enum LoginType {
     ApplicationUser = raw::TEE_LOGIN_APPLICATION_USER,
     ApplicationGroup = raw::TEE_LOGIN_APPLICATION_GROUP,
     TrustedApp = raw::TEE_LOGIN_TRUSTED_APP,
+    #[num_enum(catch_all)]
+    Unknown(u32),
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    fn identity_with_login(login: u32) -> Identity {
+        Identity::from(raw::TEE_Identity {
+            login,
+            uuid: raw::TEE_UUID {
+                timeLow: 0,
+                timeMid: 0,
+                timeHiAndVersion: 0,
+                clockSeqAndNode: [0; 8],
+            },
+        })
+    }
+
+    /// Guarantees: the login values named by the GlobalPlatform specification still
+    /// map to their named variants.
+    #[test]
+    fn known_login_types_still_map() {
+        let known = [
+            (raw::TEE_LOGIN_PUBLIC, LoginType::Public),
+            (raw::TEE_LOGIN_USER, LoginType::User),
+            (raw::TEE_LOGIN_GROUP, LoginType::Group),
+            (raw::TEE_LOGIN_APPLICATION, LoginType::Application),
+            (raw::TEE_LOGIN_APPLICATION_USER, LoginType::ApplicationUser),
+            (
+                raw::TEE_LOGIN_APPLICATION_GROUP,
+                LoginType::ApplicationGroup,
+            ),
+            (raw::TEE_LOGIN_TRUSTED_APP, LoginType::TrustedApp),
+        ];
+        for (raw_login, expected) in known {
+            assert_eq!(identity_with_login(raw_login).login_type(), expected);
+        }
+    }
+
+    /// Guarantees: reading a login value outside the named set yields `Unknown`
+    /// instead of panicking, and the raw value round-trips.
+    #[test]
+    fn unnamed_login_types_do_not_panic() {
+        for raw_login in [0x0000_0003, 0x0000_0300, 0x8000_0000, u32::MAX] {
+            let login_type = identity_with_login(raw_login).login_type();
+            assert_eq!(login_type, LoginType::Unknown(raw_login));
+            assert_eq!(u32::from(login_type), raw_login);
+        }
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@teaclave.apache.org
For additional commands, e-mail: commits-help@teaclave.apache.org