/*
 * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
 *
 * This software is dual-licensed to you under the MIT License (MIT) and
 * the Universal Permissive License (UPL). See the LICENSE file in the root
 * directory for license terms. You may choose either license, or both.
 */

/**
 * @file iotcs_tam.h
 * @brief The file contains API for IOT CS Trusted Assets Manager.
 * The Trusted Assets Manager defines methods for handling trust material used 
 * for activation and authentication to the IoT CS. Depending on the capability
 * of the device as well as on the security requirements implementations of this 
 * interface may simply store sensitive trust material in a plain persistent
 * store, in some keystore or in a secure token. 
 * This is not an API visible by the application code, but rather an SPI, used
 * internally by the IoT Client Library, and intended to provide a common 
 * interface for multiple TAM implementations.
 */

#ifndef IOTCS_TAM_H
#define IOTCS_TAM_H

#define TAM_SERVER_URI_TAG       0x1
#define TAM_CLIENT_ID_TAG        0x2
#define TAM_SHARED_SECRET_TAG    0x3
#define TAM_ENDPOINT_ID_TAG      0x4
#define TAM_TRUST_ANCHOR_TAG     0x5
#define TAM_PRIVATE_KEY_TAG      0x6
#define TAM_PUBLIC_KEY_TAG       0x7
#define TAM_CONNECTED_DEVICE_TAG 0x8

#define TAM_AES_CBC_128_IV_LENGTH 16

