crypto(9)
NAME
crypto - API for cryptographic services in the kernel
SYNOPSIS
#include <opencrypto/cryptodev.h> int32_t crypto_get_driverid(u_int8_t); int crypto_register(u_int32_t, int, u_int16_t, u_int32_t, int (*)(void *, u_int32_t *, struct cryptoini *), int (*)(void *, u_int64_t), int (*)(void *, struct cryptop *), void *); int crypto_kregister(u_int32_t, int, u_int32_t, int (*)(void *, struct cryptkop *), void *); int crypto_unregister(u_int32_t, int); int crypto_unregister_all(u_int32_t); void crypto_done(struct cryptop *); void crypto_kdone(struct cryptkop *); int crypto_newsession(u_int64_t *, struct cryptoini *, int); int crypto_freesession(u_int64_t); int crypto_dispatch(struct cryptop *); int crypto_kdispatch(struct cryptkop *); int crypto_unblock(u_int32_t, int); struct cryptop * crypto_getreq(int); void crypto_freereq(void); #define CRYPTO_SYMQ 0x1 #define CRYPTO_ASYMQ 0x2 #define EALG_MAX_BLOCK_LEN 16 struct cryptoini { int cri_alg; int cri_klen; int cri_rnd; caddr_t cri_key; u_int8_t cri_iv[EALG_MAX_BLOCK_LEN]; struct cryptoini *cri_next; }; struct cryptodesc { int crd_skip; int crd_len; int crd_inject; int crd_flags; struct cryptoini CRD_INI; struct cryptodesc *crd_next; }; struct cryptop { TAILQ_ENTRY(cryptop) crp_next; u_int64_t crp_sid; int crp_ilen; int crp_olen; int crp_etype; int crp_flags; caddr_t crp_buf; caddr_t crp_opaque; struct cryptodesc *crp_desc; int (*crp_callback) (struct cryptop *); caddr_t crp_mac; }; struct crparam { caddr_t crp_p; u_int crp_nbits; }; #define CRK_MAXPARAM 8 struct cryptkop { TAILQ_ENTRY(cryptkop) krp_next; u_int krp_op; /* ie. CRK_MOD_EXP or other */ u_int krp_status; /* return status */ u_short krp_iparams; /* # of input pa rameters */ u_short krp_oparams; /* # of output parameters */ u_int32_t krp_hid; struct crparam krp_param[CRK_MAXPARAM]; int (*krp_callback)(struct cryptkop *); };
DESCRIPTION
- crypto is a framework for drivers of cryptographic hardware
- to register
with the kernel so ``consumers'' (other kernel subsystems, - and users
through the /dev/crypto device) are able to make use of it. - Drivers register with the framework the algorithms they support, and
- provide entry
points (functions) the framework may call to establish, use, - and tear
down sessions. Sessions are used to cache cryptographic in - formation in a
particular driver (or associated hardware), so initializa - tion is not
needed with every request. Consumers of cryptographic ser - vices pass a
set of descriptors that instruct the framework (and the - drivers registered with it) of the operations that should be applied on
- the data (more
than one cryptographic operation can be requested). - Keying operations are supported as well. Unlike the symmet
- ric operators
described above, these sessionless commands perform mathe - matical operations using input and output parameters.
- Since the consumers may not be associated with a process,
- drivers may not
sleep(9). The same holds for the framework. Thus, a call - back mechanism
is used to notify a consumer that a request has been com - pleted (the callback is specified by the consumer on an per-request basis).
- The callback
is invoked by the framework whether the request was success - fully completed or not. An error indication is provided in the lat
- ter case. A
specific error code, EAGAIN, is used to indicate that a ses - sion number
has changed and that the request may be re-submitted immedi - ately with the
new session number. Errors are only returned to the invok - ing function if
not enough information to call the callback is available - (meaning, there
was a fatal error in verifying the arguments). For session - initialization and teardown there is no callback mechanism used.
- The crypto_newsession() routine is called by consumers of
- cryptographic
services (such as the ipsec(4) stack) that wish to establish - a new session with the framework. On success, the first argument
- will contain the
Session Identifier (SID). The second argument contains all - the necessary
information for the driver to establish the session. The - third argument
indicates whether a hardware driver (1) should be used or - not (0). The
various fields in the cryptoini structure are: - cri_alg Contains an algorithm identifier. Currently
- supported
- algorithms are:
- CRYPTO_DES_CBC
CRYPTO_3DES_CBC
CRYPTO_BLF_CBC
CRYPTO_CAST_CBC
CRYPTO_SKIPJACK_CBC
CRYPTO_MD5_HMAC
CRYPTO_SHA1_HMAC
CRYPTO_RIPEMD160_HMAC
CRYPTO_MD5_KPDK
CRYPTO_SHA1_KPDK
CRYPTO_AES_CBC
CRYPTO_ARC4
CRYPTO_MD5
CRYPTO_SHA1
CRYPTO_SHA2_HMAC
CRYPTO_NULL_HMAC
CRYPTO_NULL_CBC - cri_klen Specifies the length of the key in bits, for
- variable-size
- key algorithms.
- cri_rnd Specifies the number of rounds to be used with
- the algo
- rithm, for variable-round algorithms.
- cri_key Contains the key to be used with the algo
- rithm.
- cri_iv Contains an explicit initialization vector
- (IV), if it does
- not prefix the data. This field is ignored
- during initialization. If no IV is explicitly passed (see
- below on
details), a random IV is used by the device - driver processing the request.
- cri_next Contains a pointer to another cryptoini struc
- ture. Multi
- ple such structures may be linked to establish
- multi-algorithm sessions (ipsec(4) is an example con
- sumer of such a
feature). - The cryptoini structure and its contents will not be modi
- fied by the
framework (or the drivers used). Subsequent requests for - processing that
use the SID returned will avoid the cost of re-initializing - the hardware
(in essence, SID acts as an index in the session cache of - the driver).
- crypto_freesession() is called with the SID returned by crypto_newsession() to disestablish the session.
- crypto_dispatch() is called to process a request. The vari
- ous fields in
the cryptop structure are: - crp_sid Contains the SID.
- crp_ilen Indicates the total length in bytes of the
- buffer to be
- processed.
- crp_olen On return, contains the total length of
- the result.
- For symmetric crypto operations, this will
- be the same
as the input length. This will be used if - the framework needs to allocate a new buffer for
- the result (or
for re-formatting the input). - crp_callback This routine is invoked upon completion of
- the request,
- whether successful or not. It is invoked
- through the
crypto_done() routine. If the request was - not successful, an error code is set in the crp_etype
- field. It
is the responsibility of the callback rou - tine to set
the appropriate spl(9) level. - crp_etype Contains the error type, if any errors
- were encoun
- tered, or zero if the request was success
- fully processed. If the EAGAIN error code is re
- turned, the SID
has changed (and has been recorded in the - crp_sid
field). The consumer should record the - new SID and use
it in all subsequent requests. In this - case, the
request may be re-submitted immediately. - This mechanism is used by the framework to perform
- session migration (move a session from one driver to
- another,
because of availability, performance, or - other considerations).
- Note that this field only makes sense when
- examined by
the callback routine specified in - crp_callback. Errors
are returned to the invoker of - crypto_process() only
when enough information is not present to - call the
callback routine (i.e., if the pointer - passed is NULL
or if no callback routine was specified). - crp_flags Is a bitmask of flags associated with this
- request.
- Currently defined flags are:
- CRYPTO_F_IMBUF The buffer pointed to
- by crp_buf is
an mbuf chain.
- crp_buf Points to the input buffer. On return
- (when the call
- back is invoked), it contains the result
- of the
request. The input buffer may be an mbuf - chain or a
contiguous buffer, depending on crp_flags. - crp_opaque This is passed through the crypto frame
- work untouched
- and is intended for the invoking applica
- tion's use.
- crp_desc This is a linked list of descriptors.
- Each descriptor
- provides information about what type of
- cryptographic
operation should be done on the input - buffer. The various fields are:
- crd_skip The offset in the input
- buffer where
processing should start.
- crd_len How many bytes, after
- crd_skip, should
- be processed.
- crd_inject Offset from the beginning
- of the buffer
- to insert any results.
- For encryption
algorithms, this is where - the initialization vector (IV) will
- be inserted
when encrypting or where - it can be
found when decrypting - (subject to
crd_flags). For MAC algo - rithms, this
is where the result of the - keyed hash
will be inserted. - crd_flags The following flags are
- defined:
CRD_F_ENCRYPT For- encryption
algorithms, this
bitis set when
encryption is
required (when
notset, decryptionis performed). - CRD_F_IV_PRESENT For
- encryption
- al
- gorithms, this
bit - is set when
the - IV already
pre - cedes the
da - ta, so the
crd_inject - value
will - be ignored
and - no IV will
be - written in
the - buffer.
Oth - erwise, the
IV - used to
en - crypt the
pack - et will be
writ - ten at the
lo - cation pointed
to - by
crd_inject. - The
IV - length is
as - sumed to be
equal - to the
block - size of the
en - cryption algorithm.
- Some
ap - plications
that - do special
``IV - cooking'',
such - as the
half - IV mode in
ipsec(4), - can
use - this flag to
in - dicate that
the - IV should
not - be written
on - the packet.
This - flag is
typ - ically used
in - conjunction
with - the
CRD_F_IV_EX - PLICIT
flag. - CRD_F_IV_EXPLICIT For
- encryption
- al
- gorithms, this
bit - is set when
the - IV is
ex - plicitly provid
- ed by the
con - sumer in the
cri_iv - fields.
Oth - erwise, for
en - cryption operations
- the IV is
pro - vided for by
the - driver used
to - perform the
op - eration,
where - as for
de - cryption operations
- it is
point - ed to by
the - crd_inject
field. - This
flag - is typical
- ly used when
the - IV is calculat
- ed ``on the
fly'' - by the
con - sumer, and
does - not precede
the - data (some
ipsec(4) - configura
- tions, and
the - encrypted
swap - are two
such - examples).
- CRD_F_COMP For
- compression
- al
- gorithms, this
bit - is set when
com - pression is
re - quired (when
not - set, decompres
- sion is performed).
- CRD_INI This cryptoini structure
- will not be
- modified by the framework
- or the device
drivers. Since this in - formation accompanies every cryptographic
- operation
request, drivers may re - initialize
state on-demand (typically - an expensive
operation). Furthermore, - the cryptographic framework may re
- route requests
as a result of full queues - or hardware
failure, as described - above.
- crd_next Point to the next descrip
- tor. Linked
- operations are useful in
- protocols such
as ipsec(4), where multi - ple cryptographic transforms may be
- applied on
the same block of data. - crypto_getreq() allocates a cryptop structure with a linked
- list of as
many cryptodesc structures as were specified in the argument - passed to
it. - crypto_freereq() deallocates a structure cryptop and any
- cryptodesc
structures linked to it. Note that it is the responsibility - of the callback routine to do the necessary cleanups associated with
- the opaque
field in the cryptop structure. - crypto_kdispatch() is called to perform a keying operation.
- The various
fields in the cryptkop structure are: - krp_op Operation code, such as CRK_MOD_EXP.
- krp_status Return code. This errno-style variable
- indicates
- whether lower level reasons for operation
- failure.
- krp_iparams Number if input parameters to the speci
- fied operation.
- Note that each operation has a (typically
- hardwired)
number of such parameters. - krp_oparams Number if output parameters from the
- specified opera
- tion. Note that each operation has a
- (typically hardwired) number of such parameters.
- krp_kvp An array of kernel memory blocks contain
- ing the param
- eters.
- krp_hid Identifier specifying which low-level
- driver is being
- used.
- krp_callback Callback called on completion of a keying
- operation.
DRIVER-SIDE API
- The crypto_get_driverid(), crypto_register(),
- crypto_kregister(),
crypto_unregister(), crypto_unblock(), and crypto_done() - routines are
used by drivers that provide support for cryptographic prim - itives to register and unregister with the kernel crypto services frame
- work. Drivers
must first use the crypto_get_driverid() function to acquire - a driver
identifier, specifying the cc_flags as an argument (normally - 0, but software-only drivers should specify CRYPTOCAP_F_SOFTWARE). For
- each algorithm the driver supports, it must then call
- crypto_register(). The
first two arguments are the driver and algorithm identi - fiers. The next
two arguments specify the largest possible operator length - (in bits,
important for public key operations) and flags for this al - gorithm. The
last four arguments must be provided in the first call to
crypto_register() and are ignored in all subsequent calls. - They are
pointers to three driver-provided functions that the frame - work may call
to establish new cryptographic context with the driver, free - already
established context, and ask for a request to be processed - (encrypt,
decrypt, etc.); and an opaque parameter to pass when calling - each of
these routines. crypto_unregister() is called by drivers - that wish to
withdraw support for an algorithm. The two arguments are - the driver and
algorithm identifiers, respectively. Typically, drivers for - PCMCIA
crypto cards that are being ejected will invoke this routine - for all
algorithms supported by the card. crypto_unregister_all() - will unregister all algorithms registered by a driver and the driver
- will be disabled
(no new sessions will be allocated on that driver, and any - existing sessions will be migrated to other drivers). The same will be
- done if all
algorithms associated with a driver are unregistered one by - one.
- The calling convention for the three driver-supplied rou
- tines is:
- int (*newsession)(void *, u_int32_t *, struct cryptoini *);
int (*freesession)(void *, u_int64_t);
int (*process)(void *, struct cryptop *);
int (*kprocess)(void *, struct cryptkop *); - On invocation, the first argument to all routines is an
- opaque data value
supplied when the algorithm is registered with - crypto_register(). The
second argument to newsession() contains the driver identi - fier obtained
via crypto_get_driverid(). On successful return, it should - contain a
driver-specific session identifier. The third argument is - identical to
that of crypto_newsession(). - The freesession() routine takes as arguments the opaque data
- value and
the SID (which is the concatenation of the driver identifier - and the
driver-specific session identifier). It should clear any - context associated with the session (clear hardware registers, memory,
- etc.).
- The process() routine is invoked with a request to perform
- crypto processing. This routine must not block, but should queue the
- request and
return immediately. Upon processing the request, the call - back routine
should be invoked. In case of an unrecoverable error, the - error indication must be placed in the crp_etype field of the cryptop
- structure.
When the request is completed, or an error is detected, the - process()
routine should invoke crypto_done(). Session migration may - be performed,
as mentioned previously. - In case of a temporary resource exhaustion, the process()
- routine may
return ERESTART in which case the crypto services will re - queue the
request, mark the driver as ``blocked'', and stop submitting - requests for
processing. The driver is then responsible for notifying - the crypto services when it is again able to process requests through the
crypto_unblock() routine. This simple flow control mecha - nism should only
be used for short-lived resource exhaustion as it causes op - erations to be
queued in the crypto layer. Doing so is preferable to re - turning an error
in such cases as it can cause network protocols to degrade - performance by
treating the failure much like a lost packet. - The kprocess() routine is invoked with a request to perform
- crypto key
processing. This routine must not block, but should queue - the request
and return immediately. Upon processing the request, the - callback routine should be invoked. In case of an unrecoverable error,
- the error
indication must be placed in the krp_status field of the - cryptkop structure. When the request is completed, or an error is detect
- ed, the
kprocess() routine should invoked crypto_kdone().
RETURN VALUES
- crypto_register(), crypto_kregister(), crypto_unregister(), crypto_newsession(), crypto_freesession(), and
- crypto_unblock() return 0
on success, or an error code on failure. - crypto_get_driverid() returns a
non-negative value on error, and -1 on failure. - crypto_getreq() returns
a pointer to a cryptop structure and NULL on failure. - crypto_dispatch()
returns EINVAL if its argument or the callback function was - NULL, and 0
otherwise. The callback is provided with an error code in - case of failure, in the crp_etype field.
FILES
sys/opencrypto/crypto.c most of the framework code
SEE ALSO
HISTORY
- The cryptographic framework first appeared in OpenBSD 2.7
- and was written
by Angelos D. Keromytis <angelos@openbsd.org>.
BUGS
- The framework currently assumes that all the algorithms in a
crypto_newsession() operation must be available by the same - driver. If
that is not the case, session initialization will fail. - The framework also needs a mechanism for determining which
- driver is best
for a specific set of algorithms associated with a session. - Some type of
benchmarking is in order here. - Multiple instances of the same algorithm in the same session
- are not supported. Note that 3DES is considered one algorithm (and not
- three
instances of DES). Thus, 3DES and DES could be mixed in the - same
request. - BSD October 14, 2002