Quantcast
Channel: Active questions tagged kernel - Stack Overflow
Viewing all articles
Browse latest Browse all 6379

Symmetric key encryption on Linux kernel

$
0
0

I'm trying to build a Linux kernel module that encrypts a char buffer. This is the code I have wrote so far(taken from here):

/* * cryptosk.c */#include <crypto/internal/skcipher.h>#include <linux/crypto.h>#include <linux/module.h>#include <linux/random.h>#include <linux/scatterlist.h>#define SYMMETRIC_KEY_LENGTH 32#define CIPHER_BLOCK_SIZE 16struct tcrypt_result {    struct completion completion;    int err;};struct skcipher_def {    struct scatterlist sg;    struct crypto_skcipher *tfm;    struct skcipher_request *req;    struct tcrypt_result result;    char *scratchpad;    char *ciphertext;    char *ivdata;};static struct skcipher_def sk;static void test_skcipher_finish(struct skcipher_def *sk){    if (sk->tfm)        crypto_free_skcipher(sk->tfm);    if (sk->req)        skcipher_request_free(sk->req);    if (sk->ivdata)        kfree(sk->ivdata);    if (sk->scratchpad)        kfree(sk->scratchpad);    if (sk->ciphertext)        kfree(sk->ciphertext);}static int test_skcipher_result(struct skcipher_def *sk, int rc){    switch (rc) {    case 0:        break;    case -EINPROGRESS || -EBUSY:        rc = wait_for_completion_interruptible(&sk->result.completion);        if (!rc && !sk->result.err) {            reinit_completion(&sk->result.completion);            break;        }        pr_info("skcipher encrypt returned with %d result %d\n", rc,                sk->result.err);        break;    default:        pr_info("skcipher encrypt returned with %d result %d\n", rc,                sk->result.err);        break;    }    init_completion(&sk->result.completion);    return rc;}static void test_skcipher_callback(struct crypto_async_request *req, int error){    struct tcrypt_result *result = req->data;    if (error == -EINPROGRESS)        return;    result->err = error;    complete(&result->completion);    pr_info("Encryption finished successfully\n");}static int test_skcipher_encrypt(char *plaintext, char *password,                                 struct skcipher_def *sk){    int ret = -EFAULT;    unsigned char key[SYMMETRIC_KEY_LENGTH];    if (!sk->tfm) {        sk->tfm = crypto_alloc_skcipher("cbc-aes-aesni", 0, 0);        if (IS_ERR(sk->tfm)) {            pr_info("could not allocate skcipher handle\n");            return PTR_ERR(sk->tfm);        }    }    if (!sk->req) {        sk->req = skcipher_request_alloc(sk->tfm, GFP_KERNEL);        if (!sk->req) {            pr_info("could not allocate skcipher request\n");            ret = -ENOMEM;            goto out;        }    }    skcipher_request_set_callback(sk->req, CRYPTO_TFM_REQ_MAY_BACKLOG,                                  test_skcipher_callback, &sk->result);    /* clear the key */    memset((void *)key, '\0', SYMMETRIC_KEY_LENGTH);    /* Use the world's favourite password */    sprintf((char *)key, "%s", password);    /* AES 256 with given symmetric key */    if (crypto_skcipher_setkey(sk->tfm, key, SYMMETRIC_KEY_LENGTH)) {        pr_info("key could not be set\n");        ret = -EAGAIN;        goto out;    }    pr_info("Symmetric key: %s\n", key);    pr_info("Plaintext: %s\n", plaintext);    if (!sk->ivdata) {        /* see https://en.wikipedia.org/wiki/Initialization_vector */        sk->ivdata = kmalloc(CIPHER_BLOCK_SIZE, GFP_KERNEL);        if (!sk->ivdata) {            pr_info("could not allocate ivdata\n");            goto out;        }        get_random_bytes(sk->ivdata, CIPHER_BLOCK_SIZE);    }    if (!sk->scratchpad) {        /* The text to be encrypted */        sk->scratchpad = kmalloc(CIPHER_BLOCK_SIZE, GFP_KERNEL);        if (!sk->scratchpad) {            pr_info("could not allocate scratchpad\n");            goto out;        }    }    sprintf((char *)sk->scratchpad, "%s", plaintext);    sg_init_one(&sk->sg, sk->scratchpad, CIPHER_BLOCK_SIZE);    skcipher_request_set_crypt(sk->req, &sk->sg, &sk->sg, CIPHER_BLOCK_SIZE,                               sk->ivdata);    init_completion(&sk->result.completion);    /* encrypt data */    ret = crypto_skcipher_encrypt(sk->req);    ret = test_skcipher_result(sk, ret);    if (ret)        goto out;    pr_info("Encryption request successful\n");    /* decrypt data */    memset((void*)sk->scratchpad, '-', CIPHER_BLOCK_SIZE);    ret = crypto_skcipher_decrypt(sk->req);    ret = test_skcipher_result(sk, ret);    if (ret)        goto out;    sg_copy_from_buffer(&sk->sg, 1, sk->scratchpad, CIPHER_BLOCK_SIZE);    sk->scratchpad[CIPHER_BLOCK_SIZE-1] = 0;    pr_info("Decryption request successful\n");    pr_info("Decrypted: %s\n", sk->scratchpad);out:    return ret;}static int cryptoapi_init(void){    /* The world's favorite password */    char *password = "password123";    sk.tfm = NULL;    sk.req = NULL;    sk.scratchpad = NULL;    sk.ciphertext = NULL;    sk.ivdata = NULL;    test_skcipher_encrypt("Testing", password, &sk);    return 0;}static void cryptoapi_exit(void){    test_skcipher_finish(&sk);}module_init(cryptoapi_init);module_exit(cryptoapi_exit);MODULE_DESCRIPTION("Symmetric key encryption example");MODULE_LICENSE("GPL");

Encryption seems to work fine, but when I try to decrypt back to plaintext, I get only gibberish:

[Jan 3 14:33] Symmetric key: password123[  +0.000003] Plaintext: Testing[  +0.000005] Encryption request successful[  +0.000003] Decryption request successful[  +0.000001] Decrypted: \\xd6"\xed\x03@mJ\xf8\x8cV\xe3\x13E\xb3 # <--- gibberish

I've also tried to convert the hex to ascii but it does not work. What I am doing wrong?


Viewing all articles
Browse latest Browse all 6379

Latest Images

Trending Articles



Latest Images

<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>