Subject: Asynchronous crypto layer.

From: Evgeniy Polyakov <[email-masked]>
Date: Fri, 29 Oct 2004 10:22:38 +0400

I'm pleased to announce asynchronous crypto layer for Linux kernel 2.6.
It support following features:
- multiple asynchronous crypto device queues
- crypto session routing
- crypto session binding
- modular load balancing
- crypto session batching genetically implemented by design
- crypto session priority
- different kinds of crypto operation(RNG, asymmetrical crypto, HMAC and
any other)

Some design notes:
acrypto has one main crypto session queue(double linked list, probably
it should be done like crypto_route or sk_buff queue), into which each
newly allocated session is inserted and this is a place where load
balancing searches it's food. When new session is being prepared for
insertion it calls load balancer's ->find_device() method, which should
return suitable device(current simple_lb load balancer returns device
with the lowest load(device has the least number of session in it's
queue)) if it exists. After crypto_device being returned acrypto creates
new crypto routing entry which points to returned device and adds it to
crypto session routing queue. Crypto session is being inserted into
device's queue according to it's priority and it is crypto device driver
that should process it's session list according to session's priority.

All insertion and deletion are guarded by appropriate locks, but
session_list traversing is not guarded in crypto_lb_thread() since
session can be removed _only_ from that function by design, so if crypto
device (atomically) marks session as completed and not being processed
and use list_for_each_safe() for traversing it's queue all should be OK.

Each crypto load balancer must implement 2 methods: 
->rehash() and ->find_device() which will be called from any context and
under spinlock.
->rehash() method should be called to remix crypto sessions in device's
queues, for example if driver decides that it's device is broken it
marks itself as broken and load balancer(or scheduler if you like)
should remove all sessions from this queue to some other devices. 
If session can not be completed scheduler must mark it as broken and
complete it(by calling first broke_session() and then complete_session()
and stop_process_session()). Consumer must check if operation was
successful(and therefore session is not broken).
->find_device() method should return appropriate crypto device.

For crypto session to be successfully allocated crypto consumer must
provide two structures - struct crypto_session_initializer 
(hmm, why only one z?) and struct crypto_data.
struct crypto_session_initializer contains data needed to find
appropriate device, like type of operation, mode of operation, some
flags(for example SESSION_BINDED, which means that session must be bound
to specified in bdev field crypto device, it is useful for TCPA/TPM),
session priority and callback which will be called after all routing for
given session are finished.
struct crypto_data contains scatterlists for src, dst, key and iv.
It also has void *priv field and it's size which is allocated and may be
used by any crypto agent(for example VIA PadLock driver uses it to store
aes_ctx field, crypto_session can use this field to store some pointers
needed in ->callback()).
Actually callback will be called from queue_work, but I suppose it is
better to not assume calling context.
->callback() will be called after all crypto routing for given session
are done with the same parameters as were provided in initialisation
time(if session has only one routing callback will be called with
original parameters, but if it has several routes callback will be
called with parameters from the latest processed one). I believe crypto
callback should not know about crypto sessions, routings, device and so
on, proper restriction is always a good idea.

Crypto routing.
This feature allows the same session to be processed by several
devices/algorithms. For example if you need to encrypt data and then
sign it in TPM device you can create one route to encryption device and
then route it to TPM device. (Note: this feature must be discussed since
there is no time slice after session allocation, only in
crypto_device->data_ready() method and there are locking issues in
->callback() method).

Crypto device.
It can be either software emulator or hardware accelerator chip(like
HIFN 79*/83* or Via PadLock ACE/RNG, or even TPM device like each IBM
ThinkPad or some HP laptops have 
(gentle hint: _they_ even have a _windows_ software for them :) )).
It can be registered with asynchronous crypto layer and must provide
some data for it:
->data_ready() method - it is called each time new session is added to
device's queue.
Array of struct crypto_capability and it's amount - 
struct crypto_capability describes each operation given device can
handle, and has a maximum session queue length parameter.
Note: this structure can [be extended to] include "rate" parameter to
show absolute speed of given operation in some units, which therefore
can be used by scheduler(load balancer) for proper device selection.
Actually queue length can somehow reflects device's "speed".

Also attached:
- simple synchronous <-> asynchronous bridge for sha1 crypto provider.
It can be easily extended to handle whole number of synchronous software
implemented algorithms.
- driver for Via PadLock ACE - not tested, since my M10000 does not have
xcrypt module. This work is 98% by Michal Ludvig <mludvig suse.cz>, I
have just silently stolen it several days ago.

I've obtained bits of documentation for HIFN 795* so driver will be
created for it. I want to thank Wim Vandeputte <wim kd85.com> and
www.soekris.com for steps towards me in ordering and delivering process
to Russia.

Asynchronous crypto layer depends on kernel connector which was
presented in both linux-kernel@ and netdev@ several weeks ago.

Currently acrypto does not handle userspace session requests(for example
from OpenSSL) but I will implement it soon in form of char device and
it's ->mmap method.

Please review and comment, I am open for discussion.
Thank you.

-- 
	Evgeniy Polyakov

Crash is better than data corruption. -- Art Grabowski