--- gate/cspi	Mon Aug 10 11:18:29 2009
+++ fips/cspi	Tue Aug 11 16:13:02 2009
@@ -1,469 +1,469 @@
 
 #pragma ident   "@(#)cspi 1.119     06/05/03 SMI"
 
 
 		Cryptographic Service Provider Interface
 
 
 1. Overview
 -----------
 The CSPI (Cryptographic Service Provider Interface) is defined by
 routines and constants exported by providers, routines imported by
 providers, and by data structures.  Routines exported by providers
 are those that perform cryptographic operations.  The stability
 classification of this interface is Consolidation Private.
 
 Providers import two routines that allow them to register/unregister
 with the framework and two routines that notify the framework
 of changes in status. The provider currently exports 41 routines which
 may appear in a provider's ops vector.
 In addition to routines that perform cryptographic operations, the ops
 vector also offers routines for session and cryptographic context
 management, and for object manipulation.
 
 This CSPI introduces a new "crypto" module type for software cryptographic
 modules and device drivers.  Software modules in /kernel/crypto have a
 modlinkage structure containing a single pointer to a modlcrypto structure.
 Device drivers have a modlcrypto pointer as well as a modldrv pointer.
 Device drivers in /kernel/crypto have a hard link to their entry in
 /kernel/drv.
 
 The header file sys/crypto/spi.h implements the definitions described
 by this document. This file must be included by cryptographic provider.
 
 2. Data Structures
 ------------------
 Module Linkage
 --------------
 In order to support a new "crypto" module type, the following
 structure is defined in sys/modctl.h:
 
 struct modlcrypto {
 	struct mod_ops	*crypto_modops;
 	char		*crypto_linkinfo;
 };
 
 Like the "misc" module type, the new "crypto" module type does not
 have a device ops vector. Providers import the following symbol
 from genunix:
 
 struct mod_ops mod_cryptoops = {
 	mod_null, mod_null, modinfonull
 };
 
 Mechanisms
 ----------
 The crypto_mechanism structure contains a mechanism number and a pointer
 to mechanism specific parameters.  At registration time, providers passes
 their own internal mechanism numbers to the framework along with strings
 that identify each mechanism.  For each call to a provider, the mechanism
 structure passed to a provider contains the provider's internal
 mechanism number.
 
 For existing PKCS#11 mechanism numbers, the string that identifies a
 mechanism should look like the PKCS#11 #define in section 9.5,
 e.g. "CKM_DES_CBC".  For vendor-defined strings, the string should
 contain a prefix that identifies the vendor, e.g. "SUN_BLOWFISH".
 
 typedef uint64_t crypto_mech_type_t;
 
 typedef struct crypto_mechanism {
 	crypto_mech_type_t cm_type;	/* provider's mechanism number */
 	void		*cm_param;	/* mechanism parameters */
 	size_t		cm_param_len;	/* parameter length */
 } crypto_mechanism_t;
 
 For mechanisms defined by PKCS#11, the structure of a parameter should
 be the same as those defined by PKCS#11.  For vendor defined mechanisms
 that require a parameter, the structure of the parameter is private
 between the provider and users of that provider.
 
 Keys
 ----
 
 The generic representation of a key is a crypto_key_t structure: 
 
 typedef struct crypto_key {
 	crypto_key_format_t	ck_format;	/* format identifier */ 
 	union {
 		/* for CRYPTO_KEY_RAW ck_format */
 		struct { 		
 			uint_t	cku_v_length; 	/* # of bits in ck_data   */ 
 			void	*cku_v_data;	/* ptr to key value */ 
 		} cku_key_value; 
 
 		/* for CRYPTO_KEY_REFERENCE ck_format */
 		crypto_object_id_t cku_key_id;	/* reference to an object key */ 
 
 		/* for CRYPTO_KEY_ATTR_LIST ck_format */ 
 		struct { 
                       uint_t	cku_a_count;  /* number of attributes */ 
                       crypto_object_attribute_t *cku_a_oattr; /* attributes */ 
 		} cku_key_attrs; 
 	} cku_data;                         /* Crypto Key union */ 
 } crypto_key_t;
 
 and the notation shortcuts: 
 
 #define ck_data		cku_data.cku_key_value.cku_v_data 
 #define ck_length	cku_data.cku_key_value.cku_v_length 
 #define ck_obj_id	cku_data.cku_key_id 
 #define ck_count	cku_data.cku_key_attrs.cku_a_count 
 #define ck_attrs	cku_data.cku_key_attrs.cku_a_oattr 
         
 The format is identified as: 
 
 typedef enum { 
 	CRYPTO_KEY_RAW = 1,      /* ck_data is a cleartext key */ 
 	CRYPTO_KEY_REFERENCE,    /* ck_obj_id is an opaque reference */
 	CRYPTO_KEY_ATTR_LIST     /* ck_attrs is a list of object attributes */
 } crypto_key_format_t; 
 
 The type of the key (public/private/secret) and the usage
 (encrypt/decrypt/MAC/sign/verify with the associated mechanism) is
 determined by the context of the operation using that key. 
         
 - When ck_format is CRYPTO_KEY_RAW, ck_data points to the actual value of the
   key, which is ready to use. For MACs and symmetric ciphers, the value is
   typically an array of bytes. For this format, the length of the key is
   specified in bits rather than bytes. If storage is allocated for a raw
   key, then the number of bytes allocated must be the minimum number that
   can contain the key.
 
 - When ck_format is CRYPTO_KEY_REFERENCE, ck_obj_id is the identifier of
   an object key that is opaque to the consumer. The intended use is a handle
   to retrieve a key securely stored in a provider. When the key is created
   the provider returns only an object identifier to that unexposed key. The
   following type is used to encode an object identifier:
 
   typedef uint_t crypto_object_id_t;
 
   Object identifiers are also used directly by object and key management
   entry points (crypto_object_ops_t and crypto_key_ops_t). Providers that
   do not support object or key management do not implement these entry
   points, and do not support the CRYPTO_KEY_REFERENCE key format.
 
 - When ck_format is CRYPTO_KEY_ATTR_LIST, ck_attrs is a list of attributes
   that make up a composite key. Each attribute is a type-value-len tuple. The
   intended use of these kind of keys are operations with asymmetric ciphers
   that take structured keys (e.g. an RSA verification with a public key made
   of two big numbers: a modulus and a public exponent.
 
   The object attribute structure is defines as follows: 
 
   typedef crypto_object_attribute { 
 	uint64_t	oa_type;        /* attribute type */ 
 	caddr_t		oa_value;       /* attribute value */ 
 	ssize_t		oa_value_len;   /* length of attribute value */ 
   } crypto_object_attribute_t;
 
   Attribute types are defined by the #defines for CK_ATTRIBUTE_TYPE
   in section 9.4 of PKCS#11.  It is expected that the Provider is aware
   of PKCS#11 attributes and their semantics if it implements object
   and key management entry points.
 
 Input and Output Data Buffers
 -----------------------------
 
 Data buffers passed to cryptographic operations are specified by
 crypto_data_t and crypto_dual_data_t structures defined in details
 in the KEF Functional Specification Document.
 
 The cd_miscdata field in the crypto_data structure provides an alternate
 way to pass initialization information to providers.  If this field is
 non-null, then it points to information that is used to initialize
 block-chaining ciphers.  If the same crypto_data structure is passed to
 multiple update operations, then cd_miscdata must be set to NULL for
 all updates except the first one.  If cd_miscdata is non-null, then
 initialization information does not have to be present in the
 crypto_mechanism structure.
 
 When the result of a cryptographic operation is returned by a Provider
 to the framework, the Provider entry point must return the
 length in bytes of the output data. Depending on the data format,
 the Provider uses the following fields to return this value:
 
 - crypto_data_t: cd_length.
 - crypto_dual_data_t: dd_len1 if encryption or decryption is the first
   of the dual operation (e.g. encrypt_mac_atomic()), or dd_len2 if
   encryption or decryption is the second of the dual operations
   (e.g. mac_decrypt_atomic()).
 
 
 Contexts
 --------
 
 The context structure is passed from the framework to a provider.
 It contains the information needed to process a multi-part or
 single part operation. The context structure is not used
 by atomic operations.
 
 Parameters needed to perform a cryptographic operation, such
 as keys, mechanisms, input and output buffers, are passed
 as separate arguments to Provider routines. 
 
 For asynchronous providers, requests that refer to a context may be
 submitted by the framework to a provider before requests on the same
 context are completed by the provider. A Provider is required to
 maintain the order of requests that refer to the same context.
 
 /* Context */
 typedef struct crypto_ctx {
 	crypto_provider_handle_t cc_provider;
 	crypto_session_id_t	cc_session;
 	void			*cc_provider_private;	/* owned by provider */
 	void			*cc_framework_private;	/* owned by framework */
 } crypto_ctx_t;
 
 Context Templates
 -----------------
 
 For software Providers, it may be necessary to pre-process keying
 material before use. Such pre-processing can consist of computing
 the key schedule of an encryption key. Such pre-processing is done
 only once per key. In order to avoid the same pre-processing overhead
 for the same key, the framework introduces the notion of context
 templates.
 
 A context template allows software providers to pre-process keying material
 and to save the result of this pre-processing. The context template is
 later passed as argument to cryptographic Provider entry points.
 A usage example of context templates by consumers can be found in
 the k-API document.
 
 At the CSPI level, a handle to a context template is represented by
 the following structure, opaque for the Provider:
 
 typedef void *spi_ctx_template_handle_t;
 
 A context template handle of type spi_ctx_template_handle_t points
 to an instance of the following type in the framework:
 
 typedef struct kcf_ctx_template {
 	crypto_kcf_provider_handle_t	ct_kcf_provider_handle;
 	uint_t                        	ct_generation;
 	crypto_spi_ctx_template_t	*ct_provider_template;
 	size_t                          ct_ctx_template_size;
 } kcf_ctx_template_t;
 
 ct_kcf_provider_handle is used by KEF to associate a context template with
 the Software Provider that created it. The value of this field is
 set by KEF when the context template is created. kct_generation is a per
 mechanism counter maintained by the framework, incremented each time a
 software Provider for that mechanism is registered. It is copied set in
 the context template before the kcf_ctx_template is returned to a consumer
 allocating a ctx_template. It is compared against the current generation
 for that mechanism before the context template for that mechanism
 is passed to a Provider xxx_init() routine. This ensures that
 context templates are only passed to the Providers that allocated
 them. 
 
 kct_provider_template is the pointer to the context template allocated
 by the Provider, it's type is defined as follows
 
 typedef void *crypto_spi_ctx_template_t;
 
 Context templates are created by the create_ctx_template() entry
 point implemented by Providers. They are destroyed automatically
 by the KEF. The create_ctx_template() entry point is implemented
 by Software Providers only and is always executed synchronously.
 
 Request Handles
 ---------------
 
 Request handle, crypto_req_handle_t, are used by the framework to
 identify a request when it is executed asynchronously.
 The request handle is passed by the framework to the Provider for
 requests that can be processed asynchronously, and is defined as
 follows:
 
 typedef void *crypto_req_handle_t;
 
 If the request is executed asynchronously by the Provider, indicated
 by a CRYPTO_QUEUED status returned by the Provider entry point,
 The request handle will be passed back to the framework from the
 Provider during a call to crypto_op_notification().
 
 
 Kernel memory allocation and use of KM_SLEEP and KM_NOSLEEP
 -----------------------------------------------------------
 A hardware provider can always use KM_SLEEP when allocating memory
 in the context of the thread calling the SPI routine.
 
 A software provider must call a KEF routine, crypto_kmflag()
 in the context of the thread calling the SPI routine, to get this information.
 
 
 Provider Registration
 ---------------------
 
 Providers register by calling the crypto_register_provider() routine
 exported by the framework:
 
 int crypto_register_provider(crypto_provider_info_t *info,
     crypto_kcf_provider_handle_t *handle);
 
 A crypto_provider_info_t structure describing the capabilities of
 software or hardware Providers is passed to crypto_register_provider().
 After registration, providers can free crypto_provider_info if they
 allocated the structure.
 
 typedef enum {
 	CRYPTO_HW_PROVIDER = 0,
 	CRYPTO_SW_PROVIDER,
 	CRYPTO_LOGICAL_PROVIDER
 } crypto_provider_type_t;
 
 typedef union crypto_provider_dev {
 	struct modlinkage	*pd_sw; /* for CRYPTO_SW_PROVIDER */
 	dev_info_t		*pd_hw; /* for CRYPTO_HW_PROVIDER */
 					/* for CRYPTO_LOGICAL_PROVIDER */
 } crypto_provider_dev_t;
 
 #define CRYPTO_SPI_VERSION_2	2
 
 /*
  * Maximum length of the pi_provider_description field of the
  * crypto_provider_info structure.
  */
 #define	CRYPTO_PROVIDER_DESCR_MAX_LEN	32
 
 /*
  * Provider information. Passed as argument to crypto_register_provider(9F).
  * Describes the provider and its capabilities. Multiple providers can
  * register for the same device instance. In this case, the same
  * pi_provider_dev must be specified with a different pi_provider_handle.
  */
 typedef struct crypto_provider_info_v1 {
 	uint_t				pi_interface_version;
 	char				*pi_provider_description;
 	crypto_provider_type_t		pi_provider_type;
 	crypto_provider_dev_t		pi_provider_dev;
 	crypto_provider_handle_t	pi_provider_handle;
 	crypto_ops_t			*pi_ops_vector;
 	uint_t				pi_mech_list_count;
 	crypto_mech_info_t		*pi_mechanisms;
 	uint_t				pi_logical_provider_count;
 	crypto_kcf_provider_handle_t	*pi_logical_providers;
 } crypto_provider_info_v1_t;
 
 typedef struct crypto_provider_info_v2 {
 	crypto_provider_info_v1_t	v1_info;
 	uint_t				pi_flags;
 } crypto_provider_info_v2_t;
 
 typedef struct crypto_provider_info {
 	union {
 		crypto_provider_info_v2_t piu_v2;
 		crypto_provider_info_v1_t piu_v1;
 	} piu;
 } crypto_provider_info_t;
 
 The pi_provider_dev field of type crypto_provider_dev_t is specified
 by the Provider during registration. A hardware Provider will set the
 pd_hw field of this structure to the dev_info of the instance being
 registered, and pi_provider_type to CRYPTO_HW_PROVIDER. A software
 Provider will set the pd_sw field of this structure to its modlinkage,
 and pi_provider_type to CRYPTO_SW_PROVIDER. A logical Provider sets the
 pd_hw field of this field to a dev_info pointer, and pi_provider_type
 to CRYPTO_LOGICAL_PROVIDER. For the logical Provider, it is okay for the
 dev_info structure to become invalid after the logical provider registers
 since the structure is only used to pass the device name at registration.
 
 The pi_provider_handle field is a provider private handle that is specified
 by a Provider when registering with the framework, and passed by the
 framework to a Provider when invoking its entry points. pi_provider_handle
 is of type crypto_provider_handle_t, which is defined as follows:
 
 typedef void *crypto_provider_handle_t;
 
 The crypto_register_provider() entry initializes and returns to the
 Provider a handle of type crypto_kcf_provider_handle_t. This handle
 is a unique identifier for a Provider registered with the framework,
 and must be specified when the Provider invokes entry points exported
 by the framework, such as crypto_unregister_provider() and
 crypto_provider_notification().
 
 typedef uint_t crypto_kcf_provider_handle_t;
 
 Hardware providers become members of a logical provider by registering
 the logical provider first, and then putting the logical provider's handle
 in the pi_logical_providers array of each hardware provider belonging to
 the logical group. A hardware provider may belong to more than logical
 provider. pi_logical_provider_count is the number of entries in the
 array. By default, a logical provider and all its members are visible
 to pkcs11_kernel(5) and crypto_get_provider(9F). Members may be hidden
 by setting the CRYPTO_HIDE_PROVIDER flag in pi_flags.
 
 The crypto_mech_info structure is an array of mechanisms supported by a
 provider.  Mechanisms are identified by "PKCS#11 like" mechanism strings,
 e.g. "CKM_DES_CBC".  Providers must also supply a number by which they
 internally refer to the mechanism.  Providers are encouraged to use
 already defined PKCS#11 numbers if they are available.  This structure
 also contains min/max key length.
 
 The cm_function_group field identifies which functions can be
 used with the mechanism, it is a bit mask of CRYPTO_FGROUP_*. If a
 mechanism can be used by a specified group of functions, it can also be
 used by dual operations that include that group of functions. This
 applies to dual operations for which a Provider defines entry points.
 
 /*
  * The mechanism info structure crypto_mech_info_t contains a function group
  * bit mask cm_func_group_mask. This field, of type crypto_func_group_t,
  * specifies the provider entry point that can be used a particular
  * mechanism. The function group mask is a combination of the following values.
  */
 
 typedef uint32_t crypto_func_group_t;
 
 #define	CRYPTO_FG_ENCRYPT		0x00000001 /* encrypt_init() */
 #define	CRYPTO_FG_DECRYPT		0x00000002 /* decrypt_init() */
 #define	CRYPTO_FG_DIGEST		0x00000004 /* digest_init() */
 #define	CRYPTO_FG_SIGN			0x00000008 /* sign_init() */
 #define	CRYPTO_FG_SIGN_RECOVER		0x00000010 /* sign_recover_init() */
 #define	CRYPTO_FG_VERIFY		0x00000020 /* verify_init() */
 #define	CRYPTO_FG_VERIFY_RECOVER	0x00000040 /* verify_recover_init() */
 #define	CRYPTO_FG_GENERATE		0x00000080 /* key_generate() */
 #define	CRYPTO_FG_GENERATE_KEY_PAIR	0x00000100 /* key_generate_pair() */
 #define	CRYPTO_FG_WRAP			0x00000200 /* key_wrap() */
 #define	CRYPTO_FG_UNWRAP		0x00000400 /* key_unwrap() */
 #define	CRYPTO_FG_DERIVE		0x00000800 /* key_derive() */
 #define	CRYPTO_FG_MAC			0x00001000 /* mac_init() */
 #define	CRYPTO_FG_ENCRYPT_MAC		0x00002000 /* encrypt_mac_init() */
 #define	CRYPTO_FG_MAC_DECRYPT		0x00004000 /* decrypt_mac_init() */
 #define	CRYPTO_FG_ENCRYPT_ATOMIC	0x00008000 /* encrypt_atomic() */
 #define	CRYPTO_FG_DECRYPT_ATOMIC	0x00010000 /* decrypt_atomic() */
 #define	CRYPTO_FG_MAC_ATOMIC		0x00020000 /* mac_atomic() */
 #define	CRYPTO_FG_DIGEST_ATOMIC		0x00040000 /* digest_atomic() */
 #define	CRYPTO_FG_SIGN_ATOMIC		0x00080000 /* sign_atomic() */
 #define	CRYPTO_FG_SIGN_RECOVER_ATOMIC	0x00100000 /* sign_recover_atomic() */
 #define	CRYPTO_FG_VERIFY_ATOMIC		0x00200000 /* verify_atomic() */
 #define	CRYPTO_FG_VERIFY_RECOVER_ATOMIC	0x00400000 /* verify_recover_atomic() */
 #define	CRYPTO_FG_ENCRYPT_MAC_ATOMIC	0x00800000 /* encrypt_mac_atomic() */
 #define	CRYPTO_FG_MAC_DECRYPT_ATOMIC	0x01000000 /* mac_decrypt_atomic() */
 
 #define CRYPTO_MAX_MECH_NAME_LEN 32
 typedef char crypto_mech_name_t[CRYPTO_MAX_MECH_NAME_LEN];
 
 /*
  * The crypto_mech_info structure specifies one of the mechanisms
  * supported by a cryptographic provider. The pi_mechanisms field of
  * the crypto_provider_info structure contains a pointer to an array
  * of crypto_mech_info's.
  */
 typedef struct crypto_mech_info {
         crypto_mech_name_t	cm_mech_name;
         crypto_mech_type_t	cm_mech_number;
 	crypto_func_group_t	cm_func_group_mask;
         ssize_t			cm_min_key_length;	/* in bits */
         ssize_t			cm_max_key_length;	/* in bits */
 } crypto_mech_info_t;
 
 
 Provider ops vectors are defined below. The pi_ops_vector field should
 be set to NULL for Logical providers. Version 2 of the interface introduces
 crypto_mech_ops. Providers that register CRYPTO_SPI_VERSION_2 must
 register crypto_mech_ops. Version 3 introduces crypto_nostore_key_ops.
-Providers that register CRYPTO_SPI_VERSION_2 must register
-crypto_nostore_key_ops.
+Version 4 introduces crypto_fips140_ops.  Providers that register
+CRYPTO_SPI_VERSION_2 must register crypto_nostore_key_ops.

 
 typedef struct crypto_control_ops {
 	void (*provider_status)(crypto_provider_handle_t, uint_t *);
 } crypto_control_ops_t;
 
 typedef struct crypto_ctx_ops {
 	int (*create_ctx_template)(crypto_provider_handle_t,
 	    crypto_mechanism_t *, crypto_key_t *,
 	    crypto_spi_ctx_template_t *, size_t *, int);
 	int (*free_context)(crypto_ctx_t *);
 } crypto_ctx_ops_t;
 
 typedef struct crypto_digest_ops {
 	int (*digest_init)(crypto_ctx_t *, crypto_mechanism_t *, int,
 	    crypto_req_handle_t);
 	int (*digest)(crypto_ctx_t *,
 	    crypto_data_t *, crypto_data_t *, crypto_req_handle_t);
 	int (*digest_update)(crypto_ctx_t *,
 	    crypto_data_t *, crypto_req_handle_t);
 	int (*digest_key)(crypto_ctx_t *ctx,
 	    crypto_key_t *key, crypto_req_handle_t);
 	int (*digest_final)(crypto_ctx_t *ctx,
 	    crypto_data_t *, crypto_req_handle_t);
         int (*digest_atomic)(crypto_provider_handle_t, crypto_session_id_t,
 	    crypto_mechanism_t *, crypto_data_t *, 
 	    crypto_data_t *, crypto_req_handle_t);
 } crypto_digest_ops_t;
 
 typedef struct crypto_cipher_ops {
 	int (*encrypt_init)(crypto_ctx_t *,
 	    crypto_mechanism_t *, crypto_key_t *,
 	    crypto_spi_ctx_template_t, int, crypto_req_handle_t);
 	int (*encrypt)(crypto_ctx_t *,
 	    crypto_data_t *, crypto_data_t *, crypto_req_handle_t);
 	int (*encrypt_update)(crypto_ctx_t *,
 	    crypto_data_t *, crypto_data_t *, crypto_req_handle_t);
 	int (*encrypt_final)(crypto_ctx_t *,
 	    crypto_data_t *, crypto_req_handle_t);
 	int (*encrypt_atomic)(crypto_provider_handle_t, crypto_session_id_t,
 	    crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
 	    crypto_data_t *, crypto_spi_ctx_template_t, req);
 
 	int (*decrypt_init)(crypto_ctx_t *,
 	    crypto_mechanism_t *, crypto_key_t *,
 	    crypto_spi_ctx_template_t, int, crypto_req_handle_t);
 	int (*decrypt)(crypto_ctx_t *,
 	    crypto_data_t *, crypto_data_t *, crypto_req_handle_t);
 	int (*decrypt_update)(crypto_ctx_t *,
 	    crypto_data_t *, crypto_data_t *, crypto_req_handle_t);
 	int (*decrypt_final)(crypto_ctx_t *,
 	    crypto_data_t *, crypto_req_handle_t);
 	int (*decrypt_atomic)(crypto_provider_handle_t, crypto_session_id_t,
 	    crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
 	    crypto_data_t *, crypto_spi_ctx_template_t, req);
 } crypto_cipher_ops_t;
 
 typedef struct crypto_mac_ops {
 	int (*mac_init)(crypto_ctx_t *,
 	    crypto_mechanism_t *, crypto_key_t *,
 	    crypto_spi_ctx_template_t, int, crypto_req_handle_t);
 	int (*mac)(crypto_ctx_t *,
 	    crypto_data_t *, crypto_data_t *, crypto_req_handle_t);
 	int (*mac_update)(crypto_ctx_t *,
 	    crypto_data_t *, crypto_req_handle_t);
 	int (*mac_final)(crypto_ctx_t *,
 	    crypto_data_t *, crypto_req_handle_t);
 	int (*mac_atomic)(crypto_provider_handle_t, crypto_session_id_t,
 	    crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
 	    crypto_data_t *, crypto_spi_ctx_template_t, req);
 	int (*mac_verify_atomic)(crypto_provider_handle_t, crypto_session_id_t,
 	    crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
 	    crypto_data_t *, crypto_spi_ctx_template_t, int,
 	    crypto_req_handle_t);
 } crypto_mac_ops_t;
 
 typedef struct crypto_sign_ops {
         int (*sign_init)(crypto_ctx_t *,
             crypto_mechanism_t *, crypto_key_t *, crypto_spi_ctx_template_t,
             int, crypto_req_handle_t);
         int (*sign)(crypto_ctx_t *,
             crypto_data_t *, crypto_data_t *, crypto_req_handle_t);
         int (*sign_update)(crypto_ctx_t *,
             crypto_data_t *, crypto_req_handle_t);
         int (*sign_final)(crypto_ctx_t *,
             crypto_data_t *, crypto_req_handle_t);
         int (*sign_atomic)(crypto_provider_handle_t, crypto_session_id_t,
             crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
             crypto_data_t *, crypto_spi_ctx_template_t,
             int, crypto_req_handle_t);
         int (*sign_recover_init)(crypto_ctx_t *, crypto_mechanism_t *,
             crypto_key_t *, crypto_spi_ctx_template_t,
             int, crypto_req_handle_t);
         int (*sign_recover)(crypto_ctx_t *,
             crypto_data_t *, crypto_data_t *, crypto_req_handle_t);
         int (*sign_recover_atomic)(crypto_provider_handle_t,
             crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *,
             crypto_data_t *, crypto_data_t *, crypto_spi_ctx_template_t,
             int, crypto_req_handle_t);
 } crypto_sign_ops_t;
 
 typedef struct crypto_verify_ops {
         int (*verify_init)(crypto_ctx_t *,
             crypto_mechanism_t *, crypto_key_t *, crypto_spi_ctx_template_t,
             int, crypto_req_handle_t);
         int (*verify)(crypto_ctx_t *,
             crypto_data_t *, crypto_data_t *, crypto_req_handle_t);
         int (*verify_update)(crypto_ctx_t *,
             crypto_data_t *, crypto_req_handle_t);
         int (*verify_final)(crypto_ctx_t *,
             crypto_data_t *, crypto_req_handle_t);
         int (*verify_atomic)(crypto_provider_handle_t, crypto_session_id_t,
             crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
             crypto_data_t *, crypto_spi_ctx_template_t,
             int, crypto_req_handle_t);
         int (*verify_recover_init)(crypto_ctx_t *, crypto_mechanism_t *,
             crypto_key_t *, crypto_spi_ctx_template_t,
             int, crypto_req_handle_t);
         int (*verify_recover)(crypto_ctx_t *,
             crypto_data_t *, crypto_data_t *, crypto_req_handle_t);
         int (*verify_recover_atomic)(crypto_provider_handle_t,
             crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *,
             crypto_data_t *, crypto_data_t *, crypto_spi_ctx_template_t,
             int, crypto_req_handle_t);
 } crypto_verify_ops_t;
 
 typedef struct crypto_dual_ops {
 	int (*digest_encrypt_update)(
 	    crypto_ctx_t *, crypto_ctx_t *, crypto_data_t *,
 	    crypto_data_t *, crypto_req_handle_t);
 	int (*decrypt_digest_update)(
 	    crypto_ctx_t *, crypto_ctx_t *, crypto_data_t *,
 	    crypto_data_t *, crypto_req_handle_t);
 	int (*sign_encrypt_update)(
 	    crypto_ctx_t *, crypto_ctx_t *, crypto_data_t *,
 	    crypto_data_t *, crypto_req_handle_t);
 	int (*decrypt_verify_update)(
 	    crypto_ctx_t *, crypto_ctx_t *, crypto_data_t *,
 	    crypto_data_t *, crypto_req_handle_t);
 } crypto_dual_ops_t;
 
 typedef struct crypto_dual_cipher_mac_ops {
 	int (*encrypt_mac_init)(crypto_ctx_t *,
 	    crypto_mechanism_t *, crypto_key_t *, crypto_mechanism_t *,
 	    crypto_key_t *, crypto_spi_ctx_template_t,
 	    crypto_spi_ctx_template_t, int, crypto_req_handle_t req);
 	int (*encrypt_mac)(crypto_ctx_t *,
 	    crypto_data_t *, crypto_dual_data_t *, crypto_data_t *,
 	    crypto_req_handle_t);
 	int (*encrypt_mac_update)(crypto_ctx_t *,
 	    crypto_data_t *, crypto_dual_data_t *, crypto_req_handle_t);
 	int (*encrypt_mac_final)(crypto_ctx_t *,
 	    crypto_dual_data_t *, crypto_data_t *, crypto_req_handle_t);
 	int (*encrypt_mac_atomic)(crypto_provider_handle_t, crypto_session_id_t,
 	    crypto_mechanism_t *, crypto_key_t *, crypto_mechanism_t *,
 	    crypto_key_t *, crypto_data_t *, crypto_dual_data_t *,
 	    crypto_data_t *, crypto_spi_ctx_template_t,
 	    crypto_spi_ctx_template_t, crypto_req_handle_t req);
 
 	int (*mac_decrypt_init)(crypto_ctx_t *,
 	    crypto_mechanism_t *, crypto_key_t *, crypto_mechanism_t *,
 	    crypto_key_t *, crypto_spi_ctx_template_t,
 	    crypto_spi_ctx_template_t, int, crypto_req_handle_t);
 	int (*mac_decrypt)(crypto_ctx_t *,
 	    crypto_dual_data_t *, crypto_data_t *, crypto_data_t *,
 	    crypto_req_handle_t);
 	int (*mac_decrypt_update)(crypto_ctx_t *,
 	    crypto_dual_data_t *, crypto_data_t *, crypto_req_handle_t);
 	int (*mac_decrypt_final)(crypto_ctx_t *,
 	    crypto_data_t *, crypto_data_t *, crypto_req_handle_t);
 	int (*mac_decrypt_atomic)(crypto_provider_handle_t,
 	    crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *,
 	    crypto_mechanism_t *, crypto_key_t *, crypto_dual_data_t *,
     	    crypto_data_t *, crypto_data_t *ciphertext,
 	    crypto_spi_ctx_template_t, crypto_spi_ctx_template_t,
 	    crypto_req_handle_t);
 	int (*mac_verify_decrypt_atomic)(crypto_provider_handle_t,
 	    crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *,
 	    crypto_mechanism_t *, crypto_key_t *, crypto_dual_data_t *,
 	    crypto_data_t *, crypto_data_t *, crypto_spi_ctx_template_t,
 	    crypto_spi_ctx_template_t, int, crypto_req_handle_t);
 } crypto_dual_cipher_mac_ops_t;
 
 typedef struct crypto_random_number_ops {
 	int (*seed_random)(crypto_provider_handle_t, crypto_session_id_t,
 	    uchar_t *, size_t, uint_t, uint32_t, crypto_req_handle_t);
 	int (*generate_random)(crypto_provider_handle_t, crypto_session_id_t,
 	    uchar_t *, size_t, crypto_req_handle_t);
 } crypto_random_number_ops_t;
 
 typedef struct crypto_session_ops {
 	int (*session_open)(crypto_provider_handle_t, crypto_session_id_t *,
 	    crypto_req_handle_t);
 	int (*session_close)(crypto_provider_handle_t, crypto_session_id_t,
 	    crypto_req_handle_t);
 	int (*session_login)(crypto_provider_handle_t, crypto_session_id_t,
 	    crypto_user_type_t, char *, size_t, crypto_req_handle_t);
 	int (*session_logout)(crypto_provider_handle_t, crypto_session_id_t,
 	    crypto_req_handle_t);
 } crypto_session_ops_t;
 
 typedef struct crypto_object_ops {
 	int (*object_create)(crypto_provider_handle_t, crypto_session_id_t,
     	    crypto_object_attribute_t *, uint_t, crypto_object_id_t *,
 	    crypto_req_handle_t);
 	int (*object_copy)(crypto_provider_handle_t, crypto_session_id_t,
     	    crypto_object_id_t, crypto_object_attribute_t *, uint_t,
 	    crypto_object_id_t *, crypto_req_handle_t);
 	int (*object_destroy)(crypto_provider_handle_t, crypto_session_id_t,
 	    crypto_object_id_t, crypto_req_handle_t);
 	int (*object_get_size)(crypto_provider_handle_t, crypto_session_id_t,
 	    crypto_object_id_t, size_t *, crypto_req_handle_t);
 	int (*object_get_attribute_value)(crypto_provider_handle_t,
 	    crypto_session_id_t, crypto_object_id_t,
 	    crypto_object_attribute_t *, uint_t, crypto_req_handle_t);
 	int (*object_set_attribute_value)(crypto_provider_handle_t,
 	    crypto_session_id_t, crypto_object_id_t,
 	    crypto_object_attribute_t *,  uint_t, crypto_req_handle_t);
 	int (*object_find_init)(crypto_provider_handle_t, crypto_session_id_t,
 	    crypto_object_attribute_t *, uint_t, void **, int,
 	    crypto_req_handle_t);
 	int (*object_find)(crypto_provider_handle_t, void *,
 	    crypto_object_id_t *, uint_t, uint_t *, crypto_req_handle_t);
 	int (*object_find_final)(crypto_provider_handle_t, void *,
 	    crypto_req_handle_t);
 } crypto_object_ops_t;
 
 typedef struct crypto_key_ops {
 	int (*key_generate)(crypto_provider_handle_t, crypto_session_id_t,
 	    crypto_mechanism_t *, crypto_object_attribute_t *, uint_t,
 	    crypto_object_id_t *, crypto_req_handle_t);
 	int (*key_generate_pair)(crypto_provider_handle_t, crypto_session_id_t,
 	    crypto_mechanism_t *, crypto_object_attribute_t *, uint_t,
 	    crypto_object_attribute_t *, uint_t, crypto_object_id_t *,
 	    crypto_object_id_t *, crypto_req_handle_t);
 	int (*key_wrap)(crypto_provider_handle_t, crypto_session_id_t,
 	    crypto_mechanism_t *, crypto_key_t *, crypto_object_id_t *,
 	    uchar_t *, size_t, crypto_req_handle_t);
 	int (*key_unwrap)(crypto_provider_handle_t, crypto_session_id_t,
 	    crypto_mechanism_t *, crypto_key_t *, uchar_t *, size_t,
 	    crypto_object_attribute_t *, uint_t,
 	    crypto_object_id_t *, crypto_req_handle_t);
 	int (*key_derive)(crypto_provider_handle_t, crypto_session_id_t,
 	    crypto_mechanism_t *, crypto_key_t *, crypto_object_attribute_t *,
 	    uint_t, crypto_object_id_t *, crypto_req_handle_t);
         int (*key_check)(crypto_provider_handle_t, crypto_mechanism_t *,
             crypto_key_t *);
 } crypto_key_ops_t;
 
 typedef struct crypto_provider_management_ops {
 	int (*ext_info)(crypto_provider_handle_t,
 	    crypto_provider_ext_info_t *, crypto_req_handle_t);
 	int (*init_token)(crypto_provider_handle_t, char *, size_t,
 	    char *, crypto_req_handle_t);
 	int (*init_pin)(crypto_provider_handle_t, crypto_session_id_t,
 	    char *, size_t, crypto_req_handle_t);
 	int (*set_pin)(crypto_provider_handle_t, crypto_session_id_t,
 	    char *, size_t, char *, size_t, crypto_req_handle_t);	
 } crypto_provider_management_ops_t;
 
 typedef struct crypto_mech_ops {
 	int (*copyin_mechanism)(crypto_provider_handle_t,
 	    crypto_mechanism_t *, crypto_mechanism_t *, int *, int);
 	int (*copyout_mechanism)(crypto_provider_handle_t,
 	    crypto_mechanism_t *, crypto_mechanism_t *, int *, int);
 	int (*free_mechanism)(crypto_provider_handle_t, crypto_mechanism_t *);
 } crypto_mech_ops_t;
 
typedef struct crypto_nostore_key_ops {
	int (*nostore_key_generate)(crypto_provider_handle_t,
	    crypto_session_id_t, crypto_mechanism_t *,
	    crypto_object_attribute_t *, uint_t, crypto_object_attribute_t *,
	    uint_t, crypto_req_handle_t);
	int (*nostore_key_generate_pair)(crypto_provider_handle_t,
	    crypto_session_id_t, crypto_mechanism_t *,
	    crypto_object_attribute_t *, uint_t, crypto_object_attribute_t *,
	    uint_t, crypto_object_attribute_t *, uint_t,
	    crypto_object_attribute_t *, uint_t, crypto_req_handle_t);
	int (*nostore_key_derive)(crypto_provider_handle_t, crypto_session_id_t,
	    crypto_mechanism_t *, crypto_key_t *, crypto_object_attribute_t *,
	    uint_t, crypto_object_attribute_t *, uint_t, crypto_req_handle_t);
} crypto_nostore_key_ops_t;

+typedef struct crypto_fips140_ops {
+	void (*fips140_post)(int *);
+}
+
 /*
  * The crypto_ops(9S) structure contains the structures containing
  * the pointers to functions implemented by cryptographic providers.
  * It is specified as part of the crypto_provider_info(9S)
  * supplied by a provider when it registers with the kernel
  * by calling crypto_register_provider(9F).
  */
 typedef struct crypto_ops_v1 {
 	crypto_control_ops_t			*co_control_ops;
 	crypto_digest_ops_t			*co_digest_ops;
 	crypto_cipher_ops_t			*co_cipher_ops;
 	crypto_mac_ops_t			*co_mac_ops;
 	crypto_sign_ops_t			*co_sign_ops;
 	crypto_verify_ops_t			*co_verify_ops;
 	crypto_dual_ops_t			*co_dual_ops;
 	crypto_dual_cipher_mac_ops_t		*co_dual_cipher_mac_ops;
 	crypto_random_number_ops_t		*co_random_ops;
 	crypto_session_ops_t			*co_session_ops;
 	crypto_object_ops_t			*co_object_ops;
 	crypto_key_ops_t			*co_key_ops;
 	crypto_provider_management_ops_t	*co_provider_ops;
 	crypto_ctx_ops_t			*co_ctx_ops;
 } crypto_ops_v1_t;
 
 typedef struct crypto_ops_v2 {
 	crypto_ops_v1_t				v1_ops;
 	crypto_mech_ops_t			*co_mech_ops;
 } crypto_ops_v2_t;
 
 typedef struct crypto_ops_v3 {
	crypto_ops_v2_t				v2_ops;
	crypto_nostore_key_ops_t		*co_nostore_key_ops;
 } crypto_ops_v3_t;

+typedef struct crypto_ops_v4 {
+	crypto_ops_v3_t				v3_ops;
+	crypto_fips140_ops_t			*co_fips140_ops;
+} crypto_ops_v4_t;

 typedef struct crypto_ops {
 	union {
+		crypto_ops_v4_t cou_v4;
		crypto_ops_v3_t cou_v3;
 		crypto_ops_v2_t	cou_v2;
 		crypto_ops_v1_t	cou_v1;
 	} cou;
 } crypto_ops_t;
 
 Locking Considerations
 ----------------------
 
 The following locking issues must be considered by Providers when
 interacting with the framework:
 
 a) crypto_unregister_provider() can be called from user context only,
    for example from the Provider detach(9E) routine. This routine may
    sleep while pending requests are being processed by the Provider.
 
 b) Entry points exported by Providers to the framework are never
    invoked from an interrupt context.
 
 c) crypto_op_notification() and crypto_provider_notification() can be
    called by a Provider from its interrupt context while it holds locks.
 
 Multiple Registrations
 ----------------------
 
 Multiple Providers may register with the same crypto_provider_dev_t.
 In this case, they will be considered by the framework as a single
 device, i.e. only one corresponding Provider for this
 crypto_provider_dev_t will be exposed to consumers and to administrators
 via cryptoadm.
 
 Multiple Provider registration enables the following capabilities:
 some cryptographic accelerator may consist of one device with multiple
 cryptographic engines, for example one engine for asymmetric operations
 (RSA, DSA, etc) and another engine for symmetric ciphers (3DES, AES,
 etc), or two separate cryptographic engines on a single board. Device
 drivers for these devices can register two Providers for one device
 with the framework, which allows separate scheduling queues to be
 created, and allow the separate engines of a single device instance
 to be flow-controlled independently.
 
 3. Imported Routines
 --------------------
 The following routines are imported from the KEF framework.
 
 int crypto_register_provider(crypto_provider_info_t *info,
     crypto_kcf_provider_handle_t *handle)
 ----------------------------------------------------------
 This routine is used to add cryptographic providers to the KEF framework.
 Providers pass a crypto_provider_info structure to crypto_register_provider()
 and get back a handle.  The crypto_provider_info structure contains a
 list of mechanisms supported by the provider and an ops vector containing
 provider entry points.  Hardware providers call this routine in their attach
 routines.  Software providers call this routine in their _init() routine.
 
 crypto_register_provider() checks the value of the interface_version field
 and returns CRYPTO_VERSION_MISMATCH if the value is not 1.
 Valid return codes are:
 	CRYPTO_SUCCESS
 	CRYPTO_FAILED
 	CRYPTO_ARGUMENTS_BAD
 	CRYPTO_VERSION_MISMATCH
 	CRYPTO_HOST_MEMORY
 
 int crypto_unregister_provider(crypto_kcf_provider_handle_t handle)
 -------------------------------------------------------------------
 This routine is used to notify the framework when a provider is being
 removed.  Hardware providers call this routine in their detach routines.
 Software providers call this routine in their _fini() routine.
 
 Hardware providers should call this routine early to detach the provider
 from the framework.  After crypto_unregister_provider() returns, the framework
 will not call any of the provider's entry points, i.e. the provider is free to
 cleanup and free any memory. The provider must check for sessions that have
 not been closed and session objects that have not been destroyed, and free
 any memory allocated for them.
 
 Valid return codes are:
 	CRYPTO_SUCCESS
 	CRYPTO_UNKNOWN_PROVIDER
 
 void crypto_op_notification(crypto_req_handle_t req, int state)
 ------------------------------------------------------------------
 This routine is used to notify the framework that the state of an
 asynchronous request has changed. The state argument contains one
 of the valid error codes defined below.
 
 int crypto_kmflag(crypto_req_handle_t req)
 ------------------------------------------
 This routine is used by a Software cryptographic provider to get the value
 of the flag argument to be used when they allocate kernel memory.
 
 A Software provider must use this flag when allocating kernel memory as
 it can be called in conditions where it can not sleep for memory.
 Note that this routine is needed only for a Software provider.
 Hardware providers can always use KM_SLEEP.
 
 
 void crypto_provider_notification(crypto_kcf_provider_handle_t handle,
     uint_t event)
 ----------------------------------------------------------------------
 This routine is used to notify the framework that a provider's state
 has changed. Valid event codes are:
 	CRYPTO_PROVIDER_READY
 	CRYPTO_PROVIDER_BUSY
 	CRYPTO_PROVIDER_FAILED
 
 uchar_t *crypto_data_get_first(crypto_data_t *data, size_t *len)
 ----------------------------------------------------------------
 This routine returns a pointer to the first byte of usable data
 in a crypto_data structure.  The length of the contiguous data buffer
 is returned in the location pointed to by 'len'.  On failure,
 it returns a NULL pointer and sets length to 0.
 
 uchar_t *crypto_data_get_next(crypto_data_t *data, size_t *len)
 ---------------------------------------------------------------
 This routine returns a pointer to the next data buffer in a
 crypto_data structure.  The length of the contiguous data buffer
 is returned in the location pointed to by 'len'.  On failure,
 it returns a NULL pointer and sets length to 0.
 
 int crypto_data_set_len(crypto_data_t *data, size_t len)
 --------------------------------------------------------
 This routine sets the total amount of data in a crypto_data
 structure.  It returns 0 for success and -1 otherwise.
 
 4. Exported Routines
 --------------------
