--- k-api.old	Wed May  9 17:09:28 2007
+++ k-api.new	Wed May  9 17:10:42 2007
@@ -1,1115 +1,1115 @@
 #pragma ident   "@(#)k-api 1.28     05/11/07 SMI"
 
 
 		Kernel Cryptographic Programming Interface
 
 
 Overview
 --------
 This document specifies the programming interface for a particular class of
 operations, the cryptographic operations, to be offered for kernel-level
 consumers in Solaris.
 The purpose of this interface is to consolidate the existing interfaces
 to these operations and to allow access to cryptographic software and
 hardware providers, that plug-in into the Solaris kernel Cryptographic 
 framework's SPI (Service Provider Interface).
 This is one of the interfaces being exposed by the Kernel Encryption Framework
 project, PSARC case 2001/553.
 
 The intended audience is Sun and third party developers writing solaris
 kernel-level software that uses cryptography, so familiarity with the
 basic concepts of cryptography is being assumed.
 Detailed definitions can be found in [Schneier].
 
 
 PART I. General Model
 =====================
 
 Requirements:
 -------------
 This programming interface has to accommodate the following requirements:
 
 . The environmental constraints of the calling code (consumer).
     Calls come from kernel clients, that can be running either in an interrupt
     context, in the context of a user process (kernel thread that has an
     LWP) or in the context of a detached kernel thread (e.g. a taskq
     scheduler).
 
 . The mode of operation of the providers that will handle the operations.
     The functions exported by a software-based provider will typically
     execute in a synchronous way, without surrendering the CPU.
     Hardware-based providers usually operate in an asynchronous mode
     where an operation involves a programmed I/O of the HW and
     possibly an interrupt upon completion.
 
 . Parallelism.
     The whole kernel is one protected address space, where several threads
     running on different CPUs can be attempting to simultaneously operate
     on the same data.
 
 . Both the consumers and the providers can go away at any time.
     Pending parts of a multipart crypto operation may need to be canceled
     before they are completed (an IPsec SA deleted for instance).
     A software provider may be unloaded, an a hardware provider can be
     DR'ed out (for dynamic reconfiguration).
 
 . The data format: Both contiguous and scatter-gather formats should be
   supported.
     
 
 Consumer model
 --------------
 
 A generic calling sequence will have 3 parts:
 
 . Context creation and initialization
 . Context use
 . Finalizing, result collecting and context destruction.
 
 
 The context creation and initialization may re-use a previously
 pre-computed template of a cryptographic context.
 The second part can have also several steps (several updates using the
 the context for example).
 There 3 parts can be combined in one single function call operation.
 
 The consumer code is expected to be aware of kernel constraints.
 Calls coming from non-blockable contexts are expected to provide
 call-back routines, and be ready for asynchronous scheduling of their
 request.
 
 Also, consumer code that submits asynchronous requests is given back a handle
 for that request. The consumer code will use that handle to cancel the
 request if it needs to (driver closing, ...).
 The main arguments passed to an asynchronous cryptographic function (that
 returned before it is complete), are expected to be persistent and valid
 until either the operation is complete, and the call-back routine
 returns, or until the request is canceled.
 
 
 PART II. Detailed design
 ========================
 
 The common data structures crypto_mechanism_t, crypto_data_t, crypto_key_t,
 crypto_context_t and crypto_context_template_t are defined in the KEF
 functional specifications, and in the <sys/crypto/api.h> and
 <sys/crypto/common.h> attached.
 
 
 Return values
 -------------
 Crypto routines (see below) return a signed integer, informing about the
 status of the operation. The common possible return values are:
 
      CRYPTO_SUCCESS
           Operation successfully completed.
 
      CRYPTO_QUEUED
           Operation successfully queued. The callback routine will be called
 	  later, when the operation completes.
 
      CRYPTO_FAILED
           Operation failed.
 
      CRYPTO_HOST_MEMORY
           Not enough memory to complete the operation.
 
      CRYPTO_ARGUMENTS_BAD
 	  Incorrectly formatted arguments.
 
      CRYPTO_BUFFER_TOO_SMALL
           The specified output buffer is too small.
 
      CRYPTO_BUFFER_TOO_BIG
           The input buffer is too big.
 
      CRYPTO_INVALID_CONTEXT
           The specified context is not valid.
 
      CRYPTO_DATA_LEN_RANGE
           Invalid data length or range.
 
      CRYPTO_ENCRYPTED_DATA_LEN_RANGE
           Invalid ciphertext length or range.
 
      CRYPTO_MECHANISM_INVALID
           The specified mechanism argument is not valid.
 
      CRYPTO_MECHANISM_PARAM_INVALID
           The mechanism parameter is not valid.
 
      CRYPTO_KEY_SIZE_RANGE
           The specified key size is outside the range allowed for the operation.
 
      CRYPTO_MECH_NOT_SUPPORTED
           Mechanism not appropriate for function.
 
      CRYPTO_BUSY
 	  Not enough system resource to handle take a crypto request now.
 
      CRYPTO_CANCELED
           The operation was canceled. Occurs if the operation had to
           be canceled by a third party (for example following the DR'ing out
           of all the providers that can handle it).
 
      CRYPTO_SESSION_HANDLE_INVALID
           Handle does not correspond to a valid session on the provider.
 
 Other returned codes, specific to individual functions, are specified in the
 respective man pages.
 
 
 Call requests
 -------------
 
 Most of the functions of this programming interface take a a pointer to a
 crypto_call_req structure that specifies the conditions of an 
 asynchronous call and the expected behavior. A NULL crypto_call_req_t
 pointer indicates a synchronous call.
 
 The API/framework will be internally allocating memory for a request when it
 needs to queue it. This allocation uses KM_SLEEP for synchronous calls and
 KM_NOSLEEP for asynchronous calls.
 
 Some of the CSPI (provider interface) entry points, such as digest_init(), 
 may need to allocate memory. 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.
 
 typedef uint32_t crypto_call_flag_t;
 typedef void * crypto_req_t;
 
 #define	CRYPTO_ALWAYS_QUEUE	0x00000001	/* ALWAYS queue the req. */
 #define	CRYPTO_NOTIFY_OPDONE	0x00000002	/* Notify intermediate steps */
 #define CRYPTO_SKIP_REQID       0x00000004      /* Skip request ID generation */
 
 typedef struct {
 	crypto_call_flag_t	cr_flag;
 	void			(*cr_callback_func)(void *, int);
 	void			*cr_callback_arg;
 	crypto_req_t		*cr_req;	
 } crypto_call_req_t;
 
 
 Asynchronous calls
 ------------------
 A caller has to pass non NULL crypto_call_req_t pointer 
 
 When the caller passes in a non NULL crypto_call_req_t pointer, there are 2
 cases:
 
 . CRYPTO_ALWAYS_QUEUE cr_flag set:
   The calling code does not want to spend any CPU cycles on costly
   cryptographic operations, or cannot safely make any blocking call
   (blocking memory allocation, acquiring a mutex possibly held at a different
   PIL ...). This is typically the case of a call coming from an interruption
   context, or timeout handler.
   The request associated to this call is always queued and the call returns
   CRYPTO_QUEUED.
 
 . CRYPTO_ALWAYS_QUEUE cr_flag clear:
   The calling code can spend the CPU cycles on the cryptographic
   operations, and can tolerate spinning on locks. However, the calling code
   doesn't want to be put in cv_wait() internally.
   A typical consumer of this case is a streams module running its service
   or write put procedure. This is especially reasonable with message
   digest operations that are fast enough in software and the overhead of extra
   queuing/interruptions and context switching overcomes the potential
   performance gain from offloading these operations to hardware accelerators.
   The framework will return asynchronously only when it is necessary, that is
   when it needs to either queue the request, or dispatch it to a hardware
   provider.
   
 
 When a request is submitted, that is when the returned value from a crypto
 function is CRYPTO_QUEUED, the cr_req is initialized to a handle for the
 request. The consumer code will use that handle to cancel the request if
 it needs to do so.
 
 In all cases of a queued request, upon completion, the framework will call
 
 	(cr->cr_callback_f)(cr->cr_callback_arg, finish_status);
 
 where finish_status contains an integer value corresponding to the execution
 status of the request. Possible values are defined above in section
 "Return Values".
 
 Once a crypto context of a multipart crypto operation is initialized
 (an xxx_init() completed), a consumer does not need to wait for the
 completion of the previous part before submitting the next one.
 Several requests for the same crypto_context can be pending.
 The consumer code can choose to disable the callback to be invoked after the
 intermediate calls are complete with success, by leaving the cr_flag
 CRYPTO_NOTIFY_OPDONE clear in the crypto_call_req. This flag is ignored for
 back for final and single step operations, as well as for non success
 termination of the request.
 The order of submission is guaranteed to be preserved for requests of the
 same context. Thus, a notification of request completion implicitly notifies
 the completion of ALL the preceding requests.
 The typical use of this feature is a consumer that initializes a
 crypto_context, then submits the parts of the operation as it receives
 them asynchronously. The consumer doesn't have a useful thing to do with
 the information of the completion of a part of the operation. It will be
 notified only after the final is done.
 
 CRYPTO_SKIP_REQID is set in cr_flag by a client if it does not need a handle
 for the request that is submitted. The framework will skip generating a request
 ID and will skip the related routines.
 
 A client using this flag MUST make sure it won't get modunloaded when it has
 a pending request(s).
 
 
 Notes:
    1. The callback routine can run in an interrupt context, and has to
       adhere to the same restrictions as interrupt and timeout
       handlers (no sleeping, no door upcalls, no blocking memory
       allocations ...)
 
    2. The framework uses the information passed in the crypto_call_req_t
       structure to internally build its own requests, but does not keep any
       reference to that crypto_call_req_t structure. That structure does not
       need to persist until the operation finishes and the call-back routine
       is invoked (it can be allocated on the stack of the calling code).
       However, the cr_callback_f function, and the cr_callback_arg have to
       stay valid until either the operation is complete and the framework
       calls cr_callback_f, or until the request is canceled.
       Future evolutions of this API may include a consumer pre-allocation
       mechanism, depending on how many pending requests a particular consumer
       plans to have.
 
    3. Although canceling a request from a multipart operation is likely
       to make the whole operation useless, the consumer is responsible for
       explicitly canceling all the other pending requests. The consumer is
       given the choice of canceling ALL the requests submitted for one context
       (cancel_req() vs cancel_ctx()).
 
 
 Synchronous calls
 -----------------
 When the caller passes in a NULL crypto_call_req_t pointer, the
 function will be attempted and possibly block. This is typically the case
 of a consumer code running in the context a system call coming from a user
 process.
 When a request needs to be queued or dispatched to a hardware provider,
 the framework will internally schedule it asynchronously, and block
 until the operation is complete, then wakeup and return, thus simulating
 a synchronous behavior.
 
 
 Flow control
 ------------
 
 When there is a temporary shortage of queue resources to handle
 a cryptographic request, the synchronous calls will block until enough
 are released. Asynchronous calls will fail with CRYPTO_BUSY.
 The calling code can either tolerate this failure and adapt to it
 (e.g. dropping incoming IP packets, retry after some timeout), or
 may register for a notification when resources are made available.
 Four routines are provided to this effect:
 crypto_bc_t crypto_bufcall_alloc();
 int crypto_bufcall(bc_handle, func, arg);
 int crypto_unbufcall(crypto_bc_t bc_handle);
 int crypto_bufcall_free(bc_handle)
 
 The semantics of these routines is similar to the STREAMS bufcall(9F)
 routine, with one difference, which is crypto_bufcall(), takes a preallocated
 bufcall handle, so it is guaranteed to succeed.
 
 Note that the client should use bufcall(9F) when it gets a CRYPTO_HOST_MEMORY.
 It should use crypto_bufcall(), for CRYPTO_BUSY case only. 
 
 
 Deadlock avoidance
 ------------------
 
 Canceling asynchronous crypto requests and bufcalls follows the semantics of
 timeout()s in the Solaris kernel.
 The code that cancels an asynchronous request must not attempt to 
 acquire a mutex lock that could be acquired by the callback routine for
 that request.
 When the callback routine for a request already started, the cancel call
 for that request is guaranteed to block until that callback is finished.
   
 
 Functions
 =========
 The programming interface exports 5 groups of cryptographic operations:
 message digest, encrypt, decrypt, mac, and dual operations.
 It also exports 2 routines for requests managements, 2 routines for
 context templates management, 2 routines to find and release providers,
 4 routines for session management, 9 routines for object management,
 and 5 routines for key management. These are Consolidation Private interfaces.
 
 The framework also exposes a sign-up facility for notification of special
 events.
 
 The general convention adopted for the order of the arguments of the functions
 is: The IN parameters, followed by the OUT parameters, followed by the 
 request conditions.
 
 
 Supported mechanisms and extensibility
 --------------------------------------
 Mechanisms are uniquely identified in the system by a mechanism number
 that the calling code should retrieve and use for initializing
 the cm_type in the crypto_mechanism_t structure.
 The following function
 
 	crypto_mech_type_t crypto_mech2id(crypto_mech_name_t mech_name)
 
 returns the mechanism number assigned to the <mech_name> by the system.
 
 The names of the mechanism to be passes as <mech_name>
 follow the PKCS#11 naming convention.
 
 The following supported mechanisms have predefined names:
 SUN_CKM_MD5, SUN_CKM_MD5_HMAC, SUN_CKM_MD5_HMAC_GENERAL
 SUN_CKM_SHA1, SUN_CKM_SHA1_HMAC, SUNW_CKM_SHA1_HMAC_GENERAL
 SUN_CKM_DES_ECB, SUN_CKM_3DES_ECB, SUN_CKM_DES_CBC, SUN_CKM_3DES_CBC,
 SUN_CKM_DES_OFB, SUN_CKM_BLOWFISH_CBC, SUN_CKM_AES_CBC, SUN_CKM_AES_ECB,
