crypto – use Linux kernel crypto API

Crypto is an important part of the Linux kernel source code. One can tell from the standalone crypto directory under the kernel source tree. Device drivers, file system and security all need crypto. This post does not help understand the implementation of Linux kernel crypto API. Instead, a working kernel module is provided to show how to use the kernel crypto API.

0. R.t.D.C.

 * sha1_mod.c
 * A kernel module using SHA1 and Linux kernel crypto API
 * Reference:
 * Jun 9, 2014
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/crypto.h>
#include <linux/err.h>
#include <linux/scatterlist.h>

#define SHA1_LENGTH     20

static int __init sha1_init(void)
    struct scatterlist sg;
    struct crypto_hash *tfm;
    struct hash_desc desc;
    unsigned char output[SHA1_LENGTH];
    unsigned char buf[10];
    int i, j;

    printk(KERN_INFO "sha1: %s\n", __FUNCTION__);

    memset(buf, 'A', 10);
    memset(output, 0x00, SHA1_LENGTH);

    tfm = crypto_alloc_hash("sha1", 0, CRYPTO_ALG_ASYNC);
    if (IS_ERR(tfm)) {
	printk(KERN_ERR "daveti: tfm allocation failed\n");
	return 0;

    desc.tfm = tfm;
    desc.flags = 0;

    //daveti: NOTE, crypto_hash_init is needed
    //for every new hasing!

    for (j = 0; j < 3; j++) {
	sg_init_one(&sg, buf, 10);
	crypto_hash_update(&desc, &sg, 10);
	crypto_hash_final(&desc, output);

	for (i = 0; i < 20; i++) {
		printk(KERN_ERR "%02x", output[i]);
	printk(KERN_INFO "\n---------------\n");
	memset(output, 0x00, SHA1_LENGTH);


    return 0;

static void __exit sha1_exit(void)
    printk(KERN_INFO "sha1: %s\n", __FUNCTION__);



1. Pitfalls

As one might have known already, when we are trying to call crypto API for SHA1, we are querying the crypto manager (cryptomgr) eventually – a kernel thread maintains different algorithm instances and handles crypto operation requests all over the kernel. The truth is if crypto API is called, like crypto_alloc_hash(), before the cryptomgr is initialized during the kernel booting process, then NULL would be return. Make sure the crypto API is called after cryptomgr. Otherwise, you have to provide your own implementation.

If you are working in an IRQ context, be aware that some older crypto APIs may cause trouble. Based on my experience working on CentOS 6 with kernel 2.6.32, crypto_hash_digest() does not work. Instead, crypto_hash_final() works well.

About daveti

Interested in kernel hacking, compilers, machine learning and guitars.
This entry was posted in OS, Programming, Security and tagged , , , , , . Bookmark the permalink.

3 Responses to crypto – use Linux kernel crypto API

  1. Pingback: Kernel Hacking – use crypto API in the IRQ context |

  2. Hey very cool web site!! Guuy .. Beautiful .. Amazing ..
    I’ll bookmark your bllg and take the feeds also? I’m satisfied too seek out numerous useful
    info here in the post, we need work outt more techniques
    in this regard, thanks for sharing. . . . . .

  3. guest says:


    #define SHA1_LENGTH 20

    int sha1_test_in_kernel_4_9(void) {
    struct scatterlist sg;
    struct crypto_ahash *tfm;
    struct ahash_request *req;
    unsigned char buf[SHA1_LENGTH];
    unsigned char result[SHA1_LENGTH];

    printk(KERN_INFO “sha1: %s\n”, __FUNCTION__);

    memset(buf, ‘A’, SHA1_LENGTH);
    memset(result, 0x00, sizeof(result));

    print_hex_dump(KERN_INFO, “buf: “, DUMP_PREFIX_NONE, 16, 1, buf, sizeof(buf), true);

    tfm = crypto_alloc_ahash(“sha1”, 0, CRYPTO_ALG_ASYNC);
    if (IS_ERR(tfm)) {
    printk(KERN_ERR “tfm allocation failed\n”);
    return -1;

    /* … set up the scatterlists … */
    sg_init_one(&sg, buf, SHA1_LENGTH);

    req = ahash_request_alloc(tfm, GFP_ATOMIC);
    if (!req) {
    printk(KERN_ERR “ahash_request_alloc() failed\n”);
    return -2;

    ahash_request_set_callback(req, 0, NULL, NULL);
    ahash_request_set_crypt(req, &sg, result, SHA1_LENGTH);

    if (crypto_ahash_digest(req)) {
    printk(KERN_ERR “crypto_ahash_digest() failed\n”);
    return -3;


    print_hex_dump(KERN_INFO, “result: “, DUMP_PREFIX_OFFSET, 16, 1, result, sizeof(result), true);

    // check result with cmd:
    // $ echo -n AAAAAAAAAAAAAAAAAAAA | sha1sum –
    // ebd3d4adf97066c84b8ed17d6bd1e270818763e0 –

    return 0;

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.