GCM-AEAD 支持 ubuntu 系统 运行 linux kernel-3.10
GCM-AEAD support for ubuntu system running linux kernel-3.10
我正在尝试使用 GCM 加密实现用于加密的 AEAD 示例代码。但是我在设置 key
时总是得到 invalid argument 错误
static int init_aead(void)
{
printk("Starting encryption\n");
struct crypto_aead *tfm = NULL;
struct aead_request *req;
struct tcrypt_result tresult;
struct scatterlist plaintext[1] ;
struct scatterlist ciphertext[1];
struct scatterlist gmactext[1];
unsigned char *plaindata = NULL;
unsigned char *cipherdata = NULL;
unsigned char *gmacdata = NULL;
const u8 *key = kmalloc(16, GFP_KERNEL);
char *algo = "rfc4106(gcm(aes))";
unsigned char *ivp = NULL;
int ret, i, d;
unsigned int iv_len;
unsigned int keylen = 16;
/* Allocating a cipher handle for AEAD */
tfm = crypto_alloc_aead(algo, 0, 0);
init_completion(&tresult.completion);
if(IS_ERR(tfm)) {
pr_err("alg: aead: Failed to load transform for %s: %ld\n", algo,
PTR_ERR(tfm));
return PTR_ERR(tfm);
}
/* Allocating request data structure to be used with AEAD data structure */
req = aead_request_alloc(tfm, GFP_KERNEL);
if(IS_ERR(req)) {
pr_err("Couldn't allocate request handle for %s:\n", algo);
return PTR_ERR(req);
}
/* Allocting a callback function to be used , when the request completes */
aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, aead_work_done,&tresult);
crypto_aead_clear_flags(tfm, ~0);
/* Set key */
get_random_bytes((void*)key, keylen);
if((ret = crypto_aead_setkey(tfm, key, 16) != 0)) {
pr_err("Return value for setkey is %d\n", ret);
pr_info("key could not be set\n");
ret = -EAGAIN;
return ret;
}
/* Set authentication tag length */
if(crypto_aead_setauthsize(tfm, 16)) {
pr_info("Tag size could not be authenticated\n");
ret = -EAGAIN;
return ret;
}
/* Set IV size */
iv_len = crypto_aead_ivsize(tfm);
if (!(iv_len)){
pr_info("IV size could not be authenticated\n");
ret = -EAGAIN;
return ret;
}
plaindata = kmalloc(16, GFP_KERNEL);
cipherdata = kmalloc(16, GFP_KERNEL);
gmacdata = kmalloc(16, GFP_KERNEL);
ivp = kmalloc(iv_len, GFP_KERNEL);
if(!plaindata || !cipherdata || !gmacdata || !ivp) {
printk("Memory not availaible\n");
ret = -ENOMEM;
return ret;
}
for (i = 0, d = 0; i < 16; i++, d++)
plaindata[i] = d;
memset(cipherdata, 0, 16);
memset(gmacdata, 0, 16);
for (i = 0,d=0xa8; i < 16; i++, d++)
ivp[i] = d;
sg_init_one(&plaintext[0], plaindata, 16);
sg_init_one(&ciphertext[0], cipherdata, 16);
sg_init_one(&gmactext[0], gmacdata, 128);
aead_request_set_crypt(req, plaintext, ciphertext, 16, ivp);
aead_request_set_assoc(req, gmactext, 16);
ret = crypto_aead_encrypt(req);
if (ret)
printk("cipher call returns %d \n", ret);
else
printk("Failure \n");
return 0;
}
module_init(init_aead);
module_exit(exit_aead);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("My code for aead encryption test");
}
插入模块后得到以下输出
Starting encryption
Return value for setkey is -22
key could not be set
根据 AEAD 规范,aead 使用 aes-128 进行加密,因此块大小应为 128 位。
但我的系统显示 AEAD 仅支持 1 字节块大小
name : rfc4106(gcm(aes))
driver : rfc4106-gcm-aesni
module : aesni_intel
priority : 400
refcnt : 1
selftest : passed
type : nivaead
async : yes
blocksize : 1
ivsize : 8
maxauthsize : 16
geniv : seqiv
是否因为块大小而抛出无效参数错误。如果是这样,我该怎么做才能让它发挥作用?
AES 的块大小确实总是 128 位。 GCM 的块大小是另一回事。顾名思义,GCM(Galois-Counter Mode)建立在 CTR(计数器)操作模式之上,有时也称为 SIC(分段整数计数器)操作模式。这将 AES 变成流密码。根据定义,流密码的块大小为一个字节(或者,更准确地说,一个位,但 API 通常不支持位级操作)。
然而,块大小与调用中显示的密钥大小关系不大,而且参数似乎确实需要字节而不是位(通常在位中定义密钥长度)。
IV 的大小应为 12 个字节(默认值)。否则,GCM 实现可能需要额外的计算(如果存在的话)。
对于 Aes GCM RFC 4106,密钥必须为 20 个字节。我还不知道为什么。我查看了 ipsec 源代码以了解如何进行加密。
我正在尝试使用 GCM 加密实现用于加密的 AEAD 示例代码。但是我在设置 key
时总是得到 invalid argument 错误static int init_aead(void)
{
printk("Starting encryption\n");
struct crypto_aead *tfm = NULL;
struct aead_request *req;
struct tcrypt_result tresult;
struct scatterlist plaintext[1] ;
struct scatterlist ciphertext[1];
struct scatterlist gmactext[1];
unsigned char *plaindata = NULL;
unsigned char *cipherdata = NULL;
unsigned char *gmacdata = NULL;
const u8 *key = kmalloc(16, GFP_KERNEL);
char *algo = "rfc4106(gcm(aes))";
unsigned char *ivp = NULL;
int ret, i, d;
unsigned int iv_len;
unsigned int keylen = 16;
/* Allocating a cipher handle for AEAD */
tfm = crypto_alloc_aead(algo, 0, 0);
init_completion(&tresult.completion);
if(IS_ERR(tfm)) {
pr_err("alg: aead: Failed to load transform for %s: %ld\n", algo,
PTR_ERR(tfm));
return PTR_ERR(tfm);
}
/* Allocating request data structure to be used with AEAD data structure */
req = aead_request_alloc(tfm, GFP_KERNEL);
if(IS_ERR(req)) {
pr_err("Couldn't allocate request handle for %s:\n", algo);
return PTR_ERR(req);
}
/* Allocting a callback function to be used , when the request completes */
aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, aead_work_done,&tresult);
crypto_aead_clear_flags(tfm, ~0);
/* Set key */
get_random_bytes((void*)key, keylen);
if((ret = crypto_aead_setkey(tfm, key, 16) != 0)) {
pr_err("Return value for setkey is %d\n", ret);
pr_info("key could not be set\n");
ret = -EAGAIN;
return ret;
}
/* Set authentication tag length */
if(crypto_aead_setauthsize(tfm, 16)) {
pr_info("Tag size could not be authenticated\n");
ret = -EAGAIN;
return ret;
}
/* Set IV size */
iv_len = crypto_aead_ivsize(tfm);
if (!(iv_len)){
pr_info("IV size could not be authenticated\n");
ret = -EAGAIN;
return ret;
}
plaindata = kmalloc(16, GFP_KERNEL);
cipherdata = kmalloc(16, GFP_KERNEL);
gmacdata = kmalloc(16, GFP_KERNEL);
ivp = kmalloc(iv_len, GFP_KERNEL);
if(!plaindata || !cipherdata || !gmacdata || !ivp) {
printk("Memory not availaible\n");
ret = -ENOMEM;
return ret;
}
for (i = 0, d = 0; i < 16; i++, d++)
plaindata[i] = d;
memset(cipherdata, 0, 16);
memset(gmacdata, 0, 16);
for (i = 0,d=0xa8; i < 16; i++, d++)
ivp[i] = d;
sg_init_one(&plaintext[0], plaindata, 16);
sg_init_one(&ciphertext[0], cipherdata, 16);
sg_init_one(&gmactext[0], gmacdata, 128);
aead_request_set_crypt(req, plaintext, ciphertext, 16, ivp);
aead_request_set_assoc(req, gmactext, 16);
ret = crypto_aead_encrypt(req);
if (ret)
printk("cipher call returns %d \n", ret);
else
printk("Failure \n");
return 0;
}
module_init(init_aead);
module_exit(exit_aead);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("My code for aead encryption test");
}
插入模块后得到以下输出
Starting encryption
Return value for setkey is -22
key could not be set
根据 AEAD 规范,aead 使用 aes-128 进行加密,因此块大小应为 128 位。
但我的系统显示 AEAD 仅支持 1 字节块大小
name : rfc4106(gcm(aes))
driver : rfc4106-gcm-aesni
module : aesni_intel
priority : 400
refcnt : 1
selftest : passed
type : nivaead
async : yes
blocksize : 1
ivsize : 8
maxauthsize : 16
geniv : seqiv
是否因为块大小而抛出无效参数错误。如果是这样,我该怎么做才能让它发挥作用?
AES 的块大小确实总是 128 位。 GCM 的块大小是另一回事。顾名思义,GCM(Galois-Counter Mode)建立在 CTR(计数器)操作模式之上,有时也称为 SIC(分段整数计数器)操作模式。这将 AES 变成流密码。根据定义,流密码的块大小为一个字节(或者,更准确地说,一个位,但 API 通常不支持位级操作)。
然而,块大小与调用中显示的密钥大小关系不大,而且参数似乎确实需要字节而不是位(通常在位中定义密钥长度)。
IV 的大小应为 12 个字节(默认值)。否则,GCM 实现可能需要额外的计算(如果存在的话)。
对于 Aes GCM RFC 4106,密钥必须为 20 个字节。我还不知道为什么。我查看了 ipsec 源代码以了解如何进行加密。