/*
 * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
 */

/*
 * The code contained herein is licensed under the GNU General Public
 * License. You may obtain a copy of the GNU General Public License
 * Version 2 or later at the following locations:
 *
 * http://www.opensource.org/licenses/gpl-license.html
 * http://www.gnu.org/copyleft/gpl.html
 */


#ifndef FSL_SHW_KEYSTORE_H
#define FSL_SHW_KEYSTORE_H

/*!
 * @file fsl_shw_keystore.h
 *
 * @brief Definition of the User Keystore API.
 *
 */

/*! \page user_keystore User Keystore API
 *
 * Definition of the User Keystore API.
 *
 * On platforms with multiple partitions of Secure Memory, the Keystore Object 
 * (#fsl_shw_kso_t) is provided to allow users to manage a private keystore for
 * use in software cryptographic routines.  The user can define a custom set of
 * methods for managing their keystore, or use a default keystore handler.  The
 * keystore is established by #fsl_shw_establish_keystore(), and released by
 * #fsl_shw_release_keystore().  The intent of this design is to make the
 * keystore implementation as flexible as possible.
 *
 * See @ref keystore_api for the generic keystore API, and @ref
 * default_keystore for the default keystore implementation.
 *
 */

/*!
 * @defgroup keystore_api User Keystore API
 *
 * Keystore API
 *
 * These functions define the generic keystore API, which can be used in 
 * conjunction with a keystore implementation backend to support a user
 * keystore.
 */

/*!
 * @defgroup default_keystore Default Keystore Implementation
 *
 * Default Keystore Implementation
 *
 * These functions define the default keystore implementation, which is used
 * for the system keystore and for user keystores initialized by 
 * #fsl_shw_init_keystore_default().  They can be used as-is or as a reference
 * for creating a custom keystore handler.  It uses an entire Secure Memory
 * partition, divided in to equal slots of length #KEYSTORE_SLOT_SIZE.  These
 * functions are not intended to be used directly-  all user interaction with
 * the keystore should be through the @ref keystore_api and the Wrapped Key
 * interface.
 *
 * The current implementation is designed to work with both SCC and SCC2.
 * Differences between the two versions are noted below.
 */

/*! @addtogroup keystore_api
    @{ */

#ifndef KEYSTORE_SLOT_SIZE
/*! Size of each key slot, in octets.  This sets an upper bound on the size
 * of a key that can placed in the keystore.
 */
#define KEYSTORE_SLOT_SIZE 32
#endif

/*!
 * Initialize a Keystore Object.
 *
 * This function must be called before performing any other operation with the
 * Object. It allows the user to associate a custom keystore interface by
 * specifying the correct set of functions that will be used to perform actions
 * on the keystore object.  To use the default keystore handler, the function
 * #fsl_shw_init_keystore_default() can be used instead.
 *
 * @param keystore      The Keystore object to operate on.
 * @param data_init     Keystore initialization function.  This function is
 *                      responsible for initializing the keystore.  A
 *                      user-defined object can be assigned to the user_data
 *                      pointer, and will be passed to any function acting on
 *                      that keystore.  It is called during
 *                      #fsl_shw_establish_keystore().
 * @param data_cleanup  Keystore cleanup function.  This function cleans up
 *                      any data structures associated with the keyboard.  It
 *                      is called by #fsl_shw_release_keystore().
 * @param slot_alloc    Slot allocation function.  This function allocates a
 *                      key slot, potentially based on size and owner id.  It
 *                      is called by #fsl_shw_establish_key().
 * @param slot_dealloc  Slot deallocation function.
 * @param slot_verify_access Function to verify that a given Owner ID
 *                           credential matches the given slot.
 * @param slot_get_address   For SCC2: Get the virtual address (kernel or
 *                           userspace) of the data stored in the slot.
 *                           For SCC: Get the physical address of the data
 *                           stored in the slot.
 * @param slot_get_base      For SCC2: Get the (virtual) base address of the
 *                           partition that the slot is located on.
 *                           For SCC: Not implemented.
 * @param slot_get_offset    For SCC2: Get the offset from the start of the
 *                           partition that the slot data is located at (in
 *                           octets)
 *                           For SCC: Not implemented.
 * @param slot_get_slot_size Get the size of the key slot, in octets.
 */
