>

GCM 암호화를 사용하여 암호화를위한 AEAD 샘플 코드를 구현하려고합니다. 하지만 키를 설정하는 동안 항상 잘못된 인수 오류가 발생합니다

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

블록 크기 때문에 유효하지 않은 인수 오류가 발생합니까? 그렇다면 작동하려면 어떻게해야합니까?

  • 답변 # 1

    AES의 블록 크기는 실제로 항상 128 비트입니다. 그러나 GCM의 블록 크기는 다릅니다. GCM (Galois-Counter Mode)은 이름에서 알 수 있듯이 CTR (Counter) 작동 모드 위에 구축되며 SIC (Segmented Integer Counter) 작동 모드라고도합니다. 그러면 AES가 스트림 암호로 바뀝니다. 스트림 암호는 정의에 따라 1 바이트의 블록 크기를 갖습니다 (보다 정확하게는 1 비트이지만 비트 수준 작업은 일반적으로 API에서 지원되지 않습니다).

    블록 크기는 호출에 표시되는 키 크기와 거의 관련이 없으며 인수는 비트 대신 바이트가 필요합니다 (키 길이가 일반적으로 정의 됨).

    IV의 크기는 12 바이트 (기본값) 여야합니다. 그렇지 않으면 GCM 구현에서 추가 계산이 필요할 수 있습니다 (아직 존재하는 경우).

  • 답변 # 2

    Aes GCM RFC 4106의 경우 키는 20 바이트 여야합니다. 아직 이유를 모르겠습니다. 암호화가 어떻게 이루어지는 지 ipsec 소스 코드를 살펴 보았습니다.

관련 자료

  • 이전 Excel VBA 사용자 양식 기존 날짜 유효성 검사
  • 다음 php - Laravel 5 이메일을 사용하려고합니다