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

用户态下用内核Crypto API实现AES-GCM遇参数无效错误求助

问题分析与修复方案

你遇到的「Invalid Argument」错误来自以下几处代码逻辑问题,逐一修正即可解决:

1. ALG_SET_AEAD_AUTHSIZE 参数传递错误

setsockopt 的 ALG_SET_AEAD_AUTHSIZE 选项需要传入标签长度的指针,而非直接将长度作为 optlen 参数。原代码传入 NULL 作为 optval,导致内核无法获取正确的标签长度:

原错误代码:

int setTag = setsockopt(tfmfd, SOL_ALG, ALG_SET_AEAD_AUTHSIZE, NULL, taglen);

修正后:

int setTag = setsockopt(tfmfd, SOL_ALG, ALG_SET_AEAD_AUTHSIZE, &taglen, sizeof(taglen));

2. 控制消息长度计算错误

ALG_SET_OP 的 cmsg_len 错误

CMSG_LEN() 用于计算控制消息的总长度(包含 cmsghdr 结构和数据部分),不需要嵌套 CMSG_SPACE()。原代码多套一层导致长度计算过大:

原错误代码:

cmsg->cmsg_len = CMSG_LEN(CMSG_SPACE(sizeof(uint32_t)));

修正后:

cmsg->cmsg_len = CMSG_LEN(sizeof(uint32_t));

ALG_SET_IV 的 cmsg_len 错误

struct af_alg_iv 的实际大小是 ivlen(4字节)加上IV数据长度(12字节),原代码直接用 sizeof(initVector) 计算,未考虑结构本身的 ivlen 字段:

原错误代码:

cmsg->cmsg_len = CMSG_LEN(CMSG_SPACE(sizeof(initVector)));

修正后:

iv = (void *)CMSG_DATA(cmsg);
iv->ivlen = 12;
memcpy(iv->iv, initVector, 12);
// 基于实际IV结构大小计算cmsg_len
cmsg->cmsg_len = CMSG_LEN(sizeof(struct af_alg_iv) - sizeof(iv->iv) + iv->ivlen);

3. 缺少AAD数据发送逻辑

设置 ALG_SET_AEAD_ASSOCLEN 后,必须通过 sendmsg 发送对应长度的AAD数据,但原代码的 msg_iov 为空,内核无法获取AAD数据,导致参数不匹配。需要添加AAD的iovec配置:

在准备消息时补充:

// 对应aadSize=8的示例AAD数据
char aad_data[] = "testaad12";
struct iovec iov = {
    .iov_base = aad_data,
    .iov_len = aadSize
};

msg.msg_iov = &iov;
msg.msg_iovlen = 1;

完整修正后的核心代码片段

// 修正ALG_SET_AEAD_AUTHSIZE调用
int setTag = setsockopt(tfmfd, SOL_ALG, ALG_SET_AEAD_AUTHSIZE, &taglen, sizeof(taglen));
assert(setTag >= 0);

// ... 省略其他代码 ...

// Prepare Message
struct msghdr msg = { 0 };
struct cmsghdr *cmsg = NULL;
char cbuf[128] = {0};
char aad_data[] = "testaad12"; // 对应aadSize=8的AAD数据
struct iovec iov = {
    .iov_base = aad_data,
    .iov_len = aadSize
};

msg.msg_control = cbuf;
msg.msg_controllen = sizeof(cbuf);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;

// 设置加密操作类型
cmsg = CMSG_FIRSTHDR(&msg);
assert(cmsg != NULL);
cmsg->cmsg_level = SOL_ALG;
cmsg->cmsg_type = ALG_SET_OP;
cmsg->cmsg_len = CMSG_LEN(sizeof(uint32_t));
*(__u32 *) CMSG_DATA(cmsg) = ALG_OP_ENCRYPT;

// 设置IV
cmsg = CMSG_NXTHDR(&msg, cmsg);
assert(cmsg != NULL);
cmsg->cmsg_level = SOL_ALG;
cmsg->cmsg_type = ALG_SET_IV;
iv = (void *)CMSG_DATA(cmsg);
iv->ivlen = 12;
memcpy(iv->iv, initVector, 12);
cmsg->cmsg_len = CMSG_LEN(sizeof(struct af_alg_iv) - sizeof(iv->iv) + iv->ivlen);

// 设置AAD长度
uint32_t *assoclen = NULL;
cmsg = CMSG_NXTHDR(&msg, cmsg);
assert(cmsg != NULL);
cmsg->cmsg_level = SOL_ALG;
cmsg->cmsg_type = ALG_SET_AEAD_ASSOCLEN;
cmsg->cmsg_len = CMSG_LEN(sizeof(*assoclen));
assoclen = (void *) CMSG_DATA(cmsg);
*assoclen = (uint32_t)aadSize;

// 发送包含AAD的初始消息
int send_result = sendmsg(openfd, &msg, MSG_MORE);
if(send_result < 0){
    perror("sendmsg failed");
}
assert(send_result > 0);

额外注意事项

  • 确认硬件加速器驱动支持gcm(aes)的AEAD模式,可通过cat /proc/crypto | grep -A10 -B2 "gcm(aes)"查看驱动注册信息。
  • 后续需发送明文数据并接收密文+标签,发送明文时若为最后一段需去掉MSG_MORE标志。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 21:01:40