1

I am trying to use the kernel space implementation of the md5 algorithm (md5.h and md5.c). It turns out that md5.h does not declare the functions found in md5.c, so I could not simply include md5.h into my c file. I also wanted to avoid altering md5.h to declare the functions, since that could have unintended consequences. Is there any other way to use md5 in kernel space?

Gregory-Turtle
  • 1,657
  • 3
  • 20
  • 30

4 Answers4

1

Use Crypto API instead of rolling your own.

Community
  • 1
  • 1
Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
  • I tried this and it seemed to work. But when I tried to print the results (as unsigned long long), they always came out as even numbers that only differed by the last 4 digits. Am I supposed to read them in a different format? If long long is fine, what would cause this pattern? – Gregory-Turtle Jun 20 '12 at 20:24
  • You might want to put that in a different question, Gregory-Turtle. – Maarten Bodewes Jun 24 '12 at 14:22
0
#include <crypto/hash.h>

bool md5_hash(char *result, char* data, size_t len){
    struct shash_desc *desc;
    desc = kmalloc(sizeof(*desc), GFP_KERNEL);
    desc->tfm = crypto_alloc_shash("md5", 0, CRYPTO_ALG_ASYNC);

    if(desc->tfm == NULL)
        return false;

    crypto_shash_init(desc);
    crypto_shash_update(desc, data, len);
    crypto_shash_final(desc, result);
    crypto_free_shash(desc->tfm);

    return true;
}
0

Beware, the code posted by wande chen will cause kernel heap corruption.

struct shash_desc *desc;

desc = kmalloc(sizeof(*desc), GFP_KERNEL);

desc->tfm = crypto_alloc_shash("md5", 0, CRYPTO_ALG_ASYNC);

This is because md5 engine will use memory past struct shash_desc for storing md5 context.

The correct way to allocate struct shash_desc can be found here.

*shash = crypto_alloc_shash(name, 0, 0);

size = sizeof(struct shash_desc) + crypto_shash_descsize(*shash);

*sdesc = kmalloc(size, GFP_KERNEL);

Community
  • 1
  • 1
kunix
  • 1
  • 1
0
struct sdesc {
    struct shash_desc shash;
    char ctx[];
};

static struct sdesc *init_sdesc(struct crypto_shash *alg)
{
    struct sdesc *sdesc;
    int size;

    size = sizeof(struct shash_desc) + crypto_shash_descsize(alg);
    sdesc = kmalloc(size, GFP_KERNEL);
    if (!sdesc)
        return ERR_PTR(-ENOMEM);
    sdesc->shash.tfm = alg;
    return sdesc;
}

static int calc_hash(struct crypto_shash *alg,
             const unsigned char *data, unsigned int datalen,
             unsigned char *digest)
{
    struct sdesc *sdesc;
    int ret;

    sdesc = init_sdesc(alg);
    if (IS_ERR(sdesc)) {
        pr_info("can't alloc sdesc\n");
        return PTR_ERR(sdesc);
    }

    ret = crypto_shash_digest(&sdesc->shash, data, datalen, digest);
    kfree(sdesc);
    return ret;
}

static int do_md5(const unsigned char *data, unsigned char *out_digest)
{
    struct crypto_shash *alg;
    char *hash_alg_name = "md5";
    unsigned int datalen = strlen(data); // remove the null byte

    alg = crypto_alloc_shash(hash_alg_name, 0, 0);
    if(IS_ERR(alg)){
        pr_info("can't alloc alg %s\n", hash_alg_name);
        return PTR_ERR(alg);
    }

    unsigned char hash[32];
    calc_hash(alg, data, datalen, hash);

    // Very dirty print of 8 first bytes for comparaison with sha256sum
    printk(KERN_INFO "HASH(%s, %i): %02x%02x%02x%02x%02x%02x%02x%02x\n",
          data, datalen, hash[0] & 0xFFu, hash[1] & 0xFFu, hash[2] & 0xFFu, hash[3] & 0xFFu, hash[4] & 0xFFu, 
          hash[5] & 0xFFu, hash[6] & 0xFFu, hash[7] & 0xFFu);

    char c[3];
    for (int i = 0; i < 16; i++)
    {
        sprintf( c, "%02x", hash[i] & 0xFFu);
        memcpy(out_digest+i*2, c, 2);
    }

    crypto_free_shash(alg);
    return 0;
}

tested.
  • Welcome to SO. Clarifying & explaining your answer would be beneficial for users who will look up this answer in the future. – Frightera Feb 05 '21 at 08:20