diff --git a/Cargo.toml b/Cargo.toml index 8001e1c01937a969855491f68f6e9cc363fef8b4..77000594438fdba0a79257a8a12d582297ffab68 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,3 @@ name = "rust_dice" cty = "0.2" mbedtls-sys = { version="2.28", package="mbedtls-sys-auto-smx", default-features = false, optional = false } mbedtls = { version="0.13", package = "mbedtls-smx", default-features = false} - -[build-dependencies] -bindgen = "0.72" -cc = "1.0.45" \ No newline at end of file diff --git a/build.rs b/build.rs deleted file mode 100644 index 4fc51feb96f5216f564a51a78027aeb2f4b9e63c..0000000000000000000000000000000000000000 --- a/build.rs +++ /dev/null @@ -1,96 +0,0 @@ -use std::env; -use std::path::{Path, PathBuf}; -use std::process::Command; - -fn main() { - let target = env::var("TARGET").unwrap(); - let host = env::var("HOST").unwrap(); - let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); - - // 探测交叉编译工具链的 Sysroot - // 优先读取 Makefile 传入的 CC,如果没有则默认为 aarch64-linux-musl-gcc - let cc_env = env::var("CC").unwrap_or_else(|_| "aarch64-linux-musl-gcc".to_string()); - - let mut clang_args = vec!["-Iopendice/dice/include".to_string()]; - - // 只有在交叉编译(Host != Target)或者指定了特殊 Target 时,才注入 Sysroot - if !(host.contains("aarch64") && target.contains("aarch64")) && target != host { - // 尝试获取 GCC 的 sysroot - if let Ok(output) = Command::new(&cc_env).arg("-print-sysroot").output() { - let sysroot = String::from_utf8_lossy(&output.stdout).trim().to_string(); - if !sysroot.is_empty() && Path::new(&sysroot).exists() { - clang_args.push(format!("--sysroot={}", sysroot)); - - // 补丁:显式添加 include 路径,防止某些版本的 clang 找不到 musl 头文件 - let include_path = format!("{}/include", sysroot); - if Path::new(&include_path).exists() { - clang_args.push(format!("-I{}", include_path)); - } - } - } - // 显式指定 target 给 bindgen (clang),防止它用宿主机的配置来解析 C 代码 - clang_args.push(format!("--target={}", target)); - } - - // 编译 C 静态库 - let src_files = [ - "opendice/dice/src/android.c", - "opendice/dice/src/mbedtls_sm2dsa_ops.c", - "opendice/dice/src/cbor_cert_op.c", - "opendice/dice/src/cbor_reader.c", - "opendice/dice/src/cbor_writer.c", - "opendice/dice/src/clear_memory.c", - "opendice/dice/src/dice.c", - "opendice/dice/src/mbedtls_ops.c", - "opendice/dice/src/mbedtls_sm2dsa_utils.c", - "opendice/dice/src/utils.c", - "opendice/tee_dice.c", - ]; - - let mut cc_build = cc::Build::new(); - cc_build - .include("opendice/dice/include") - .include(env::var("DEP_MBEDTLS_SMX_INCLUDE").unwrap_or_default()) - .files(&src_files) - .flag_if_supported("-fno-stack-protector") - .flag_if_supported("-Wno-unused-variable") - .flag_if_supported("-Wno-unused-parameter") - .flag_if_supported("-Wno-pointer-sign") - .flag_if_supported("-Wno-int-conversion"); - - // 如果在交叉编译环境,cc 也会需要 sysroot - for arg in &clang_args { - if arg.starts_with("--sysroot") { - cc_build.flag(arg); - } - } - cc_build.compile("opendice"); - - // 生成 Bindings - let mut builder = bindgen::Builder::default() - .header("opendice/dice/include/dice/android.h") - .header("opendice/tee_dice.h") - .header("opendice/dice/include/dice/mbedtls_sm2dsa_utils.h") - .use_core() - .ctypes_prefix("cty") - .layout_tests(false); - - // 注入探测到的所有 Clang 参数 - for arg in clang_args { - builder = builder.clang_arg(arg); - } - - let bindings = builder.generate().expect("Unable to generate bindings"); - - bindings - .write_to_file(out_dir.join("dice-bindings.rs")) - .expect("Couldn't write bindings!"); - - // Cargo 链接指令 - println!("cargo:rustc-link-lib=static=opendice"); - println!("cargo:rerun-if-changed=opendice/dice/include/dice/android.h"); - println!("cargo:rerun-if-changed=opendice/tee_dice.h"); - for file in &src_files { - println!("cargo:rerun-if-changed={}", file); - } -} diff --git a/src/android.rs b/src/android.rs new file mode 100644 index 0000000000000000000000000000000000000000..30daf1d5f7ade7c9d1fae2b930607f1296733ebb --- /dev/null +++ b/src/android.rs @@ -0,0 +1,318 @@ +use crate::cbor_cert_op::{ + CborOut, DICE_CDI_SIZE, DiceInputValues, DiceResult, dice_clear_memory, + dice_cose_encode_public_key, Principal +}; +use crate::cbor_reader::CborIn; +use crate::dice::{ + DICE_PRIVATE_KEY_SEED_SIZE, dice_derive_cdi_private_key_seed, dice_main_flow +}; +use crate::mbedtls_sm2dsa::dice_keypair_from_seed; + +pub const DICE_PUBLIC_KEY_BUFFER_SIZE: usize = 64; +pub const DICE_PRIVATE_KEY_BUFFER_SIZE: usize = 32; +pub const DICE_SIGNATURE_BUFFER_SIZE: usize = 64; + +pub struct DiceAndroidConfigValues<'a> { + pub configs: u32, + pub component_name: &'a str, + pub component_version: u64, + pub security_version: u64, +} + +pub const DICE_ANDROID_CONFIG_COMPONENT_NAME: u32 = 1 << 0; +pub const DICE_ANDROID_CONFIG_COMPONENT_VERSION: u32 = 1 << 1; +pub const DICE_ANDROID_CONFIG_RESETTABLE: u32 = 1 << 2; +pub const DICE_ANDROID_CONFIG_SECURITY_VERSION: u32 = 1 << 3; +pub const DICE_ANDROID_CONFIG_RKP_VM_MARKER: u32 = 1 << 4; + +fn population_count(n: u32) -> usize { + n.count_ones() as usize +} + +pub fn dice_android_format_config_descriptor( + config_values: &DiceAndroidConfigValues, + buffer: &mut [u8], +) -> Result { + const K_COMPONENT_NAME_LABEL: i64 = -70002; + const K_COMPONENT_VERSION_LABEL: i64 = -70003; + const K_RESETTABLE_LABEL: i64 = -70004; + const K_SECURITY_VERSION_LABEL: i64 = -70005; + const K_RKP_VM_MARKER_LABEL: i64 = -70006; + + let mut out = CborOut::new(buffer); + out.write_map(population_count(config_values.configs as u32)); + if config_values.configs & DICE_ANDROID_CONFIG_COMPONENT_NAME != 0 && !config_values.component_name.is_empty() { + out.write_int(K_COMPONENT_NAME_LABEL); + out.write_tstr(config_values.component_name); + } + + if config_values.configs & DICE_ANDROID_CONFIG_COMPONENT_VERSION != 0 { + out.write_int(K_COMPONENT_VERSION_LABEL); + out.write_uint(config_values.component_version); + } + + if config_values.configs & DICE_ANDROID_CONFIG_RESETTABLE != 0 { + out.write_int(K_RESETTABLE_LABEL); + out.write_null(); + } + + if config_values.configs & DICE_ANDROID_CONFIG_SECURITY_VERSION != 0 { + out.write_int(K_SECURITY_VERSION_LABEL); + out.write_uint(config_values.security_version); + } + + if config_values.configs & DICE_ANDROID_CONFIG_RKP_VM_MARKER != 0 { + out.write_int(K_RKP_VM_MARKER_LABEL); + out.write_null(); + } + + if out.is_overflowed() { + Err(DiceResult::BufferTooSmall) + } else { + Ok(out.size()) + } +} + +pub fn dice_android_main_flow( + context:&mut u8, + current_cdi_attest: &[u8;DICE_CDI_SIZE], + current_cdi_seal: &[u8;DICE_CDI_SIZE], + chain: &[u8], + input_values: &DiceInputValues, + mut buffer: &mut [u8], + next_cdi_attest: &mut [u8; DICE_CDI_SIZE], + next_cdi_seal: &mut [u8; DICE_CDI_SIZE], +) -> Result { + let mut input = CborIn::new(chain); + let chain_item_count = input.read_array() + .map_err(|_| DiceResult::InvalidInput)?; + + if chain_item_count < 2 || chain_item_count == usize::MAX { + return Err(DiceResult::InvalidInput); + } + + let chain_items_offset = input.offset(); + for _ in 0..chain_item_count { + input.read_skip() + .map_err(|_| DiceResult::InvalidInput)?; + } + + let chain_items_size = input.offset() - chain_items_offset; + let mut out = CborOut::new(buffer); + out.write_array(chain_item_count+1); + let new_chain_prefix_size = out.size(); + if out.is_overflowed() || chain_items_size > buffer.len().saturating_sub(new_chain_prefix_size) { + // Continue with an empty buffer to measure the required size. + buffer = &mut []; + } else { + // Copy the chain items to the buffer. + let src_slice = &chain[chain_items_offset..chain_items_offset + chain_items_size]; + let dest_slice = &mut buffer[new_chain_prefix_size..new_chain_prefix_size + chain_items_size]; + dest_slice.copy_from_slice(src_slice); + buffer = &mut buffer[new_chain_prefix_size + chain_items_size..]; + } + + let certificate_size = dice_main_flow( + context, + current_cdi_attest, + current_cdi_seal, + input_values, + Some(buffer), + next_cdi_attest, + next_cdi_seal + )?; + + let actual_size = new_chain_prefix_size + chain_items_size + certificate_size; + + Ok(actual_size) +} + + + +fn dice_android_main_flow_with_new_dice_chain( + context:&mut u8, + current_cdi_attest: &[u8;DICE_CDI_SIZE], + current_cdi_seal: &[u8;DICE_CDI_SIZE], + input_values: &DiceInputValues, + mut buffer: &mut [u8], + next_cdi_attest: &mut [u8; DICE_CDI_SIZE], + next_cdi_seal: &mut [u8; DICE_CDI_SIZE], +) -> Result { + let mut current_cdi_private_key_seed = [0u8; DICE_PRIVATE_KEY_SEED_SIZE]; + let mut attestation_public_key = [0u8; DICE_PUBLIC_KEY_BUFFER_SIZE]; + let mut attestation_private_key = [0u8; DICE_PRIVATE_KEY_BUFFER_SIZE]; + + if let Err(e) = dice_derive_cdi_private_key_seed(context, current_cdi_attest, &mut current_cdi_private_key_seed) { + dice_clear_memory(context, DICE_PRIVATE_KEY_SEED_SIZE, current_cdi_private_key_seed.as_mut_ptr()); + return Err(e); + } + + match dice_keypair_from_seed(¤t_cdi_private_key_seed) { + Ok((pub_key, priv_key)) => { + attestation_public_key[..pub_key.len()].copy_from_slice(&pub_key); + attestation_private_key[..priv_key.len()].copy_from_slice(&priv_key); + } + Err(e) => { + dice_clear_memory(context, DICE_PRIVATE_KEY_SEED_SIZE, current_cdi_private_key_seed.as_mut_ptr()); + dice_clear_memory(context, DICE_PRIVATE_KEY_BUFFER_SIZE, attestation_private_key.as_mut_ptr()); + return Err(e); + } + } + + let mut out = CborOut::new(buffer); + out.write_array(2); + let encoded_size_used = out.size(); + if out.is_overflowed() { + buffer = &mut []; + } else if buffer.len() > encoded_size_used { + buffer = &mut buffer[encoded_size_used..]; + } else { + buffer = &mut []; + } + + let mut encoded_pub_key_size: usize = 0; + match dice_cose_encode_public_key(context, Principal::Authority, &attestation_public_key, buffer) { + Ok(size) => { + encoded_pub_key_size = size; + if size > 0 && buffer.len() > size { + buffer = &mut buffer[size..]; + } else { + buffer = &mut []; + } + } + + Err(DiceResult::BufferTooSmall) => { + buffer = &mut []; + } + + Err(e) => { + dice_clear_memory(context, DICE_PRIVATE_KEY_SEED_SIZE, current_cdi_private_key_seed.as_mut_ptr()); + dice_clear_memory(context, DICE_PRIVATE_KEY_BUFFER_SIZE, attestation_private_key.as_mut_ptr()); + return Err(e); + } + }; + + let chain_size = dice_main_flow( + context, current_cdi_attest, current_cdi_seal, input_values, + if buffer.is_empty() { None } else { Some(buffer) }, next_cdi_attest, next_cdi_seal)?; + + dice_clear_memory(context, DICE_PRIVATE_KEY_SEED_SIZE, current_cdi_private_key_seed.as_mut_ptr()); + dice_clear_memory(context, DICE_PRIVATE_KEY_BUFFER_SIZE, attestation_private_key.as_mut_ptr()); + + Ok(chain_size + encoded_size_used + encoded_pub_key_size) + +} + + +const K_CDI_ATTEST_LABEL:i64 = 1; +const K_CDI_SEAL_LABEL:i64 = 2; +const K_DICE_CHAIN_LABEL:i64 = 3; + +pub fn dice_android_handover_main_flow( + context: &mut u8, + handover: &[u8], + input_values: &DiceInputValues, + buffer: &mut [u8], +) -> Result { + let (current_cdi_attest, current_cdi_seal, chain) = dice_android_handover_parse(handover)?; + + let mut out = CborOut::new(buffer); + out.write_map(3); + out.write_int(K_CDI_ATTEST_LABEL); + // 预留空间给CDI_Attest + out.write_bstr(&[0u8; DICE_CDI_SIZE]); + out.write_int(K_CDI_SEAL_LABEL); + // 预留空间给CDI_Seal + out.write_bstr(&[0u8; DICE_CDI_SIZE]); + out.write_int(K_DICE_CHAIN_LABEL); + + let mut ignored_cdi_attest = [0u8; DICE_CDI_SIZE]; + let mut ignored_cdi_seal = [0u8; DICE_CDI_SIZE]; + let mut actual_next_cdi_attest = [0u8; DICE_CDI_SIZE]; + let mut actual_next_cdi_seal = [0u8; DICE_CDI_SIZE]; + + let out_size = out.size(); + let out_overflowed = out.is_overflowed(); + drop(out); + + let (next_cdi_attest, next_cdi_seal, remaining_buffer) = if out_overflowed { + // 进入测量模式:使用临时缓冲区 + (&mut ignored_cdi_attest, &mut ignored_cdi_seal, &mut [][..]) + } else { + // 正常模式:更新 buffer 指针(切片收缩) + if buffer.len() > out_size { + (&mut actual_next_cdi_attest, &mut actual_next_cdi_seal, &mut buffer[out_size..]) + } else { + (&mut ignored_cdi_attest, &mut ignored_cdi_seal, &mut [][..]) + } + }; + + let chain_size = if let Some(chain_data) = chain { + dice_android_main_flow(context, current_cdi_attest, current_cdi_seal, + chain_data, input_values, remaining_buffer, next_cdi_attest, next_cdi_seal)? + } else { + dice_android_main_flow_with_new_dice_chain(context, current_cdi_attest, current_cdi_seal, + input_values, remaining_buffer, next_cdi_attest, next_cdi_seal)? + }; + + Ok(out_size + chain_size) + +} + +pub fn dice_android_handover_parse( + handover: &[u8], +) -> Result<(&[u8; DICE_CDI_SIZE], &[u8; DICE_CDI_SIZE], Option<&[u8]>), DiceResult> { + let mut input = CborIn::new(handover); + + // 1. 读取 Map 头部 + let num_pairs = input.read_map().map_err(|_| DiceResult::InvalidInput)?; + if num_pairs < 2 { + return Err(DiceResult::InvalidInput); + } + + // 2. 读取 Attestation CDI (Label 1) + let label = input.read_int().map_err(|_| DiceResult::InvalidInput)?; + if label != K_CDI_ATTEST_LABEL { + return Err(DiceResult::InvalidInput); + } + let cdi_attest = input.read_bstr().map_err(|_| DiceResult::InvalidInput)?; + if cdi_attest.len() != DICE_CDI_SIZE { + return Err(DiceResult::InvalidInput); + } + + // 3. 读取 Sealing CDI (Label 2) + let label = input.read_int().map_err(|_| DiceResult::InvalidInput)?; + if label != K_CDI_SEAL_LABEL { + return Err(DiceResult::InvalidInput); + } + let cdi_seal = input.read_bstr().map_err(|_| DiceResult::InvalidInput)?; + if cdi_seal.len() != DICE_CDI_SIZE { + return Err(DiceResult::InvalidInput); + } + + // 4. 处理可选的 Dice Chain (Label 3) + let mut dice_chain = None; + if num_pairs >= 3 { + // 尝试读取下一个 Label,但不一定要报错 + if let Ok(label) = input.read_int() { + if label == K_DICE_CHAIN_LABEL { + let start = input.offset(); + input.read_skip().map_err(|_| DiceResult::InvalidInput)?; + let end = input.offset(); + // 截取 handover 的一部分作为 chain + dice_chain = Some(&handover[start..end]); + } + } + } + + // 转换为固定大小数组引用 + let cdi_attest_array: &[u8; DICE_CDI_SIZE] = cdi_attest.try_into() + .map_err(|_| DiceResult::InvalidInput)?; + let cdi_seal_array: &[u8; DICE_CDI_SIZE] = cdi_seal.try_into() + .map_err(|_| DiceResult::InvalidInput)?; + + Ok((cdi_attest_array, cdi_seal_array, dice_chain)) +} + + + \ No newline at end of file diff --git a/src/cbor_cert_op.rs b/src/cbor_cert_op.rs index 6d4506c54ff5206deb03d9ade712e87a6ba52f0c..a88cfbb73b45d9c6a154b9dee245330faa846417 100644 --- a/src/cbor_cert_op.rs +++ b/src/cbor_cert_op.rs @@ -1,4 +1,5 @@ -use crate::mbedtls_sm2dsa::{dice_hash, dice_kdf, dice_keypair_from_seed, dice_sign}; +use crate::mbedtls_sm2dsa::{dice_hash, dice_keypair_from_seed, dice_sign}; +use crate::dice::dice_derive_cdi_certificate_id; extern crate cty; pub const DICE_PUBLIC_KEY_BUFFER_SIZE: usize = 64; @@ -32,13 +33,6 @@ pub const K_COSE_KEY_KTY_EC2: i64 = 2; // Operations pub const K_COSE_KEY_OPS_VERIFY: i64 = 2; -pub const kIdSalt: [u8; 64] = [ - 0xDB, 0xDB, 0xAE, 0xBC, 0x80, 0x20, 0xDA, 0x9F, 0xF0, 0xDD, 0x5A, 0x24, 0xC8, 0x3A, 0xA5, 0xA5, - 0x42, 0x86, 0xDF, 0xC2, 0x63, 0x03, 0x1E, 0x32, 0x9B, 0x4D, 0xA1, 0x48, 0x43, 0x06, 0x59, 0xFE, - 0x62, 0xCD, 0xB5, 0xB7, 0xE1, 0xE0, 0x0F, 0xC6, 0x80, 0x30, 0x67, 0x11, 0xEB, 0x44, 0x4A, 0xF7, - 0x72, 0x09, 0x35, 0x94, 0x96, 0xFC, 0xFF, 0x1D, 0xB9, 0x52, 0x0B, 0xA5, 0x1C, 0x7B, 0x29, 0xEA, -]; - // DicePrincipal 枚举定义 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum Principal { @@ -84,6 +78,7 @@ pub enum DiceResult { } #[repr(u8)] +#[derive(PartialEq)] pub enum CborType { UnsignedInt = 0, NegativeInt = 1, @@ -264,7 +259,7 @@ impl<'a> CborOut<'a> { } } -pub fn EncodeProtectedAttributes( +pub fn encode_protected_attributes( context: &mut u8, // 假设 context 是某种上下文指针,使用 &mut u8 作为占位符 principal: Principal, buffer: &mut [u8], // 使用切片替代 uint8_t* 和 size_t @@ -281,9 +276,9 @@ pub fn EncodeProtectedAttributes( out.write_map(1); // 获取密钥参数 - // 这里调用之前定义的 KeyParam 和 DiceGetKeyParam + // 这里调用之前定义的 KeyParam 和 dice_get_key_param // 使用 ? 语法糖直接处理错误返回 - let key_param = DiceGetKeyParam(context, principal)?; + let key_param = dice_get_key_param(context, principal)?; // 写入算法信息 out.write_int(COSE_HEADER_ALG_LABEL); @@ -300,7 +295,7 @@ pub fn EncodeProtectedAttributes( /// 获取 Dice 密钥参数,SM2算法 /// 在纯 Rust 风格中,我们直接返回 Result /// 这样调用者可以直接拿到结果,而不是传入一个待修改的指针 -pub fn DiceGetKeyParam( +pub fn dice_get_key_param( _context: &mut u8, _principal: Principal, ) -> Result, DiceResult> { @@ -325,26 +320,7 @@ pub struct TbsResult { pub payload_offset: usize, } -pub fn dice_derive_cdi_certificate_id( - _context: &mut u8, - cdi_public_key: &[u8], - id: &mut [u8; DICE_ID_SIZE], // 确保这是 20 字节 -) -> Result<(), DiceResult> { - // 1. 定义 64 字节的固定 Salt - const ID_INFO: &[u8] = b"ID"; - - // 2. 调用 KDF (HKDF-Extract + HKDF-Expand) - // 直接传入 id 数组引用,结果会写进 id 中 - dice_kdf(cdi_public_key, Some(&kIdSalt), Some(ID_INFO), id) - .map_err(|_| DiceResult::PlatformError)?; - - // 3. 按照 DICE 标准清除最高位 - id[0] &= 0x7F; - - Ok(()) -} - -pub fn EncodeCoseTbs( +pub fn encode_cose_tbs( buffer: &mut [u8], protected_attributes: &[u8], payload_size: usize, @@ -380,7 +356,7 @@ pub fn EncodeCoseTbs( }) } -pub fn EncodeCoseSign1( +pub fn encode_cose_sign1( context: &mut u8, protected_attributes: &[u8], payload: &[u8], @@ -427,8 +403,8 @@ pub fn EncodeCoseSign1( } // 5. 获取签名参数并写入签名 - // 这里假设 DiceGetKeyParam 已经在别处实现 - let key_param = DiceGetKeyParam(context, Principal::Authority)?; + // 这里假设 dice_get_key_param 已经在别处实现 + let key_param = dice_get_key_param(context, Principal::Authority)?; out.write_bstr(&signature[..key_param.signature_size]); // 6. 检查溢出 @@ -440,7 +416,7 @@ pub fn EncodeCoseSign1( Ok(encoded_size) } -pub fn DiceCoseSignAndEncodeSign1( +pub fn dice_cose_sign_and_encode_sign1( context: &mut u8, payload: &[u8], aad: &[u8], @@ -453,18 +429,18 @@ pub fn DiceCoseSignAndEncodeSign1( // 假设这个函数返回 (实际长度) let prot_attrs_size = - EncodeProtectedAttributes(context, Principal::Authority, &mut protected_attributes) + encode_protected_attributes(context, Principal::Authority, &mut protected_attributes) .map_err(|_| DiceResult::PlatformError)?; let prot_attrs_slice = &protected_attributes[..prot_attrs_size]; // 2. 构建 TBS (To-Be-Signed) 结构 // 注意:TBS 会直接写在传入的 buffer 中 - let tbs_res = match EncodeCoseTbs(buffer, prot_attrs_slice, payload.len(), aad) { + let tbs_res = match encode_cose_tbs(buffer, prot_attrs_slice, payload.len(), aad) { Ok(res) => res, Err((DiceResult::BufferTooSmall, _tbs_size)) => { // 在 no_std 环境下无法使用 vec! 动态分配 - // 由于 EncodeCoseSign1 需要足够的空间来计算最终大小,这里无法完美处理 + // 由于 encode_cose_sign1 需要足够的空间来计算最终大小,这里无法完美处理 // 最安全的做法是直接返回错误,由调用者提供足够的 buffer return Err(DiceResult::BufferTooSmall); } @@ -490,7 +466,7 @@ pub fn DiceCoseSignAndEncodeSign1( .map_err(|_| DiceResult::PlatformError)?; // 5. 生成最终的 COSE_Sign1 结构 // 此时我们会覆写 buffer(重新从开头开始写,把之前的 TBS 覆盖掉) - EncodeCoseSign1( + encode_cose_sign1( context, prot_attrs_slice, payload, @@ -512,6 +488,7 @@ pub enum DiceConfigType { Inline, Descriptor, } + pub struct DiceInputValues<'a> { pub code_hash: [u8; DICE_HASH_SIZE], pub code_descriptor: &'a [u8], // 对应 const uint8_t* + size_t @@ -524,7 +501,34 @@ pub struct DiceInputValues<'a> { pub hidden: [u8; DICE_HIDDEN_SIZE], } -pub fn EncodeCwt( +// Provide a convenient way to create an all-zero/default value. +// Implementing `Default` allows callers to use `DiceInputValues::default()` +// or `DiceInputValues { ..Default::default() }` and keeps the layout +// compatible with the C-style zero initialization semantics. +impl<'a> Default for DiceInputValues<'a> { + fn default() -> Self { + Self { + code_hash: [0u8; DICE_HASH_SIZE], + code_descriptor: &[], + config_type: DiceConfigType::Inline, + config_value: [0u8; DICE_INLINE_CONFIG_SIZE], + config_descriptor: &[], + authority_hash: [0u8; DICE_HASH_SIZE], + authority_descriptor: &[], + mode: DiceMode::NotInitialized, + hidden: [0u8; DICE_HIDDEN_SIZE], + } + } +} + +impl<'a> DiceInputValues<'a> { + /// Convenience constructor identical to `Default::default()`. + pub fn new_zero() -> Self { + Default::default() + } +} + +pub fn encode_cwt( context: &mut u8, input_values: &DiceInputValues, authority_id_hex: &str, @@ -548,7 +552,7 @@ pub fn EncodeCwt( const KEY_USAGE_CERT_SIGN: u8 = 32; // 2. 获取 KeyParam (假设已经定义了该函数) - let key_param = DiceGetKeyParam(context, Principal::Subject)?; + let key_param = dice_get_key_param(context, Principal::Subject)?; // 3. 计算 Map 键值对数量 let mut map_pairs = 7; @@ -640,7 +644,6 @@ pub fn EncodeCwt( } } -//dice.c中的函数DiceDeriveCdiCertificateId的Rust版本 // no_std compatible hex encoding function pub fn dice_hex_encode(input: &[u8], output: &mut [u8]) { const HEX_MAP: &[u8; 16] = b"0123456789abcdef"; @@ -658,6 +661,21 @@ pub fn dice_hex_encode(input: &[u8], output: &mut [u8]) { } } +pub fn dice_clear_memory(_context: &mut u8, size: usize, address: *mut u8) { + // 检查空指针,虽然在 Rust 中调用者应确保安全,但为了逻辑一致性可以加上 + if address.is_null() { + return; + } + + for i in 0..size { + unsafe { + // 使用 write_volatile 确保每一位都被写入 0 + // offset 操作相当于 C 里的 p[i] + core::ptr::write_volatile(address.add(i), 0); + } + } +} + pub fn dice_generate_certificate( context: &mut u8, subject_seed: &[u8; DICE_PRIVATE_KEY_SEED_SIZE], @@ -682,7 +700,7 @@ pub fn dice_generate_certificate( // 4. 获取 Subject ID let mut subject_id = [0u8; DICE_ID_SIZE]; - let _subj_key_param = DiceGetKeyParam(context, Principal::Subject)?; + let _subj_key_param = dice_get_key_param(context, Principal::Subject)?; dice_derive_cdi_certificate_id(context, &subject_public, &mut subject_id)?; let mut subject_id_hex = [0u8; 41]; @@ -693,13 +711,13 @@ pub fn dice_generate_certificate( // 5. 派生 Authority 密钥对 let authority_public = [0u8; DICE_PUBLIC_KEY_BUFFER_SIZE]; dice_keypair_from_seed(authority_seed).map_err(|_| { - subject_private_buf.fill(0); + dice_clear_memory(context, DICE_PRIVATE_KEY_BUFFER_SIZE, subject_private_buf.as_mut_ptr()); DiceResult::PlatformError })?; // 6. 获取 Authority ID let mut authority_id = [0u8; DICE_ID_SIZE]; - let _auth_key_param = DiceGetKeyParam(context, Principal::Authority)?; + let _auth_key_param = dice_get_key_param(context, Principal::Authority)?; dice_derive_cdi_certificate_id(context, &authority_public, &mut authority_id)?; let mut authority_id_hex = [0u8; 41]; @@ -709,15 +727,15 @@ pub fn dice_generate_certificate( // 7. 编码公钥为 COSE_Key let mut encoded_pub_key = [0u8; DICE_MAX_PUBLIC_KEY_SIZE]; - let encoded_pub_key_size = DiceCoseEncodePublicKey( + let encoded_pub_key_size = dice_cose_encode_public_key( context, Principal::Subject, &subject_public, &mut encoded_pub_key, ) .map_err(|_| { - subject_private_buf.fill(0); - authority_private_buf.fill(0); + dice_clear_memory(context, DICE_PRIVATE_KEY_BUFFER_SIZE, subject_private_buf.as_mut_ptr()); + dice_clear_memory(context, DICE_PRIVATE_KEY_BUFFER_SIZE, authority_private_buf.as_mut_ptr()); DiceResult::PlatformError })?; let encoded_pub_key_slice = &encoded_pub_key[..encoded_pub_key_size]; @@ -725,17 +743,15 @@ pub fn dice_generate_certificate( // 8. 编码受保护属性 let mut protected_attrs = [0u8; DICE_MAX_PROTECTED_ATTRIBUTES_SIZE]; let prot_attrs_size = - EncodeProtectedAttributes(context, Principal::Authority, &mut protected_attrs).map_err( - |_| { - subject_private_buf.fill(0); - authority_private_buf.fill(0); + encode_protected_attributes(context, Principal::Authority, &mut protected_attrs).map_err(|_| { + dice_clear_memory(context, DICE_PRIVATE_KEY_BUFFER_SIZE, subject_private_buf.as_mut_ptr()); + dice_clear_memory(context, DICE_PRIVATE_KEY_BUFFER_SIZE, authority_private_buf.as_mut_ptr()); DiceResult::PlatformError - }, - )?; + })?; let prot_attrs_slice = &protected_attrs[..prot_attrs_size]; // 9. 计算 CWT 大小 - let cwt_size = match EncodeCwt( + let cwt_size = match encode_cwt( context, input_values, &authority_id_str, @@ -745,18 +761,18 @@ pub fn dice_generate_certificate( ) { Ok(s) => s, Err(e) => { - subject_private_buf.fill(0); - authority_private_buf.fill(0); + dice_clear_memory(context, DICE_PRIVATE_KEY_BUFFER_SIZE, subject_private_buf.as_mut_ptr()); + dice_clear_memory(context, DICE_PRIVATE_KEY_BUFFER_SIZE, authority_private_buf.as_mut_ptr()); return Err(e); } }; // 10. 编码 TBS - let tbs_res = match EncodeCoseTbs(certificate, prot_attrs_slice, cwt_size, &[]) { + let tbs_res = match encode_cose_tbs(certificate, prot_attrs_slice, cwt_size, &[]) { Ok(r) => r, Err((e, _)) => { - subject_private_buf.fill(0); - authority_private_buf.fill(0); + dice_clear_memory(context, DICE_PRIVATE_KEY_BUFFER_SIZE, subject_private_buf.as_mut_ptr()); + dice_clear_memory(context, DICE_PRIVATE_KEY_BUFFER_SIZE, authority_private_buf.as_mut_ptr()); return Err(e); } }; @@ -764,19 +780,19 @@ pub fn dice_generate_certificate( // 11. 填充 Payload 区域 let payload_offset = tbs_res.payload_offset; let payload_end = payload_offset.checked_add(cwt_size).ok_or_else(|| { - subject_private_buf.fill(0); - authority_private_buf.fill(0); + dice_clear_memory(context, DICE_PRIVATE_KEY_BUFFER_SIZE, subject_private_buf.as_mut_ptr()); + dice_clear_memory(context, DICE_PRIVATE_KEY_BUFFER_SIZE, authority_private_buf.as_mut_ptr()); DiceResult::PlatformError })?; if payload_end > certificate.len() { - subject_private_buf.fill(0); - authority_private_buf.fill(0); + dice_clear_memory(context, DICE_PRIVATE_KEY_BUFFER_SIZE, subject_private_buf.as_mut_ptr()); + dice_clear_memory(context, DICE_PRIVATE_KEY_BUFFER_SIZE, authority_private_buf.as_mut_ptr()); return Err(DiceResult::BufferTooSmall); } let payload_buf = &mut certificate[payload_offset..payload_end]; - let final_cwt_size = match EncodeCwt( + let final_cwt_size = match encode_cwt( context, input_values, &authority_id_str, @@ -786,15 +802,15 @@ pub fn dice_generate_certificate( ) { Ok(s) => s, Err(_) => { - subject_private_buf.fill(0); - authority_private_buf.fill(0); + dice_clear_memory(context, DICE_PRIVATE_KEY_BUFFER_SIZE, subject_private_buf.as_mut_ptr()); + dice_clear_memory(context, DICE_PRIVATE_KEY_BUFFER_SIZE, authority_private_buf.as_mut_ptr()); return Err(DiceResult::PlatformError); } }; if final_cwt_size != cwt_size { - subject_private_buf.fill(0); - authority_private_buf.fill(0); + dice_clear_memory(context, DICE_PRIVATE_KEY_BUFFER_SIZE, subject_private_buf.as_mut_ptr()); + dice_clear_memory(context, DICE_PRIVATE_KEY_BUFFER_SIZE, authority_private_buf.as_mut_ptr()); return Err(DiceResult::PlatformError); } @@ -807,22 +823,22 @@ pub fn dice_generate_certificate( &mut signature, ) .map_err(|_| { - subject_private_buf.fill(0); - authority_private_buf.fill(0); + dice_clear_memory(context, DICE_PRIVATE_KEY_BUFFER_SIZE, subject_private_buf.as_mut_ptr()); + dice_clear_memory(context, DICE_PRIVATE_KEY_BUFFER_SIZE, authority_private_buf.as_mut_ptr()); DiceResult::PlatformError })?; // 13. 生成最终 COSE_Sign1 - // 注意:EncodeCoseSign1 会写入到 certificate,所以需要复制 payload 以避免借用冲突 + // 注意:encode_cose_sign1 会写入到 certificate,所以需要复制 payload 以避免借用冲突 let mut payload_copy = [0u8; 2048]; let payload_len = payload_end - payload_offset; if payload_len > payload_copy.len() { - subject_private_buf.fill(0); - authority_private_buf.fill(0); + dice_clear_memory(context, DICE_PRIVATE_KEY_BUFFER_SIZE, subject_private_buf.as_mut_ptr()); + dice_clear_memory(context, DICE_PRIVATE_KEY_BUFFER_SIZE, authority_private_buf.as_mut_ptr()); return Err(DiceResult::BufferTooSmall); } payload_copy[..payload_len].copy_from_slice(&certificate[payload_offset..payload_end]); - let cert_size = EncodeCoseSign1( + let cert_size = encode_cose_sign1( context, prot_attrs_slice, &payload_copy[..payload_len], @@ -831,26 +847,26 @@ pub fn dice_generate_certificate( certificate, ) .map_err(|e| { - subject_private_buf.fill(0); - authority_private_buf.fill(0); + dice_clear_memory(context, DICE_PRIVATE_KEY_BUFFER_SIZE, subject_private_buf.as_mut_ptr()); + dice_clear_memory(context, DICE_PRIVATE_KEY_BUFFER_SIZE, authority_private_buf.as_mut_ptr()); e })?; // 14. 清除敏感数据 - subject_private_buf.fill(0); - authority_private_buf.fill(0); + dice_clear_memory(context, DICE_PRIVATE_KEY_BUFFER_SIZE, subject_private_buf.as_mut_ptr()); + dice_clear_memory(context, DICE_PRIVATE_KEY_BUFFER_SIZE, authority_private_buf.as_mut_ptr()); Ok(cert_size) } // FFI: 编码公钥为 COSE_Key -pub fn DiceCoseEncodePublicKey( +pub fn dice_cose_encode_public_key( context: &mut u8, principal: Principal, public_key: &[u8; DICE_PUBLIC_KEY_BUFFER_SIZE], buffer: &mut [u8], ) -> Result { - let key_param = DiceGetKeyParam(context, principal)?; + let key_param = dice_get_key_param(context, principal)?; let mut out = CborOut::new(buffer); // 1. 根据 KTY 确定 Map 长度 diff --git a/src/cbor_reader.rs b/src/cbor_reader.rs new file mode 100644 index 0000000000000000000000000000000000000000..ca0642d77ef95f725d1e5adaa0703f8a40d42570 --- /dev/null +++ b/src/cbor_reader.rs @@ -0,0 +1,348 @@ +use crate::cbor_cert_op::{ CborType }; + +pub struct CborIn<'a> { + pub buffer: &'a [u8], + pub cursor: usize, +} + +#[derive(Debug, PartialEq, Eq)] +pub enum CborReadResult { + Ok, + End, + Malformed, + NotFound, +} + +impl<'a> CborIn<'a> { + pub fn new(buffer: &'a [u8]) -> Self { + CborIn { + buffer, + cursor: 0, + } + } + + /// 对应 CborInOffset + /// 获取当前的偏移量 + pub fn offset(&self) -> usize { + self.cursor + } + + /// 对应 CborInAtEnd + /// 检查是否已经读取到末尾 + pub fn is_at_end(&self) -> bool { + self.cursor == self.buffer.len() + } + + pub fn read_would_overflow(&self, size: usize) -> bool { + + match self.cursor.checked_add(size) { + Some(end_pos) => { + // 如果没有溢出,检查是否超过了缓冲区的实际长度 + end_pos > self.buffer.len() + } + None => { + // 如果 cursor + size 发生了 usize 溢出,说明肯定超出了内存范围 + true + } + } + } + + pub fn peek_initial_value_and_argument(&self) -> Result<(u8, CborType, u64), CborReadResult> { + // 检查是否已到末尾 + if self.cursor >= self.buffer.len() { + return Err(CborReadResult::End); + } + + let initial_byte = self.buffer[self.cursor]; + + // 解析类型:C 里的 (initial_byte >> 5) 对应 enum 的判别值 + // 这里使用 try_from 的逻辑,或者简单的 match + let cbor_type = match initial_byte >> 5 { + 0 => CborType::UnsignedInt, + 1 => CborType::NegativeInt, + 2 => CborType::ByteString, + 3 => CborType::TextString, + 4 => CborType::Array, + 5 => CborType::Map, + 6 => CborType::Tag, + 7 => CborType::Simple, + _ => return Err(CborReadResult::Malformed), // 理论上 3-bit 不会超过 7 + }; + + let additional_info = initial_byte & 0x1f; + let mut bytes: u8 = 1; + let value: u64; + + if additional_info <= 23 { + value = additional_info as u64; + } else if (24..=27).contains(&additional_info) { + // 计算后续字节数: 24->2, 25->3, 26->5, 27->9 + // 逻辑: 1 + 2^(additional_info - 24) + bytes = 1 + (1 << (additional_info - 24)); + + if self.read_would_overflow(bytes as usize) { + return Err(CborReadResult::End); + } + + // 使用切片操作和 big-endian 转换,替代 C 语言的手动位移 + // 这样更安全且可读性更高 + let start = self.cursor + 1; + let end = self.cursor + bytes as usize; + let data = &self.buffer[start..end]; + + value = match additional_info { + 24 => data[0] as u64, + 25 => u16::from_be_bytes([data[0], data[1]]) as u64, + 26 => u32::from_be_bytes([data[0], data[1], data[2], data[3]]) as u64, + 27 => u64::from_be_bytes([ + data[0], data[1], data[2], data[3], + data[4], data[5], data[6], data[7] + ]), + _ => unreachable!(), + }; + } else { + // 不支持不定长 (31) 或保留值 (28-30) + return Err(CborReadResult::Malformed); + } + + Ok((bytes, cbor_type, value)) + } + + pub fn read_size(&mut self, expected_type: CborType) -> Result { + // 1. 调用之前转换好的 peek 函数(注意:peek 不改变 cursor) + let (bytes, actual_type, raw_val) = self.peek_initial_value_and_argument()?; + + // 2. 校验类型是否匹配 + if actual_type != expected_type { + return Err(CborReadResult::NotFound); + } + + // 3. 校验 raw_val 是否超过当前平台的 usize 限制 (对应 C 的 SIZE_MAX) + // 在 32 位系统上 raw_val 可能超过 usize,在 64 位系统上通常不会 + if raw_val > usize::MAX as u64 { + return Err(CborReadResult::Malformed); + } + + let size = raw_val as usize; + + // 4. 更新 cursor (Consume the bytes) + // 这里可以直接加,因为 peek 内部已经用 read_would_overflow 检查过边界了 + self.cursor += bytes as usize; + + Ok(size) + } + + /// 对应 C 语言的 CborReadStr + /// 用于读取 ByteString 或 TextString,返回数据切片 + pub fn read_str(&mut self, expected_type: CborType) -> Result<&'a [u8], CborReadResult> { + // 使用 clone 模拟 C 的 peeker 结构体拷贝(CborIn 仅包含引用和索引,拷贝成本极低) + let mut peeker = CborIn { + buffer: self.buffer, + cursor: self.cursor, + }; + + // 获取字符串长度 + let size = peeker.read_size(expected_type)?; + + // 检查数据内容是否溢出 + if peeker.read_would_overflow(size) { + return Err(CborReadResult::End); + } + + let start = peeker.cursor; + let end = start + size; + let data = &self.buffer[start..end]; + + // 更新原始 cursor:跳过 header 字节 + 数据长度 + self.cursor = end; + + Ok(data) + } + + /// 对应 C 语言的 CborReadSimple + /// 检查是否为特定的 Simple Value(如 true, false, null) + pub fn read_simple(&mut self, expected_val: u8) -> Result<(), CborReadResult> { + let (bytes, actual_type, raw_val) = self.peek_initial_value_and_argument()?; + + if actual_type != CborType::Simple || raw_val != expected_val as u64 { + return Err(CborReadResult::NotFound); + } + + self.cursor += bytes as usize; + Ok(()) + } + + /// 对应 C 语言的 CborReadInt + /// 支持正整数和负整数转换,返回 i64 + pub fn read_int(&mut self) -> Result { + let (bytes, actual_type, raw_val) = self.peek_initial_value_and_argument()?; + + if actual_type != CborType::UnsignedInt && actual_type != CborType::NegativeInt { + return Err(CborReadResult::NotFound); + } + + // CBOR 负数定义为 -1 - raw_val,因此 raw_val 最大为 i64::MAX + // 才能保证结果在 i64 范围内 (即 -1 - 2^63+1 = -2^63) + if raw_val > i64::MAX as u64 && actual_type == CborType::UnsignedInt { + return Err(CborReadResult::Malformed); + } + + let val = if actual_type == CborType::NegativeInt { + // C 逻辑: -1 - (int64_t)raw + // 这里需要注意溢出保护,但 raw_val <= i64::MAX 已经处理了大部分情况 + -1i64.checked_sub(raw_val as i64).ok_or(CborReadResult::Malformed)? + } else { + raw_val as i64 + }; + + self.cursor += bytes as usize; + Ok(val) + } + + /// 对应 C 语言的 CborReadUint + /// 仅读取正整数 + pub fn read_uint(&mut self) -> Result { + let (bytes, actual_type, raw_val) = self.peek_initial_value_and_argument()?; + + if actual_type != CborType::UnsignedInt { + return Err(CborReadResult::NotFound); + } + + self.cursor += bytes as usize; + Ok(raw_val) + } + + pub fn read_bstr(&mut self) -> Result<&'a [u8], CborReadResult> { + self.read_str(CborType::ByteString) + } + + pub fn read_tstr(&mut self) -> Result<&'a [u8], CborReadResult> { + self.read_str(CborType::TextString) + } + + pub fn read_array(&mut self) -> Result { + self.read_size(CborType::Array) + } + + pub fn read_map(&mut self) -> Result { + self.read_size(CborType::Map) + } + + pub fn read_tag(&mut self) -> Result { + match self.peek_initial_value_and_argument() { + Ok((bytes, CborType::Tag, tag_val)) => { + self.cursor += bytes as usize; + Ok(tag_val) + } + // 如果类型不匹配 + Ok(_) => Err(CborReadResult::NotFound), + // 如果 peek 本身就出错了(如 End 或 Malformed),直接透传错误 + Err(e) => Err(e), + } + } + + fn read_false(&mut self) -> Result<(), CborReadResult> { + self.read_simple(20) + } + + fn read_true(&mut self) -> Result<(), CborReadResult> { + self.read_simple(21) + } + + pub fn read_null(&mut self) -> Result<(), CborReadResult> { + self.read_simple(22) + } + + pub fn read_skip(&mut self) -> Result<(), CborReadResult> { + // 定义栈大小,与 C 语言定义的宏 CBOR_READ_SKIP_STACK_SIZE 对应 + const STACK_SIZE: usize = 16; + let mut size_stack = [0usize; STACK_SIZE]; + let mut stack_depth: usize = 0; + + let mut peeker_cursor = self.cursor; + + // 初始化:我们要跳过 1 个完整的数据项 + size_stack[stack_depth] = 1; + stack_depth += 1; + + while stack_depth > 0 { + // 1. Peek 当前项 + let (bytes, cbor_type, val) = self.peek_at(peeker_cursor)?; + + // 2. 消耗 Header 字节 + peeker_cursor += bytes as usize; + + // 3. 当前层级待处理项减 1 + size_stack[stack_depth - 1] -= 1; + if size_stack[stack_depth - 1] == 0 { + stack_depth -= 1; + } + + // 4. 根据类型决定下一步动作 + // 使用 match 代替 switch + let next_nesting_count: u64 = match cbor_type { + // 基础类型直接跳过 + CborType::UnsignedInt | CborType::NegativeInt | CborType::Simple => { + 0 + } + // 字符串类型需要跳过其内容 + CborType::ByteString | CborType::TextString => { + if val > usize::MAX as u64 || self.peek_would_overflow_at(peeker_cursor, val as usize) { + return Err(CborReadResult::End); + } + peeker_cursor += val as usize; + 0 + } + // Map 的键值对是成对出现的,所以数量 * 2 + CborType::Map => { + val.checked_mul(2).ok_or(CborReadResult::Malformed)? + } + // Tag 后面跟着 1 个数据项 + CborType::Tag => 1, + // Array 后面跟着 val 个数据项 + CborType::Array => val, + }; + + // 5. 如果有嵌套内容(Array, Map, Tag),压入栈中 + if next_nesting_count > 0 { + if stack_depth == STACK_SIZE { + return Err(CborReadResult::Malformed); // 栈溢出 + } + if next_nesting_count > usize::MAX as u64 { + return Err(CborReadResult::End); + } + size_stack[stack_depth] = next_nesting_count as usize; + stack_depth += 1; + } + } + + // 最终更新原始光标 + self.cursor = peeker_cursor; + Ok(()) + } + + /// 辅助方法:在指定位置进行 peek 而不移动 self.cursor + fn peek_at(&self, pos: usize) -> Result<(u8, CborType, u64), CborReadResult> { + let tmp_in = CborIn { + buffer: self.buffer, + cursor: pos, + }; + tmp_in.peek_initial_value_and_argument() + } + + /// 辅助方法:在指定位置检查是否溢出 + fn peek_would_overflow_at(&self, pos: usize, size: usize) -> bool { + match pos.checked_add(size) { + Some(end) => end > self.buffer.len(), + None => true, + } + } +} + + + + + + + + diff --git a/src/dice.rs b/src/dice.rs new file mode 100644 index 0000000000000000000000000000000000000000..19813c9e0689178d3d6ac94ec159cdc0af05a6ee --- /dev/null +++ b/src/dice.rs @@ -0,0 +1,196 @@ +use crate::cbor_cert_op::{ + DiceResult, DICE_ID_SIZE, DICE_HASH_SIZE, DICE_CDI_SIZE, DICE_HIDDEN_SIZE, + dice_clear_memory, DiceInputValues, DiceConfigType, dice_generate_certificate +}; +use crate::mbedtls_sm2dsa::{ dice_kdf, dice_hash }; + +pub const DICE_CODE_SIZE: usize = 64; +pub const DICE_CONFIG_SIZE: usize = 64; +pub const DICE_AUTHORITY_SIZE: usize = 64; +pub const DICE_MODE_SIZE: usize = 1; +pub const DICE_PRIVATE_KEY_SEED_SIZE: usize = 32; + +pub const K_ASYM_SALT: [u8; 64] = [ + 0x63, 0xB6, 0xA0, 0x4D, 0x2C, 0x07, 0x7F, 0xC1, 0x0F, 0x63, 0x9F, + 0x21, 0xDA, 0x79, 0x38, 0x44, 0x35, 0x6C, 0xC2, 0xB0, 0xB4, 0x41, + 0xB3, 0xA7, 0x71, 0x24, 0x03, 0x5C, 0x03, 0xF8, 0xE1, 0xBE, 0x60, + 0x35, 0xD3, 0x1F, 0x28, 0x28, 0x21, 0xA7, 0x45, 0x0A, 0x02, 0x22, + 0x2A, 0xB1, 0xB3, 0xCF, 0xF1, 0x67, 0x9B, 0x05, 0xAB, 0x1C, 0xA5, + 0xD1, 0xAF, 0xFB, 0x78, 0x9C, 0xCD, 0x2B, 0x0B, 0x3B +]; + +pub const K_ID_SALT: [u8; 64] = [ + 0xDB, 0xDB, 0xAE, 0xBC, 0x80, 0x20, 0xDA, 0x9F, 0xF0, 0xDD, 0x5A, 0x24, 0xC8, 0x3A, 0xA5, 0xA5, + 0x42, 0x86, 0xDF, 0xC2, 0x63, 0x03, 0x1E, 0x32, 0x9B, 0x4D, 0xA1, 0x48, 0x43, 0x06, 0x59, 0xFE, + 0x62, 0xCD, 0xB5, 0xB7, 0xE1, 0xE0, 0x0F, 0xC6, 0x80, 0x30, 0x67, 0x11, 0xEB, 0x44, 0x4A, 0xF7, + 0x72, 0x09, 0x35, 0x94, 0x96, 0xFC, 0xFF, 0x1D, 0xB9, 0x52, 0x0B, 0xA5, 0x1C, 0x7B, 0x29, 0xEA, +]; + +pub fn dice_derive_cdi_private_key_seed( + _context: &mut u8, + cdi_attest: &[u8; DICE_CDI_SIZE], + cdi_private_key_seed: &mut [u8; DICE_PRIVATE_KEY_SEED_SIZE], +) -> Result<(),DiceResult> { + + const ID_INFO: &[u8] = b"Key Pair"; + + dice_kdf(cdi_attest, Some(&K_ASYM_SALT), Some(ID_INFO), cdi_private_key_seed) + .map_err(|_| DiceResult::PlatformError)?; + + Ok(()) +} + + +pub fn dice_derive_cdi_certificate_id( + _context: &mut u8, + cdi_public_key: &[u8], + id: &mut [u8; DICE_ID_SIZE], // 确保这是 20 字节 +) -> Result<(),DiceResult> { + // 1. 定义 64 字节的固定 Salt + const ID_INFO: &[u8] = b"ID"; + + // 2. 调用 KDF (HKDF-Extract + HKDF-Expand) + // 直接传入 id 数组引用,结果会写进 id 中 + dice_kdf(cdi_public_key, Some(&K_ID_SALT), Some(ID_INFO), id) + .map_err(|_| DiceResult::PlatformError)?; + + // 3. 按照 DICE 标准清除最高位 + id[0] &= 0x7F; + + Ok(()) +} + +/// DiceMainFlow 的 Rust 实现 +/// +/// 根据输入值和当前 CDI 计算下一个 CDI 值和匹配的证书。 +/// +/// # 参数 +/// - `context`: 集成方提供的上下文指针(可为 null) +/// - `current_cdi_attest`: 当前的验证 CDI(如果是系统第一次调用,应使用 UDS) +/// - `current_cdi_seal`: 当前的密封 CDI(如果是系统第一次调用,应使用 UDS) +/// - `input_values`: 描述目标程序或系统的输入值集合 +/// - `next_cdi_certificate`: 存储生成的证书的缓冲区,为 None 表示不生成证书 +/// - `next_cdi_attest`: 返回派生的验证 CDI +/// - `next_cdi_seal`: 返回派生的密封 CDI +/// +/// # 返回值 +/// 返回实际生成的证书大小(字节数) +pub fn dice_main_flow( + context: &mut u8, + current_cdi_attest: &[u8; DICE_CDI_SIZE], + current_cdi_seal: &[u8; DICE_CDI_SIZE], + input_values: &DiceInputValues, + next_cdi_certificate: Option<&mut [u8]>, + next_cdi_attest: &mut [u8; DICE_CDI_SIZE], + next_cdi_seal: &mut [u8; DICE_CDI_SIZE], +) -> Result { + // 输入缓冲区布局: + // | Code Input | Config Input | Authority Input | Mode Input | Hidden Input | + const K_CODE_OFFSET: usize = 0; + const K_CONFIG_OFFSET: usize = K_CODE_OFFSET + DICE_CODE_SIZE; + const K_AUTHORITY_OFFSET: usize = K_CONFIG_OFFSET + DICE_CONFIG_SIZE; + const K_MODE_OFFSET: usize = K_AUTHORITY_OFFSET + DICE_AUTHORITY_SIZE; + const K_HIDDEN_OFFSET: usize = K_MODE_OFFSET + DICE_MODE_SIZE; + const INPUT_BUFFER_SIZE: usize = DICE_CODE_SIZE + DICE_CONFIG_SIZE + + DICE_AUTHORITY_SIZE + DICE_MODE_SIZE + DICE_HIDDEN_SIZE; + + // 1. 组装输入缓冲区 + let mut input_buffer = [0u8; INPUT_BUFFER_SIZE]; + + // 复制代码哈希 + input_buffer[K_CODE_OFFSET..K_CODE_OFFSET + DICE_CODE_SIZE] + .copy_from_slice(&input_values.code_hash); + + // 处理配置值:内联或哈希描述符 + if input_values.config_type == DiceConfigType::Inline { + input_buffer[K_CONFIG_OFFSET..K_CONFIG_OFFSET + DICE_CONFIG_SIZE] + .copy_from_slice(&input_values.config_value); + } else if input_values.config_descriptor.is_empty() { + return Err(DiceResult::InvalidInput); + } else { + let mut config_hash = [0u8; DICE_HASH_SIZE]; + dice_hash(context, input_values.config_descriptor, &mut config_hash) + .map_err(|_| DiceResult::PlatformError)?; + input_buffer[K_CONFIG_OFFSET..K_CONFIG_OFFSET + DICE_CONFIG_SIZE] + .copy_from_slice(&config_hash); + } + + // 复制授权机构哈希 + input_buffer[K_AUTHORITY_OFFSET..K_AUTHORITY_OFFSET + DICE_AUTHORITY_SIZE] + .copy_from_slice(&input_values.authority_hash); + + // 设置模式(1 字节) + input_buffer[K_MODE_OFFSET] = input_values.mode as u8; + + // 复制隐藏输入 + input_buffer[K_HIDDEN_OFFSET..K_HIDDEN_OFFSET + DICE_HIDDEN_SIZE] + .copy_from_slice(&input_values.hidden); + + // 2. 计算验证和密封的输入哈希 + let mut attest_input_hash = [0u8; DICE_HASH_SIZE]; + dice_hash(context, &input_buffer, &mut attest_input_hash) + .map_err(|_| DiceResult::PlatformError)?; + + let mut seal_input_hash = [0u8; DICE_HASH_SIZE]; + dice_hash( + context, + &input_buffer[K_AUTHORITY_OFFSET..K_AUTHORITY_OFFSET + DICE_AUTHORITY_SIZE + DICE_MODE_SIZE + DICE_HIDDEN_SIZE], + &mut seal_input_hash + ).map_err(|_| DiceResult::PlatformError)?; + + // 3. 派生下一个 CDI 值 + dice_kdf( + current_cdi_attest, + Some(&attest_input_hash), + Some(b"CDI_Attest"), + next_cdi_attest + ).map_err(|_| DiceResult::PlatformError)?; + + dice_kdf( + current_cdi_seal, + Some(&seal_input_hash), + Some(b"CDI_Seal"), + next_cdi_seal + ).map_err(|_| DiceResult::PlatformError)?; + + // 4. 生成证书(如果需要) + let certificate_size = if let Some(cert_buffer) = next_cdi_certificate { + if cert_buffer.is_empty() { + // 缓冲区为空,不生成证书 + 0 + } else { + // 派生当前和下一个 CDI 的私钥种子 + let mut current_cdi_private_key_seed = [0u8; DICE_PRIVATE_KEY_SEED_SIZE]; + dice_derive_cdi_private_key_seed(context, current_cdi_attest, &mut current_cdi_private_key_seed)?; + + let mut next_cdi_private_key_seed = [0u8; DICE_PRIVATE_KEY_SEED_SIZE]; + dice_derive_cdi_private_key_seed(context, next_cdi_attest, &mut next_cdi_private_key_seed)?; + + // 生成证书 + let cert_size = dice_generate_certificate( + context, + &next_cdi_private_key_seed, + ¤t_cdi_private_key_seed, + input_values, + cert_buffer, + )?; + + // 清除敏感的私钥种子 + dice_clear_memory(context, DICE_PRIVATE_KEY_SEED_SIZE, current_cdi_private_key_seed.as_mut_ptr()); + dice_clear_memory(context, DICE_PRIVATE_KEY_SEED_SIZE, next_cdi_private_key_seed.as_mut_ptr()); + + cert_size + } + } else { + // 不生成证书 + 0 + }; + + // 5. 清除敏感输入缓冲区 + dice_clear_memory(context, input_buffer.len(), input_buffer.as_mut_ptr()); + dice_clear_memory(context, DICE_HASH_SIZE, attest_input_hash.as_mut_ptr()); + dice_clear_memory(context, DICE_HASH_SIZE, seal_input_hash.as_mut_ptr()); + + Ok(certificate_size) +} + diff --git a/src/lib.rs b/src/lib.rs index 1de19d915fa6c67b9e5a82f48eadd3449b7135f2..87028b1efb57aba308608b232296088b86d6ecf3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,99 +6,32 @@ extern crate cty; pub mod cbor_cert_op; -mod mbedtls_sm2dsa; +pub mod mbedtls_sm2dsa; +pub mod cbor_reader; +pub mod dice; +pub mod tee_dice; +pub mod android; + pub use mbedtls_sm2dsa::{sm2_keypair_from_seed, sm2_sign, sm2_verify}; +pub use android::dice_android_handover_parse; +pub use tee_dice::{dice_init, dice_tee_handover_main_flow_chain, dice_tee_handover_main_flow_chain_code_hash}; +pub use cbor_cert_op::{DiceResult, DiceConfigType, DiceMode, DiceInputValues}; extern crate alloc; -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum DiceResult { - Ok, - InvalidInput, - BufferTooSmall, - PlatformError, -} - -mod bindings { - #![allow(non_camel_case_types)] - #![allow(non_snake_case)] - #![allow(non_upper_case_globals)] - #![allow(dead_code)] - include!(concat!(env!("OUT_DIR"), "/dice-bindings.rs")); -} - -pub use bindings::DICE_HIDDEN_SIZE; -pub use bindings::DiceAndroidConfigValues; -pub use bindings::DiceAndroidFormatConfigDescriptor; -pub use bindings::DiceAndroidHandoverParse; -pub use bindings::DiceAndroidMainFlow; -pub use bindings::DiceDeriveCdiPrivateKeySeed; -pub use bindings::DiceMainFlow; -pub use bindings::SM2KeypairFromSeed; -pub use bindings::{ - DICE_ANDROID_CONFIG_COMPONENT_NAME, DICE_ANDROID_CONFIG_COMPONENT_VERSION, - DICE_ANDROID_CONFIG_RESETTABLE, DICE_ANDROID_CONFIG_RKP_VM_MARKER, - DICE_ANDROID_CONFIG_SECURITY_VERSION, -}; -pub use bindings::{ - DiceConfigType, DiceConfigType_kDiceConfigTypeDescriptor, DiceConfigType_kDiceConfigTypeInline, -}; -pub use bindings::{DiceInputValues, DiceInputValues_}; -pub use bindings::{DiceMode, DiceMode_kDiceModeDebug, DiceMode_kDiceModeNormal}; -pub use bindings::{ - DiceResult_kDiceResultBufferTooSmall, DiceResult_kDiceResultInvalidInput, - DiceResult_kDiceResultOk, DiceResult_kDiceResultPlatformError, -}; - -pub fn dice_parse_handover<'a>(buffer: &'a [u8]) -> Result<(&'a [u8], &'a [u8], &'a [u8]), u32> { - let mut cdi_attest_ptr: *const u8 = core::ptr::null(); - let mut cdi_seal_ptr: *const u8 = core::ptr::null(); - let mut chain_ptr: *const u8 = core::ptr::null(); - let mut chain_size: usize = 0; - - let ret = unsafe { - bindings::DiceAndroidHandoverParse( - buffer.as_ptr(), - buffer.len(), - &mut cdi_attest_ptr, - &mut cdi_seal_ptr, - &mut chain_ptr, - &mut chain_size, - ) - }; - - if ret != bindings::DiceResult_kDiceResultOk { - return Err(ret); - } - - // 注意:长度按 DICE CDI 定义通常是 32 字节 - let cdi_attest = - unsafe { core::slice::from_raw_parts(cdi_attest_ptr, bindings::DICE_CDI_SIZE as usize) }; - let cdi_seal = - unsafe { core::slice::from_raw_parts(cdi_seal_ptr, bindings::DICE_CDI_SIZE as usize) }; - let chain = unsafe { core::slice::from_raw_parts(chain_ptr, chain_size) }; - - Ok((cdi_attest, cdi_seal, chain)) +/// Parse the Android handover buffer and extract CDI values and optional chain. +/// +/// * `buffer` – the handover buffer to parse. +/// +/// Returns a tuple of (cdi_attest, cdi_seal, chain) slices, or a DiceResult error. +pub fn dice_parse_handover<'a>(buffer: &'a [u8]) -> Result<(&'a [u8], &'a [u8], &'a [u8]), DiceResult> { + let (cdi_attest, cdi_seal, chain) = dice_android_handover_parse(buffer)?; + let chain_slice = chain.unwrap_or(&[]); + Ok((cdi_attest.as_slice(), cdi_seal.as_slice(), chain_slice)) } -pub fn dice_main_flow_chain<'a>(handover: &[u8], buffer: &'a mut [u8]) -> Result<&'a [u8], u32> { - let mut actual_size: usize = 0; - - let ret = unsafe { - bindings::DiceTeeHandoverMainFlowChain( - handover.as_ptr(), - handover.len(), - buffer.as_mut_ptr(), - buffer.len(), - &mut actual_size, - ) - }; - - if ret != bindings::DiceResult_kDiceResultOk { - return Err(ret); - } - - // 返回 buffer[..actual_size] 作为只读 slice +pub fn dice_main_flow_chain<'a>(handover: &[u8], buffer: &'a mut [u8]) -> Result<&'a [u8], DiceResult> { + let actual_size = dice_tee_handover_main_flow_chain(handover, buffer)?; Ok(&buffer[..actual_size]) } @@ -106,25 +39,7 @@ pub fn dice_main_flow_chain_codehash<'a>( handover: &[u8], codehash: &[u8], buffer: &'a mut [u8], -) -> Result<&'a [u8], u32> { - let mut actual_size: usize = 0; - - let ret = unsafe { - bindings::DiceTeeHandoverMainFlowChainCodeHash( - handover.as_ptr(), - handover.len(), - codehash.as_ptr(), - codehash.len(), - buffer.as_mut_ptr(), - buffer.len(), - &mut actual_size, - ) - }; - - if ret != bindings::DiceResult_kDiceResultOk { - return Err(ret); - } - - // 返回 buffer[..actual_size] 作为只读 slice +) -> Result<&'a [u8], DiceResult> { + let actual_size = dice_tee_handover_main_flow_chain_code_hash(handover, codehash, buffer)?; Ok(&buffer[..actual_size]) } diff --git a/src/mbedtls_sm2dsa.rs b/src/mbedtls_sm2dsa.rs index df8d5ed651b3828e3f21537293914e1acb93396b..815c771effe123dfbcea756c0c7425e6c9ec99fa 100644 --- a/src/mbedtls_sm2dsa.rs +++ b/src/mbedtls_sm2dsa.rs @@ -6,6 +6,8 @@ use mbedtls::hash::{Hmac, Type as HashType}; use mbedtls::pk::{EcGroupId, Pk, Type as PkType}; use mbedtls::rng::HmacDrbg as MbedtlsHmacDrbg; +use crate::cbor_cert_op::DiceResult; + // 重新定义常量(如果在其他地方没有定义的话) const DICE_PRIVATE_KEY_BUFFER_SIZE: usize = 32; const DICE_SIGNATURE_BUFFER_SIZE: usize = 64; @@ -254,12 +256,13 @@ pub fn sm2_verify(message: &[u8], signature: &[u8; 64], public_key: &[u8; 64]) - /// # 返回 /// * `Ok(([u8; 64], [u8; 32]))` - 成功时返回 (公钥, 私钥) 元组 /// * `Err(i32)` - 失败,返回错误码 -pub fn dice_keypair_from_seed(seed: &[u8; 32]) -> Result<([u8; 64], [u8; 32]), i32> { +pub fn dice_keypair_from_seed(seed: &[u8; 32]) -> Result<([u8; 64], [u8; 32]), DiceResult> { let mut public_key = [0u8; 64]; let mut private_key = [0u8; 32]; // 调用现有的 sm2_keypair_from_seed 函数 - sm2_keypair_from_seed(&mut public_key, &mut private_key, seed)?; + sm2_keypair_from_seed(&mut public_key, &mut private_key, seed) + .map_err(|_| DiceResult::PlatformError)?; Ok((public_key, private_key)) } diff --git a/src/tee_dice.rs b/src/tee_dice.rs new file mode 100644 index 0000000000000000000000000000000000000000..3ecf25ed9aba575bd7ab9ed5306a63aba22d653b --- /dev/null +++ b/src/tee_dice.rs @@ -0,0 +1,133 @@ +use crate::cbor_cert_op::{ + CborOut, DiceResult, DICE_CDI_SIZE, DICE_INLINE_CONFIG_SIZE, DiceInputValues +}; +use crate::mbedtls_sm2dsa::dice_kdf; +use crate::android::dice_android_handover_main_flow; + +pub const K_CDI_ATTEST_LABEL: i64 = 1; +pub const K_CDI_SEAL_LABEL: i64 = 2; +pub const K_CHAIN_LABEL: i64 = 3; +const DICE_HASH_SIZE: usize = 64; + + +pub const CODE_HASH: [u8; DICE_HASH_SIZE] = [ + 0x59, 0x0d, 0x30, 0x26, 0xdb, 0x37, 0xb7, 0x77, 0x98, 0x31, 0xf5, + 0xb7, 0x4f, 0xa4, 0x9a, 0xe4, 0x5d, 0x09, 0xc4, 0x6a, 0x50, 0x71, + 0x5a, 0xb0, 0x5e, 0x3d, 0xe2, 0xb6, 0x09, 0xf1, 0x82, 0x79, 0x03, + 0xeb, 0x9c, 0x29, 0x32, 0x13, 0xfe, 0x08, 0xc8, 0x7f, 0x35, 0x0f, + 0x86, 0x66, 0x2c, 0x99, 0x7d, 0x7b, 0x24, 0xff, 0xbb, 0xe0, 0x65, + 0x77, 0x2f, 0x84, 0x4a, 0xcb, 0x23, 0x7b, 0xf4, 0x90 +]; + +pub const CONFIG_VALUE: [u8; DICE_INLINE_CONFIG_SIZE] = [ + 0x83, 0x7b, 0x07, 0x82, 0xb8, 0x25, 0x61, 0xf3, 0x0a, 0xb3, 0x6f, + 0x95, 0x82, 0x93, 0xd5, 0x1d, 0x44, 0xaf, 0x04, 0x26, 0x94, 0x77, + 0x6d, 0x0f, 0x81, 0xee, 0xd7, 0x7d, 0xc3, 0xf6, 0x6a, 0x93, 0xd4, + 0x8f, 0x19, 0x7a, 0xad, 0x70, 0xbd, 0x41, 0xfc, 0x20, 0x20, 0x0e, + 0x29, 0x3e, 0xa9, 0x4d, 0x05, 0x56, 0x96, 0xf3, 0x8c, 0x51, 0x69, + 0x5b, 0xb0, 0xb6, 0xd3, 0xf2, 0xfe, 0x53, 0x96, 0xd0 +]; + + + +pub fn dice_tee_handover_main_flow( + buffer: &mut [u8], +) -> Result { + + let mut out = CborOut::new(buffer); + out.write_map(2); + out.write_int(K_CDI_ATTEST_LABEL); + let next_cdi_attest= match out.alloc_bstr(DICE_CDI_SIZE) { + Some(bstr) => bstr, + None => return Err(DiceResult::PlatformError), + }; + + const DATA_CDI: &[u8] = b"CDI_Attest"; + dice_kdf(DATA_CDI, Some(DATA_CDI), Some(DATA_CDI), next_cdi_attest) + .map_err(|_| DiceResult::PlatformError)?; + + out.write_int(K_CDI_SEAL_LABEL); + let next_cdi_seal =match out.alloc_bstr(DICE_CDI_SIZE) { + Some(bstr) => bstr, + None => return Err(DiceResult::PlatformError), + }; + + const DATA_CDI_SEAL: &[u8] = b"CDI_Seal"; + dice_kdf(DATA_CDI_SEAL, Some(DATA_CDI_SEAL), Some(DATA_CDI_SEAL), next_cdi_seal) + .map_err(|_| DiceResult::PlatformError)?; + + Ok(out.size()) +} + +pub fn dice_tee_handover_main_flow_chain_origin( + buffer: &mut [u8], +) -> Result { + // 1. 初始化 handover 缓冲区 (等同于 uint8_t handover[128] = {0}) + let mut handover = [0u8; 128]; + let handover_size: usize = handover.len(); + + // 2. 初始化 input_values (使用之前定义的 Default 或手动构建) + let mut input_values = DiceInputValues::new_zero(); + + // 3. 复制数据 (等同于 memcpy) + // 假设 code_hash 和 config_value 是全局常量或可访问的变量 + input_values.code_hash.copy_from_slice(&CODE_HASH); + input_values.config_value.copy_from_slice(&CONFIG_VALUE); + // authority_hash 已经在 new_zero() 中初始化为全 0,无需手动 memset + + // 4. 调用 TEE 层获取数据 + // 注意:Rust 传递 &mut [u8] 会自动处理长度 + let _handover_actual_size = dice_tee_handover_main_flow(&mut handover)?; + + // 5. 调用之前写好的 Android 处理流程 + // 只传递实际被写入的 handover 部分 + let actual_handover = &handover[..handover_size]; + + // 返回 Result,包含实际写入 buffer 的大小 + dice_android_handover_main_flow( + &mut 0, // 对应 C 中的 NULL context + actual_handover, + &input_values, + buffer, + ) +} + +/// Corresponds to `DiceTeeHandoverMainFlowChain` in C. +/// +/// * `handover` – slice containing the upstream handover data. +/// * `buffer` – output buffer where the Android flow will write its result. +pub fn dice_tee_handover_main_flow_chain( + handover: &[u8], + buffer: &mut [u8], +) -> Result { + let mut input_values = DiceInputValues::new_zero(); + input_values.code_hash.copy_from_slice(&CODE_HASH); + input_values.config_value.copy_from_slice(&CONFIG_VALUE); + // authority_hash is already zero from new_zero() + + dice_android_handover_main_flow(&mut 0, handover, &input_values, buffer) +} + +/// Corresponds to `DiceTeeHandoverMainFlowChainCodeHash` in C. +/// This variant allows the caller to specify a custom code hash. +pub fn dice_tee_handover_main_flow_chain_code_hash( + handover: &[u8], + codehash: &[u8], + buffer: &mut [u8], +) -> Result { + let mut input_values = DiceInputValues::new_zero(); + // copy at most the size of the destination + let len = core::cmp::min(codehash.len(), input_values.code_hash.len()); + input_values.code_hash[..len].copy_from_slice(&codehash[..len]); + input_values.config_value.copy_from_slice(&CONFIG_VALUE); + // authority_hash remains zero + + dice_android_handover_main_flow(&mut 0, handover, &input_values, buffer) +} + +pub fn dice_init() { + // correspond to C's DiceTeeHandoverMainFlowChainOrigin(256, NULL, NULL) + // allocate a dummy buffer and ignore the result + let mut buf = [0u8; 256]; + let _ = dice_tee_handover_main_flow_chain_origin(&mut buf); +} \ No newline at end of file