-70 routines, divided into 15 groups, are exported by providers:
+71 routines, divided into 16 groups, are exported by providers:
 
 Group		Function
 -------------------------------
 control		provider_status()
 
 context		create_ctx_template()
 		free_context()
 
 digest		digest_init()
 		digest()
 		digest_update()
 		digest_key()
 		digest_final()
 		digest_atomic()
 
 cipher		encrypt_init()
 		encrypt()
 		encrypt_update()
 		encrypt_final()
 		encrypt_atomic()
 
 		decrypt_init()
 		decrypt()
 		decrypt_update()
 		decrypt_final()
 		decrypt_atomic()
 
 MAC		mac_init()
 		mac()
 		mac_update()
 		mac_final()
 		mac_atomic()
 		mac_verify_atomic()
 
 sign		sign_init()
 		sign()
 		sign_update()
 		sign_final()
 		sign_atomic()
 		sign_recover_init()
 		sign_recover()
 		sign_recover_atomic()
 
 verify		verify_init()
 		verify()
 		verify_update()
 		verify_final()
 		verify_atomic()
 		verify_recover_init()
 		verify_recover()
 		verify_recover_atomic()		
 
 dual		digest_encrypt_update()
 		decrypt_digest_update()
 		sign_encrypt_update()
 		decrypt_verify_update()
 
 cipher/mac dual	encrypt_mac_init()
 		encrypt_mac()
 		encrypt_mac_update()
 		encrypt_mac_final()
 		encrypt_mac_atomic()
 		mac_decrypt_init()
 		mac_decrypt()
 		mac_decrypt_update()
 		mac_decrypt_final()
 		mac_decrypt_atomic()
 		mac_verify_decrypt_atomic()
 
 random		seed_random()
 		generate_random()
 
 session		session_open()
 		session_close()
 		session_login()
 		session_logout()
 
 object		object_create()
 		object_copy()
 		object_destroy()
 		object_get_size()
 		object_get_attribute_value()
 		object_set_attribute_value()
 		object_find_init()
 		object_find()
 		object_find_final()
 
 key		key_generate()
 		key_generate_pair()
 		key_wrap()
 		key_unwrap()
 		key_derive()
 
 provider	ext_info()
 		init_token()
 		init_pin()
 		set_pin()
 
 mechanism	copyin_mechanism()
 		copyout_mechanism()
 		free_mechanism()
 
 nostore key	key_generate()
		key_generate_pair()
		key_derive()

 fips140
		fips140_post();

 session, object, key, and provider management entry points are optional.
 However session management entry points are required if the object
 or key management entry points are defined. Context templates management
 entry points can be implemented by Software Providers only.
 
 The following error codes can be returned to the framework
 by provider functions:
 
 CRYPTO_SUCCESS			operation was successful
 CRYPTO_HOST_MEMORY		operation failed due to lack of host memory
 CRYPTO_FAILED			operation failed
 CRYPTO_QUEUED			operation queued
 CRYPTO_BUFFER_TOO_SMALL		buffer too small to store result
 CRYPTO_BUFFER_TOO_BIG		input data buffer too big for Provider
 CRYPTO_INVALID_CONTEXT		invalid context argument
 CRYPTO_DATA_LEN_RANGE		invalid data length or range
 CRYPTO_ENCRYPTED_DATA_LEN_RANGE	invalid ciphertext length or range
 CRYPTO_SIGNATURE_INVALID	invalid signature
 CRYPTO_SIGNATURE_LEN_RANGE	invalid signature length
 CRYPTO_MECHANISM_INVALID	invalid mechanism number
 CRYPTO_MECHANISM_PARAM_INVALID	invalid mechanism parameter
 CRYPTO_KEY_SIZE_RANGE		key size is outside the range allowed
 CRYPTO_SESSION_HANDLE_INVALID	invalid Provider session id
 CRYPTO_PIN_INVALID		invalid PIN
 CRYPTO_ATTRIBUTE_TYPE_INVALID	invalid attribute type
 CRYPTO_ATTRIBUTE_VALUE_INVALID	invalid attribute value
 CRYPTO_OBJECT_HANDLE_INVALID	invalid object handle
 CRYPTO_ARGUMENTS_BAD		invalid argument
 CRYPTO_VERSION_MISMATCH		CSPI version mismatch
 CRYPTO_MECH_NOT_SUPPORTED	mechanism not appropriate for function
 CRYPTO_NOT_SUPPORTED		function not supported by provider
 CRYPTO_USER_ALREADY_LOGGED_IN	login was already done on session
 CRYPTO_USER_NOT_LOGGED_IN	operation requires user to login
 CRYPTO_INCONSISTENT_ATTRIBUTE	attribute inconsistent for operation
 CRYPTO_NO_PERMISSION		no permission to perform operation
 CRYPTO_WRITE_PROTECTED		token is write protected
 CRYPTO_INVALID_MAC		computed MAC does not match expected MAC
 
 Note: A provider supporting init/update/final can not fail with
 CRYPTO_BUFFER_TOO_BIG during update. If it can not support this, it should
 have only the atomic entry point.
 
 Recoverable errors
 -------------------
 We define the following error codes as recoverable. All these error codes
 *require* that the provider does not modify any of the input parameters.
 
 The provider MUST return different error codes in cases where the input
 parameters are modified. Further to this case, it MUST return CRYPTO_FAILED,
 if no specific error code except one of the following is available.
 
 - CRYPTO_BUFFER_TOO_BIG
  Input data buffer too big for this mechanism of the Provider. This
  error code MUST not be returned by an update operation.
 
 - CRYPTO_BUSY
  This is an optional error code the provider may return if flow control
  is in effect. The provider MUST notify the framework (or already MUST have
  notified) with a crypto_provider_notification(CRYPTO_PROVIDER_BUSY) before
  returning this error.
 
 - CRYPTO_DEVICE_ERROR
  The device has failed. This error code should be returned for all
  the pending requests on the internal wait queue of the provider and
  any new requests sent to the provider.
 
  The provider SHOULD notify the framework with a
  crypto_provider_notification(CRYPTO_PROVIDER_FAILED, ..), so that
  new requests won't be sent to the provider.
 
 - CRYPTO_DEVICE_MEMORY
  Operation failed due to lack of memory on the device. Note that this
  is different from CRYPTO_HOST_MEMORY, which is a failure of kmem_alloc().
 
 - CRYPTO_KEY_SIZE_RANGE
  key size is outside the range allowed or possible on this provider for
  the mechanism. For example, a non-full strength version of a provider
  may return this error for a key size outside its supported range.
 
 - CRYPTO_NO_PERMISSION
  The client has no permission to perform operation on the provider.
  The permission check mechanism is private to the provider and the client.
  The framework does not do any checks.
 
 
 The ctx_provider_private field in the context structure may be used by a
 provider to store a pointer to provider-supplied storage.  Such storage is
 typically allocated by providers in initialization routines such as
 digest_init().  If the ctx_provider_private field is null, then a provider
 is free to use the field.  If, however, the field is non-null, then
 pre-initialized storage is being passed to a provider.
 
 In-place cryptographic operations are specified by setting
 input the output argument to NULL.  All providers are expected to
 support this convention.
 
 void provider_status(crypto_provider_handle_t provider, uint_t *status)
 ----------------------------------------------------------------------
 The provider argument identifies the provider for which status is requested.
 Valid status codes are:
 		CRYPTO_PROVIDER_READY
 		CRYPTO_PROVIDER_BUSY
 		CRYPTO_PROVIDER_FAILED
 
 
 int create_ctx_template(
     crypto_provider_handle_t provider,
     crypto_mechanism_t *mechanism,
     crypto_key_t *key,
     crypto_spi_ctx_template_t *ctx_template,
     size_t *ctx_template_size,
     crypto_req_handle_t req)
 ---------------------------------------------------------------------
 Allocate and pre-compute a template for a cryptographic context,
 to be used later for operations sharing the same mechanism and keying
 material (e.g. a pre-expanded key schedule for "mechanism" and "key").
 This entry point can be implemented by Software Providers only.
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_MECH_NOT_SUPPORTED
 
 
 int free_context(
     crypto_ctx_t *ctx)
 ---------------------------------------------------------------------
 The provider must free the provider-private data it associated with
 a context, pointed to by cc_provider_private.
 Return Values:  CRYPTO_SUCCESS
 		CRYPTO_INVALID_CONTEXT
 
 
 int digest_init(
     crypto_ctx_t *ctx,
     crypto_mechanism_t *mechanism,
     crypto_req_handle_t req)
 ---------------------------------------------------------------------
 Initialize a digest operation.  Storage may be allocated by a provider
 and stored in ctx_provider_private.  digest_init() can only be followed
 by a call to digest(), digest_update(), or digest_key().
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_ARGUMENTS_BAD
 		CRYPTO_INVALID_CONTEXT
 		CRYPTO_MECHANISM_INVALID
 		CRYPTO_MECHANISM_PARAM_INVALID
 		CRYPTO_MECH_NOT_SUPPORTED
 		CRYPTO_SESSION_HANDLE_INVALID
 
 
 int digest(
     crypto_ctx_t *ctx,
     crypto_data_t *data,
     crypto_data_t *digest,
     crypto_req_handle_t req)
 --------------------------------------------------------------------------
 Perform a single-part digest operation.  The caller of this function is
 responsible for allocating storage for the digest. The provider will not
 allocate storage. A call to encrypt must be preceded by a call to
 digest_init(). After the completion of this operation, no subsequent
 digest operations may be performed using the context. After the
 completion of this operation, no subsequent digest operations may be
 performed using the context.
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_ARGUMENTS_BAD
 		CRYPTO_INVALID_CONTEXT
 		CRYPTO_DATA_LEN_RANGE
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_BUFFER_TOO_BIG
 
 
 int digest_update(
     crypto_ctx_t *ctx,
     crypto_data_t *data,
     crypto_req_handle_t req)
 ----------------------------------------------------------------
 Perform a multi-part digest operation.  This operation may be followed
 by one or more calls to digest_update() or digest_key(), or by a single
 call to digest_final().
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_INVALID_CONTEXT
 		CRYPTO_DATA_LEN_RANGE
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_BUFFER_TOO_BIG
 
 
 int digest_key(
     crypto_ctx_t *ctx,
     crypto_key_t *key,
     crypto_req_handle_t req)
 -----------------------------------------------------------
 Perform a multi-part digest operation by digesting the value of a key.
 This operation may be followed by one or more calls to digest_update()
 or digest_key(), or by a single call to digest_final().
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_ARGUMENTS_BAD
 		CRYPTO_INVALID_CONTEXT
 		CRYPTO_KEY_SIZE_RANGE
 		CRYPTO_SESSION_HANDLE_INVALID
 
 
 int digest_final(
     crypto_ctx_t *ctx,
     crypto_data_t *digest,
     crypto_req_handle_t req)
 -----------------------------------------------------------------
 This operation terminates a multi-part digest operation.  The caller of this
 function is responsible for allocating storage for the digest.  After the
 completion of this operation, no subsequent digest operations may be performed
 using the context.
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_ARGUMENTS_BAD
 		CRYPTO_INVALID_CONTEXT
 		CRYPTO_SESSION_HANDLE_INVALID
 
 
 int digest_atomic(
     crypto_provider_handle_t provider,
     crypto_session_id_t session_id,
     crypto_mechanism_t *mechanism,
     crypto_data_t *data,
     crypto_data_t *digest,
     crypto_req_handle_t req)
 ----------------------------------------------------------------
 This operation performs an atomic digest operation on the specified data.
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_ARGUMENTS_BAD
 		CRYPTO_MECHANISM_INVALID
 		CRYPTO_MECHANISM_PARAM_INVALID
 		CRYPTO_MECH_NOT_SUPPORTED
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_BUFFER_TOO_BIG
 
 
 int encrypt_init(
     crypto_ctx_t *ctx,
     crypto_mechanism_t *mechanism,
     crypto_key_t *key,
     crypto_spi_ctx_template_t ctx_template,
     crypto_req_handle_t req)
 -------------------------------------------------------------------------
 Initialize an encryption operation.  Storage may be allocated by a provider
 and stored in ctx_provider_private.  encrypt_init() can only be followed
 by a call to encrypt() or encrypt_update().
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_ARGUMENTS_BAD
 		CRYPTO_INVALID_CONTEXT
 		CRYPTO_MECHANISM_INVALID
 		CRYPTO_MECHANISM_PARAM_INVALID
 		CRYPTO_KEY_SIZE_RANGE
 		CRYPTO_MECH_NOT_SUPPORTED
 		CRYPTO_SESSION_HANDLE_INVALID
 
 
 int encrypt(
     crypto_ctx_t *ctx,
     crypto_data_t *plaintext,
     crypto_data_t *ciphertext
     crypto_req_handle_t req)
 ----------------------------------------------------------------
 Perform a single-part encryption operation.  The caller of this function
 is responsible for allocating storage for the ciphertext. A call to
 encrypt must be preceded by a call to encrypt_init().
 After the completion of this operation, no subsequent encryption
 operations may be performed using the context.
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_ARGUMENTS_BAD
 		CRYPTO_INVALID_CONTEXT
 		CRYPTO_DATA_LEN_RANGE
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_BUFFER_TOO_BIG
 
 
 int encrypt_update(
     crypto_ctx_t *ctx,
     crypto_data_t *plaintext,
     crypto_data_t *ciphertext
     crypto_req_handle_t req)
 -----------------------------------------------------------------------
 Perform a multi-part encryption operation.  The caller of this function is
 responsible for allocating storage for the ciphertext.  This operation may
 be followed by one or more calls to encrypt_update() or a single call to
 encrypt_final().
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_ARGUMENTS_BAD
 		CRYPTO_INVALID_CONTEXT
 		CRYPTO_DATA_LEN_RANGE
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_BUFFER_TOO_BIG
 
 
 int encrypt_final(
     crypto_ctx_t *ctx,
     crypto_data_t *ciphertext,
     crypto_req_handle_t req)
 -----------------------------------------------------------------------
 This operation terminates a multi-part encryption operation.  The caller of
 this function is responsible for allocating storage for the ciphertext.
 After the completion of this operation, no subsequent encryption operations
 may be performed using the context.
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_INVALID_CONTEXT
 		CRYPTO_SESSION_HANDLE_INVALID
 
 
 int encrypt_atomic(
     crypto_provider_handle_t provider,
     crypto_session_id_t session_id,
     crypto_mechanism_t *mechanism,
     crypto_key_t *key,
     crypto_data_t *plaintext,
     crypto_data_t *ciphertext,
     crypto_spi_ctx_template_t ctx_template,
     crypto_req_handle_t req)
 -------------------------------------------------------------------------
 This operation performs an atomic encryption on the specified data using
 the specified key and mechanism.
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_ARGUMENTS_BAD
 		CRYPTO_MECHANISM_INVALID
 		CRYPTO_MECHANISM_PARAM_INVALID
 		CRYPTO_MECH_NOT_SUPPORTED
 		CRYPTO_DATA_LEN_RANGE
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_KEY_SIZE_RANGE
 		CRYPTO_BUFFER_TOO_BIG
 
 
 int decrypt_init(
     crypto_ctx_t *ctx,
     crypto_mechanism_t *mechanism,
     crypto_key_t *key,
     crypto_spi_ctx_template_t ctx_template,
     crypto_req_handle_t req)
 -------------------------------------------------------------------------
 Initialize a decryption operation.  Storage may be allocated by a provider
 and stored in ctx_provider_private.  decrypt_init() can only be followed
 by a call to decrypt() or decrypt_update().
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_ARGUMENTS_BAD
 		CRYPTO_INVALID_CONTEXT
 		CRYPTO_MECHANISM_INVALID
 		CRYPTO_MECHANISM_PARAM_INVALID
 		CRYPTO_MECH_NOT_SUPPORTED
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_KEY_SIZE_RANGE
 
 
 int decrypt(
     crypto_ctx_t *ctx,
     crypto_data_t *ciphertext,
     crypto_data_t *plaintext,
     crypto_req_handle_t req)
 -----------------------------------------------------------------
 Perform a single-part decryption operation.  The caller of this function is
 responsible for allocating storage for the plaintext. A call to
 encrypt must be preceded by a call to decrypt_init().
 After the completion of this operation, no subsequent decryption
 operations may be performed using the context.
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_ARGUMENTS_BAD
 		CRYPTO_INVALID_CONTEXT
 		CRYPTO_ENCRYPTED_DATA_LEN_RANGE
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_BUFFER_TOO_BIG
 
 
 int decrypt_update(
     crypto_ctx_t *ctx,
     crypto_data_t *ciphertext,
     crypto_data_t *plaintext,
     crypto_req_handle_t req)
 ------------------------------------------------------------------------
 Perform a multi-part decryption operation.  The caller of this function is
 responsible for allocating storage for the plaintext.  This operation may be
 followed by one or more calls to decrypt_update() or a single call to
 decrypt_final().
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_INVALID_CONTEXT
 		CRYPTO_ENCRYPTED_DATA_LEN_RANGE
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_BUFFER_TOO_BIG
 
 
 int decrypt_final(
     crypto_ctx_t *ctx,
     crypto_data_t *plaintext,
     crypto_req_handle_t req)
 ----------------------------------------------------------------------
 This operation terminates a multi-part decryption operation.  The caller
 of this function is responsible for allocating storage for the plaintext.
 After the completion of this operation, no subsequent decryption operations
 may be performed using the context.
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_INVALID_CONTEXT
 		CRYPTO_ENCRYPTED_DATA_LEN_RANGE
 		CRYPTO_SESSION_HANDLE_INVALID
 
 
 int decrypt_atomic(
     crypto_provider_handle_t provider,
     crypto_session_id_t session_id,
     crypto_mechanism_t *mechanism,
     crypto_key_t *key,
     crypto_data_t *ciphertext,
     crypto_data_t *plaintext,
     crypto_spi_ctx_template_t ctx_template,
     crypto_req_handle_t req)
 -------------------------------------------------------------------------
 This operation performs an atomic decryption on the specified data using
 the specified key and mechanism.
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_ARGUMENTS_BAD
 		CRYPTO_MECHANISM_INVALID
 		CRYPTO_MECHANISM_PARAM_INVALID
 		CRYPTO_MECH_NOT_SUPPORTED
 		CRYPTO_ENCRYPTED_DATA_LEN_RANGE
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_BUFFER_TOO_BIG
		CRYPTO_BUFFER_TOO_SMALL
 		CRYPTO_KEY_SIZE_RANGE
 
 
 int mac_init(
     crypto_ctx_t *ctx,
     crypto_mechanism_t *mechanism,
     crypto_key_t *key,
     crypto_spi_ctx_template_t ctx_template,
     crypto_req_handle_t req)
 ------------------------------------------------------------------------
 Initialize a MAC operation.  Storage may be allocated by a provider
 and stored in ctx_provider_private.  mac_init() can only be followed
 by a call to mac() or mac_update().
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_INVALID_CONTEXT
 		CRYPTO_KEY_SIZE_RANGE
 		CRYPTO_SESSION_HANDLE_INVALID
 
 
 int mac(
     crypto_ctx_t *ctx,
     crypto_data_t *data,
     crypto_data_t *mac,
     crypto_req_handle_t req)
 -----------------------------------------------------------------------
 Compute a MAC on the specified plaintext in a single operation.  The caller
 of this function is responsible for allocating storage for the MAC.
 A call to mac() must be preceded by a call to mac_init().
 After the completion of this operation, no subsequent MAC operations
 may be performed using the context.
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_INVALID_CONTEXT
 		CRYPTO_DATA_LEN_RANGE
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_BUFFER_TOO_BIG
 
 
 int mac_update(
     crypto_ctx_t *ctx,
     crypto_data_t *data,
     crypto_req_handle_t req)
 ----------------------------------------------------------
 Perform a multi-part MAC operation.  This operation may be followed by
 one or more calls to mac_update() or a single call to mac_final().
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_INVALID_CONTEXT
 		CRYPTO_DATA_LEN_RANGE
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_BUFFER_TOO_BIG
 
 
 int mac_final(
     crypto_ctx_t *ctx,
     crypto_data_t *mac,
     crypto_req_handle_t req)
 --------------------------------------------------------
 This operation terminates a multi-part MAC operation.  The caller of this
 function is responsible for allocating storage for the MAC.  After the
 completion of this operation, no subsequent MAC operations may be performed
 using the context.
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_INVALID_CONTEXT
 		CRYPTO_BUFFER_TOO_SMALL
 		CRYPTO_SESSION_HANDLE_INVALID
 
 
 int mac_atomic(
     crypto_provider_handle_t provider,
     crypto_session_id_t session_id,
     crypto_mechanism_t *mechanism,
     crypto_key_t *key,
     crypto_data_t *data,
     crypto_data_t *mac,
     crypto_spi_ctx_template_t ctx_template,
     crypto_req_handle_t req)
 -------------------------------------------------------------------------
 This operation performs an atomic mac operation on the specified data using
 the specified key and mechanism.
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_MECHANISM_INVALID
 		CRYPTO_MECHANISM_PARAM_INVALID
 		CRYPTO_MECH_NOT_SUPPORTED
 		CRYPTO_INVALID_PLAINTEXT
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_BUFFER_TOO_BIG
 		CRYPTO_KEY_SIZE_RANGE
 
 
 int mac_verify_atomic(
     crypto_provider_handle_t provider,
     crypto_session_id_t session_id,
     crypto_mechanism_t *mechanism,
     crypto_key_t *key,
     crypto_data_t *data,
     crypto_data_t *mac,
     crypto_spi_ctx_template_t ctx_template,
     crypto_req_handle_t req)
 -------------------------------------------------------------------------
 This operation performs an atomic mac operation on the specified data using
 the specified key and mechanism. The 'mac' argument points to the
 expected MAC value. If the computed and expected MAC values don't match,
 this entry point returns CRYPTO_INVALID_MAC.
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_MECHANISM_INVALID
 		CRYPTO_MECHANISM_PARAM_INVALID
 		CRYPTO_MECH_NOT_SUPPORTED
 		CRYPTO_INVALID_PLAINTEXT
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_BUFFER_TOO_BIG
 		CRYPTO_KEY_SIZE_RANGE
 		CRYPTO_INVALID_MAC
 
 
 int sign_init(
     crypto_ctx_t *ctx,
     crypto_mechanism_t *mechanism,
     crypto_key_t *key,
     crypto_spi_ctx_template_t ctx_template,
     crypto_req_handle_t req)
 ---------------------------------------------------------------
 Initialize a signature operation.  Storage may be allocated by a provider
 and stored in ctx_provider_private.  sign_init() can only be followed
 by a call to sign() or sign_update().
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_INVALID_CONTEXT
 		CRYPTO_MECHANISM_INVALID
 		CRYPTO_MECHANISM_PARAM_INVALID
 		CRYPTO_MECH_NOT_SUPPORTED
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_KEY_SIZE_RANGE
 
 
 int sign(
     crypto_ctx_t *ctx,
     crypto_data_t *data,
     crypto_data_t *signature,
     crypto_req_handle_t req)
 -----------------------------------------------------------
 Sign the specified plaintext in a single operation.  The caller of this
 function is responsible for allocating storage for the signature. A call to
 sign() must be preceded by a call to sign_init(). After the completion
 of this operation, no subsequent signing operations may be performed
 using the context.
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_INVALID_CONTEXT
 		CRYPTO_DATA_LEN_RANGE
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_BUFFER_TOO_BIG
 
 
 int sign_update(
     crypto_ctx_t *ctx,
     crypto_data_t *data,
     crypto_req_handle_t req)
 ------------------------------------------------------------
 Perform a multi-part signing operation.  This operation may be followed by
 one or more calls to sign_update() or a single call to sign_final().
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_INVALID_CONTEXT
 		CRYPTO_DATA_LEN_RANGE
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_BUFFER_TOO_BIG
 
 
 int sign_final(
     crypto_ctx_t *ctx,
     crypto_data_t *signature,
     crypto_req_handle_t req)
 ----------------------------------------------------------------
 This operation terminates a multi-part signing operation.  The caller of this
 function is responsible for allocating storage for the signature.  After the
 completion of this operation, no subsequent signing operations may be
 performed using the context.
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_INVALID_CONTEXT
 		CRYPTO_BUFFER_TOO_SMALL
 		CRYPTO_SESSION_HANDLE_INVALID
 
 
 int sign_atomic(
     crypto_provider_handle_t provider,
     crypto_session_id_t session_id,
     crypto_mechanism_t *mechanism,
     crypto_key_t *key,
     crypto_data_t *data,
     crypto_data_t *signature,
     crypto_spi_ctx_template_t ctx_template,
     crypto_req_handle_t req)
 -------------------------------------------------------------------------
 This operation performs a sign operation on the specified data using
 the specified key and mechanism.
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_MECHANISM_INVALID
 		CRYPTO_MECHANISM_PARAM_INVALID
 		CRYPTO_MECH_NOT_SUPPORTED
 		CRYPTO_DATA_LEN_RANGE
 		CRYPTO_BUFFER_TOO_SMALL
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_BUFFER_TOO_BIG
 		CRYPTO_KEY_SIZE_RANGE
 
 
 int sign_recover_init(
     crypto_ctx_t *ctx,
     crypto_mechanism_t *mechanism,
     crypto_key_t *key,
     crypto_spi_ctx_template_t ctx_template,
     crypto_req_handle_t req)
 ---------------------------------------------------------------------------
 Initialize a signing operation where the data can be recovered from
 the signature.  Storage may be allocated by a provider and stored in
 ctx_provider_private.  sign_recover_init() can only be followed by a
 call to sign_recover().
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_INVALID_CONTEXT
 		CRYPTO_MECHANISM_INVALID
 		CRYPTO_MECHANISM_PARAM_INVALID
 		CRYPTO_MECH_NOT_SUPPORTED
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_KEY_SIZE_RANGE
 
 
 int sign_recover(
     crypto_ctx_t *ctx,
     crypto_data_t *data,
     crypto_data_t *signature,
     crypto_req_handle_t req)
 -------------------------------------------------------------
 Sign the specified plaintext in a single operation so that the data can be
 recovered from the signature.  A call to sign_recover() must be preceded
 by a call to sign_init(). The caller of this function is responsible
 for allocating storage for the signature.  After the completion of
 this operation, no subsequent signing operations may be performed
 using the context.
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_INVALID_CONTEXT
 		CRYPTO_DATA_LEN_RANGE
 		CRYPTO_BUFFER_TOO_SMALL
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_BUFFER_TOO_BIG
 
 
 int sign_recover_atomic(
     crypto_provider_handle_t provider,
     crypto_session_id_t session_id,
     crypto_mechanism_t *mechanism,
     crypto_key_t *key,
     crypto_data_t *data,
     crypto_data_t *signature,
     crypto_spi_ctx_template_t ctx_template,
     crypto_req_handle_t req)
 ------------------------------------------------------------------------
 Performs an atomic sign recover operation.
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_MECHANISM_INVALID
 		CRYPTO_MECHANISM_PARAM_INVALID
 		CRYPTO_MECH_NOT_SUPPORTED
 		CRYPTO_DATA_LEN_RANGE
 		CRYPTO_BUFFER_TOO_SMALL
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_BUFFER_TOO_BIG
 		CRYPTO_KEY_SIZE_RANGE
 
 
 int verify_init(
     crypto_ctx_t *ctx,
     crypto_mechanism_t *mechanism,
     crypto_key_t *key,
     crypto_spi_ctx_template_t ctx_template,
     crypto_req_handle_t req)
 -----------------------------------------------------------------------
 Initialize a verify operation.  Storage may be allocated by a provider
 and stored in ctx_provider_private.  verify_init() can only be followed
 by a call to verify() or verify_update().
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_INVALID_CONTEXT
 		CRYPTO_MECHANISM_INVALID
 		CRYPTO_MECHANISM_PARAM_INVALID
 		CRYPTO_MECH_NOT_SUPPORTED
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_KEY_SIZE_RANGE
 
 
 int verify(
     crypto_ctx_t *ctx,
     crypto_data_t *data,
     crypto_data_t *signature,
     crypto_req_handle_t req)
 -----------------------------------------------------------
 Verify the specified signature in a single operation. A call to
 verify() must be preceded by a call to verify_init(). After the completion
 of this operation, no subsequent signing operations may be performed
 using the context.
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_INVALID_CONTEXT
 		CRYPTO_DATA_LEN_RANGE
 		CRYPTO_SIGNATURE_INVALID
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_SIGNATURE_LEN_RANGE
 		CRYPTO_BUFFER_TOO_BIG
 
 
 int verify_update(
     crypto_ctx_t *ctx,
     crypto_data_t *data,
     crypto_req_handle_t req)
 ----------------------------------------------------------------
 Perform a multi-part verify operation.  This operation may be followed by
 one or more calls to verify_update() or a single call to verify_final().
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_INVALID_CONTEXT
 		CRYPTO_DATA_LEN_RANGE
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_BUFFER_TOO_BIG
 
 
 int verify_final(
     crypto_ctx_t *ctx,
     crypto_data_t *signature,
     crypto_req_handle_t req)
 --------------------------------------------------------------------
 This operation terminates a multi-part verify operation.  After the completion
 of this operation, no subsequent verify operations may be performed using
 the context.
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_INVALID_CONTEXT
 		CRYPTO_SIGNATURE_INVALID
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_SIGNATURE_LEN_RANGE
 
 
 int verify_atomic(
     crypto_provider_handle_t provider,
     crypto_session_id_t session_id,
     crypto_mechanism_t *mechanism,
     crypto_key_t *key,
     crypto_data_t *data,
     crypto_data_t *signature,
     crypto_spi_ctx_template_t ctx_template,
     crypto_req_handle_t req)
 -----------------------------------------------------------------------
 This operation performs a verify operation on the specified data using
 the specified key and mechanism.
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_INVALID_CONTEXT
 		CRYPTO_MECHANISM_INVALID
 		CRYPTO_MECHANISM_PARAM_INVALID
 		CRYPTO_MECH_NOT_SUPPORTED
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_DATA_LEN_RANGE
 		CRYPTO_BUFFER_TOO_BIG
 		CRYPTO_KEY_SIZE_RANGE
 		CRYPTO_SIGNATURE_INVALID
 		CRYPTO_SIGNATURE_LEN_RANGE
 
 
 int verify_recover_init(
     crypto_ctx_t *ctx,
     crypto_mechanism_t *mechanism,
     crypto_key_t *key,
     crypto_spi_ctx_template_t ctx_template,
     crypto_req_handle_t req)
 ----------------------------------------------------------------------------
 Initialize a verify operation where the data can be recovered from the
 signature.  Storage may be allocated by a provider and stored in
 ctx_provider_private.  verify_recover_init() can only be followed
 by a call to verify_recover().
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_INVALID_CONTEXT
 		CRYPTO_MECHANISM_INVALID
 		CRYPTO_MECHANISM_PARAM_INVALID
 		CRYPTO_MECH_NOT_SUPPORTED
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_KEY_SIZE_RANGE
 
 
 int verify_recover(
     crypto_ctx_t *ctx,
     crypto_data_t *signature,
     crypto_data_t *data,
     crypto_req_handle_t req)
 ----------------------------------------------------------------------
 Verify the specified signature and retrieve the data from the signature
 in a single operation. A call to verify_recover() must be preceded by a
 call to verify_recover_init(). After the completion of this operation,
 no subsequent verify operations may be performed using the context.
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_INVALID_CONTEXT
 		CRYPTO_DATA_LEN_RANGE
 		CRYPTO_SIGNATURE_INVALID
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_BUFFER_TOO_BIG
 		CRYPTO_SIGNATURE_LEN_RANGE
 
 
 int verify_recover_atomic(
     crypto_provider_handle_t provider,
     crypto_session_id_t session_id,
     crypto_mechanism_t *mechanism,
     crypto_key_t *key,
     crypto_data_t *signature,
     crypto_data_t *data,
     crypto_spi_ctx_template_t ctx_template,
     crypto_req_handle_t req)
 ------------------------------------------------------------------------
 Performs an atomic verify recover operation.
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_MECHANISM_INVALID
 		CRYPTO_MECHANISM_PARAM_INVALID
 		CRYPTO_MECH_NOT_SUPPORTED
 		CRYPTO_DATA_LEN_RANGE
 		CRYPTO_SIGNATURE_INVALID
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_BUFFER_TOO_BIG
 		CRYPTO_KEY_SIZE_RANGE
 		CRYPTO_SIGNATURE_LEN_RANGE
 
 
 int digest_encrypt_update(
     crypto_ctx_t *digest_ctx,
     crypto_ctx_t *encrypt_ctx,
     crypto_data_t *plaintext,
     crypto_data_t *ciphertext,
     crypto_req_handle_t req)
 -----------------------------------------------------------
 Perform a multi-part digest and encrypt operation.  The caller of this
 function is responsible for allocating storage for the ciphertext.
 This operation must be preceded by encrypt_init() and digest_init().
 It may be followed by one or more calls to digest_encrypt_update().
 It is terminated by calls to both encrypt_final() and digest_final().
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_INVALID_CONTEXT
 		CRYPTO_INVALID_PLAINTEXT
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_BUFFER_TOO_BIG
 
 
 int decrypt_digest_update(
     crypto_ctx_t *decrypt_ctx,
     crypto_ctx_t *digest_ctx,
     crypto_data_t *ciphertext,
     crypto_data_t *plaintext,
     crypto_req_handle_t req)
 -------------------------------------------------------------------------
 Perform a multi-part decrypt and digest operation.  The caller of this
 function is responsible for allocating storage for the plaintext.
 This operation must be preceded by decrypt_init() and digest_init().
 It may be followed by one or more calls to decrypt_digest_update().
 It is terminated by calls to both decrypt_final() and digest_final().
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_INVALID_CONTEXT
 		CRYPTO_INVALID_PLAINTEXT
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_BUFFER_TOO_BIG
 
 
 int sign_encrypt_update(
     crypto_ctx_t *sign_ctx,
     crypto_ctx_t *encrypt_ctx,
     crypto_data_t *plaintext,
     crypto_data_t *ciphertext,
     crypto_req_handle_t req)
 -----------------------------------------------------------
 Perform a multi-part sign and encrypt operation.  The caller of this
 function is responsible for allocating storage for the ciphertext.
 This operation must be preceded by encrypt_init() and sign_init().
 It may be followed by one or more calls to sign_encrypt_update().
 It is terminated by calls to encrypt_final() and sign_final().
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_INVALID_CONTEXT
 		CRYPTO_INVALID_PLAINTEXT
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_BUFFER_TOO_BIG
 
 
 int decrypt_verify_update(
     crypto_ctx_t *decrypt_ctx,
     crypto_ctx_t *verify_ctx,
     crypto_data_t *ciphertext,
     crypto_data_t *plaintext,
     crypto_req_handle_t req)
 -------------------------------------------------------------------------
 Perform a multi-part decrypt and verify operation.  The caller of this
 function is responsible for allocating storage for the plaintext.
 This operation must be preceded by decrypt_init() and verify_init().
 It may be followed by one or more calls to decrypt_verify_update().
 It is terminated by calls to decrypt_final() and verify_final().
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_INVALID_CONTEXT
 		CRYPTO_INVALID_PLAINTEXT
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_BUFFER_TOO_BIG
 
 
 int encrypt_mac_init(
     crypto_ctx_t *ctx,
     crypto_mechanism_t *encrypt_mech,
     crypto_key_t *encrypt_key,
     crypto_mechanism_t *mac_mech,
     crypto_key_t *mac_key,
     crypto_spi_ctx_template_t encr_ctx_template,
     crypto_spi_ctx_template_t mac_ctx_template,
     crypto_req_handle_t req)
 -------------------------------------------------------------------------
 Initializes a dual encryption and MAC operation. This operation must
 be followed by a encrypt_mac() or encrypt_mac_update().
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_INVALID_CONTEXT
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_MECHANISM_INVALID
 		CRYPTO_MECHANISM_PARAM_INVALID
 		CRYPTO_MECH_NOT_SUPPORTED
 		CRYPTO_KEY_SIZE_RANGE
 
 
 int encrypt_mac(
     crypto_ctx_t *ctx,
     crypto_dual_data_t *plaintext,
     crypto_data_t *ciphertext,
     crypto_data_t *mac,
     crypto_req_handle_t req)
 -------------------------------------------------------------------------
 Performs a single part encrypt and MAC operation. Must be preceded
 by a call to encrypt_mac_init(). The Provider is
 responsible to free the private data it associated with the context.
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_INVALID_CONTEXT
 		CRYPTO_INVALID_PLAINTEXT
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_BUFFER_TOO_SMALL
 		CRYPTO_BUFFER_TOO_BIG
 
 
 int encrypt_mac_update(
     crypto_ctx_t *ctx,
     crypto_dual_data_t *plaintext,
     crypto_data_t *ciphertext,
     crypto_req_handle_t req)
 ----------------------------------------------------------------------
 Perform a multi-part encrypt and MAC operation.  The caller of this
 function is responsible for allocating storage for the ciphertext.
 This operation must be preceded by encrypt_mac_init().
 It may be followed by one or more calls to encrypt_mac_update().
 It is terminated by a call to encrypt_mac_final().
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_INVALID_CONTEXT
 		CRYPTO_INVALID_PLAINTEXT
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_BUFFER_TOO_BIG
 
 
 int encrypt_mac_final(
     crypto_ctx_t *ctx,
     crypto_data_t *ciphertext,
     crypto_data_t *mac,
     crypto_req_handle_t req)
 ----------------------------------------------------------------------
 Terminates a encrypt and MAC multi-part operation. The Provider is
 responsible to free the private data it associated with the context.
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_INVALID_CONTEXT
 		CRYPTO_INVALID_PLAINTEXT
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_BUFFER_TOO_SMALL
 		CRYPTO_BUFFER_TOO_BIG
 
 
 int encrypt_mac_atomic(
     crypto_provider_handle_t provider,
     crypto_session_id_t session_id,
     crypto_mechanism_t *encrypt_mech,
     crypto_key_t *encrypt_key,
     crypto_mechanism_t *mac_mech,
     crypto_key_t *mac_key,
     crypto_dual_data_t *plaintext,
     crypto_data_t *ciphertext,
     crypto_data_t *mac,
     crypto_spi_ctx_template_t encr_ctx_template,
     crypto_spi_ctx_template_t mac_ctx_template,
     crypto_req_handle_t req)
 -------------------------------------------------------------------------
 Performs an atomic encrypt and MAC operation.
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_MECHANISM_INVALID
 		CRYPTO_MECHANISM_PARAM_INVALID
 		CRYPTO_MECH_NOT_SUPPORTED
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_INVALID_PLAINTEXT
 		CRYPTO_BUFFER_TOO_SMALL
 		CRYPTO_BUFFER_TOO_BIG
 		CRYPTO_KEY_SIZE_RANGE
 
 
 int mac_decrypt_init(
     crypto_ctx_t *ctx,
     crypto_mechanism_t *mac_mech,
     crypto_key_t *mac_key,
     crypto_mechanism_t *decrypt_mech,
     crypto_key_t *decrypt_key,
     crypto_spi_ctx_template_t mac_ctx_template,
     crypto_spi_ctx_template_t decr_ctx_template,
     crypto_req_handle_t req)
 -------------------------------------------------------------------------
 Initializes a dual MAC and decryption operation. This operation must
 be followed by a mac_decrypt() or mac_decrypt_update().
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_INVALID_CONTEXT
 		CRYPTO_MECHANISM_INVALID
 		CRYPTO_MECHANISM_PARAM_INVALID
 		CRYPTO_MECH_NOT_SUPPORTED
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_KEY_SIZE_RANGE
 
 
 int mac_decrypt(
     crypto_ctx_t *ctx,
     crypto_dual_data_t *ciphertext,
     crypto_data_t *mac,
     crypto_data_t *plaintext,
     crypto_req_handle_t req)
 -------------------------------------------------------------------------
 Performs a single part MAC and decrypt operation. Must be preceded
 by a call to mac_decrypt_init(). The Provider is
 responsible to free the private data it associated with the context.
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_INVALID_CONTEXT
 		CRYPTO_INVALID_PLAINTEXT
 		CRYPTO_ENCRYPTED_DATA_LEN_RANGE
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_BUFFER_TOO_SMALL
 		CRYPTO_BUFFER_TOO_BIG
 
 
 int mac_decrypt_update(
     crypto_ctx_t *ctx,
     crypto_dual_data_t *ciphertext,
     crypto_data_t *plaintext,
     crypto_req_handle_t req)
 ----------------------------------------------------------------------
 Perform a multi-part MAC and decrypt operation.  The caller of this
 function is responsible for allocating storage for the ciphertext.
 This operation must be preceded by mac_decrypt_init().
 It may be followed by one or more calls to mac_decrypt_update().
 It is terminated by a call to mac_decrypt_final().
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_INVALID_CONTEXT
 		CRYPTO_INVALID_PLAINTEXT
 		CRYPTO_ENCRYPTED_DATA_LEN_RANGE
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_BUFFER_TOO_BIG
 
 
 int mac_decrypt_final(
     crypto_ctx_t *ctx,
     crypto_data_t *mac,
     crypto_data_t *plaintext,
     crypto_req_handle_t req)
 ----------------------------------------------------------------------
 Terminates a MAC and decrypt multi-part operation. The Provider is
 responsible to free the private data it associated with the context.
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_INVALID_CONTEXT
 		CRYPTO_ARGUMENTS_BAD
 		CRYPTO_ENCRYPTED_DATA_LEN_RANGE
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_BUFFER_TOO_SMALL
 
 
 int mac_decrypt_atomic(
     crypto_provider_handle_t provider,
     crypto_session_id_t session_id,
     crypto_mechanism_t *mac_mech,
     crypto_key_t *mac_key,
     crypto_mechanism_t *decrypt_mech,
     crypto_key_t *decrypt_key,
     crypto_dual_data_t *ciphertext,
     crypto_data_t *mac,
     crypto_data_t *plaintext,
     crypto_spi_ctx_template_t mac_ctx_template,
     crypto_spi_ctx_template_t decr_ctx_template,
     crypto_req_handle_t req)
 -------------------------------------------------------------------------
 Performs an atomic MAC and decrypt operation.
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_MECHANISM_INVALID
 		CRYPTO_MECHANISM_PARAM_INVALID
 		CRYPTO_MECH_NOT_SUPPORTED
 		CRYPTO_ENCRYPTED_DATA_LEN_RANGE
 		CRYPTO_BUFFER_TOO_SMALL
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_BUFFER_TOO_BIG
 		CRYPTO_KEY_SIZE_RANGE
 
 int mac_verify_decrypt_atomic(
     crypto_provider_handle_t provider,
     crypto_session_id_t session_id,
     crypto_mechanism_t *mac_mech,
     crypto_key_t *mac_key,
     crypto_mechanism_t *decrypt_mech,
     crypto_key_t *decrypt_key,
     crypto_dual_data_t *ciphertext,
     crypto_data_t *mac,
     crypto_data_t *plaintext,
     crypto_spi_ctx_template_t mac_ctx_template,
     crypto_spi_ctx_template_t decr_ctx_template,
     crypto_req_handle_t req)
 -------------------------------------------------------------------------
 Performs an atomic MAC and decrypt operation. The 'mac' argument
 specifies the expected MAC value. If the computed and expected MAC
 values don't match, this entry point returns CRYPTO_INVALID_MAC
 and does not perform the decryption operation.
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_MECHANISM_INVALID
 		CRYPTO_MECHANISM_PARAM_INVALID
 		CRYPTO_MECH_NOT_SUPPORTED
 		CRYPTO_ENCRYPTED_DATA_LEN_RANGE
 		CRYPTO_BUFFER_TOO_SMALL
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_BUFFER_TOO_BIG
 		CRYPTO_KEY_SIZE_RANGE
 		CRYPTO_INVALID_MAC
 
 
 int seed_random(
     crypto_provider_handle_t provider,
     uchar_t *buf,
     size_t len,
     uint_t entropy_estimate,
     uint32_t flags,
     crypto_req_handle_t req)
 ------------------------------------------------------------------
 This operation sends seed material to a random number generator.
 If the CRYPTO_SEED_NOW flag is set, seed material is mixed into the
 random pool immediately. If not set, seed material is mixed at the time
 of the next CRYPTO_SEED_NOW operation, or with the periodic mixing of the
 random pool.
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 
 
 int generate_random(
     crypto_provider_handle_t provider,
     uchar_t *buf,
     size_t len,
     crypto_req_handle_t req)
 -----------------------------------------------------------------
 This operation returns a random number.  The caller of this function is
 responsible for allocating storage for the random number.
 Return Values:	CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_BUFFER_TOO_SMALL
 
 
 int session_open(
     crypto_provider_handle_t provider,
     crypto_session_id_t *session_id,
     crypto_req_handle_t req)
 ---------------------------------------------------------------
 Used to create a new Provider session. The Provider returns the identifier
 of the new session in the location pointed to by session_id.
 Return values:  CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 
 
 int session_close(
     crypto_provider_handle_t provider,
     crypto_session_id_t session_id,
     crypto_req_handle_t req)
 ---------------------------------------------------------------
 Closes a Provider session. The session to be closed is specified
 by the session_id argument.
 Return values:  CRYPTO_SUCCESS
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_SESSION_HANDLE_INVALID
 
 
 int session_login(
     crypto_provider_handle_t provider,
     crypto_session_id_t session_id,
     crypto_user_type_t user_type,
     char *pin,
     size_t pin_len,
     crypto_req_handle_t req)
 ---------------------------------------------------------------
 Used to perform a login operation on an opened session. The Provider
 verifies the specified PIN. If the Provider can differentiate between
 different users, it needs to define the format of the PIN string so
 that it can identify the user from the value of the specified PIN
 user_type specifies the type of user logging in, and can be set to
 CRYPTO_SO or CRYPTO_USER.
 Return values:  CRYPTO_SUCCESS
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_PIN_INVALID
 		CRYPTO_USER_ALREADY_LOGGED_IN
 
 
 int session_logout(
     crypto_provider_handle_t provider,
     crypto_session_id_t session_id,
     crypto_req_handle_t req)
 ---------------------------------------------------------------
 Used to logout an opened session. The Provider must invalidate
 the object handles associated with the specified session and
 free the session objects associated with that session.
 Return values:  CRYPTO_SUCCESS
 		CRYPTO_QUEUED
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_USER_NOT_LOGGED_IN
 
 
 int object_create(
     crypto_provider_handle_t provider,
     crypto_session_id_t session_id,
     crypto_object_attribute_t *template,
     uint_t attribute_count,
     crypto_object_id_t *object
     crypto_req_handle_t req)
 ---------------------------------------------------------------------------
 Creates a new object. session_id specifies the session to be
 used. The object to be created is specified by the arguments template and
 attribute_count. If the state of the session or permissions of the user
 logged in does not allow the object to be created, the operation fails with a
 CRYPTO_NO_PERMISSION error. The object handle corresponding
 to the newly created object is returned in the location pointed to by
 the object argument.
 Return values:  CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_NO_PERMISSION
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_ATTRIBUTE_TYPE_INVALID
 		CRYPTO_ATTRIBUTE_VALUE_INVALID
 
 
 int object_copy(
     crypto_provider_handle_t provider,
     crypto_session_id_t session_id,
     crypto_object_id_t object,
     crypto_object_attribute_t *template,
     uint_t attribute_count,
     crypto_object_id_t *new_object,
     crypto_req_handle_t req)
 -------------------------------------------------------------------------
 Copies an object, creating a new object. session_id specifies
 the session to be used. The object to be copied is specified by the
 object argument. The template array may specify new values for
 attributes for the new object created. attribute_count specifies the number
 of elements in the template array.
 If an attribute value is cannot be changed, for example CKA_EXTRACTABLE
 in the existing object is FALSE and template specifies a
 CKA_EXTRACTABLE attribute value of FALSE, the operation fails with
 a CRYPTO_INCONSISTENT_ATTRIBUTE error. The handle of the new object
 is returned using the new_object parameter.
 Return values:  CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_NO_PERMISSION
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_OBJECT_HANDLE_INVALID
 		CRYPTO_ATTRIBUTE_TYPE_INVALID
 		CRYPTO_ATTRIBUTE_VALUE_INVALID
 		CRYPTO_INCONSISTENT_ATTRIBUTE
 
 
 int object_destroy(
     crypto_provider_handle_t provider, 
     crypto_session_id_t session_id,
     crypto_object_id_t object,
     crypto_req_handle_t req)
 ----------------------------------------------------------------------------
 Destroys an existing object. The handle of the object to be destroyed is
 specified by the object argument.
 Return values:  CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_NO_PERMISSION
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_OBJECT_HANDLE_INVALID
 
 
 int object_get_size(
     crypto_provider_handle_t provider,
     crypto_session_id_t session_id,
     crypto_object_id_t object,
     size_t *size,
     crypto_req_handle_t req)
 ---------------------------------------------------------------------------
 Returns the size, in bytes, needed to store the specified object on the
 Provider.
 Return values:  CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_NO_PERMISSION
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_OBJECT_HANDLE_INVALID
 
 
 int object_get_attribute_value(
     crypto_provider_handle_t provider,
     crypto_session_id_t session_id,
     crypto_object_id_t object,
     crypto_object_attribute_t *template,
     uint_t attribute_count,
     crypto_req_handle_t req)
 ------------------------------------------------------------------------
 Obtains the value of one or more attributes of the specified object.
 attribute_count specifies the number of attributes in the template. For
 each crypto_object_attribute_t in the template, the Provider must following the
 same algorithm as the one defined for the PKCS#11 C_GetAttributeValue()
 method.
 Return values:  CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_NO_PERMISSION
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_OBJECT_HANDLE_INVALID
 
 
 int object_set_attribute_value(
     crypto_provider_handle_t provider,
     crypto_session_id_t session_id,
     crypto_object_id_t object,
     crypto_object_attribute_t *template,
     uint_t attribute_count,
     crypto_req_handle_t req)
 ---------------------------------------------------------------------------
 Modifies one or more attributes associated with the object specified
 by the object and session_id arguments.
 Attributes are specified by the template argument. attribute_count
 specifies the number elements in the template array.
 Return values:  CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_NO_PERMISSION
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_OBJECT_HANDLE_INVALID
 		CRYPTO_ATTRIBUTE_TYPE_INVALID
 		CRYPTO_ATTRIBUTE_VALUE_INVALID
 		CRYPTO_INCONSISTENT_ATTRIBUTE
 
 
 int object_find_init(
     crypto_provider_handle_t provider,
     crypto_session_id_t session_id,
     crypto_object_attribute_t *template,
     uint_t attribute_count,
     void **provider_private,
     crypto_req_handle_t req)
 -----------------------------------------------------------------
 Initializes an find object sequence of operations on the session specified
 by session_id. template specifies the attributes to match
 with the Provider object. Matching is done on every object that is
 accessible by the specified session. A call to object_find_init() is
 followed by a call to object_find().
 The Provider can return a pointer to a Provider-private structure
 in provider_private. This pointer will be passed to the Provider
 from the framework for following object_find().
 Return values:  CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_ATTRIBUTE_TYPE_INVALID
 		CRYPTO_ATTRIBUTE_VALUE_INVALID
 
 
 int object_find(
     crypto_provider_handle_t provider,
     void *provider_private,
     crypto_object_id_t *objects,
     uint_t max_object_count,
     uint_t *object_count,
     crypto_req_handle_t req)
 -----------------------------------------------------------------
 Continues a search for objects that was previously initiated by
 a call to object_find_init(), obtaining additional object handles.
 The maximum number of objects to be returned is specified by 
 max_object_count. Object handles are returned in the pre-allocated
 array specified by objects. The number of objects found is returned
 in object_count and can be zero if no more objects are found.
 Return values:  CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_SESSION_HANDLE_INVALID
 
 
 int object_find_final(
     crypto_provider_handle_t provider,
     void *provider_private,
     crypto_req_handle_t req)
 -------------------------------------------------------------------------
 Terminates a search for token and session objects. The Provider is
 responsible to release any resources associated with provider_private.
 Return values:  CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_SESSION_HANDLE_INVALID
 
 
 int key_generate(
     crypto_provider_handle_t provider,
     crypto_session_id_t session_id,
     crypto_mechanism_t *mechanism;
     crypto_object_attribute_t *template,
     uint_t attribute_count,
     crypto_object_id_t *object,
     crypto_req_handle_t req)
 -----------------------------------------------------------------------------
 Generates a secret key or domain parameter. The mechanism argument
 contains the mechanism and mechanism parameters to be used. template
 contains the attributes to assign to the new object. The Provider sets
 the CKA_CLASS attribute to CKO_DOMAIN_PARAMETER if the mechanism is for
 domain parameter generation or to CKO_SECRET_KEY otherwise. On successful
 execution, key_generate() returns the handle to the new object using
 the object pointer argument.
 Return values:  CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_ATTRIBUTE_TYPE_INVALID
 		CRYPTO_ATTRIBUTE_VALUE_INVALID
 		CRYPTO_INCONSISTENT_ATTRIBUTE
 		CRYPTO_MECHANISM_INVALID
 		CRYPTO_MECHANISM_PARAM_INVALID
 
 
 int key_generate_pair(
     crypto_provider_handle_t provider,
     crypto_session_id_t session_id,
     crypto_mechanism_t *mechanism,
     crypto_object_attribute_t *public_key_template,
     uint_t public_key_attribute_count,
     crypto_object_attribute_t *private_key_template,
     uint_t private_key_attribute_count,
     crypto_object_id_t *public_key,
     crypto_object_id_t *private_key,
     crypto_req_handle_t req_handle)
 --------------------------------------------------------------------------
 Generates a key public/private key pair using the mechanism specified
 by mechanism. The public_key_template and private_key_template
 can be used to specify a set of attributes to associate with
 the public and private key, respectively. Two new objects are created
 and their handles returned in public_key and private_key.
 Return values:  CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_ATTRIBUTE_TYPE_INVALID
 		CRYPTO_ATTRIBUTE_VALUE_INVALID
 		CRYPTO_INCONSISTENT_ATTRIBUTE
 		CRYPTO_MECHANISM_INVALID
 		CRYPTO_MECHANISM_PARAM_INVALID
 
 
 int key_wrap(
     crypto_provider_handle_t provider,
     crypto_session_id_t session_id,
     crypto_mechanism_t *mechanism,
     crypto_key_t *wrapping_key
     crypto_object_id_t *key,
     uchar_t *wrapped_key,
     size_t *wrapped_key_len,
     crypto_req_handle_t req)
 ---------------------------------------------------------------------
 Wraps the private or secret key specified by key with
 the key specified by wrapping_key, and return the resulting wrapped
 key in the buffer wrapped_key. On output, wrapped_key_len
 is set by the Provider to contain the length, in bytes, of the
 wrapped key. The wrapping key can be specified
 either by reference, i.e. a handle to a Provider object, or by
 value. The wrapped key must have its CKA_EXTRACTABLE attribute set
 to TRUE.
 Return values:  CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_KEY_SIZE_RANGE
 		CRYPTO_MECH_NOT_SUPPORTED
 		CRYPTO_KEY_NOT_WRAPPABLE
 
 
 int key_unwrap(
     crypto_provider_handle_t provider,
     crypto_session_id_t session_id,
     crypto_mechanism_t *mechanism,
     crypto_key_t *unwrapping_key
     uchar_t *wrapped_key,
     size_t wrapped_key_len,
     crypto_object_attribute_t *template,
     uint_t attribute_count,
     crypto_object_id_t *key,
     crypto_req_handle_t req)
 -------------------------------------------------------------------
 Unwraps (decrypts) the wrapped key wrapped_key of length wrapped_key_len.
 A new key object is created and its object id returned in key. By
 default, the new key will have its CKA_ALWAYS_SENSITIVE attribute
 set to FALSE, the CKA_NEVER_EXTRACTABLE attribute set to FALSE, and
 the CKA_EXTRACTABLE attribute set to TRUE.
 The unwrapping key and mechanism are specified by unwrapping_key and
 mechanism, respectively. If the unwrapping key is passed by attributes
 or by reference, it must have the CKA_UNWRAP attribute set to TRUE.
 Return values:  CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_KEY_SIZE_RANGE
 		CRYPTO_MECH_NOT_SUPPORTED
 
 
 int key_derive(
     crypto_provider_handle_t provider,
     crypto_session_id_t session_id,
     crypto_mechanism_t *mechanism;
     crypto_key_t base_key;
     crypto_object_attribute_t *template,
     uint_t attribute_count,
     crypto_object_id_t *key,
     crypto_req_handle_t req)
 -------------------------------------------------------------------------
 Derives the key specified by base_key using the mechanism specified
 by mechanism and creates a handle to the derived key in the location
 pointed to by the key argument. The new key inherits the attributes of the
 base key. The template argument can be used to specify attributes
 of the newly created object.
 Return values:  CRYPTO_SUCCESS
 		CRYPTO_HOST_MEMORY
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_KEY_SIZE_RANGE
 		CRYPTO_MECH_NOT_SUPPORTED
 		CRYPTO_ATTRIBUTE_TYPE_INVALID
 		CRYPTO_ATTRIBUTE_VALUE_INVALID
 
 
 int ext_info(
     crypto_provider_handle_t provider,
     crypto_provider_ext_info_t *ext_info,
     crypto_req_handle_t req)
 ----------------------------------------------------------------------
 Returns the extended info corresponding to the provider. The extended
 provider info structure is preallocated by the caller.
 Return values:  CRYPTO_SUCCESS
                 CRYPTO_FAILED
                 CRYPTO_QUEUED
 
 
 int init_token(
     crypto_provider_handle_t provider,
     char *pin,
     size_t pin_len,
     char *label,
     crypto_req_handle_t req)
 ----------------------------------------------------------------------
 Initialize a token using the session specified by 'session'.  'pin' is the
 pin of the security officer.  'label' is the 32 byte label of the token.
 Return values:  CRYPTO_SUCCESS
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_PIN_INVALID
 		CRYPTO_WRITE_PROTECTED
 
 
 int init_pin(
     crypto_provider_handle_t provider,
     crypto_session_id_t session,
     char *pin,
     size_t pin_len,
     crypto_req_handle_t req)
 --------------------------------------------------------------------
 Initialize the normal user's PIN using the session specified by 'session'
 and the PIN specified by 'pin' and 'pin_len'.
 Return values:  CRYPTO_SUCCESS
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_PIN_INVALID
 		CRYPTO_WRITE_PROTECTED
 
 
 int set_pin(
     crypto_provider_handle_t provider,
     crypto_session_id_t session,
     char *old_pin,
     size_t old_len,
     char *new_pin,
     size_t new_len,
     crypto_req_handle_t req)
 -----------------------------------------------------------------------
 Change the value of a PIN using the session specified by 'session'.  'old_pin'
 is the current value of the pin and 'new_pin' is the new value.
 Return values:  CRYPTO_SUCCESS
 		CRYPTO_FAILED
 		CRYPTO_QUEUED
 		CRYPTO_SESSION_HANDLE_INVALID
 		CRYPTO_PIN_INVALID
 		CRYPTO_WRITE_PROTECTED
 
 
 int copyin_mechanism(
     crypto_provider_handle_t provider,
     crypto_mechanism_t *umech,
     crypto_mechanism_t *kmech,
     int *error,
     int mode)
 
 -----------------------------------------------------------------------
 Allocate memory and copyin a mechanism parameter from user address space
 into kernel address space. 'umech' is a crypto_mechanism structure with
 its parameter field pointing into user address space. 'kmech' is also a 
 crypto_mechanism structure but its parameter field is updated to point
 to a kernel copy of the 'umech' parameter. If copyin() fails then 'error'
 should be set to EFAULT and CRYPTO_FAILED returned. 'mode' is the datamodel
 mode of the application in whose address space 'umech' resides. Providers
 that support this entry point must be capable of performing the operation
 without queueing the operation for later processing. Said another way,
 the operation must be performed in the context of the caller.
 
 If a provider registers such an entry point, then the framework will call
 it with the user-provided crypto_mechanism_t, before calling the provider
 entry point that uses the mechanism (e.g. the provider's (*derive_key)()).
 The provider's (*copyin_mechanism)() entry point expects to be called in
 the context of the calling process, with a mechanism parameter that is a
 userland pointer. The provider is responsible for allocating kernel memory
 of the right size for the mechanism, and copyin()'ing the mechanism parameter
 structure, and its members at all levels when applicable.
 
 Providers that register version 2 of the SPI must register this entry point.
 
 Return values:  CRYPTO_SUCCESS
 		CRYPTO_FAILED
 		CRYPTO_ARGUMENTS_BAD
 		CRYPTO_HOST_MEMORY
 		CRYPTO_MECHANISM_INVALID
 		CRYPTO_MECHANISM_PARAM_INVALID
 
 
 int copyout_mechanism(
     crypto_provider_handle_t provider,
     crypto_mechanism_t *kmech,
     crypto_mechanism_t *umech,
     int *error,
     int mode)
 
 -----------------------------------------------------------------------
 Copyout a mechanism parameter from kernel address space into user address
 space. 'kmech' is a crypto_mechanism structure with its parameter field
 pointing into kernel address space. 'umech' is also a crypto_mechanism
 structure but its parameter field points into user address space.  If
 copyout() fails then 'error' should be set to EFAULT and CRYPTO_FAILED
 returned. 'mode' is the datamodel mode of the application in whose address
 space 'umech' resides. Providers that support this entry point must be
 capable of performing the operation without queueing the operation for
 later processing. Said another way, the operation must be performed in
 the context of the caller.
 
 Providers that register version 2 of the SPI must register this entry point.
 
 Return values:  CRYPTO_SUCCESS
 		CRYPTO_FAILED
 		CRYPTO_ARGUMENTS_BAD
 		CRYPTO_MECHANISM_INVALID
 		CRYPTO_MECHANISM_PARAM_INVALID
 
 
 int free_mechanism(
     crypto_provider_handle_t provider,
     crypto_mechanism_t *kmech)
 
 -----------------------------------------------------------------------
 Free a mechanism parameter allocated by copyin_mechanism.
 
 Providers that register version 2 of the SPI must register this entry point.
 
 Return values:  CRYPTO_SUCCESS
 		CRYPTO_FAILED
 		CRYPTO_ARGUMENTS_BAD
 		CRYPTO_MECHANISM_INVALID
 		CRYPTO_MECHANISM_PARAM_INVALID
 

 int nostore_key_generate(
     crypto_provider_handle_t provider,
     crypto_session_id_t session_id,
     crypto_mechanism_t *mechanism;
     crypto_object_attribute_t *in_template,
     uint_t in_attribute_count,
     crypto_object_attribute_t *out_template,
     uint_t out_attribute_count,
     crypto_req_handle_t req)
 -----------------------------------------------------------------------------
 Similar to key_generate() except that generated values are returned in
 'out_template' rather than by reference to an object ID. The generated key
 is returned in the CKA_VALUE_ATTRIBUTE attribute. Providers that register
 version 3 of the SPI must register this entry point.


 int nostore_key_generate_pair(
     crypto_provider_handle_t provider,
     crypto_session_id_t session_id,
     crypto_mechanism_t *mechanism,
     crypto_object_attribute_t *in_public_key_template,
     uint_t in_public_key_attribute_count,
     crypto_object_attribute_t *in_private_key_template,
     uint_t in_private_key_attribute_count,
     crypto_object_attribute_t *out_public_key_template,
     uint_t out_public_key_attribute_count,
     crypto_object_attribute_t *out_private_key_template,
     uint_t out_private_key_attribute_count,
     crypto_req_handle_t req_handle)
 --------------------------------------------------------------------------
 Similar to key_generate_pair() except that generated values are returned
 in 'out_public_key_template' and 'out_private_key_template' rather than
 object IDs. The particular attributes that hold returned values depend
 upon the specified mechanism. For example, the generated attribute for
 a public key is CKA_EC_POINT for CKM_EC_KEY_PAIR_GEN, whereas the generated
 attribute is CKA_MODULUS for CKM_RSA_PKCS_KEY_PAIR_GEN. Providers that
 register version 3 of the SPI must register this entry point.


 int nostore_key_derive(
     crypto_provider_handle_t provider,
     crypto_session_id_t session_id,
     crypto_mechanism_t *mechanism;
     crypto_key_t base_key;
     crypto_object_attribute_t *in_template,
     uint_t in_attribute_count,
     crypto_object_attribute_t *out_template,
     uint_t out_attribute_count,
     crypto_req_handle_t req)
 -------------------------------------------------------------------------
 Similar to derive_key() except that generated values are returned in
 'out_template' rather than by reference to an object ID. The generated key
 is returned in the CKA_VALUE_ATTRIBUTE attribute. Providers that register
 version 3 of the SPI must register this entry point.


+void fips140_post(int *rv)
+-------------------------------------------------------------------------
+This provides kcf with the function to perform FIPS 140-2 Power-On Self
+Tests (POST).  This is used as part of a FIPS 140  boundary.  Providers that
+register version 4 of the SPI must register this entry point.  If the
+modules is not part of a FIPS 140 boundary, the entry point may be NULL.

 5. Package Installation
 -----------------------
 
 Hardware Providers requirements:
 1. Modules for hardware providers must be installed in /kernel/crypto or
    /platform/<arch>/kernel/crypto, with a hard-link to /kernel/drv or
    /platform/<arch>/kernel/drv, respectively.
 
 Software Providers requirements:
 1. Modules for software providers must be installed in /kernel/crypto
    or /platform/<arch>/kernel/crypto
 
 
 
 
 				APPENDIX A
 
 	Mapping of PKCS#11 Function Names to Provider Entry Points
 
 
 	C_Initialize()				no mapping
 	C_Finalize()				no mapping
 	C_GetInfo()				no mapping
 	C_GetFunctionList()			no mapping
 	C_GetSlotList()				no mapping
 	C_GetSlotInfo()				no mapping
 	C_GetTokenInfo()			no mapping
 	C_GetMechanismList()			no mapping
 	C_GetMechanismInfo()			no mapping
 	C_InitToken()				init_token()
 	C_InitPIN()				init_pin()
 	C_SetPIN()				set_pin()
 	C_OpenSession()				session_open()
 	C_CloseSession()			session_close()
 	C_CloseAllSessions()			no mapping
 	C_GetSessionInfo()			no mapping
 	C_GetOperationState()			no mapping
 	C_SetOperationState()			no mapping
 	C_Login()				session_login()
 	C_Logout()				session_logout()
 	C_CreateObject()			object_create()
 	C_CopyObject()				object_copy()
 	C_DestroyObject()			object_destroy()
 	C_GetObjectSize()			object_get_size()
 	C_GetAttributeValue()			object_get_attribute_value()
 	C_SetAttributeValue()			object_set_attribute_value()
 	C_FindObjectsInit()			object_find_init()
 	C_FindObjects()				object_find()
 	C_FindObjectsFinal()			object_find_final()
 	C_EncryptInit()				encrypt_init()
 	C_Encrypt()				encrypt()
 	C_EncryptUpdate()			encrypt_update()
 	C_EncryptFinal()			encrypt_final()
 	C_DecryptInit()				decrypt_init()
 	C_Decrypt()				decrypt()
 	C_DecryptUpdate()			decrypt_update()
 	C_DecryptFinal()			decrypt_final()
 	C_DigestInit()				digest_init()
 	C_Digest()				digest()
 	C_DigestUpdate()			digest_update()
 	C_DigestKey()				digest_key()
 	C_DigestFinal()				digest_final()
 	C_SignInit()				sign_init(), mac_init()
 	C_Sign()				sign(), mac()
 	C_SignUpdate()				sign_update(), mac_update()
 	C_SignFinal()				sign_final(), mac_final()
 	C_SignRecoverInit()			sign_recover_init()
 	C_SignRecover()				sign_recover()
 	C_VerifyInit()				verify_init()
 	C_Verify()				verify()
 	C_VerifyUpdate()			verify_update()
 	C_VerifyFinal()				verify_final()
 	C_VerifyRecoverInit()			verify_recover_init()
 	C_VerifyRecover()			verify_recover()
 	C_DigestEncryptUpdate()			digest_encrypt_update()
 	C_DecryptDigestUpdate()			decrypt_digest_update()
 	C_SignEncryptUpdate()			encrypt_mac_update()
 	C_DecryptVerifyUpdate()			mac_decrypt_update()
 	C_GenerateKey()				key_generate()
 	C_GenerateKeyPair()			key_generate_pair()
 	C_WrapKey()				key_wrap()
 	C_UnwrapKey()				key_unwrap()
 	C_DeriveKey()				key_derive()
 	C_SeedRandom()				seed_random()
 	C_GenerateRandom()			generate_random()
 	C_GetFunctionStatus()			no mapping
 	C_CancelFunction()			no mapping
 	C_WaitForSlotEvent()			no mapping
