| OPENCRYPTO(9) | Kernel Developer's Manual | OPENCRYPTO(9) | 
opencrypto, crypto_get_driverid,
  crypto_register,
  crypto_kregister,
  crypto_unregister,
  crypto_unregister_all,
  crypto_done, crypto_kdone,
  crypto_newsession,
  crypto_freesession,
  crypto_dispatch,
  crypto_kdispatch,
  crypto_getreq, crypto_freereq
  crypto_kgetreq,
  crypto_kfreereq —
#include
  <opencrypto/cryptodev.h>
int32_t
  
  crypto_get_driverid(u_int32_t);
int
  
  crypto_register(u_int32_t,
    int,
    u_int16_t,
    u_int32_t,
    int (*)(void *, u_int32_t *,
    struct cryptoini *), int
    (*)(void *, u_int32_t *),
    int (*)(u_int64_t),
    int (*)(struct cryptop
    *), void *);
int
  
  crypto_kregister(u_int32_t,
    int,
    u_int32_t,
    int (*)(void *, struct cryptkop
    *, int), 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);
void
  
  crypto_freesession(u_int64_t);
void
  
  crypto_dispatch(struct
    cryptop *);
void
  
  crypto_kdispatch(struct
    cryptkop *);
struct cryptop *
  
  crypto_getreq(int);
void
  
  crypto_freereq(struct
    cryptop *);
struct cryptop *
  
  crypto_kgetreq(int,
    int);
void
  
  crypto_kfreereq(struct
    cryptop *);
#define EALG_MAX_BLOCK_LEN      16
struct cryptoini {
	int                cri_alg;
	int                cri_klen;
	int                cri_rnd;
	void            *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;
	void            *crp_buf;
	void            *crp_opaque;
	struct cryptodesc *crp_desc;
	int              (*crp_callback)(struct cryptop *);
	void            *crp_mac;
};
struct crparam {
        void         *crp_p;
        u_int           crp_nbits;
};
#define CRK_MAXPARAM    8
struct cryptkop {
	TAILQ_ENTRY(cryptkop) krp_next;
        u_int              krp_op;         /* i.e. 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];	  /* kvm */
        int               (*krp_callback)(struct cryptkop *);
};
opencrypto is a framework for drivers of cryptographic
  hardware to register with the kernel so “consumers” (other
  kernel subsystems, and eventually users through an appropriate 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 information in a particular driver (or associated hardware), so
  initialization is not needed with every request. Consumers of cryptographic
  services 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 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 use condition variables:
    condvar(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 invoked 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 number. Errors are only returned to the invoking function if not
    enough information to call the callback is available (meaning, there was a
    fatal error in verifying the arguments). No callback mechanism is used for
    session initialization and teardown.
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 should be used (1) or not (0).
    The various fields in the cryptoini structure are:
CRYPTO_DES_CBC
CRYPTO_3DES_CBC
CRYPTO_BLF_CBC
CRYPTO_CAST_CBC
CRYPTO_CAMELLIA_CBC
CRYPTO_SKIPJACK_CBC
CRYPTO_ARC4
CRYPTO_AES_CBC
CRYPTO_AES_CTR
CRYPTO_AES_GCM_16
CRYPTO_AES_GMAC
CRYPTO_AES_128_GMAC
CRYPTO_AES_192_GMAC
CRYPTO_AES_256_GMAC
CRYPTO_AES_XCBC_MAC_96
CRYPTO_MD5
CRYPTO_MD5_HMAC
CRYPTO_MD5_HMAC_96
CRYPTO_MD5_KPDK
CRYPTO_NULL_CBC
CRYPTO_NULL_HMAC
CRYPTO_SHA1
CRYPTO_SHA1_HMAC
CRYPTO_SHA1_HMAC_96
CRYPTO_SHA1_KPDK
CRYPTO_SHA2_256_HMAC
CRYPTO_SHA2_384_HMAC
CRYPTO_SHA2_512_HMAC
CRYPTO_RIPEMD160_HMAC
CRYPTO_RIPEMD160_HMAC_96
CRYPTO_DEFLATE_COMP
CRYPTO_DEFLATE_COMP_NOGROW
CRYPTO_GZIP_COMP
    
    The cryptoini structure and its contents will not be modified 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 various fields in the cryptop structure
    are:
crypto_done() routine. If the request was not
      successful, an error code is set in the crp_etype
      field.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).
CRYPTO_F_IMBUFCRD_F_ENCRYPTCRD_F_IV_PRESENTCRD_F_IV_EXPLICIT flag.CRD_F_IV_EXPLICITCRD_F_COMPcrypto_getreq() allocates a
    cryptop structure with a linked list of as many
    cryptodesc structures as were specified in the
    argument passed to it, which must be at least 1.
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 crytokop
    structure are:
crypto_kgetreq() allocates a
    cryptkop structure. The first argument means the same
    as crypto_getreq(), except it is currently limited
    to be exactly 1. The second argument means flags passed to
    pool_get().
crypto_kfreereq() deallocates a structure
    cryptkop structure.
The following sysctl entries exist to adjust the behaviour of the system from userland:
crypto_getreq()
      fails.
    crypto_kgetreq() fails.
    The following sysctl entries exist to get statistics.
crypto_getreq() failed as overflow
      opencrypto.crypto_ret_q.maxlen.crypto_kgetreq() failed as overflow
      opencrypto.crypto_ret_kq.maxlen.crypto_get_driverid(),
  crypto_register(),
  crypto_kregister(),
  crypto_unregister(),
  crypto_unregister_all(), 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
  identifier, specifying the 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 argument is the driver identifier. The second argument is an array of
  CRYPTO_ALGORITHM_MAX + 1 elements, indicating which
  algorithms are supported. The last three arguments are pointers to three
  driver-provided functions that the framework 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.)
  crypto_unregister() is called by drivers that wish to
  withdraw support for an algorithm. The two arguments are the driver and
  algorithm identifiers, respectively. algorithms supported by the card. If all
  algorithms associated with a driver are unregistered, the driver will be
  disabled (no new sessions will be allocated on that driver, and any existing
  sessions will be migrated to other drivers).
  crypto_unregister_all() will unregister all registered
  algorithms, disable the driver, and migrate existing sessions to other
  drivers.
