#ifndef KEYMASTER_H
#define KEYMASTER_H

#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <cdefs.h>
#include <keymaster_defs.h>

#ifdef __cplusplus
extern "C" {
#endif  // __cplusplus

/*
 * Generates a key, or key pair, returning a key blob
 * Key generation parameters are defined as keymaster tag/value pairs, provided in \p params.
 * See keymaster_tag_t (attached) for the full list.
 * - KM_TAG_ALGORITHM;
 * - KM_TAG_PURPOSE; and
 * - (KM_TAG_USER_SECURE_ID and KM_TAG_USER_AUTH_TYPE) or KM_TAG_NO_AUTH_REQUIRED.
 * The following tags will take default values if unspecified:
 * - KM_TAG_KEY_SIZE will default to the size of the key provided.
 * - KM_TAG_RSA_PUBLIC_EXPONENT will default to the value in the key provided (for RSA keys)
 * 
 * @param[in]  params     Parameters defining the generated key.
 * @param[out] key_blob   Used to return the opaque key blob.  Must be non-NULL.  The caller
 *                        assumes ownership of the contained key_material.  
 */
keymaster_error_t generate_key(const keymaster_key_param_set_t* params,
                               keymaster_key_blob_t* key_blob);

/*
 * Exports a public key, returning a byte array in the specified format.
 * Currently KM_KEY_FORMAT_X509 is the only format supported.
 * 
 * @param[in]  export_format The format to be used for exporting the key.
 * @param[in]  key_to_export The key to export.
 *                           Is set of NULL, if KM_TAG_USE_HARDWARE_UNIQUE_KEY is set.
 * @param[out] export_data   The exported key material.  The caller assumes ownership.
 */
keymaster_error_t export_key(keymaster_key_format_t export_format,
                            const keymaster_key_blob_t* key_to_export,
                            keymaster_blob_t* export_data);

/*
 * Begins a cryptographic operation using the specified key.  If all is well, begin() will
 * return KM_ERROR_OK and create an operation handle which must be passed to subsequent calls to
 * update(), finish() or abort().
 *
 * It is critical that each call to begin() be paired with a subsequent call to finish() or
 * abort(), to allow the keymaster implementation to clean up any internal operation state.
 * Failure to do this may leak internal state space or other internal resources and may
 * eventually cause begin() to return KM_ERROR_TOO_MANY_OPERATIONS when it runs out of space for
 * operations.  Any result other than KM_ERROR_OK from begin(), update() or finish() implicitly
 * aborts the operation, in which case abort() need not be called (and will return
 * KM_ERROR_INVALID_OPERATION_HANDLE if called).
 *
 * @param[in]  key              The key to be used for the operation. \p key must have a purpose compatible
 *                              with p purpose and all of its usage requirements must be satisfied, or begin() will return
 *                              an appropriate error code.
 *
 * @param[in]  in_params        Additional parameters for the operation.  This is typically used to
 *                              provide authentication data, with KM_TAG_AUTH_TOKEN.  If KM_TAG_APPLICATION_ID or
 *                              KM_TAG_APPLICATION_DATA were provided during generation, they must be provided here, or the
 *                              operation will fail with KM_ERROR_INVALID_KEY_BLOB.  For operations that require a nonce or
 *                              IV, on keys that were generated with KM_TAG_CALLER_NONCE, in_params may contain a tag
 *                              KM_TAG_NONCE.
 *                              KM_TAG_USE_HARDWARE_UNIQUE_KEY tag is to be used
 *                              to let KM in SPU know to use the device unique key to operate on the data.
 *		                        This tag is of type keymaster_unique_key_list_t and currently 2 keys can be supported.
 *
 * @param[out] out_params       Output parameters.  Used to return additional data from the operation
 *                              initialization, notably to return the IV or nonce from operations that generate an IV or
 *                              nonce.  The caller takes ownership of the output parameters array and must free it with
 *                              keymaster_free_param_set().  out_params may be set to NULL if no output parameters are
 *                              expected.  If out_params is NULL, and output paramaters are generated, begin() will return
 *                              KM_ERROR_OUTPUT_PARAMETER_NULL.
 *
 * @param[out] operation_handle The newly-created operation handle which must be passed to
 *                              update(), finish() or abort().  If operation_handle is NULL, begin() will return
 *                              KM_ERROR_OUTPUT_PARAMETER_NULL.
 */
keymaster_error_t begin(const keymaster_key_blob_t* key,
						const keymaster_key_param_set_t* in_params,
						keymaster_key_param_set_t* out_params,
						keymaster_operation_handle_t* operation_handle);

/*
 * Provides data to, and possibly receives output from, an ongoing cryptographic operation begun
 * with begin().
 *
 * If operation_handle is invalid, update() will return KM_ERROR_INVALID_OPERATION_HANDLE.
 *
 * update() may not consume all of the data provided in the data buffer.  update() will return
 * the amount consumed in *data_consumed.  The caller should provide the unconsumed data in a
 * subsequent call.
 *
 * @param[in]  operation_handle The operation handle returned by begin().
 *
 * @param[in]  input            Data to be processed, per the parameters established in the call to begin().
 *                              Note that update() may or may not consume all of the data provided.  See \p input_consumed.
 *
 * @param[out] input_consumed   Amount of data that was consumed by update().  If this is less
 *                              than the amount provided, the caller should provide the remainder in a subsequent call to
 *                              update().
 *
 * @param[out] output           The output data, if any.  The caller assumes ownership of the allocated
 *                              buffer.  output must not be NULL.
 *
 * Note that update() may not provide any output, in which case output->data_length will be
 * zero, and output->data may be either NULL or zero-length (so the caller should always free()
 * it).
 */
keymaster_error_t update(keymaster_operation_handle_t operation_handle,
                   const keymaster_blob_t* input, size_t* input_consumed,
                   keymaster_blob_t* output);

/*
 * Finalizes a cryptographic operation begun with begin() and invalidates \p operation_handle.
 *
 * @param[in]  operation_handle  The operation handle returned by begin().  This handle will be
 *                               invalidated.
 * @param[in]  input             Data to be processed, per the parameters established in the call to
 *                               begin(). finish() must consume all provided data or return KM_ERROR_INVALID_INPUT_LENGTH.
 *
 * @param[in]  signature         The signature to be verified if the purpose specified in the begin()
 *                               call was KM_PURPOSE_VERIFY.
 *
 * @param[out] output            The output data, if any.  The caller assumes ownership of the allocated buffer.
 *
 * If the operation being finished is a signature verification or an AEAD-mode decryption and
 * verification fails then finish() will return KM_ERROR_VERIFICATION_FAILED.
 */
keymaster_error_t finish(keymaster_operation_handle_t operation_handle,
                         const keymaster_blob_t* signature,
                         keymaster_blob_t* output);

/*
 * Aborts a cryptographic operation begun with begin(), freeing all internal resources and
 * invalidating \p operation_handle.
 */
keymaster_error_t keymaster_abort(keymaster_operation_handle_t operation_handle);

/*
 * Get Auth Token key
 * @param[in]  at_key  Auth token key blob.
                       The caller is responsible to allocate memory for the auth token key.
					   The key size uses is 32 bytes.
 */
keymaster_error_t get_atkey(keymaster_blob_t *atKey);

/*
 * Get Pre shared key used to compute the per boot auth token key. More details can be
 * found https://android.googlesource.com/platform/hardware/interfaces/+/master/keymaster/4.0/IKeymasterDevice.hal.
 *
 * @param[in]  psk  Pre shared key used to compute per boot auth token key..
                       The caller is responsible to allocate memory for the auth token key.
                  The key size required is 32 bytes.
 */
keymaster_error_t get_psk(keymaster_blob_t *psk);

/*
 * Provisions the attestation key
 * @param[in]  level   Security level to provision the key. (Strongbox or TEE).
 * @param[in]  keybox  The keybox entries that contains all the keys and the corresponding
                       certificate chain that need to be provisioned.
					   Android requires 2 (one each for RSA and ECC)
					   The format of the key and the cert should be in ASN1 DER encoded format.
 */
keymaster_error_t attestation_key_provision(keymaster_security_level_t level,
      km_install_keybox_t *keybox);

/*
 * Performs AES wrap on input data
 * @param[in]  salt   Cryptographic salt used for KDF
 * @param[in]  input  The data to wrap
 * @param[out] output The wrapped data
 */
keymaster_error_t strongbox_wrap(const keymaster_blob_t* salt, const keymaster_blob_t* input,
                                 keymaster_blob_t* output);

/*
 * Performs AES unwrap on input data
 * @param[in]  salt   Cryptographic salt used for KDF
 * @param[in]  input  The wrapped data
 * @param[out] output The data to wrap
 */
keymaster_error_t strongbox_unwrap(const keymaster_blob_t* salt, const keymaster_blob_t* input,
                                   keymaster_blob_t* output);

#ifdef __cplusplus
}
#endif  // __cplusplus
#endif  // KEYMASTER_H
