home | help
CRYPTO(9)		    Kernel Developer's Manual		       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 parameters */
	     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  (func-
     tions)  the  framework  may call to establish, use, and tear down sessions.
     Sessions are used to cache cryptographic information in a particular driver
     (or associated hardware), so initialization is not needed	with  every  re-
     quest.   Consumers of cryptographic services pass a set of descriptors that
     instruct the framework (and the drivers registered with it) of  the  opera-
     tions that should be applied on the data (more than one cryptographic oper-
     ation can be requested).

     Keying  operations  are  supported as well.  Unlike the symmetric operators
     described above, these sessionless commands perform mathematical 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 callback mechanism is
     used  to  notify a consumer that a request has been completed (the callback
     is specified by the consumer on an per-request basis).  The callback is in-
     voked by the framework whether the request was  successfully  completed  or
     not.  An error indication is provided in the latter case.	A specific error
     code,  EAGAIN,  is  used  to indicate that a session number has changed and
     that the request may be re-submitted immediately with the new session  num-
     ber.   Errors  are only returned to the invoking function if not enough in-
     formation to call the callback is available (meaning, there was a fatal er-
     ror 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 Ses-
     sion Identifier (SID).  The second argument contains all the necessary  in-
     formation	for the driver to establish the session.  The third argument in-
     dicates whether a hardware driver (1) should be used or not (0).  The vari-
     ous 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 algorithm, for
	       variable-round algorithms.

     cri_key   Contains the key to be used with the algorithm.

     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 structure.  Multiple such
	       structures may be linked to establish multi-algorithm sessions is
	       an example consumer of such a feature).

     The cryptoini structure and its contents will not be modified by the frame-
     work  (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 various 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 sym-
		   metric  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  respon-
		   sibility  of  the  callback	routine  to  set the appropriate
		   spl(9) level.

     crp_etype	   Contains the error type, if any errors were	encountered,  or
		   zero  if  the  request  was	successfully  processed.  If the
		   EAGAIN error code is returned, 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  migra-
		   tion  (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 re-
		   turned 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  rou-
		   tine was specified).

     crp_flags	   Is  a  bitmask  of  flags associated with this request.  Cur-
		   rently 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 callback 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 framework untouched and is
		   intended for the invoking application's use.

     crp_desc	   This is a linked list of descriptors.  Each	descriptor  pro-
		   vides  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 in-
			       serted when encrypting or where it can  be  found
			       when  decrypting (subject to crd_flags).  For MAC
			       algorithms, 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	bit  is set when encryp-
						  tion	is  required  (when  not
						  set, decryption is performed).

			       CRD_F_IV_PRESENT   For	encryption   algorithms,
						  this bit is set  when  the  IV
						  already  precedes the data, so
						  the crd_inject value	will  be
						  ignored  and	no  IV	will  be
						  written in the buffer.  Other-
						  wise, the IV used  to  encrypt
						  the  packet will be written at
						  the  location  pointed  to  by
						  crd_inject.	The IV length is
						  assumed to  be  equal  to  the
						  blocksize  of  the  encryption
						  algorithm.  Some  applications
						  that	do special "IV cooking",
						  such as the  half-IV	mode  in
						  ipsec(4), can use this flag to
						  indicate  that  the  IV should
						  not be written on the  packet.
						  This flag is typically used in
						  conjunction	   with      the
						  CRD_F_IV_EXPLICIT flag.

			       CRD_F_IV_EXPLICIT  For	encryption   algorithms,
						  this bit is set when the IV is
						  explicitly   provided  by  the
						  consumer in the cri_iv fields.
						  Otherwise, for encryption  op-
						  erations  the  IV  is provided
						  for by the driver used to per-
						  form	the  operation,  whereas
						  for  decryption  operations it
						  is   pointed	 to    by    the
						  crd_inject  field.   This flag
						  is typically used when the  IV
						  is  calculated "on the fly" by
						  the  consumer,  and  does  not
						  precede    the    data   (some
						  ipsec(4)  configurations,  and
						  the  encrypted  swap	are  two
						  such examples).

			       CRD_F_COMP	  For  compression   algorithms,
						  this	bit is set when compres-
						  sion	is  required  (when  not
						  set,	 decompression	is  per-
						  formed).

		   CRD_INI     This cryptoini structure will not be modified  by
			       the  framework or the device drivers.  Since this
			       information accompanies every cryptographic oper-
			       ation 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 descriptor.  Linked  operations
			       are  useful  in protocols such as ipsec(4), where
			       multiple 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 struc-
     tures 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 specified operation.  Note
		    that each operation has a (typically  hardwired)  number  of
		    such parameters.

     krp_oparams    Number  if	output	parameters from the specified operation.
		    Note that each operation has a (typically hardwired)  number
		    of such parameters.

     krp_kvp	    An array of kernel memory blocks containing the parameters.

     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 primitives to register
     and unregister with the kernel crypto  services  framework.   Drivers  must
     first  use  the  crypto_get_driverid() function to acquire a driver identi-
     fier, specifying the cc_flags as an argument (normally 0, but software-only
     drivers should specify CRYPTOCAP_F_SOFTWARE).  For each algorithm the  dri-
     ver supports, it must then call crypto_register().  The first two arguments
     are  the  driver and algorithm identifiers.  The next two arguments specify
     the largest possible operator length (in bits, important for public key op-
     erations) and flags for this algorithm.  The last four  arguments	must  be
     provided in the first call to crypto_register() and are ignored in all sub-
     sequent  calls.   They are pointers to three driver-provided functions that
     the framework may call to establish new cryptographic context with the dri-
     ver, 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  algo-
     rithms associated with a driver are unregistered one by one.

     The calling convention for the three driver-supplied routines 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 sec-
     ond argument to newsession() contains the driver  identifier  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	process-
     ing.   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 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  previ-
     ously.

     In  case  of a temporary resource exhaustion, the process() routine may re-
     turn ERESTART in which case the crypto services will requeue  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 mechanism should only be used for short-lived resource
     exhaustion as it causes operations to be queued in the crypto layer.  Doing
     so is preferable to returning an error in such cases as it can  cause  net-
     work  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 pro-
     cessing.  This routine must not block, but should queue the request and re-
     turn 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 re-
     quest is completed, or an error is detected, the kprocess() routine  should
     invoked crypto_kdone().

RETURN VALUES
     crypto_register(),  crypto_kregister(), crypto_unregister(), crypto_newses-
     sion(), 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 call-
     back  is  provided  with an error code in case of failure, in the crp_etype
     field.

FILES
     sys/crypto/crypto.c  most of the framework code

SEE ALSO
     ipsec(4), malloc(9), sleep(9)

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_newses-
     sion()  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  sup-
     ported.   Note  that  3DES  is  considered one algorithm (and not three in-
     stances of DES).  Thus, 3DES and DES could be mixed in the same request.

FreeBSD 5.0			October 14, 2002		       CRYPTO(9)

home | help