The calling convention for the three driver-supplied routines is:
int (*newsession) (void *, u_int32_t *, struct cryptoini *); void (*freesession) (void *, u_int64_t); int (*process) (void *, struct cryptop *, int);
On invocation, the first argument to
    newsession() contains the driver identifier obtained
    via crypto_get_driverid(). On successfully
    returning, it should contain a driver-specific session identifier. The
    second argument is identical to that of
    crypto_newsession().
The freesession() routine takes as
    argument the SID (which is the concatenation of the driver identifier and
    the driver-specific session identifier returned by
    newsession().) 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 callback routine should be invoked. In case of error, the error
    indication must be placed in the crp_etype field of
    the cryptop structure. The hint
    argument can be set to CRYPTO_HINT_MORE when there
    will be more request right after this request. 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.
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 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 detected, the kprocess() routine
    should invoke crypto_kdone().
crypto_register(),
  crypto_kregister(),
  crypto_unregister(), and
  crypto_newsession() 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_kgetreq() returns a pointer to a
  cryptkop structure and NULL on
  failure. crypto_dispatch() arranges to invoke the
  callback with an error code in the crp_etype field, or
  zero on success.
Angelos D. Keromytis, Jason L. Wright, and Theo de Raadt, The Design of the OpenBSD Cryptographic Framework, Usenix, 2003, June 2003.
Sam Leffler ported the crypto framework to FreeBSD and made performance improvements.
Jonathan Stone
    <jonathan@NetBSD.org>
    ported the cryptoframe from FreeBSD to
    NetBSD. opencrypto first
    appeared in NetBSD 2.0.
crypto_newsession() operation must be available by the
  same driver. If that's 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.
| May 26, 2017 | NetBSD 10.0 |