LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   AES_CBC output difference between OpenSSL and Kernel crypto API (https://www.linuxquestions.org/questions/programming-9/aes_cbc-output-difference-between-openssl-and-kernel-crypto-api-4175515934/)

abirt 08-22-2014 08:26 AM

AES_CBC output difference between OpenSSL and Kernel crypto API
 
Hi all,

I made the same encryption code with OpenSSL API and kernel crypto API to test AES_CBC encryption for 3 different keys: 128, 192 and 256 bit long. I am using the same input and IV (initialization vector) for the three tests.
Here is the code used for AES_CBC encryption module with kernel crypto API:
Code:

int init_module(void)
{
int keylen[3]={16, 24, 32}, ret = 0, innents = 0, outnents = 0, inlen = 100, outlen = 112, j = 0;
uint8_t in[112], out[112], *key, iv[16];
struct crypto_ablkcipher *tfm;
struct scatterlist *insg, *outsg;
struct ablkcipher_request *req;
struct async_crypto_result tresult;

        printk(KERN_INFO "\n....Scatterlist crypto API: aes(cbc) start....\n");

        memset(in, 0x01, inlen);
        memset(in+inlen, (outlen-inlen), (outlen-inlen));
        innents = sg_init(outlen, in, &insg);
        printk("\n..Input+padding: %d: ", outlen);
        khexdump(outlen, in);

        memset(out, 0, outlen);
        outnents = sg_init(outlen, out, &outsg);
        printk("\n..Output: %d: ", outlen);
        khexdump(outlen, out);

        memset(iv, 0x0a, 16);
        printk("\n..IV: 16: ");
        khexdump(16, iv);

        tfm = crypto_alloc_ablkcipher("cbc(aes)", 0, 0);
        if (IS_ERR(tfm)) {
                printk(KERN_WARNING "\n..error::failed to load aes(cbc) transform\n");
                return 0;
        }

        init_completion(&tresult.completion);

        if ( !(req = ablkcipher_request_alloc(tfm, GFP_KERNEL)) ) {
                printk(KERN_WARNING "\n..error::failed to allocate request\n");
                goto ret_0;
        }

        ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, async_crypto_complete, &tresult);
        crypto_ablkcipher_clear_flags(tfm, ~0);

        for (j = 0; j < 3; j++) {
                key = kmalloc(keylen[j] * sizeof(uint8_t), GFP_KERNEL);
                if (IS_ERR(key)) {
                        printk(KERN_WARNING "\n..error::key allocation failure\n");
                        goto ret_1;
                }
                memset(key, 0x0b, keylen[j]);       
                printk("\n..Key: %d: ", keylen[j]);
                khexdump(keylen[j], key);
               
                if ((ret = crypto_ablkcipher_setkey(tfm, key, keylen[j]))) {
                        printk(KERN_WARNING "\n..error::failed to set key\n");
                        kfree(key);
                        goto ret_1;
                }
                ablkcipher_request_set_crypt(req, insg, outsg, outlen, iv);
                ret = crypto_ablkcipher_encrypt(req);
                if (ret == -EINPROGRESS || ret == -EBUSY) {
                        ret = wait_for_completion_interruptible(&tresult.completion);
                        if (!ret)
                                ret = tresult.err;
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0))                       
                        INIT_COMPLETION(tresult.completion);
#else
                        reinit_completion(&(tresult.completion));
#endif
                }
                if (ret) {
                        printk(KERN_WARNING "\n..error::crypto_ablkcipher_digest returns: %d\n", ret);
                        kfree(key);
                        goto ret_1;
                }
                sg_copy_to_buffer(outsg, outnents, out, outlen);
                printk("\n..Output: %d:  ", outlen);
                khexdump(outlen, out);
                kfree(key);
        }       
ret_1:       
        ablkcipher_request_free(req);
ret_0:
        sg_free(insg, innents);
        sg_free(outsg, outnents);
        crypto_free_ablkcipher(tfm);
return 0;
}

And here is the code used for OpenSSL:
Code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/sha.h>
#include <openssl/md5.h>
#include <sys/time.h>

typedef const EVP_CIPHER* (*encrfun)(void);