extern void fsl_shw_init_keystore(fsl_shw_kso_t * keystore,
				  fsl_shw_return_t(*data_init) (fsl_shw_uco_t *
								user_ctx,
								void
								**user_data),
				  void (*data_cleanup) (fsl_shw_uco_t *
							user_ctx,
							void **user_data),
				  fsl_shw_return_t(*slot_alloc) (void
								 *user_data,
								 uint32_t size,
								 uint64_t
								 owner_id,
								 uint32_t *
								 slot),
				  fsl_shw_return_t(*slot_dealloc) (void
								   *user_data,
								   uint64_t
								   owner_id,
								   uint32_t
								   slot),
				  fsl_shw_return_t(*slot_verify_access) (void
									 *user_data,
									 uint64_t
									 owner_id,
									 uint32_t
									 slot),
				  void *(*slot_get_address) (void *user_data,
							     uint32_t handle),
				  uint32_t(*slot_get_base) (void *user_data,
							    uint32_t handle),
				  uint32_t(*slot_get_offset) (void *user_data,
							      uint32_t handle),
				  uint32_t(*slot_get_slot_size) (void
								 *user_data,
								 uint32_t
								 handle));

/*!
 * Initialize a Keystore Object.
 *
 * This function must be called before performing any other operation with the
 * Object. It sets the user keystore object up to use the default keystore
 * handler.  If a custom keystore handler is desired, the function
 * #fsl_shw_init_keystore() can be used instead.
 *
 * @param keystore      The Keystore object to operate on.
 */
extern void fsl_shw_init_keystore_default(fsl_shw_kso_t * keystore);

/*!
 * Establish a Keystore Object.
 *
 * This function establishes a keystore object that has been set up by a call
 * to #fsl_shw_init_keystore().  It is a wrapper for the user-defined
 * data_init() function, which is specified during keystore initialization.
 *
 * @param user_ctx      The user context that this keystore should be attached
 *                      to
 * @param keystore      The Keystore object to operate on.
 *
 * @return    A return code of type #fsl_shw_return_t.
 */
extern fsl_shw_return_t fsl_shw_establish_keystore(fsl_shw_uco_t * user_ctx,
						   fsl_shw_kso_t * keystore);

/*!
 * Release a Keystore Object.
 *
 * This function releases an established keystore object.  It is a wrapper for
 * the user-defined data_cleanup() function, which is specified during keystore
 * initialization.
 *
 * @param user_ctx      The user context that this keystore should be attached
 *                      to.
 * @param keystore      The Keystore object to operate on.
 */
extern void fsl_shw_release_keystore(fsl_shw_uco_t * user_ctx,
				     fsl_shw_kso_t * keystore);

/*!
 * Allocate a slot in the Keystore.
 *
 * This function attempts to allocate a slot to hold a key in the keystore.  It
 * is called by #fsl_shw_establish_key() when establishing a Secure Key Object,
 * if the key has been flagged to be stored in a user keystore by the
 * #fsl_shw_sko_set_keystore() function.  It is a wrapper for the
 * implementation-specific function slot_alloc().
 *
 * @param keystore      The Keystore object to operate on.
 * @param[in] size      Size of the key to be stored (octets).
 * @param[in] owner_id  ID of the key owner.
 * @param[out] slot     If successful, assigned slot ID
 *
 * @return    A return code of type #fsl_shw_return_t.
 */
extern fsl_shw_return_t keystore_slot_alloc(fsl_shw_kso_t * keystore,
					    uint32_t size,
					    uint64_t owner_id, uint32_t * slot);

/*!
 * Deallocate a slot in the Keystore.
 *
 * This function attempts to allocate a slot to hold a key in the keystore.
 * It is called by #fsl_shw_extract_key() and #fsl_shw_release_key() when the
 * key that it contains is to be released.  It is a wrapper for the
 * implmentation-specific function slot_dealloc().
 
 * @param keystore      The Keystore object to operate on.
 * @param[in] owner_id  ID of the key owner.
 * @param[in] slot     If successful, assigned slot ID.
 *
 * @return    A return code of type #fsl_shw_return_t.
 */
extern fsl_shw_return_t keystore_slot_dealloc(fsl_shw_kso_t * keystore,
					      uint64_t owner_id, uint32_t slot);

