You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

LPC55S69板Rust调用C库crypto_sign_keypair接口卡死问题求助

问题:Rust调用LPC55S69上的C加密库接口时永久卡死

我在LPC55S69开发板上用Rust调用一个C加密库,目标接口来自pqm4项目中dilithium2的m4f实现:

int crypto_sign_keypair(uint8_t *pk, uint8_t *sk);

我的Rust代码如下,调用crypto_sign_keypair时程序永久卡死:

#![no_std]
#![no_main]
pub const PUBLICKEYBYTES: usize = 1312;
pub const SECRETKEYBYTES: usize = 2558;

extern "C" {
    pub fn crypto_sign_keypair(pk: *mut u8, sk: *mut u8) -> cty::c_int;
}

#[cortex_m_rt::entry]
fn main() -> ! {
  let mut public_key: [u8; PUBLICKEYBYTES] = [0u8; PUBLICKEYBYTES];
  let mut secret_key: [u8; SECRETKEYBYTES] = [0u8; SECRETKEYBYTES];
  let res = unsafe { crypto_sign_keypair(public_key.as_mut_ptr(), secret_key.as_mut_ptr()) }; // 此处卡死
}

相同的接口在C程序中运行正常,C调用示例:

#define SECRETKEYBYTES 2558
#define PUBLICKEYBYTES 1312
int main(void) {
  uint8_t sk[SECRETKEYBYTES], pk[PUBLICKEYBYTES];
  crypto_sign_keypair(pk, sk);
}

请问Rust代码哪里出错了?


排查方向与解决方案

1. 栈空间不足导致溢出

LPC55S69的默认栈空间通常较小(比如2KB),而Rust代码中public_key和secret_key两个数组合计占用3870字节(1312+2558),直接分配在栈上会触发栈溢出,导致程序卡死。

解决方法:

  • 将数组改为静态分配(存放在RAM的静态区域):
#![no_std]
#![no_main]
pub const PUBLICKEYBYTES: usize = 1312;
pub const SECRETKEYBYTES: usize = 2558;

extern "C" {
    pub fn crypto_sign_keypair(pk: *mut u8, sk: *mut u8) -> cty::c_int;
}

// 静态分配数组,避免栈溢出
static mut PUBLIC_KEY: [u8; PUBLICKEYBYTES] = [0u8; PUBLICKEYBYTES];
static mut SECRET_KEY: [u8; SECRETKEYBYTES] = [0u8; SECRETKEYBYTES];

#[cortex_m_rt::entry]
fn main() -> ! {
  let res = unsafe { 
    crypto_sign_keypair(PUBLIC_KEY.as_mut_ptr(), SECRET_KEY.as_mut_ptr()) 
  };
  loop {} // 必须添加死循环,符合no_main的要求
}
  • 或者修改项目链接脚本,增大栈的分配大小。

2. 编译目标与C库ABI不匹配

C库是针对Cortex-M4F编译的,需要确保Rust的编译目标和C库的编译选项一致,尤其是浮点ABI设置:

  • 检查.cargo/config.toml中是否指定了正确的硬浮点目标:
[build]
target = "thumbv7em-none-eabihf"
  • 确保C库编译时启用了-mfloat-abi=hard、-mfpu=fpv4-sp-d16等对应选项,否则会因寄存器调用约定不匹配导致程序卡死。

3. 未初始化硬件随机数发生器(RNG)

crypto_sign_keypair生成密钥依赖硬件随机数,C程序中可能已经初始化了LPC55S69的RNG模块,但Rust代码中缺少这一步,导致C库卡在等待随机数据的环节。

解决方法:
调用C接口前,用Rust HAL库初始化RNG:

#![no_std]
#![no_main]
pub const PUBLICKEYBYTES: usize = 1312;
pub const SECRETKEYBYTES: usize = 2558;

use lpc55_hal::peripherals::RNG;
use lpc55_hal::prelude::*;
use cortex_m_rt::entry;

extern "C" {
    pub fn crypto_sign_keypair(pk: *mut u8, sk: *mut u8) -> cty::c_int;
}

#[entry]
fn main() -> ! {
  // 初始化HAL和RNG
  let hal = lpc55_hal::new();
  let _rng = hal.RNG.enabled();

  let mut public_key: [u8; PUBLICKEYBYTES] = [0u8; PUBLICKEYBYTES];
  let mut secret_key: [u8; SECRETKEYBYTES] = [0u8; SECRETKEYBYTES];
  
  let res = unsafe { crypto_sign_keypair(public_key.as_mut_ptr(), secret_key.as_mut_ptr()) };
  
  loop {}
}

4. 内存对齐问题(可能性较低)

虽然u8数组默认是1字节对齐,但部分加密库可能要求指针按4字节或8字节对齐。可以尝试强制数组对齐:

#[repr(align(4))]
struct AlignedPublicKey([u8; PUBLICKEYBYTES]);
#[repr(align(4))]
struct AlignedSecretKey([u8; SECRETKEYBYTES]);

// 在main中使用:
let mut public_key = AlignedPublicKey([0u8; PUBLICKEYBYTES]);
let mut secret_key = AlignedSecretKey([0u8; SECRETKEYBYTES]);
let res = unsafe { 
  crypto_sign_keypair(public_key.0.as_mut_ptr(), secret_key.0.as_mut_ptr()) 
};

内容的提问来源于stack exchange,提问作者tarun14110

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 05:27:54