The Linux Kernel Cryptographic API

A new general framework offers much-needed crypto services to all parts of the kernel.

Page Vectors

Before discussing the API structure, let's briefly look at
memory pages and page vectors. As mentioned previously, a page is
the fundamental unit of memory managed by the kernel (on i386,
pages are 4KB in size). Consider a buffer containing, say, 1,460
bytes of user-space data. It belongs to a specific page in the
kernel, offset from the start of the page by some amount, and has a
length of 1,460 bytes. This buffer can be represented as a
page-based tuple:

{ page, offset, length }

An interface, such as the cryptographic API that works
directly with pages, needs to deal with this tuple, or page vector.
An existing kernel data structure called a scatterlist is employed,
which contains a page vector and normally is used for
scatter-gather DMA operations.

The cryptographic API uses scatterlists to operate on arrays
of discontiguous page vectors. The primary purpose of
scatter-gather in the kernel is to avoid unnecessary copying of
data. It also seems to result in cleaner code. Many readers will be
familiar with scatter-gather I/O in the form of the readv() and
writev() system calls. The kernel cryptographic API uses the same
general concept but operates on pages instead of plain memory
buffers.

Transforms—objects that instantiate algorithms,
manage internal state and handle common implementation logic.
Transforms are managed by crypto_alloc_tfm() and crypto_free_tfm().
A set of API wrappers are provided to simplify transform use and to
allow the properties of a transform's underlying algorithm to be
queried.

The following pseudo-code demonstrates a typical use of the
transform interface, where some kernel code needs to encrypt data
using the Blowfish cipher in electronic codebook (ECB) mode:

As shown in Figure 1, the API is layered so that core logic
is hidden from cryptography users and algorithm implementors. This
core logic includes generic transform management, scatterlist
manipulation and abstraction of underlying algorithms. Further
down, per-algorithm-type logic is handled, such as cipher
processing modes and utilizing digests for generating message
authentication codes.

Figure 1. Structure of the Kernel Cryptographic
API

The algorithm management layer contains logic for locating,
loading and reference counting algorithm implementations. The
latter is required to prevent nasty things from happening if an
attempt is made to unload an algorithm module that is still in
use.

An algorithm runtime query interface is provided so that
calling code can determine which algorithms are available on the
system. This is primarily intended for use by key negotiation
protocols, such as ISAKMP/IKE.

Finally, the algorithm registration interface allows modules
to register one or more algorithms, specifying various properties
such as the name of the algorithm, its block size and minimum and
maximum key sizes. The list of currently registered algorithms and
their properties may be viewed in /proc/crypto.

Conclusions

This is still a young API that is likely to evolve somewhat,
especially if some of the future design goals listed here are
implemented.

In terms of API users, IPSec works and performs well,
especially for a first cut with no performance optimizations.
Existing kernel components that need cryptography are expected to
convert to the new API over time, and hopefully, cool new projects
will be developed because of it.

Acknowledgements

Many thanks to David Miller and Nancy Chan for reviewing this
article.