#ifndef _QC_SO_H_
#define _QC_SO_H_

#define QC_ENUM_32BIT_MAX ((int32_t) -1)

/** Secure object type. */
typedef enum {
	/** Regular secure object. */
	QC_SO_TYPE_REGULAR = 0x00000001,
	/** make sure enum is 32 bit wide. */
	QC_SO_TYPE_SPACER = QC_ENUM_32BIT_MAX,
} qc_so_type_t;

/** Secure object context.
 * A context defines which key to use to encrypt/decrypt a secure object.
 * Also serves as an identifier for so
 */
typedef enum {
	/** Trustlet/tzapp context. */
	QC_SO_CONTEXT_TLT = 0x73706179,
	/** make sure enum is 32 bit wide. */
	QC_SO_CONTEXT_SPACER = QC_ENUM_32BIT_MAX,

} qc_so_context_t;

/** Secure object lifetime.
 * A lifetime defines how long a secure object is valid.
 */
typedef enum {
	/** SO does not expire. */
	QC_SO_LIFETIME_PERMANENT = 0x00000000,
	/** make sure enum is 32 bit wide. */
	QC_SO_LIFETIME_SPACER = QC_ENUM_32BIT_MAX,

} qc_so_lifetime_t;

#define UUID_LENGTH 16
/** Universally Unique Identifier (UUID) according to ISO/IEC 11578. */
typedef struct {
	uint8_t value[UUID_LENGTH]; /**< Value of the UUID. */
} qc_uuid_t, *qc_uuid_ptr;

/** Service provider Trustlet/tzapp id.
 * The combination of service provider id and Trustlet UUID forms a unique
 * Trustlet identifier.
 */
typedef struct {
	/** Trustlet UUID. For tzapp, it is tzapp name */
	qc_uuid_t uuid;
} qc_tzapp_id_t;

/*
 *  +--------+--------+------------------+----------+
 *  | Header |   IV   |  encrypted-data  |   tag    |
 *  +--------+--------+------------------+----------+
 *
 *  /--------/12 bytes/-- encryptedLen --/ 16 bytes /
 *
 *  /---- toBeHashedLen -----------------/
 *
 *  /------------- totalSoSize ---------------------/
 *
 */

typedef struct {
	/** Type of secure object. */
	uint32_t type;
	/** Secure object version. */
	uint32_t version;
	/** Secure object context. */
	qc_so_context_t context;
	/** Secure object lifetime. */
	qc_so_lifetime_t lifetime;
	/** Producer tzapp id. */
	qc_tzapp_id_t producer;
	/** Length of encrypted user data (after unencrypted data, excl. tag */
	uint32_t encryptedLen;
} qc_so_header_t;

/** Maximum size of the payload (plain length + encrypted length) of a secure object. */
#define QC_SO_PAYLOAD_MAX_SIZE      (1U << 15)

#define QC_SO_IV_SIZE               12

#define QC_SO_TAG_SIZE              16

/** Block size of encryption algorithm used for secure objects. */
#define QC_SO_ENCRYPT_BLOCK_SIZE    16

/** Maximum number of ISO padding bytes. */
#define QC_SO_MAX_PADDING_SIZE (QC_SO_ENCRYPT_BLOCK_SIZE)

/** Size of hash used for secure objects */
#define QC_SO_HASH_SIZE             32

#define QC_SO_SIZE(encryptedLen) ( \
		(encryptedLen > QC_SO_PAYLOAD_MAX_SIZE) ? 0 : \
		sizeof(qc_so_header_t) + QC_SO_IV_SIZE + encryptedLen + QC_SO_TAG_SIZE \
		)

#endif /* end of _QC_SO_H_ */
