AES-GCM 与用户空间的内核加密 API

问题描述 投票:0回答:2

我正在尝试使用内核加密 API 从用户空间与硬件加速器进行通信。 我使用

af_alg
与内核进行通信。我可以使用 API 进行散列或“正常”对称加密,但我无法让它与 aead 算法一起使用。驱动程序已在
/proc/crypto
下注册。 我按照用户空间接口的内核文档来准备消息,但每次都会收到相同的错误Invalig Argument

#ifndef AF_ALG
#define AF_ALG 38
#endif
#ifndef SOL_ALG
#define SOL_ALG 279
#endif

int main(void)
{
 int openfd;
 int tfmfd;

 char key [16] = "SecretKeyforAES!";
 char initVector[12] = "123456789012";
 //initiaze vector, in/out vector and buffer
 struct af_alg_iv *iv;
 struct iovec iov;
 char buf[64];
 //size of the aad and the auth tag
 uint32_t aadSize = 8;
 uint32_t taglen = 12;

 //define algorithm used for cryptography
 struct sockaddr_alg sa = {
        .salg_family = AF_ALG,
        .salg_type = "aead",
        .salg_name = "gcm(aes)"
 };
 //create and bind socket
 tfmfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
 printf("open socket\n");
 int bindvalue = bind(tfmfd, (struct sockaddr *) &sa, sizeof(sa));
 if(bindvalue != 0){
        perror("send != 0");
 }
 assert(bindvalue == 0);

 printf("socket bound\n");

//set socket options: key, AEAD Authentication size
 setsockopt(tfmfd, SOL_ALG, ALG_SET_KEY, key, 16);
 int setTag = setsockopt(tfmfd, SOL_ALG, ALG_SET_AEAD_AUTHSIZE, NULL, taglen);
 assert(setTag >= 0);
 printf("set socket options\n");
 //accept connection
 openfd = accept(tfmfd, NULL, 0);

//check errors with the connections
 assert(tfmfd > 0);
 assert(openfd > 0);

 //Prepare Message
 struct msghdr msg = { 0 };
 struct cmsghdr *cmsg = NULL;
 char cbuf[128] = {0};

 msg.msg_control = cbuf;
 msg.msg_controllen = sizeof(cbuf);
 msg.msg_iovlen = 0;
 msg.msg_iov = NULL;

 //set the Headervalues for the  Operation
 cmsg = CMSG_FIRSTHDR(&msg);
 assert(cmsg != NULL);
 cmsg->cmsg_level = SOL_ALG;
 cmsg->cmsg_type = ALG_SET_OP;
 cmsg->cmsg_len = CMSG_LEN(CMSG_SPACE(sizeof(uint32_t)));
 *(__u32 *) CMSG_DATA(cmsg) = ALG_OP_ENCRYPT;

 //set headervalues for IV
 cmsg = CMSG_NXTHDR(&msg, cmsg);
 assert(cmsg != NULL);
 cmsg->cmsg_level = SOL_ALG;
 cmsg->cmsg_type = ALG_SET_IV;
 cmsg->cmsg_len = CMSG_LEN(CMSG_SPACE(sizeof(initVector))); //iv_msg_size

 //set value for iv
 iv = (void *)CMSG_DATA(cmsg);
 iv->ivlen = 12;
 memcpy(iv->iv, initVector, 12);

 //set headervalues for 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;
 printf("Header values set\n");

 //send initial message
 int send = sendmsg(openfd, &msg, MSG_MORE);
 if(send < 0){
        perror("send < 0");  //This is where the error occures
 }
 assert(send > 0); //This assertion fails following the error above
 printf("Send initial Message...\n");

按照内核文档,我准备了带有算法、iv 和 aad 信息长度的初始消息。 我也使用 setsockopt 设置 taglen 和模式。我阅读了

msghdr
cmsg
sendmsg
的手册页,但没有发现我的错误。

编辑:

  • 添加了对绑定失败的检查,但检查退出时显示 0 -> 无错误
c linux-kernel cryptography userspace
2个回答
0
投票

你数得不太正确

cmsg_len

对于第一个正确的值,虽然

CMSG_LEN(CMSG_SPACE(sizeof(uint32_t)))
反映了
ALG_SET_OP

但不是

CMSG_LEN(CMSG_SPACE(sizeof(initVector))); //iv_msg_size
,其中数据为
iv = (void *)CMSG_DATA(cmsg);
->
struct af_alg_iv *iv;
。 因此应该是
CMSG_LEN(sizeof(struct af_alg_iv) + sizeof(initVector))

此外,

char cbuf[128] = {0};
必须包含辅助数据的总大小,什么是
char cbuf[CMSG_SPACE(sizeof(uint32_t)) + CMSG_SPACE(sizeof(struct af_alg_iv) + sizeof(initVector))] = {0}


0
投票

设置

cmsg_len
的两个位置不应包含对
CMSG_SPACE()
宏的调用,因为该宏会使用
sizeof(struct cmsghdr)
来扩展消息长度。

© www.soinside.com 2019 - 2024. All rights reserved.