/*!
 * Load cleartext key data into a key slot
 *
 * This function loads a key slot with cleartext data.
 *
 * @param keystore      The Keystore object to operate on.
 * @param[in] owner_id  ID of the key owner.
 * @param[in] slot      If successful, assigned slot ID.
 * @param[in] key_data  Pointer to the location of the cleartext key data.
 * @param[in] key_length Length of the key data (octets).
 *
 * @return    A return code of type #fsl_shw_return_t.
 */
extern fsl_shw_return_t
keystore_slot_load(fsl_shw_kso_t * keystore, uint64_t owner_id, uint32_t slot,
		   const uint8_t * key_data, uint32_t key_length);

/*!
 * Read cleartext key data from a key slot
 *
 * This function returns the key in a key slot.
 *
 * @param keystore      The Keystore object to operate on.
 * @param[in]  owner_id   ID of the key owner.
 * @param[in]  slot       ID of slot where key resides.
 * @param[in]  key_length Length of the key data (octets).
 * @param[out] key_data   Pointer to the location of the cleartext key data.
 *
 * @return    A return code of type #fsl_shw_return_t.
 */
extern fsl_shw_return_t
keystore_slot_read(fsl_shw_kso_t * keystore, uint64_t owner_id, uint32_t slot,
		   uint32_t key_length, uint8_t * key_data);

/*!
 * Encrypt a keyslot
 *
 * This function encrypts a key using the hardware secret key.
 *
 * @param user_ctx      User context
 * @param keystore      The Keystore object to operate on.
 * @param[in] owner_id  ID of the key owner.
 * @param[in] slot      Slot ID of the key to encrypt.
 * @param[in] length    Length of the key
 * @param[out] destination  Pointer to the location where the encrypted data
 *                          is to be stored.
 *
 * @return    A return code of type #fsl_shw_return_t.
 */
extern fsl_shw_return_t
keystore_slot_encrypt(fsl_shw_uco_t * user_ctx,
		      fsl_shw_kso_t * keystore, uint64_t owner_id,
		      uint32_t slot, uint32_t length, uint8_t * destination);

/*!
 * Decrypt a keyslot
 *
 * This function decrypts a key using the hardware secret key.
 *
 * @param user_ctx      User context
 * @param keystore      The Keystore object to operate on.
 * @param[in] owner_id  ID of the key owner.
 * @param[in] slot      Slot ID of the key to encrypt.
 * @param[in] length    Length of the key
 * @param[in] source    Pointer to the location where the encrypted data
 *                      is stored.
 *
 * @return    A return code of type #fsl_shw_return_t.
 */
extern fsl_shw_return_t
keystore_slot_decrypt(fsl_shw_uco_t * user_ctx,
		      fsl_shw_kso_t * keystore, uint64_t owner_id,
		      uint32_t slot, uint32_t length, const uint8_t * source);

/* @} */

/*! @addtogroup default_keystore
    @{ */

/*!
 * Data structure to hold per-slot information
 */
typedef struct keystore_data_slot_info_t {
	uint8_t allocated;	/*!< Track slot assignments */
	uint64_t owner;		/*!< Owner IDs */
	uint32_t key_length;	/*!< Size of the key */
} keystore_data_slot_info_t;

/*!
 * Data structure to hold keystore information.
 */
typedef struct keystore_data_t {
	void *base_address;	/*!< Base of the Secure Partition */
	uint32_t slot_count;	/*!< Number of slots in the keystore */
	struct keystore_data_slot_info_t *slot;	/*!< Per-slot information */
} keystore_data_t;

/*!
 * Default keystore initialization routine.
 *
 * This function acquires a Secure Partition Object to store the keystore,
 * divides it into slots of length #KEYSTORE_SLOT_SIZE, and builds a data
 * structure to hold key information.
 *
 * @param user_ctx       User context
 * @param[out] user_data Pointer to the location where the keystore data
 *                       structure is to be stored.
 *
 * @return    A return code of type #fsl_shw_return_t.
 */
fsl_shw_return_t shw_kso_init_data(fsl_shw_uco_t * user_ctx, void **user_data);