void hexdump(int len, uint8_t *val)
{
int i = 0;
        for (i = 0; i < len; i++)
                printf("%02x ", val[i]);       
        printf("\n");
}

int main(int argv, char **argc)
{
int keylen[3] = {16, 24, 32}, inlen = 100, bs = 0, outlen = 112, i = 0;
uint8_t in[100], out[112], *key = NULL, iv[16] = {0};
EVP_CIPHER_CTX *x = NULL;
encrfun encralg[3] = {EVP_aes_128_cbc, EVP_aes_192_cbc, EVP_aes_256_cbc};

        memset(in, 1, inlen);       
        printf("\nIn: %d: ", inlen);
        hexdump(inlen, in);
       
        memset(out, 0, outlen);

        memset(iv, 0x0a, 16);       
        printf("\nIV: 16: ");
        hexdump(16, iv);

        x = malloc(sizeof(EVP_CIPHER_CTX));
        if (!x) {
                printf("\nerror::EVP_CIPHER_CTX allocation failure\n");
                return 0;
        }

        for (i = 0; i < 3; i++) {
                key = malloc(keylen[i] * sizeof(uint8_t));
                if (!key) {
                        printf("error::key allocation failure\n");
                        free(x);
                        return 0;
                }
                memset(key, 0x0b, keylen[i]);
                printf("\nKey: %d: ", keylen[i]);
                hexdump(keylen[i], key);

                EVP_CIPHER_CTX_init(x);
                if (!EVP_EncryptInit(x, encralg[i](), NULL, NULL)) {
                        printf("error::EVP_EncryptInit()\n");
                        free(key);
                        EVP_CIPHER_CTX_cleanup(x);
                        free(x);
                        return 0;
                }

                EVP_CIPHER_CTX_set_key_length(x, keylen[i]);
                if (!EVP_EncryptInit(x, NULL, key, iv)) {
                        printf("error::EVP_EncryptInit()\n");
                        free(key);
                        EVP_CIPHER_CTX_cleanup(x);
                        free(x);       
                        return 0;
                }

                bs = EVP_CIPHER_CTX_block_size(x);
                if (!EVP_EncryptUpdate(x, out, &bs, in, inlen)) {
                        printf("error::EVP_EncryptUpdate()\n");
                        free(key);
                        EVP_CIPHER_CTX_cleanup(x);
                        free(x);
                        return 0;
                }
                outlen = 0;
                outlen += bs;
                if (!EVP_EncryptFinal(x, out+bs, &bs)) {
                        printf("error::EVP_EncryptUpdate()\n");
                        free(key);
                        EVP_CIPHER_CTX_cleanup(x);
                        free(x);
                        return 0;
                }
                outlen += bs;
                printf("\nOut: %d: ", outlen);
                hexdump(outlen, out);
                memset(out, 0, outlen);

                EVP_CIPHER_CTX_cleanup(x);
                free(key);
        }
        free(x);
return 0;
}

My problem is that I am getting the same result between OpenSSL and kernel crypto only for AES_CBC_128. However, the results for AES_CBC_192 and AES_CBC_256 are different even if I am using the same IV, input and keys.
Here is the result of OpenSSL:
Code:

In: 100: 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01

IV: 16: 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a

Key: 16: 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b
Out: 112: a5 59 0b 5f 0d 7d a9 fb 1d 1d a3 d0 95 87 0f 01 3e ad 82 55 3e 59 35 78 70 5d 49 5f 4e da e3 77 48 ac 5e 41 ab 5a 7f 1e 14 e6 b9 02 17 f1 11 55 ff 4f bc 32 3e 72 9d 0e d1 ba 9f f4 87 83 fb ee 91 61 ff 15 81 3d b6 7a e5 ff a4 71 a8 6f 38 79 39 1c 2f a0 6d ff 85 64 02 39 9c f7 e3 7e a5 f9 ce 3d 16 ea 65 cf 91 0b 50 db f6 73 52 de be 1c

