Поддержка GCM-AEAD для системы Ubuntu с ядром Linux-3.10

Я пытаюсь реализовать пример кода AEAD для шифрования с использованием шифрования GCM. Но я всегда получаю ошибку недопустимого аргумента при установке ключа

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");
     }

При вставке модуля я получаю следующий вывод

Запуск шифрования
Возвращаемое значение для setkey: -22
Ключ не может быть установлен

Согласно спецификации AEAD, aead использует для шифрования aes-128, поэтому размер блока должен быть 128 бит.

Но моя система показывает поддержку размера блока только в 1 байт для AEAD.

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

Возникает ли ошибка недопустимого аргумента из-за размера блока. Если да, то что я должен сделать, чтобы заставить его работать?


person addy    schedule 29.06.2016    source источник


Ответы (2)


Размер блока AES действительно всегда 128 бит. Однако размер блока GCM — это другое дело. GCM (режим счетчика Галуа), как следует из названия, построен на основе режима работы CTR (счетчик), иногда также называемого режимом работы SIC (сегментированный целочисленный счетчик). Это превращает AES в потоковый шифр. Потоковые шифры по определению имеют размер блока в один байт (или, точнее, в один бит, но операции на уровне битов обычно не поддерживаются API).

Однако размер блока имеет мало общего с размером ключа, отображаемым в вызове, и аргумент, похоже, требует байтов, а не битов (в которых обычно определяется длина ключа).

Размер IV должен быть 12 байт (по умолчанию). В противном случае реализации GCM могут потребоваться дополнительные вычисления (если они вообще существуют).

person Maarten Bodewes    schedule 29.06.2016
comment
Не могли бы вы проверить, помогают ли приведенные выше комментарии решить проблему? - person Maarten Bodewes; 29.06.2016
comment
Спасибо за вашу помощь. У меня есть еще одно сомнение. Определяет ли размер блока: 1 длину размера входного блока или размер выходного блока? . В соответствии с определением crypto_aead_setkey в последнем основном ядре. При предоставлении 16-байтового ключа для дескриптора шифрования AES выполняется AES-128 [lxr.free-electrons.com/source/crypto/aead.c#L52]. Если размер блока равен размеру входных данных, то есть 1 байт, и мы предоставляем 16-байтовый ключ, будет ли это работать? Если нет, то по какой причине я получаю сообщение об ошибке -EINVAL? - person addy; 29.06.2016
comment
Размер блока и размер ключа напрямую не связаны друг с другом. Однако размер блока ввода и вывода всегда одинаков. Однако это зависит от реализации, сколько байтов обрабатывается во времени; к сожалению, у меня осталось всего 30 минут, чтобы поесть и приготовить каяк :) - person Maarten Bodewes; 29.06.2016
comment
Спасибо еще раз :) . Можете ли вы указать мне, что я делаю неправильно здесь и что я должен сделать, чтобы заставить его работать? - person addy; 29.06.2016

Для Aes GCM RFC 4106 ключ должен быть 20 байт. Я пока не знаю, почему. Я просмотрел исходный код ipsec, чтобы увидеть, как там делается шифрование.

person mip    schedule 04.04.2019