After my first post about Linux kernel crypto API, I keep playing with kernel crypto API for DSA and RSA implementations (will talk about these in my future posts). The truth is crypto API is NOT designed for IRQ context. That is the reason why if a device driver wants crypto functionalities, there are usually 2 ways for the developer to do it, either writing its own crypto stuffs, making sure it highly efficient and no sleep, or delaying the work into the bottom half, such as work queue or a kernel thread. This post dose NOT talk either of these solutions. Instead, this post discusses the general way to make crypto API work in the IRQ context. Happy hacking~
0. kmalloc
The most common way to break the kernel within an IRQ context is kmalloc with GFP_KERNEL flag, which, as you may have known already, could sleep. While sometimes it may work (like SegV may not happen each time), once there is a heavy load on the kernel, you will see kernel panic/oops frequently. The key here is to use GFP_ATOMIC flag.
1. MPI
Most crypto APIs are based on MPI ported from GnuPG. Let us do a quick search based on Linux kernel 3.18.3 under lib/mpi:
Daves-MacBook-Pro-2:mpi daveti$ pwd
/Users/daveti/linux-3.18.3/lib/mpi
Daves-MacBook-Pro-2:mpi daveti$ grep GFP *
mpicoder.c: p = buffer = kmalloc(n, GFP_KERNEL);
mpih-mul.c: ctx->next = kzalloc(sizeof *ctx, GFP_KERNEL);
mpiutil.c: a = kmalloc(sizeof *a, GFP_KERNEL);
mpiutil.c: return kmalloc(len, GFP_KERNEL);
mpiutil.c: p = kmalloc(nlimbs * sizeof(mpi_limb_t), GFP_KERNEL);
mpiutil.c: a->d = kzalloc(nlimbs * sizeof(mpi_limb_t), GFP_KERNEL);
Daves-MacBook-Pro-2:mpi daveti$
2. crypto API
Once MPI lib is patched, we need to take care of crypto API itself. If we still follow the stupid grep we have done for MPI, under crypto/, you may find there are so many places we need to change. Instead, we will be a little bit smart here – depending on the crypto API you want to use, only patch that crypto API related source. For example, we would like to use synchronous hash here, crypto_alloc_shash(). The implementation of shash is crypto/shash.c. Stupid grep works then:
Daves-MacBook-Pro-2:crypto daveti$ pwd
/Users/daveti/linux-3.18.3/crypto
Daves-MacBook-Pro-2:crypto daveti$ grep GFP shash.c
buffer = kmalloc(absize, GFP_KERNEL);
GFP_KERNEL);
Daves-MacBook-Pro-2:crypto daveti$
Are we done? Apparently not, because of the design of crypto framework, which provides the unified API (crypto API) for different crypto algorithms, we need to patch the crypto framework itself, which is crypto/api.c. Again stupid grep helps:
Daves-MacBook-Pro-2:crypto daveti$ pwd
/Users/daveti/linux-3.18.3/crypto
Daves-MacBook-Pro-2:crypto daveti$ grep GFP api.c
larval = kzalloc(sizeof(*larval), GFP_KERNEL);
tfm = kzalloc(tfm_size, GFP_KERNEL);
mem = kzalloc(total, GFP_KERNEL);
Daves-MacBook-Pro-2:crypto daveti$
3. Summary
Most of the time, these patches should make your crypto API work in the IRQ context. At least I have used it in the netfilter and USB ep0 handler. Note, if you would like to submit your code into the mainline, you probably have to follow the traditional ways.
I have noticed you don’t monetize your site, don’t waste your traffic, you can earn additional bucks every month
because you’ve got high quality content. If you want to know how
to make extra bucks, search for: Ercannou’s essential adsense alternative