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?
Asked
Active
Viewed 4,770 times
4 Answers
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;
}
-
Elaborating your answer with a little explanation is a good practice here - https://stackoverflow.com/help/how-to-answer – Tushar Walzade Jan 23 '19 at 08:49
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);
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