-SUN_CKM_AES_CTR
+SUN_CKM_AES_CTR, SUN_CKM_AES_CCM
 
 The CKM_XXX mechanisms are described in more detail in the [PKCS#11]
 chapter 12.
 
 Example: the string to be passed for the MD5 mechanism is defined in the
 <sys/crypto/api.h> as by the constant SUN_CKM_MD5:
 
 #define	SUN_CKM_MD5	"CKM_MD5"
 
 
 The kernel SPI allows providers to advertise a new mechanism to the
 framework, identified by its name (a string).
 Customers who need to use a new mechanism (that they installed a provider
 for) will also call crypto_mech2id() to
 find the crypto_mech_type_t assigned to the new mechanism.
 
 
 Context templates management
 ----------------------------
 The key schedule for a symmetric cipher can be pre-expanded a saved in a
 context template to be copied and reused several times. Similarly, the
 inner and outer contexts of an HMAC envelop can be pre-computed and
 reused.
 
 The crypto_ctx_template_t is defined as an opaque pointer.
 
 The following function
 
      int crypto_create_ctx_template(crypto_mechanism_t *mech,
           crypto_key_t *key, crypto_ctx_template *tmpl, int kmflag);
 
 will allocate, initialize, pre-compute, and return a context template for
 use later in the operations.
 The consumer code must destroy the context template once it is done with it.
 
      void crypto_destroy_ctx_template(crypto_ctx_template tmpl);
 
 The crypto_context_t used in the following functions is defined as an opaque
 pointer.
 
 The following function can be used to verify that the specified context
 template can be used for a cryptographic operation:
 
      boolean_t crypto_ctx_template_is_valid(crypto_ctx_template tmpl);
 
 
 Provider Selection
 ------------------
 Routine names with a _prov suffix are for use with open sessions to specific
 providers. The same routine names without the _prov suffix pick the best
 provider for the specified mechanism. An example is crypto_encrypt_prov()
 and crypto_encrypt().
 
 The following function
 
      crypto_provider_t crypto_get_provider(char *label, char *manuf,
          char *serial);
 
 was written to find providers. 'label' is the provider label, 'manuf'
 the manufacturer ID, and 'serial' is the serial number. These values are
 typically predefined by the provider's vendor, or set during the device
 initialization. They may be obtained by calling C_GetTokenInfo() in
 pkcs11_kernel(5), and passed to the kernel. They can also be obtained
 with cryptoadm(1M) as follows:
 
 cryptoadm list -v provider='/usr/lib/security/$ISA/pkcs11_kernel.so'
 
 'manuf' and 'serial' are optional and should be set to NULL if unused.
 If successful, the provider is held until released by crypto_release_provider().
 If providers are removed while they are in use, then subsequent operations
 will return CRYPTO_DEVICE_ERROR. After receiving this error,
 crypto_release_provider() should be called to release any remaining
 resources associated with the provider.
 
      int crypto_release_provider(crypto_provider_t provider);
 
 
 Message Digest
 --------------
 
 A message can be digested in one single step:
 
 int crypto_digest(crypto_mechanism_t *mech,	/* mechanism		  */
     crypto_data_t      *data,			/* data to be hashed      */
     crypto_data_t      *digest,			/* storage for the digest */
     crypto_call_req_t  *cr)			/* Call req conditions	  */
 
 or in multiple parts, init-updates-final:
 
 int crypto_digest_init(crypto_mechanism_t *mech, /* mechanism 		    */
     crypto_context_t   *ctxp,			/* store for context handle */
     crypto_call_req_t  *cr)			/* Call req conditions	    */
 
 Examples of mechanism types are CKM_MD5, CKM_SHA1, etc ...
 
 *ctxp is allocated and initialized by this routine, and will be used for next
 operations.
 
 int crypto_digest_update(crypto_context_t ctx,	/* Allocated by digest_init */
     crypto_data_t      *data,			/* data to be hashed       */
     crypto_call_req_t  *cr)			/* Call req conditions	   */
 	
 int crypto_digest_final(crypto_context_t ctx,
     crypto_data_t      *digest,			/* storage for the digest */
     crypto_call_req_t  *cr)			/* Call req conditions	  */
 
 crypto_digest_final() internally destroys the crypto_context_t ctx, so the
 consumer code must not refer to it after that function returns.
 
 crypto_digest() and crypto_digest_init() have variants that take a
 provider handle and a session ID as their first two arguments; they are
 crypto_digest_prov() and crypto_digest_init_prov(). Rather than letting
 the framework pick the best provider for a specified mechanism, these two
 functions are used when a session has been established to a particular
 provider by calling crypto_get_provider() and crypto_session_open().
 
 
 Message Authentication Code
 ---------------------------
 
 A message authentication code can be computed in one single step:
 
 int crypto_mac(crypto_mechanism_t *mech,	/* mechanism 		  */
     crypto_data_t      *data,			/* data to be MAC'ed      */
     crypto_key_t       *key,			/* Authentication key	  */
     crypto_ctx_template_t tmpl,			/* context template 	  */
     crypto_data_t      *mac,			/* storage for the MAC    */
     crypto_call_req_t  *cr)			/* Call req conditions	  */
 
 Or in multiple parts, init-updates-final:
 
 int crypto_mac_init(crypto_mechanism_t *mech,	/* mechanism 		    */
     crypto_key_t       *key,			/* Authentication key	    */
     crypto_ctx_template_t tmpl,			/* context template 	    */
     crypto_context_t   *ctxp,			/* store for context handle */
     crypto_call_req_t  *cr)			/* Call req conditions	    */
 
 Examples of mechanism types are CKM_HMAC_MD5, CKM_HMAC_SHA1, etc ...
 
 *ctxp is allocated and initialized by this routine, and will be used for next
 operations (consolidation-private).
 
 int crypto_mac_update(crypto_context_t ctx,	/* from crypto_mac_init()  */
     crypto_data_t      *data,			/* data to be MAC'ed       */
     crypto_call_req_t  *cr)			/* Call req conditions	   */
 	
 int crypto_mac_final(crypto_context_t ctx,	/* from crypto_mac_init()  */
     crypto_data_t      *mac,			/* storage for the mac     */
     crypto_call_req_t  *cr)			/* Call req conditions	   */
 
 crypto_mac_final() internally destroys the crypto_context_t ctx, so the
 consumer code must not refer to it after that function returns.
 
 crypto_mac_verify(), instead of returning the computed MAC, takes as
 argument the value of an expected MAC. If the value of the computed MAC does
 not match the value of the expected MAC, the error code CRYPTO_INVALID_MAC
 is returned.
 
 int crypto_mac_verify(crypto_mechanism_t *mech,	/* mechanism 		  */
     crypto_data_t      *data,			/* data to be MAC'ed      */
     crypto_key_t       *key,			/* Authentication key	  */
     crypto_ctx_template_t tmpl,			/* context template 	  */
     crypto_data_t      *mac,			/* expected MAC           */
     crypto_call_req_t  *cr)			/* Call req conditions	  */
 
 crypto_mac(), crypto_mac_init(), and crypto_mac_verify() have variants that
 take a provider handle and a session ID as their first two arguments; they
 are crypto_mac_prov(), crypto_mac_init_prov(), and crypto_mac_verify_prov().
 Rather than letting the framework pick the best provider for a specified
 mechanism, these three functions are used when a session has been established
 to a particular provider by calling crypto_get_provider()
 and crypto_session_open().
 
 
 Signature Generation and Verification
 --------------------------------------
 A signature is different from MAC in that it offers non-repudiation.
 The private key in the public key/private key key pair is used for
 signing and the public key is used for verification.
 
 Examples of mechanism types are CKM_MD5_RSA_PKCS, CKM_SHA1_RSA_PKCS.
 
 The signature can be computed in a single step:
 int crypto_sign(crypto_mechanism_t *mech,	/* mechanism		*/
     crypto_key_t       *key,			/* Private key 		*/
     crypto_data_t      *data,			/* data to be signed	*/
     crypto_ctx_template_t tmpl,			/* context template     */
     crypto_data_t      *signature,		/* output buffer	*/
     crypto_call_req_t  *crq)			/* Call req conditions  */
 
 Or in multiple parts, init-updates-final:
 int crypto_sign_init(crypto_mechanism_t *mech,	/* mechanism                */
     crypto_key_t       *key,			/* public key	            */	
     crypto_ctx_template_t tmpl,			/* context template         */
     crypto_context_t   *ctxp,			/* store for context handle */
     crypto_call_req_t  *crq)			/* Call req conditions      */
 
 *ctxp is allocated and initialized by this routine, and will be used for next
 operations (consolidation-private).
 
 int crypto_sign_update(crypto_context_t context, /* from crypto_sign_init() */
     crypto_data_t      *data,			/* data to be signed       */
     crypto_call_req_t  *cr)			/* Call req conditions     */
 
 int crypto_sign_final(crypto_context_t context,
     crypto_data_t      *signature,		/* output buffer */
     crypto_call_req_t  *cr)
 
 crypto_sign_final() internally destroys the crypto_context_t ctx, so the
 consumer code must not refer to it after that function returns.
 
 crypto_sign() and crypto_sign_init() have variants that take a provider handle
 and a session ID as their first two arguments; they are crypto_sign_prov() and
 crypto_sign_init_prov(). Rather than letting the framework pick the best
 provider for a specified mechanism, these two functions are used when a
 session has been established to a particular provider by calling
 crypto_get_provider() and crypto_session_open().
 
 The verify() routines follow the same model except that the signature
 argument is an input argument and the key used is the public key.
 
 There are two single step routines which offer recovery of data from the
 signature:
 /* Same as crypto_sign() above */
 int crypto_sign_recover(crypto_mechanism_t *mech, /* mechanism		*/
     crypto_key_t       *key,			/* public key		*/
     crypto_data_t      *data,			/* data to be signed	*/
     crypto_ctx_template_t tmpl,			/* context template	*/
     crypto_data_t      *signature,		/* output buffer	*/
     crypto_call_req_t  *crq)			/* Call req conditions	*/
 
 int crypto_verify_recover(crypto_mechanism_t *mech,
     crypto_key_t       *key,
     crypto_data_t      *signature,	/* Input signature */
     crypto_ctx_template_t tmpl,
     crypto_data_t      *data,		/* output data to be recovered */
     crypto_call_req_t  *crq)
 
 Like the signing and verification routines, these two routines have
 variants that take a provider handle and a session ID as their first
 two arguments; they are crypto_sign_recover_prov() and
 crypto_verify_recover_prov().
 
 
 Encryption
 ----------
 The following routines are for encryption and decryption of single and
 multiple part operations.
 When the pointer to the output crypto_data_t is NULL (ciphertext for
 encryption operations and cleartext for decryption operations),
 it is an indication that the transformation needs to be done in-place.
 When the 2 pointers are different, they must not overlap.
 
 
 int crypto_encrypt(crypto_mechanism_t *mech,	/* mechanism              */
     crypto_data_t      *pt,			/* plaintext		  */
     crypto_key_t       *key,			/* Encryption key	  */
     crypto_ctx_template_t tmpl,			/* context template 	  */
     crypto_data_t      *ct,			/* storage for ciphertext */
     crypto_call_req_t  *cr)			/* Call req conditions	  */
 
 int crypto_encrypt_init(crypto_mechanism_t *mech, /* mechanism 		    */
     crypto_key_t       *key,			/* Encryption key	    */
     crypto_ctx_template_t tmpl,			/* context template 	    */
     crypto_context_t   *ctxp,			/* store for context handle */
     crypto_call_req_t  *cr)			/* Call req conditions      */
 
 Examples of mechanism types are CKM_AES_CBC, CKM_DES_ECB, etc ...
 Using the PKCS#11 convention, the initialization vector for CBC modes
 of symmetric ciphers is a parameter passed in the crypto_mechanism_t.
 
 Note that the framework does not check for weak keys. It is up to the
 plugged-in providers to fail the call to their _encrypt_init() entry point
 if they chose to enforce the checking for weak keys.
 
 *ctxp is allocated and initialized by this routine, and will be used for next
 operations.
 
 int crypto_encrypt_update(crypto_context_t *ctx, /* Allocated by encrypt_init */
     crypto_data_t      *pt,			/* plaintext	              */
     crypto_data_t      *ct,			/* storage for ciphertext     */
     crypto_call_req_t  *cr)			/* Call req conditions	      */
 	
 int crypto_encrypt_final(crypto_context_t *ctx,
     crypto_data_t      *ct,			/* last CT's piece	  */
     crypto_call_req_t  *cr)			/* Call req conditions	  */
 
 The second argument above, ct, is a storage for the encryption of the
 last pending piece of plaintext residual from previous updates, because
 of block size constraints for the mechanism. The necessary padding are added,
 and the encryption of the last padded block is put in the ct.
 
 crypto_encrypt_final() internally destroys the crypto_context_t ctx, so
 the consumer code must not refer to it after that function returns.
 
 crypto_encrypt() and crypto_encrypt_init() have variants that take a
 provider handle and a session ID as their first two arguments; they are
 crypto_encrypt_prov() and crypto_encrypt_init_prov(). Rather than letting
 the framework pick the best provider for a specified mechanism, these two
 functions are used when a session has been established to a particular
 provider by calling crypto_get_provider() and crypto_session_open().
 
 int crypto_decrypt(crypto_mechanism_t *mech,    /* mechanism              */
     crypto_data_t      *ct,			/* ciphertext	   	  */
     crypto_key_t       *key,			/* Decryption key	  */
     crypto_ctx_template_t tmpl,			/* context template 	  */
     crypto_data_t      *pt,			/* store for plaintext    */
     crypto_call_req_t  *cr)			/* Call req conditions	  */
 
 int crypto_decrypt_init(crypto_mechanism_t *mech, /* mechanism 		    */
     crypto_key_t       *key,			/* Decryption key	    */
     crypto_ctx_template_t tmpl,			/* context template 	    */
     crypto_context_t   *ctxp,			/* store for context handle */
     crypto_call_req_t  *cr)			/* Call req conditions      */
 
 Examples of mechanism types are CKM_AES128_CBC, CKM_DES_ECB, etc ...
 Using the PKCS#11 convention, the initialization vector for CBC modes
 of symmetric ciphers is a parameter passed in the crypto_mechanism_t.
 
 *ctxp is allocated and initialized by this routine, and will be used for next
 operations.
 
 int crypto_decrypt_update(crypto_context_t ctx,	/* Allocated by decrypt_init */
     crypto_data_t      *ct,			/* ciphertext		     */
     crypto_data_t      *pt,			/* store for plaintext       */
     crypto_call_req_t  *cr)			/* Call req conditions	     */
 	
 int crypto_decrypt_final(crypto_context_t ctx,
     crypto_data_t      *pt,			/* last PT's piece	  */
     crypto_call_req_t  *cr)			/* Call req conditions	  */
 
 The second argument above, pt, is a storage for the decryption of the
 last pending piece of ciphertext residual from previous updates, because
 of block size constraints for the mechanism. The necessary padding are added,
 and the decryption of the last padded block is put in the pt.
 
 crypto_decrypt_final() internally destroys the crypto_context_t ctx, so
 the consumer code must not refer to it after that function returns.
 
 Like the encryption routines, the decryption routines have variants that
 take a provider handle and a session ID as their first two arguments;
 they are crypto_decrypt_prov() and crypto_decrypt_init_prov().
 
 
 Dual-operation routines
 -----------------------
 Two sets of dual operation routines are offered, for combined encryption & MAC
 and MAC & decryption.
 
 int
 crypto_encrypt_mac(crypto_mechanism_t *encr_mech, /* encryption mechanism  */
     crypto_mechanism_t *mac_mech,		/* MAC mechanism   	  */
     crypto_data_t      *pt,			/* input data		  */
     crypto_key_t       *encr_key,		/* Encryption key	  */
     crypto_key_t       *mac_key,		/* MAC key	  	  */
     crypto_ctx_template_t encr_tmpl,		/* Encr. context template */
     crypto_ctx_template_t mac_tmpl,		/* MAC context template   */
     crypto_dual_data_t *ct,			/* storage for ciphertext */
     crypto_data_t      *mac,			/* storage for the MAC    */
     crypto_call_req_t  *cr)			/* Call req conditions	  */
 
 int
 crypto_encrypt_mac_init(crypto_mechanism_t *encr_mech, /* encryption mech */
     crypto_mechanism_t *mac_mech,      		/* MAC mechanism   	  */
     crypto_key_t       *encr_key,		/* Encryption key	  */
     crypto_key_t       *mac_key,		/* MAC key	  	  */
     crypto_ctx_template_t encr_tmpl,		/* Encr. context template */
     crypto_ctx_template_t mac_tmpl,		/* MAC context template   */
     crypto_context_t   *ctxp,			/* store for context handle */
     crypto_call_req_t  *cr)			/* Call req conditions	  */
 
 int
 crypto_encrypt_mac_update(crypto_context_t ctx, /* Allocated above	  */
     crypto_data_t      *pt,			/* input data		  */
     crypto_dual_data_t *ct,			/* storage for ciphertext */
     crypto_call_req_t  *cr)			/* Call req conditions	  */
 
 The MAC is computed on the result of the encryption.
 It covers the portion of data in the 'ct' argument starting at dd_offset2,
 for a length of dd_len2.
 A crypto_dual_data is needed because the MAC may cover portions of the
 messages not to be encrypted.
 A NULL 'pt' (plaintext) pointer indicates an in-place encryption.
 in that case, the input plaintext should be passed in the 'ct' argument.
 The crypto_context internally carries both states of the encryption and the MAC.
 
 int
 crypto_encrypt_mac_final(crypto_context_t ctx,	/* Allocated above	    */
     crypto_dua_data_t  *ct,			/* last CT's piece	    */
     crypto_data_t      *mac,			/* storage for the MAC      */
     crypto_call_req_t  *cr)			/* Call req conditions	    */
 	
 
 Although consumers of software providers usually find it more interesting
 to first validate the MAC before spending the resources on decryption,
 the dual MAC & Decrypt routines can be found useful with hardware providers
 offering this combination.
 
 crypto_encrypt_mac() and crypto_encrypt_mac_init() have variants that take
 a provider handle and a session ID as their first two arguments; they are
 crypto_encrypt_mac_prov() and crypto_encrypt_mac_init_prov(). Rather than
 letting the framework pick the best provider for a specified mechanism,
 these two functions are used when a session has been established to a
 particular provider by calling crypto_get_provider() and
 crypto_session_open().
 
 The consumer can call crypto_get_mech_list() to retrieve the list of
 mechanisms currently supported by the providers registered with the
 framework.
 
 int
 crypto_mac_decrypt(crypto_mechanism_t *mac_mech, /* MAC mechanism	  */
     crypto_mechanism_t *decr_mech,      	/* Decryption mechanism   */
     crypto_dual_data_t *ct,			/* input dual data	  */
     crypto_key_t       *mac_key,		/* MAC key	  	  */
     crypto_key_t       *decr_key,		/* Decryption key	  */
     crypto_ctx_template_t mac_tmpl,		/* MAC context template   */
     crypto_ctx_template_t decr_tmpl,		/* Decr. context template */
     crypto_data_t      *mac,			/* storage for the MAC    */
     crypto_data_t      *pt,			/* storage for plaintext  */
     crypto_call_req_t  *cr)			/* Call req conditions	  */
 
 int
 crypto_mac_decrypt_init(crypto_mechanism_t *mac_mech, /* MAC mechanism	    */
     crypto_mechanism_t *decr_mech,      	/* Decryption mechanism     */
     crypto_ctx_template_t mac_tmpl,		/* MAC context template     */
     crypto_ctx_template_t decr_tmpl,		/* Decr. context template   */
     crypto_context_t   **ctxp,			/* store for context handle */
     crypto_call_req_t  *cr)			/* Call req conditions	    */
 
 int
 crypto_mac_decrypt_update(crypto_context_t *ctx, /* Allocated above	    */
     crypto_dual_data_t *ct,			/* ciphertext	            */
     crypto_data_t      *pt,			/* storage for plaintext    */
     crypto_call_req_t  *cr)			/* Call req conditions	    */
 
 The MAC is computed on the ciphertext before decryption. The crypto_context
 internally carries both states of the MAC and the decryption.
 A crypto_dual_data is needed because the MAC may cover portions of the
 messages not to be decrypted.
 
 int
 crypto_mac_decrypt_final(crypto_context_t *ctx,	/* Allocated above	    */
     crypto_data_t      *mac,			/* storage for the MAC      */
     crypto_data_t      *pt,			/* last PT's piece	    */
     crypto_call_req_t  *cr)			/* Call req conditions	    */
 
 crypto_mac_verify_decrypt(), instead of returning the computed MAC, compares
 the value of the computed MAC with the expected value of the MAC passed
 as argument. If these values don't match, this function returns
 CRYPTO_INVALID_MAC and the decryption operation is not performed.
 
 int
 crypto_mac_verify_decrypt(crypto_mechanism_t *mac_mech, /* MAC mechanism  */
     crypto_mechanism_t *decr_mech,      	/* Decryption mechanism   */
     crypto_dual_data_t *ct,			/* input dual data	  */
     crypto_key_t       *mac_key,		/* MAC key	  	  */
     crypto_key_t       *decr_key,		/* Decryption key	  */
     crypto_ctx_template_t mac_tmpl,		/* MAC context template   */
     crypto_ctx_template_t decr_tmpl,		/* Decr. context template */
     crypto_data_t      *mac,			/* expected MAC           */
     crypto_data_t      *pt,			/* storage for plaintext  */
     crypto_call_req_t  *cr)			/* Call req conditions	  */
 
 crypto_mac_decrypt(), crypto_mac_decrypt_init(), and
 crypto_mac_verify_decrypt() have variants that take a provider handle and a
 session ID as their first two arguments; they are crypto_mac_decrypt_prov(),
 crypto_mac_decrypt_init_prov(), and crypto_mac_verify_decrypt_prov().
 Rather than letting the framework pick the best provider for a specified
 mechanism, these two functions are used when a session has been established
 to a particular provider by calling crypto_get_provider() and
 crypto_session_open().
 
 Requests management
 -------------------
 
 crypto_req_t is the opaque handle retrieved from the crypto_call_cond passed
 to a successfully submitted asynchronous call. (cr->cr_req)
 
 To cancel the request:
 
 void
 crypto_cancel_req(crypto_req_t req)
 
 When several requests for the same context are pending, the consumer may
 Wish to cancel them together by calling:
 
 crypto_cancel_ctx(crypto_context_t ctx)
 
 All the crypto_req_t handles for pending requests under that context will be
 canceled.  Also, the crypto_context_t ctx will be destroyed, so
 the consumer code must not refer to it after this function returns.
 
 A client should call crypto_cancel_ctx() if in a mult-part operation
 (init-updates-final), an intermediate step fails and the client wants
 to exit the operation.  This is required as a client can potentially retry
 the intermediate step (e.g. It got a CRYPTO_BUSY) or it can continue
 with the next step (e.g. ECB mode for a block cipher. Each block can be
 independent and the client may not care about failure in one block).
 
 After a request is canceled (either individually or with a context), the
 callback function will not be called.
 
 
 bufcall functions
 -----------------
 
 crypto_bc_t is defined as an opaque handle.
 
 crypto_bc_t crypto_bufcall_alloc();
 A blocking function that allocates a crypto_bufcall handle, valid
 for later use by crypto_bufcall(). It is typically called in a cb_open()
 entry point.
 
 int crypto_bufcall(bc_handle, func, arg);
 When called with a valid and not in use crypto_bufcall handle, crypto_bufcall()
 crypto_bufcall() schedules (*func)(arg) to be called, later, when it is
 possible to submit asynchronous crypto requests.
 
 int crypto_unbufcall(crypto_bc_t bc_handle);
 This routine cancels a previous call crypto_bufcall(). 'bc_handle' becomes
 becomes a valid for other calls to crypto_bufcall() again.
 Typically, a kernel module's cb_close() entry point must call
 crypto_unbufcall() for all the pending crypto bufcalls.
 
 int crypto_bufcall_free(bc_handle)
 This routine releases the crypto_bufcall handle allocated by
 crypto_bufcall_alloc();
 This routine must be called by a kernel module before is unloads.
 
 Internal framework's events notification
 ----------------------------------------
 An internal Solaris client only may call the following functions:
 
 crypto_mech_name_t *crypto_get_mech_list(uint_t *count, int kmflag);
 
 To obtain a list of the mechanisms supported by the providers currently
 registered with the framework.
 
 void crypto_free_mech_list(crypto_mech_name_t *mech_names, uint_t count);
 
 To free a list of mechanisms previously allocated by crypto_get_mech_list().
 
 typedef void *crypto_notify_handle_t;
 typedef void (*crypto_notify_callback_t)(uint32_t event,
 	void *event_arg);
 crypto_notify_handle_t crypto_notify_events(crypto_notify_callback_t *nf,
 	uint32_t event_mask)
 
 This routine signs-up the caller for a notification when any of the events
 specified by event_mask occurs.
 In this release, we define one event:
 
 #define CRYPTO_EVENT_PROVIDERS_CHANGE
 
 the framework will call the specified callback function whenever the
 event happens. Details on event argument that is passed to a callback
 function are available in the crypto_notify_events(9F) man page.
 
 Clients that sign-up for such a service must sign-off before getting unloaded,
 by calling
 void crypto_unnotify_events(crypto_notify_handle_t)
 
 Session Management
 ------------------
 
 crypto_session_open() and crypto_session_close() open and close sessions
 to specific providers.
 
 int crypto_session_open(crypto_provider_t provider, /* Provider handle   */
     crypto_session_id_t *sidp,			/* Pointer to session ID */
     crypto_call_req_t   *cr)			/* Call req conditions   */
  
 int crypto_session_close(crypto_provider_t provider,
     crypto_session_id_t sid,			/* Session ID          */
     crypto_call_req_t   *cr)			/* Call req conditions */
 
 crypto_session_login() changes the state of a session to authenticated,
 and crypto_session_logout() changes it back to unauthenticated.
 
 int crypto_session_login(crypto_provider_t provider,
     crypto_session_id_t sid,			/* Session ID               */
     crypto_user_type_t  type,			/* CRYPTO_SO or CRYPTO_USER */
     char		*pin,			/* Pin                      */
     ulong_t		len,			/* Pin length               */
     crypto_call_req_t   *cr)			/* Call req conditions      */
  
 int crypto_session_logout(crypto_provider_t provider,
     crypto_session_id_t sid,			/* Session ID          */
     crypto_call_req_t   *cr)			/* Call req conditions */
 
 Object Management
 -----------------
 These routines are used to create, copy, and find objects. They are also
 used to set the properties of objects. Most of these objects take an
 array of attributes as an argument which is described in
 crypto_object_attribute(9S).
 
 int crypto_object_create(crypto_provider_t provider,
     crypto_session_id_t sid,			/* Session ID               */
     crypto_object_attribute_t *attrs,		/* Array of attributes      */
     uint_t		count,			/* Number of attributes     */
     crypto_object_id_t  *object_handle,		/* Pointer to object handle */
     crypto_call_req_t   *cr)			/* Call req conditions      */
 
 int crypto_object_destroy(crypto_provider_t provider,
     crypto_session_id_t sid,			/* Session ID          */
     crypto_object_id_t	object_handle,		/* Object handle       */
     crypto_call_req_t   *cr)			/* Call req conditions */
 
 int crypto_object_copy(crypto_provider_t provider,
     crypto_session_id_t sid,			/* Session ID            */
     crypto_object_id_t	object_handle,		/* Object handle         */
     crypto_object_attribute_t *attrs,		/* Array of attributes   */
     uint_t		count,			/* Number of attributes  */
     crypto_object_id_t	*new_handle,		/* Pointer to new handle */
     crypto_call_req_t   *cr)			/* Call req conditions   */
 
 int crypto_object_get_attribute_value(crypto_provider_t provider,
     crypto_session_id_t sid,			/* Session ID           */
     crypto_object_id_t	object_handle,		/* Object handle        */
     crypto_object_attribute_t *attrs,		/* Array of attributes  */
     uint_t		count,			/* Number of attributes */
     crypto_call_req_t   *cr)			/* Call req conditions  */
 
 int crypto_object_set_attribute_value(crypto_provider_t provider,
     crypto_session_id_t sid,			/* Session ID           */
     crypto_object_id_t	object_handle,		/* Object handle        */
     crypto_object_attribute_t *attrs,		/* Array of attributes  */
     uint_t		count,			/* Number of attributes */
     crypto_call_req_t   *cr)			/* Call req conditions  */
 
 int crypto_object_get_size(crypto_provider_t provider,
     crypto_session_id_t sid,			/* Session ID          */
     crypto_object_id_t object_handle,		/* Object handle       */
     size_t		*size,			/* Pointer to size     */
     crypto_call_req_t   *cr)			/* Call req conditions */
 
 The following three functions are used to find objects that match attributes
 specified by crypto_object_find_init(). Typically, the object handles of
 all matched objects are stored interally by crypto_object_find_init()
 and returned in subsequent calls to crypto_object_find().
 
 int crypto_object_find_init(crypto_provider_t provider,
     crypto_session_id_t sid,			/* Session ID          */
     crypto_object_attribute_t *attrs,		/* Array of attributes */
     uint_t count, void **cookie,		/* Pointer to cookie   */
     crypto_call_req_t   *cr)			/* Call req conditions */
 
 int crypto_object_find_init(crypto_provider_t provider,
     crypto_session_id_t sid,			/* Session ID                */
     crypto_object_attribute_t *attrs,		/* Array of attributes       */
     uint_t count, void **cookie,		/* Pointer to cookie pointer */
     crypto_call_req_t   *cr)			/* Call req conditions       */
 
 int crypto_object_find_final(crypto_provider_t provider,
     void		*cookie,		/* Pointer to cookie   */
     crypto_call_req_t	*cr)			/* Call req conditions */
 
 Key Management
 --------------
 
 These operations are used to generate keys, wrap/unwrap keys, and derive
 a new key from an existing key. In all cases, there has to be an open
 session to a provider.
 
 The following function generates symmetric keys:
 
 int crypto_key_generate(crypto_provider_t provider,
     crypto_session_id_t sid,			/* Session ID           */
     crypto_mechanism_t *mech,			/* Mechanism            */
     crypto_object_attribute_t *attrs,		/* Array of attributes  */
     uint_t count,				/* Number of attributes */
     crypto_object_id_t *handle,			/* Pointer to new key   */
     crypto_call_req_t	*cr)			/* Call req conditions  */
 
 The following function generates asymmetric public/private key pairs:
 
 int crypto_key_generate_pair(crypto_provider_t provider,
     crypto_session_id_t sid,			/* Session ID             */
     crypto_mechanism_t *mech,			/* Mechanism              */
     crypto_object_attribute_t *pub_attrs,	/* Array of attributes    */
     uint_t pub_count,				/* Number of attributes   */
     crypto_object_attribute_t *pri_attrs,	/* Array of attributes    */
     uint_t pri_count,				/* Number of attributes   */
     crypto_object_id_t *pub_handle,		/* Pointer to public key  */
     crypto_object_id_t *pri_handle,		/* Pointer to private key */
     crypto_call_req_t	*cr)			/* Call req conditions    */
 
 The following function will encrypt a key with another key and store
 the result, including the key's attributes, in a buffer. The contents
 of the buffer is called the wrapped key.
 
 int crypto_key_wrap(crypto_provider_t provider,
     crypto_session_id_t	sid,			/* Session ID              */
     crypto_mechanism_t	*mech,			/* Mechanism               */
     crypto_key_t	*wrapping_key,		/* Pointer to wrapping key */
     crypto_object_id_t	*key,			/* Object (key) to wrap    */
     uchar_t		*wrapped_key,		/* Buffer for wrapped key  */
     size_t		*wrapped_key_len,	/* Length of buffer        */
     crypto_call_req_t	*cr)			/* Call req conditions     */
 
 Wrapped keys are unwrapped with the following function:
 
 int crypto_key_unwrap(crypto_provider_t provider,
     crypto_session_id_t	sid,			/* Session ID                */
     crypto_mechanism_t	*mech,			/* Mechanism                 */
     crypto_key_t	*unwrapping_key,	/* Pointer to unwrapping key */
     uchar_t		*wrapped_key,		/* Buffer with wrapped key   */
     size_t		*wrapped_key_len,	/* Length of buffer          */
     crypto_object_attribute_t *attrs,		/* Array of attributes       */
     uint_t count,				/* Number of attributes      */
     crypto_object_id_t *key,			/* Object (unwrapped key)    */
     crypto_call_req_t	*cr)			/* Call req conditions       */
 
 crypto_key_derive() derives a new key from an existing key.
 
 int crypto_key_derive(crypto_provider_t provider,
     crypto_session_id_t sid,			/* Session ID           */
     crypto_mechanism_t *mech,			/* Mechanism            */
     crypto_key_t *base_key,			/* Existing key         */
     crypto_object_attribute_t *attrs,		/* Array of attributes  */
     uint_t count,				/* Number of attributes */
     crypto_object_id_t *new_key,		/* New key              */
     crypto_call_req_t	*cr)			/* Call req conditions  */
 
 Finally, some keys are known to be weak, and some providers have an entry
 point for detecting weak keys. Providers that support this check must not
 queue the request for later execution. Only keys by value are supported.
 
 int crypto_key_check_prov(crypto_provider_t provider,
     crypto_mechanism_t *mech,			/* Mechanism */
     crypto_key_t *key)				/* Key       */
 
 
 References:
 ==========
 [PKCS11]
 	/net/sac.eng/export/sac/PSARC/2001/488/incept.materials/pkcs11v2-11.pdf
 
 [Schneier]
 	Applied Cryptography, Bruce Schneier.  Wiley, 1998 ISBN: 0471117099
 