Key: 24: 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b
Out: 112: 77 12 21 56 62 fb ab 5b 0e 70 d8 5e 33 2e 1b 37 b1 92 bc b9 b5 0f d9 c4 49 b4 51 d3 3a dd f8 fc 6c 02 0a c9 08 89 b6 8b 57 ed 07 6e 4d 35 98 76 4a b7 f3 cc 35 2a 9b c4 59 37 18 cd a4 a8 3e f7 76 70 f4 6f ca 02 9f 6b 65 d8 0b 86 b5 48 16 92 c0 b6 8a 2d b5 3f fc 87 4f a5 8f 23 51 16 76 3c cf 5c 4f 14 e0 70 41 6d 7e 1a d6 a2 0c 2a ee cb

Key: 32: 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b
Out: 112: d3 80 2e c9 73 e6 93 5a a3 2d 7b 88 f5 6a 21 19 fe 8b ff 7a 6e 18 e2 6e 0c 12 33 da 58 53 87 10 70 73 b3 29 eb fa 6a 69 85 00 3c 05 6f de 2b 8f 19 85 ed e2 28 5b 72 e9 7e 67 2d d5 e9 b4 c3 b3 74 c7 9b 8c ce 85 bd a2 d1 d4 87 ec 1e cf 18 30 63 05 3e 12 ea 32 87 8a 63 20 8a 66 e3 34 24 63 31 65 f9 16 bd e7 b8 de 41 ca 2e 47 46 62 aa ab

And here is the result of kernel crypto:
Code:

[23260.400939] ..Input+padding: 112: 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 0c 0c 0c 0c 0c 0c 0c 0c 0c 0c 0c 0c

[23260.401049] ..IV: 16: 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a

[23260.401069] ..Key: 16: 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b
[23260.401085] ..Output: 112:  a5 59 0b 5f 0d 7d a9 fb 1d 1d a3 d0 95 87 0f 01 3e ad 82 55 3e 59 35 78 70 5d 49 5f 4e da e3 77 48 ac 5e 41 ab 5a 7f 1e 14 e6 b9 02 17 f1 11 55 ff 4f bc 32 3e 72 9d 0e d1 ba 9f f4 87 83 fb ee 91 61 ff 15 81 3d b6 7a e5 ff a4 71 a8 6f 38 79 39 1c 2f a0 6d ff 85 64 02 39 9c f7 e3 7e a5 f9 ce 3d 16 ea 65 cf 91 0b 50 db f6 73 52 de be 1c

[23260.401140] ..Key: 24: 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b
[23260.401155] ..Output: 112:  a1 4b 6f 74 ff c9 29 30 d1 a2 48 03 e1 6b 7b e3 78 4d 7d 12 fa 7f 8e 79 2e c3 0b f5 c3 09 ae 38 e4 1c 62 b9 e1 cf 71 da 67 8b 91 40 af e5 8e 17 03 38 d9 1b ff 67 5a a8 20 d2 c6 27 f7 17 4f 90 70 9a 50 45 ec 3c 29 c9 21 65 29 92 70 a4 31 e6 7d 00 08 e1 38 c1 9a 04 12 37 bf 6d 00 a8 62 84 4f 72 52 30 4e f8 89 d8 01 4b da fb a7 06 28 ef

[23260.401211] ..Key: 32: 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b
[23260.401229] ..Output: 112:  0c bf 3e 4e a8 2e a0 a8 9c 08 b4 a0 d7 38 2d bc 6d 4f 7b 61 b7 56 5e ad 1f 06 aa b0 0a 71 58 2b 1d de 06 86 60 43 e6 c5 8e a7 6d 68 8e ea 57 99 8e e1 e6 32 58 f4 15 ff d9 2b 0c 88 e3 8d 97 44 59 f4 40 99 5b 1a af 77 94 dc 9e 41 9a 2c 6c 24 71 43 29 04 7a 5b 47 e7 89 bf 50 3f d6 85 d5 8e e9 a6 bd 2c a3 80 ff 6d a4 55 1a 1b be 7b 48 50

Could you help me to find the origin of the problem, Thanks in advance.

Best regards

ntubski 08-22-2014 11:42 AM

It looks like the kernel crypto API writes the MAC into your iv buffer, so you should reset it each time.

abirt 08-25-2014 02:22 AM

Thanks ntubski, that was the solution to the problem.
best regards


All times are GMT -5. The time now is 03:11 PM.