#ifdef __cplusplus
extern "C" {
#endif  

#include "iotcs.h"

    /**
     * @brief IoT trusted assets manager initialization.
     *
     * IoT trusted assets manager initialization.
     * This function reads data from persistent storage and allocates resources that
     * will be freed when calling {@link tam_finalize}.
     * This function must be called by iotcs_init.
     * @param path a path to trusted assets store.
     * @param password a password that was used to decode trusted assets store using the provisioner tool.
     * @retval IOTCS_RESULT_INVALID_ARGUMENT if path or password are NULL
     * @retval IOTCS_RESULT_OK if succeeded.
     * @retval IOTCS_RESULT_FAIL otherwise.
     */
    extern iotcs_result tam_init(const char* path, const char* password);

    /**
     * @brief IoT trusted assets manager finalization.
     *
     * Frees all allocated resources. 
     * This function must be called by iotcs_finalize.
     */
    extern void tam_finalize(void);

    /**
     * @brief Returns whether the client is activated.
     *
     * @return whether the client is activated.
     */
    extern int tam_is_activated(void);

    /**
     * @brief Resets the trust material back to its provisioning state.
     * 
     * In particular the key pair is erased. The client will have to go, at least,
     * through activation again; depending on the provisioning policy in place, 
     * the client may have to go through registration again.
     *
     * @retval IOTCS_RESULT_OK if succeeded.
     * @retval IOTCS_RESULT_FAIL otherwise.
     */
    extern iotcs_result tam_reset(void);

    /**
     * @brief Retrieves the IoT CS server host name.
     *
     * @return the IoT CS server host name (null-terminated string)
     */
    extern const char* tam_get_server_host(void);

    /**
     * @brief Retrieves the IoT CS server port.
     *
     * @return the IoT CS server port (a positive integer)
     */
    extern int tam_get_server_port(void);

    /**
     * @brief Retrieves the ID of this client. 
     * 
     * If the client is a device the client ID
     * is the activation ID; if the client is a pre-activated enterprise application
     * the client ID corresponds to the assigned endpoint ID. The client ID is
     * used along with a client secret derived from the shared secret to perform
     * secret-based client authentication with the IoT CS server.
     *
     * @return the ID assigned to this client (null-terminated string)
     */
    extern const char* tam_get_client_id(void);

    /**
     * @brief Retrieves the assigned endpoint ID.
     * 
     * @return the endpoint ID (null-terminated string)
     */
    extern const char* tam_get_endpoint_id(void);

    /**
     * @brief Retrieves the server protocol scheme that should be used to talk to the IoT CS.
     *
     * The IoT CS client library code recognizes "https" and
     * "mqtts" (for MQTT over SSL).
     * 
     * @return the IoT CS server protocol scheme (null-terminated string)
     */
    extern const char* tam_get_server_scheme(void);


    /**
     * @brief Retrieves the public key to be used for certificate request.
     *
     * @param len the value that will contain the public key length
     * @return the DER-encoded public key
     */
    extern const unsigned char* tam_get_device_public_key(size_t *len);

    /**
     * @brief Retrieves the trust anchors count.
     *
     * Retrieves the number of trust anchors or most-trusted Certification Authority 
     * certificates to be used to validate the IoT CS server certificate chain.
     * @return the count of certificates
     */
    extern size_t tam_get_trust_anchors_count(void);
    /**
     * @brief Retrieves the n-th trust anchors certificate.
     *
     * Retrieves one of the trust anchors or most-trusted Certification Authority 
     * certificates (CA) to be used to validate the IoT CS server certificate chain.
     *
     * @param index the certificate to retrieve
     * @param len a pointer to hold the size of the certificate
     * @return a DER-encoded certificate or NULL if no certificate has this index
     */
    extern const char *tam_get_trust_anchor_certificate(size_t index, size_t *len);

    /**
     * @brief Sets the credentials as returned by the activation procedure.
     *
     * Sets the assigned endpoint ID and certificate as returned by the
     * activation procedure. Upon a call to this method, a compliant
     * implementation of the Trusted Assets Manager interface must ensure
     * the persistence of the provided endpoint credentials. This method can
     * only be called once; unless the Trusted Assets Manager has been reset.
     * 
     * @param endpoint_id a string holding the endpoint_id
     * @param length endpoint_id length
     * @retval IOTCS_RESULT_INVALID_ARGUMENT if some of the input parameters are invalid..
     * @retval IOTCS_RESULT_OK if succeeded.
     * @retval IOTCS_RESULT_FAIL otherwise.
     */
    extern iotcs_result tam_set_endpoint_credentials(const char* endpoint_id, int length);

    /**
     * @brief Generates the device key pair.
     * 
     * Generates the key pair to be used for assertion-based client authentication 
     * with the IoT CS.
     *
     * @param algorithm the key algorithm (null-terminated string).
     * @param key_size the key size in bits.
     * @retval IOTCS_RESULT_FAIL if trusted assets manager isn't initialized.
     * @retval IOTCS_RESULT_INVALID_ARGUMENT if some of the input parameters are invalid.
     * @retval IOTCS_RESULT_OK if succeeded.
     * @retval IOTCS_RESULT_FAIL otherwise.
     */
    extern iotcs_result tam_generate_key_pair(const char* algorithm, size_t key_size);

    /**
     * @brief Signs the provided data using the specified algorithm and the private key. 
     * 
     * This method is only use for assertion-based client authentication with the 
     * IoT CS.
     *
     * @param data the data to sign.
     * @param datalen the data size.
     * @param algorithm the signature algorithm to use.
     * @param signature the buffer that will contain the output signature. If {@code NULL}, only the size is returned.
     * @param maxlen the maximum buffer size.
     * @return the signature length or 0 if any error occurs retrieving the necessary key material or performing the operation.
     */
    extern size_t tam_sign_with_private_key(const char* data, size_t datalen, const char* algorithm, char* signature, size_t maxlen);

    /**
     * @brief Signs the provided data using the specified algorithm and the shared
     * secret.
     * 
     * This method is only use for secret-based client authentication with the 
     * IoT CS server.
     *
     * @param data the data to be hashed.
     * @param dlen the length in bytes of the data to be hashed.
     * @param algorithm the hash algorithm to use (null-terminated string).
     * @param hash the buffer that will contain the hash of the data.
     * @param maxsize the maximum buffer size.
     * @param hardware_id the activation id of the indirect connected device whose shared secret is to be used for signing.
     *        NULL value of hardware_id means that directly connected device shared secret will be used.
     * @return the signature length or 0 if any error occurs retrieving the necessary key material or performing the operation.
     */
    extern size_t tam_sign_with_shared_secret(const char* data, size_t dlen, const char* algorithm, char* hash, size_t maxsize,
            const char* hardware_id);

#ifdef __cplusplus
}
#endif

#endif /* IOTCS_TAM_H */