/*!
 * Default keystore cleanup routine.
 *
 * This function releases the Secure Partition Object and the memory holding
 * the keystore data structure, that obtained by the shw_kso_init_data
 * function. 
 *
 * @param user_ctx          User context
 * @param[in,out] user_data Pointer to the location where the keystore data
 *                          structure is stored.
 */
void shw_kso_cleanup_data(fsl_shw_uco_t * user_ctx, void **user_data);

/*!
 * Default keystore slot access verification
 *
 * This function compares the supplied Owner ID to the registered owner of
 * the key slot, to see if the supplied ID is correct.
 *
 * @param[in] user_data Pointer to the location where the keystore data
 *                      structure stored.
 * @param[in] owner_id  Owner ID supplied as a credential.
 * @param[in] slot      Requested slot
 *
 * @return    A return code of type #fsl_shw_return_t.
 */
fsl_shw_return_t shw_slot_verify_access(void *user_data, uint64_t owner_id,
					uint32_t slot);

/*!
 * Default keystore slot allocation
 *
 * This function first checks that the requested size is equal to or less than
 * the maximum keystore slot size.  If so, it searches the keystore for a free
 * key slot, and if found, marks it as used and returns a slot reference to the
 * user.
 *
 * @param[in] user_data Pointer to the location where the keystore data
 *                      structure stored.
 * @param[in] size      Size of the key data that will be stored in this slot
 *                      (octets)
 * @param[in] owner_id  Owner ID supplied as a credential.
 * @param[out] slot     Requested slot
 *
 * @return    A return code of type #fsl_shw_return_t.
 */
fsl_shw_return_t shw_slot_alloc(void *user_data, uint32_t size,
				uint64_t owner_id, uint32_t * slot);

/*!
 * Default keystore slot deallocation
 *
 * This function releases the given key slot in the keystore, making it
 * available to store a new key.
 *
 * @param[in] user_data Pointer to the location where the keystore data
 *                      structure stored.
 * @param[in] owner_id  Owner ID supplied as a credential.
 * @param[in] slot      Requested slot
 *
 * @return    A return code of type #fsl_shw_return_t.
 */
fsl_shw_return_t shw_slot_dealloc(void *user_data,
				  uint64_t owner_id, uint32_t slot);

/*!
 * Default keystore slot address lookup
 *
 * This function calculates the address where the key data is stored.
 *
 * @param[in] user_data Pointer to the location where the keystore data
 *                      structure stored.
 * @param[in] slot      Requested slot
 *
 * @return    SCC2: Virtual address (kernel or userspace) of the key data.
 *            SCC: Physical address of the key data.
 */
void *shw_slot_get_address(void *user_data, uint32_t slot);

/*!
 * Default keystore slot base address lookup
 *
 * This function calculates the base address of the Secure Partition on which
 * the key data is located.  For the reference design, only one Secure
 * Partition is used per Keystore, however in general, any number may be used.
 *
 * @param[in] user_data Pointer to the location where the keystore data
 *                      structure stored.
 * @param[in] slot      Requested slot
 *
 * @return    SCC2: Secure Partition virtual (kernel or userspace) base address.
 *            SCC: Secure Partition physical base address.
 */
uint32_t shw_slot_get_base(void *user_data, uint32_t slot);

/*!
 * Default keystore slot offset lookup
 *
 * This function calculates the offset from the base of the Secure Partition
 * where the key data is located.
 *
 * @param[in] user_data Pointer to the location where the keystore data
 *                      structure stored.
 * @param[in] slot      Requested slot
 *
 * @return    SCC2: Key data offset (octets)
 *            SCC: Not implemented
 */
uint32_t shw_slot_get_offset(void *user_data, uint32_t slot);

/*!
 * Default keystore slot offset lookup
 *
 * This function returns the size of the given key slot.  In the reference
 * implementation, all key slots are of the same size, however in general,
 * the keystore slot sizes can be made variable.
 *
 * @param[in] user_data Pointer to the location where the keystore data
 *                      structure stored.
 * @param[in] slot      Requested slot
 *
 * @return    SCC2: Keystore slot size.
 *            SCC: Not implemented
 */
uint32_t shw_slot_get_slot_size(void *user_data, uint32_t slot);

/* @} */

#endif /* FSL_SHW_KEYSTORE_H */
