Skip to main content

teec_protocol/
lib.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (C) 2025-2026 KylinSoft Co., Ltd. <https://www.kylinos.cn/>
3// See LICENSES for license details.
4
5//! TEE Client-Application 通信协议定义
6//!
7//! 提供 CA(Client Application)与 TA(Trusted Application)之间通信的协议类型。
8//! 这些类型用于序列化/反序列化请求和响应数据,通过机密通信通道(TLS + VSOCK)传输。
9
10#![allow(dead_code)]
11#![allow(non_camel_case_types)]
12
13use bytemuck::{Pod, Zeroable};
14use serde::{Deserialize, Serialize};
15
16/// 数据包分块大小:32KiB
17pub const CHUNK_SIZE: u64 = 32 * 1024;
18
19/// 最大消息大小限制(10MB),防止 OOM 攻击
20pub const MAX_MESSAGE_SIZE: usize = 10 * 1024 * 1024;
21
22/// 数据包类型枚举,定义协议支持的不同操作类型
23#[derive(Debug, PartialEq, Eq, Default)]
24pub enum PacketType {
25    #[default]
26    Unknown = 0,
27    OpenSession = 1,
28    CloseSession = 2,
29    InvokeCommand = 3,
30    RequestCancellation = 4,
31}
32
33impl From<u64> for PacketType {
34    fn from(value: u64) -> Self {
35        match value {
36            0 => PacketType::Unknown,
37            1 => PacketType::OpenSession,
38            2 => PacketType::CloseSession,
39            3 => PacketType::InvokeCommand,
40            4 => PacketType::RequestCancellation,
41            _ => PacketType::Unknown,
42        }
43    }
44}
45
46impl From<PacketType> for u64 {
47    fn from(value: PacketType) -> Self {
48        match value {
49            PacketType::Unknown => 0,
50            PacketType::OpenSession => 1,
51            PacketType::CloseSession => 2,
52            PacketType::InvokeCommand => 3,
53            PacketType::RequestCancellation => 4,
54        }
55    }
56}
57
58/// 协议头结构,使用 #[repr(C)] 确保内存布局与 C 兼容
59/// 满足 bytemuck::Pod 要求:所有字段必须为基本类型
60#[repr(C)]
61#[derive(Debug, Copy, Clone, Pod, Zeroable)]
62pub struct PacketHeader {
63    /// 数据包类型标识,对应 PacketType 枚举的数值表示
64    pub data_type: u64,
65    /// 数据包负载大小
66    pub data_size: u64,
67}
68
69impl PacketHeader {
70    /// 协议头结构体的大小
71    pub const SIZE: usize = size_of::<PacketHeader>();
72
73    /// 将协议头序列化为字节切片
74    pub fn as_bytes(&self) -> &[u8] {
75        bytemuck::bytes_of(self)
76    }
77
78    /// 从字节切片反序列化协议头
79    pub fn from_bytes(buf: &[u8]) -> Self {
80        *bytemuck::from_bytes(buf)
81    }
82}
83
84/// TA 注册请求。
85///
86/// TA 启动后通过此消息向 TEE OS 注册自身,声明其 UUID 及实例属性。
87#[derive(Serialize, Deserialize, Debug, Clone)]
88pub enum TARequest {
89    Register {
90        uuid: String,
91        instance_id: u32,
92        socket_path: String,
93        is_single_instance: bool,
94        is_multi_session: bool,
95        is_instance_keep_alive: bool,
96    },
97}
98
99/// TEE 请求枚举,定义 CA 发送给 TA 的所有请求类型
100///
101/// 这些请求会被序列化并通过机密通信通道(TLS + VSOCK)发送给 TA。
102#[derive(Serialize, Deserialize)]
103pub enum TEE_Request {
104    OpenSession {
105        uuid: String,
106        connection_method: u32,
107        params: TEE_Parameters,
108        #[serde(default)]
109        ca_auth_info: Option<CaAuthInfo>,
110    },
111    CloseSession {
112        session_id: u32,
113    },
114    InvokeCommand {
115        session_id: u32,
116        cmd_id: u32,
117        params: TEE_Parameters,
118    },
119    RequestCancellation {
120        session_id: u32,
121    },
122}
123
124/// CA 认证信息(用于 TA 的 ACL 访问控制)
125#[derive(Serialize, Deserialize, Debug, Clone)]
126pub struct CaAuthInfo {
127    /// CA 的唯一标识(UUID v5,基于调用者路径生成)
128    pub ca_uuid: String,
129    /// 验签是否通过(包含签名验证和证书链验证)
130    pub verified: bool,
131}
132
133/// TEE 响应枚举,定义 TA 返回给 CA 的所有响应类型
134///
135/// 这些响应会被序列化并通过机密通信通道(TLS + VSOCK)发送给 CA。
136#[derive(Serialize, Deserialize)]
137pub enum TEE_Response {
138    OpenSession { session_id: u32, result: u32 },
139    CloseSession { result: u32 },
140    InvokeCommand { params: TEE_Parameters, result: u32 },
141    RequestCancellation { result: u32 },
142}
143
144/// TEE 参数容器,包含最多 4 个参数
145///
146/// 这些参数会被序列化到请求/响应数据包中,通过网络传输。
147#[derive(Serialize, Deserialize, Default, Clone)]
148pub struct TEE_Parameters(
149    pub TEE_Parameter,
150    pub TEE_Parameter,
151    pub TEE_Parameter,
152    pub TEE_Parameter,
153);
154
155/// 单个 TEE 参数,包含参数值/数据和参数类型标识。
156///
157/// `param` 携带实际数据(VALUE (a,b) 或 MEMREF buffer),
158/// `param_type` 指示该参数的读写方向(输入/输出/双向)。
159#[derive(Serialize, Deserialize, Default, Clone)]
160pub struct TEE_Parameter {
161    pub param: TEE_Param,
162    pub param_type: TEE_ParamType,
163}
164
165/// TEE 参数的联合数据载体。
166///
167/// - `data`:用于 MEMREF 类型参数的缓冲区数据
168/// - `values`:用于 VALUE 类型参数的 (a, b) 对
169#[derive(Serialize, Deserialize, Default, Clone)]
170pub struct TEE_Param {
171    pub data: Vec<u8>,
172    pub values: TEE_Value,
173}
174
175/// TEE VALUE 类型参数的值对。
176///
177/// 对应 GP TEE Client API 中的 `TEEC_Value`,
178/// 包含两个 32 位无符号整数 `a` 和 `b`。
179#[derive(Serialize, Deserialize, Clone, Copy, Default)]
180pub struct TEE_Value {
181    pub a: u32,
182    pub b: u32,
183}
184
185/// TEE 参数类型枚举,指示参数的读写方向。
186#[derive(Serialize, Deserialize, Default, Debug, PartialEq, Eq, Clone, Copy)]
187pub enum TEE_ParamType {
188    #[default]
189    None = 0,
190    ValueInput = 1,
191    ValueOutput = 2,
192    ValueInout = 3,
193    MemrefInput = 5,
194    MemrefOutput = 6,
195    MemrefInout = 7,
196}
197
198impl From<u32> for TEE_ParamType {
199    fn from(value: u32) -> Self {
200        match value {
201            0 => TEE_ParamType::None,
202            1 => TEE_ParamType::ValueInput,
203            2 => TEE_ParamType::ValueOutput,
204            3 => TEE_ParamType::ValueInout,
205            5 => TEE_ParamType::MemrefInput,
206            6 => TEE_ParamType::MemrefOutput,
207            7 => TEE_ParamType::MemrefInout,
208            _ => TEE_ParamType::None,
209        }
210    }
211}
212
213impl From<TEE_ParamType> for u32 {
214    fn from(value: TEE_ParamType) -> Self {
215        match value {
216            TEE_ParamType::None => 0,
217            TEE_ParamType::ValueInput => 1,
218            TEE_ParamType::ValueOutput => 2,
219            TEE_ParamType::ValueInout => 3,
220            TEE_ParamType::MemrefInput => 5,
221            TEE_ParamType::MemrefOutput => 6,
222            TEE_ParamType::MemrefInout => 7,
223        }
224    }
225}
226
227/// 将路径转换为 UUID v5(用于生成 CA 唯一标识符)
228///
229/// 使用 NIL UUID 作为命名空间,路径字符串作为名称,
230/// 生成的 UUID 可用于 TEE_Request::OpenSession 的 ca_auth_info.ca_uuid 字段。
231pub fn path_to_uuid(path: &str) -> String {
232    use uuid::Uuid;
233    let namespace = Uuid::nil();
234    Uuid::new_v5(&namespace, path.as_bytes()).to_string()
235}
236
237/// 协议中使用的类型别名,为兼容 Teaclave TrustZone SDK。
238pub use TEE_ParamType as ParamType;
239/// 协议中使用的类型别名,为兼容 Teaclave TrustZone SDK。
240pub use TEE_Parameter as Parameter;
241/// 协议中使用的类型别名,为兼容 Teaclave TrustZone SDK。
242pub use TEE_Parameters as Parameters;
243/// 协议中使用的类型别名,为兼容 Teaclave TrustZone SDK。
244pub use TEE_Value as Value;
245
246#[cfg(test)]
247mod protocol_tests {
248    use super::*;
249
250    #[test]
251    fn test_tee_param_type_from_u32() {
252        // 测试 TEE_ParamType 的 From<u32> 实现 - 覆盖所有分支
253        assert_eq!(TEE_ParamType::from(0), TEE_ParamType::None);
254        assert_eq!(TEE_ParamType::from(1), TEE_ParamType::ValueInput);
255        assert_eq!(TEE_ParamType::from(2), TEE_ParamType::ValueOutput);
256        assert_eq!(TEE_ParamType::from(3), TEE_ParamType::ValueInout);
257        assert_eq!(TEE_ParamType::from(4), TEE_ParamType::None); // 未知值 -> None
258        assert_eq!(TEE_ParamType::from(5), TEE_ParamType::MemrefInput);
259        assert_eq!(TEE_ParamType::from(6), TEE_ParamType::MemrefOutput);
260        assert_eq!(TEE_ParamType::from(7), TEE_ParamType::MemrefInout);
261        assert_eq!(TEE_ParamType::from(8), TEE_ParamType::None); // 未知值 -> None
262        assert_eq!(TEE_ParamType::from(99), TEE_ParamType::None); // 未知值 -> None
263        assert_eq!(TEE_ParamType::from(255), TEE_ParamType::None); // 边界值
264    }
265
266    #[test]
267    fn test_tee_param_type_into_u32() {
268        // 测试 TEE_ParamType 的 Into<u32> 实现 - 覆盖所有变体
269        assert_eq!(u32::from(TEE_ParamType::None), 0);
270        assert_eq!(u32::from(TEE_ParamType::ValueInput), 1);
271        assert_eq!(u32::from(TEE_ParamType::ValueOutput), 2);
272        assert_eq!(u32::from(TEE_ParamType::ValueInout), 3);
273        assert_eq!(u32::from(TEE_ParamType::MemrefInput), 5);
274        assert_eq!(u32::from(TEE_ParamType::MemrefOutput), 6);
275        assert_eq!(u32::from(TEE_ParamType::MemrefInout), 7);
276    }
277
278    #[test]
279    fn test_tee_param_type_roundtrip() {
280        // 测试双向转换的往返一致性
281        let values = vec![0, 1, 2, 3, 5, 6, 7];
282        for value in values {
283            let param_type = TEE_ParamType::from(value);
284            let back_to_u32: u32 = param_type.into();
285            assert_eq!(value, back_to_u32);
286        }
287    }
288
289    #[test]
290    fn test_tee_value_default() {
291        // 测试 TEE_Value 的 Default trait
292        let default_val = TEE_Value::default();
293        assert_eq!(default_val.a, 0);
294        assert_eq!(default_val.b, 0);
295    }
296
297    #[test]
298    fn test_tee_parameter_default() {
299        // 测试 TEE_Parameter 的 Default trait
300        let default_param = TEE_Parameter::default();
301        assert_eq!(default_param.param_type, TEE_ParamType::None);
302        assert_eq!(default_param.param.values.a, 0);
303        assert_eq!(default_param.param.values.b, 0);
304        assert!(default_param.param.data.is_empty());
305    }
306
307    #[test]
308    fn test_packet_header_serialization_roundtrip() {
309        // 测试 PacketHeader 序列化/反序列化的往返一致性
310        let original = PacketHeader {
311            data_type: 0x1234_5678_9ABC_DEF0,
312            data_size: 0xFEDC_BA98_7654_3210,
313        };
314
315        let bytes = original.as_bytes();
316        let restored = PacketHeader::from_bytes(bytes);
317
318        assert_eq!(original.data_type, restored.data_type);
319        assert_eq!(original.data_size, restored.data_size);
320    }
321
322    #[test]
323    fn test_packet_type_conversion() {
324        // 测试协议类型转换 - 覆盖所有分支
325        assert_eq!(PacketType::from(0), PacketType::Unknown);
326        assert_eq!(PacketType::from(1), PacketType::OpenSession);
327        assert_eq!(PacketType::from(2), PacketType::CloseSession);
328        assert_eq!(PacketType::from(3), PacketType::InvokeCommand);
329        assert_eq!(PacketType::from(4), PacketType::RequestCancellation);
330        assert_eq!(PacketType::from(5), PacketType::Unknown); // 未知值 -> Unknown
331        assert_eq!(PacketType::from(0xFFFFFFFF), PacketType::Unknown); // 边界值
332
333        assert_eq!(u64::from(PacketType::Unknown), 0);
334        assert_eq!(u64::from(PacketType::OpenSession), 1);
335        assert_eq!(u64::from(PacketType::CloseSession), 2);
336        assert_eq!(u64::from(PacketType::InvokeCommand), 3);
337        assert_eq!(u64::from(PacketType::RequestCancellation), 4);
338    }
339
340    #[test]
341    fn test_packet_header_size() {
342        use core::mem;
343
344        // 测试协议头数据大小
345        let packet0 = PacketHeader {
346            data_type: u64::from(PacketType::OpenSession),
347            data_size: CHUNK_SIZE,
348        };
349
350        let packet1 = PacketHeader {
351            data_type: u64::from(PacketType::CloseSession),
352            data_size: 44,
353        };
354
355        assert_eq!(mem::size_of_val(&packet0), PacketHeader::SIZE);
356        assert_eq!(mem::size_of_val(&packet1), PacketHeader::SIZE);
357        assert_eq!(PacketHeader::SIZE, mem::size_of::<PacketHeader>());
358    }
359
360    #[test]
361    fn test_path_to_uuid_consistency() {
362        // 相同路径应该生成相同的 UUID
363        let uuid1 = path_to_uuid("/usr/bin/test");
364        let uuid2 = path_to_uuid("/usr/bin/test");
365        assert_eq!(uuid1, uuid2);
366    }
367
368    #[test]
369    fn test_path_to_uuid_uniqueness() {
370        // 不同路径应该生成不同的 UUID
371        let uuid1 = path_to_uuid("/usr/bin/test1");
372        let uuid2 = path_to_uuid("/usr/bin/test2");
373        assert_ne!(uuid1, uuid2);
374    }
375
376    #[test]
377    fn test_path_to_uuid_deterministic() {
378        // 测试 UUID v5 的确定性:相同路径总是生成相同的 UUID
379        // 这是 UUID v5 的核心特性,用于 CA 身份标识的稳定性
380
381        // 已知路径的已知 UUID(回归测试,确保算法稳定)
382        assert_eq!(
383            path_to_uuid("/usr/bin/test"),
384            "f2d62525-c975-5075-8bfd-ea1a7c98adc3"
385        );
386
387        // 不同路径生成不同 UUID
388        assert_ne!(path_to_uuid("/usr/bin/test"), path_to_uuid("/usr/bin/ls"));
389    }
390}