From: Roberto Sassu <myrobmail@gmail.com>
To: linux-crypto@vger.kernel.org
Subject: Suspect bug in the authenc module
Date: Sat, 27 Feb 2010 12:14:15 +0100 [thread overview]
Message-ID: <201002271214.15414.myrobmail@gmail.com> (raw)
[-- Attachment #1: Type: Text/Plain, Size: 3009 bytes --]
Hello
i'm trying to use the authenc module and i wrote a small kernel module that
simply encrypts/decrypts a fixed data using the hmac(sha1) as authentication
algorithm and cbc(aes) as encryption algorithm.
The used platform is a KVM quest with Fedora 12 i686 and the latest kernel
2.6.33.
I have taken the code from the testmgr and from net/ipv4/esp4.c.
But, when testing the code, attached in this mail, the crypto_aead_decrypt()
function always replies -EBADMSG.
I tried the same code in a 64-bit machine (user mode kernel and Fedora 12) and
the decryption was successful. I noted, when comparing the auth portion in
both systems, that this computed during the encryption from the 32bit KVM
guest, was different and with no fixed value. I investigated in the code of
authenc and i recorded some partial result of the encryption operation. That
is the log:
--------- testing authenc: encrypt ---------------
assoc: 495C501F1D94CC81BAB7B603AFA5C1A1D85C4268E06CDA8905AC56AC1B2AD386
alg: No test for authenc(hmac(sha1),cbc(aes)) (authenc(hmac(sha1-
generic),cbc(aes-asm)))
Setting ahash key: 313233343536373839303132
Setting blk key: 31323334353637383930313233343536
crypto_authenc_encrypt: ivsize 16 iv: 01010101010101010101010101010101
crypto_authenc_genicv: dump vdst:
CFE3A997243F38B0D6A89DCAB5126DC93952E493E72EA590CC8D186A4E1654860000000000000000000000000000000000000000
crypto_authenc_genicv ivsize 16,dst offset 3392 iv
01010101010101010101010101010101
crypto_authenc_genicv: iv after sg_init_table 00000000000000000101010101010101
crypto_authenc_genicv: vdst == iv + ivsize? 0
crypto_authenc_genicv: scatterlist dst 0 before fn assignement (line 355):
3242265088, 388, 32, dump:
495C501F1D94CC81BAB7B603AFA5C1A1D85C4268E06CDA8905AC56AC1B2AD386
crypto_authenc_genicv: scatterlist dst 1 before fn assignement (line 355):
3727819872, 0, 0, dump:
crypto_authenc_genicv: scatterlist dst 2 before fn assignement (line 355):
3241960448, 1152, 16, dump: 00000000000000000101010101010101
crypto_authenc_genicv: scatterlist dst 3 before fn assignement (line 355):
3747577608, 0, 0, dump:
crypto_authenc_genicv: scatterlist dst 0 after fn assignement (line 355):
3242265088, 388, 32, dump:
495C501F1D94CC81BAB7B603AFA5C1A1D85C4268E06CDA8905AC56AC1B2AD386
crypto_authenc_genicv: scatterlist dst 1 after fn assignement (line 355):
3727819872, 0, 0, dump:
crypto_authenc_genicv: scatterlist dst 2 after fn assignement (line 355):
3241960448, 1152, 16, dump: 0000000000000000C01886E0201986E0
crypto_authenc_genicv: scatterlist dst 2 after fn assignement (line 355)::
3747577608, 0, 0, dump:
--------------------------------------------------
Just for test, i tried to add a 16bit long offset when defining the memory
address for the "iv" in the function crypto_authenc_encrypt() for the 32-bit
kernel, and everything works fine.
I don't know if i made a mistake in the code that causes this misbehaviour in
the authenc module or if it is a bug.
Thanks in advance for the reply.
[-- Attachment #2: testaeadesp.c --]
[-- Type: text/x-csrc, Size: 5385 bytes --]
#include <crypto/hash.h>
#include <linux/err.h>
#include <linux/module.h>
#include <linux/scatterlist.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <crypto/rng.h>
#include <crypto/authenc.h>
#include <linux/pagemap.h>
#include <linux/rtnetlink.h>
#define MAX_IVLEN 16
#define AUTHSIZE 20
int testmode = 0;
module_param(testmode, int, 0);
void hexdump(unsigned char *buf, int len)
{
while(--len >=0)
printk("%02X", *buf++);
printk("\n");
}
struct tcrypt_result {
struct completion completion;
int err;
};
static void tcrypt_complete(struct crypto_async_request *req, int err)
{
struct tcrypt_result *res = req->data;
if (err == -EINPROGRESS)
return;
res->err = err;
complete(&res->completion);
}
static int testrun(void)
{
const char *algo = "authenc(hmac(sha1),cbc(aes))";
struct crypto_aead *tfm;
unsigned int i;
int ret = -ENOMEM;
unsigned char *ekey = "1234567890123456";
unsigned char *akey = "123456789012";
unsigned char *key, *pp;
unsigned int ekeylen = 16;
unsigned int akeylen = 12;
unsigned int keylen = 0;
struct aead_request *req;
struct tcrypt_result result;
unsigned int authsize = AUTHSIZE;
char *assoc = "\x49\x5c\x50\x1f\x1d\x94\xcc\x81"
"\xba\xb7\xb6\x03\xaf\xa5\xc1\xa1"
"\xd8\x5c\x42\x68\xe0\x6c\xda\x89"
"\x05\xac\x56\xac\x1b\x2a\xd3\x86";
int assoclen = 32;
unsigned char iv[MAX_IVLEN];
mm_segment_t old_fs = get_fs();
struct file *fp;
struct scatterlist src_sg, dst_sg;
struct scatterlist asg;
char *filename = "file1.txt";
char *string = "ciao";
struct crypto_authenc_key_param *param;
struct rtattr *rta;
char *input;
int blksize = 0;
int clen = 16; /* len of data */
printk("assoc: ");
hexdump(assoc, 32);
tfm = crypto_alloc_aead(algo, 0, 0);
if (IS_ERR(tfm)) {
printk(KERN_ERR "alg: aead: Failed to load transform for %s: "
"%ld\n", algo, PTR_ERR(tfm));
goto out;
}
blksize = ALIGN(crypto_aead_blocksize(tfm), 4);
clen = ALIGN(clen + 2, blksize);
input = kzalloc(clen + AUTHSIZE, GFP_KERNEL);
if(!testmode) {
set_fs(KERNEL_DS);
fp = filp_open(filename, O_RDONLY, 0);
if(IS_ERR(fp)) {
printk("Error opening file: %s\n", filename);
set_fs(old_fs);
goto out;
}
fp->f_op->read(fp, input, clen + AUTHSIZE, &fp->f_pos);
filp_close(fp, NULL);
set_fs(old_fs);
} else
memcpy(input, string, strlen(string));
init_completion(&result.completion);
req = aead_request_alloc(tfm, GFP_KERNEL);
if (!req) {
printk(KERN_ERR "alg: aead: Failed to allocate request for "
"%s\n", algo);
goto out_tfm;
}
aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
tcrypt_complete, &result);
memset(iv, 1, MAX_IVLEN);
crypto_aead_clear_flags(tfm, ~0);
crypto_aead_set_flags(tfm, CRYPTO_TFM_REQ_WEAK_KEY);
keylen = akeylen + ekeylen + RTA_SPACE(sizeof(*param));
key = kzalloc(keylen, GFP_KERNEL);
if (!key)
goto out_req;
pp = key;
rta = (void *)pp;
rta->rta_type = CRYPTO_AUTHENC_KEYA_PARAM;
rta->rta_len = RTA_LENGTH(sizeof(*param));
param = RTA_DATA(rta);
pp += RTA_SPACE(sizeof(*param));
if(akeylen) {
memcpy(pp, akey, akeylen);
pp += akeylen;
}
ret = crypto_aead_setauthsize(tfm, authsize);
if (ret) {
printk(KERN_ERR "alg: aead: Failed to set "
"authsize to %u on test for %s\n",
authsize, algo);
goto out_key;
}
param->enckeylen = cpu_to_be32(ekeylen);
memcpy(pp, ekey, ekeylen);
ret = crypto_aead_setkey(tfm, key, keylen);
if (ret) {
printk(KERN_ERR "alg: aead: Failed to set "
"the key for %s\n",
algo);
goto out_key;
}
sg_init_one(&src_sg, input, clen + AUTHSIZE);
sg_init_one(&dst_sg, input, clen + AUTHSIZE);
sg_init_one(&asg, assoc, assoclen);
aead_request_set_crypt(req, &src_sg, &dst_sg, clen + (testmode ? 0 : authsize), iv);
aead_request_set_assoc(req, &asg, assoclen);
ret = testmode ?
crypto_aead_encrypt(req) :
crypto_aead_decrypt(req);
switch (ret) {
case 0:
if(!testmode)
printk("File OK\n");
break;
case -EINPROGRESS:
case -EBUSY:
ret = wait_for_completion_interruptible(
&result.completion);
if (!ret && !(ret = result.err)) {
INIT_COMPLETION(result.completion);
break;
}
case -EBADMSG:
printk("File corrupted\n");
default:
printk(KERN_ERR "alg: aead: %s failed "
"for %s: ret=%d\n", testmode ? "encrypt" : "decrypt", algo, -ret);
}
if(ret)
goto out_key;
printk("%s: %d\n", testmode ? "encrypt" : "decrypt", ret);
if(testmode) {
set_fs(KERNEL_DS);
fp = filp_open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0700);
if(IS_ERR(fp)) {
printk("Error opening file: %s\n", filename);
set_fs(old_fs);
goto out_key;
}
fp->f_op->write(fp, input, clen + AUTHSIZE, &fp->f_pos);
hexdump(input + clen, AUTHSIZE);
filp_close(fp, NULL);
set_fs(old_fs);
} else {
printk("Decrypted: %s\n", input);
}
kfree(input);
out_key:
kfree(key);
out_req:
aead_request_free(req);
out_tfm:
crypto_free_aead(tfm);
out:
return ret;
}
int __init testaead_start(void) {
int ret;
printk("--------- testing authenc: %s ---------------\n", testmode ? "encrypt" : "decrypt");
ret = testrun();
printk("Result: %d\n", ret);
printk("--------------------------------------------------\n");
return -1;
}
void __exit testaead_stop(void) {
}
module_init(testaead_start);
module_exit(testaead_stop);
MODULE_LICENSE("GPL");
next reply other threads:[~2010-02-27 11:14 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-02-27 11:14 Roberto Sassu [this message]
2010-03-01 13:24 ` Suspect bug in the authenc module Steffen Klassert
2010-03-04 10:54 ` Roberto Sassu
2010-03-05 7:26 ` Herbert Xu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=201002271214.15414.myrobmail@gmail.com \
--to=myrobmail@gmail.com \
--cc=linux-crypto@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).