How to use crypto API in Solaris kernel code

Guest Author

http-equiv="content-type">How to use crypto API in Solaris kernel code

Now that OpenSolaris is a
reality, we can finally blog about the source code. I will start with
how to do crypto stuff from the kernel code.

Solaris 10 has the kernel crypto framework (kCF) which offers crypto
API for other kernel modules or drivers. IPSec and Kerberos are some of
components that make use of it. This API is not public yet and hence
you won't see any man pages (They should very likely be public in
Nevada). The complete list of API is in href="http://cvs.opensolaris.org/source/xref/usr/src/uts/common/sys/crypto/api.h">uts/common/sys/crypto/api.h.

Let us start with a simple digest operation. The digest API are


    crypto_digest_init(), crypto_digest_update(),

If you are familiar with PKCS #11, these routines follow similar naming
conventions except that crypto_digest() does not need an
crypto_digest_init(). Let us look at crypto_digest(). The prototype is

    int crypto_digest(crypto_mechanism_t \*mech,
crypto_data_t \*data, crypto_data_t \*digest, crypto_call_req_t \*cr);

The structures are defined in href="http://cvs.opensolaris.org/source/xref/usr/src/uts/common/sys/crypto/common.h">uts/common/sys/crypto/common.h.
It is best to explain each argument by looking at an actual example.
Looking in href="http://cvs.opensolaris.org/source/xref/usr/src/uts/common/io/cryptmod.c">uts/common/io/cryptmod.c,
we find

rv = crypto_digest(&mech, &d1, &d2, NULL);

The first argument specifies the cryptographic mechanism  to be
used and its parameters.

mech.cm_type = digest_type;

mech.cm_param = 0;

mech.cm_param_len = 0;

cm_type identifies the type of the mechanism. This field must be set to
the value returned by crypto_mech2id(). crypto_mech2id() gets the kCF
internal mechanism id assigned for a mechanism name. This call needs to
be made only once since the id stays the same till a reboot. For
example in this file, a
SHA1 mechanism id is obtained

sha1_hash_mech = crypto_mech2id(SUN_CKM_SHA1);

and it is passed as digest_type to the kef_digest() routine.

cm_param specifies the parameter for a mechanism. It is zero here. But,
it needs to be specified for some mechanisms. For example, the IV for a
CKM_DES_CBC mechanism is passed in this field. cm_param_len specifies
the length of cm_param, in bytes.

The second argument describes the data that is to be digested.

v1.iov_base = (void \*)input;

v1.iov_len = inlen;


d1.cd_format = CRYPTO_DATA_RAW;

d1.cd_offset = 0;

d1.cd_length = v1.iov_len;

d1.cd_raw = v1;

cd_format specifies the format of the data which can be one of
format means that the input is a iovec_t which basically means a
pointer to a buffer and its length. CRYPTO_DATA_MBLK format is useful
in networking code where mblk_t structures are common. cd_offset
specifies an offset from the beginning of the data. The digesting
starts at that offset byte. cd_length specifies the length of the data
to be used for the digesting. cd_raw is used to specify the address of
a iovec_t buffer. As can be guessed, this field  is valid only if
cd_format is equal to CRYPTO_DATA_RAW.

The third argument describes the output data.

v2.iov_base = (void \*)output;

v2.iov_len = hashlen;


d2.cd_format = CRYPTO_DATA_RAW;

d2.cd_offset = 0;

d2.cd_length = v2.iov_len;

d2.cd_raw = v2;

The fourth argument describes the calling conditions.  A NULL
value, as is the case here, means that caller is prepared to block till
the operation completes. Callers in an interrupt context usually can't
block and need to specify a value for this argument making it an
asynchronous interface.

One asynchronous example is in href="http://cvs.opensolaris.org/source/xref/usr/src/uts/common/inet/ip/ipsecah.c">uts/common/inet/ip/ipsecah.c.
I will talk about it in my next post.

Technorati Tag:

Technorati Tag:

Be the first to comment

Comments ( 0 )
Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.