#ifndef JOSE_H
#define JOSE_H

#include "stdint.h"
#include "stddef.h"
#include "string.h"
#include "stdio.h"

#define TZ_SPAY_MAX_RSA_KEY_LEN	  512
#define JWE_HEADER_MAX_LEN        256
#define JWE_KID_MAX_LEN           64
#define JOSE_MAX_BUF_SIZE         4096
#define PARTNER_APP_ID_MAX_LEN     22

#ifdef SUPPORT_P2P
#define JWS_HEADER_MAX_LEN        JWE_HEADER_MAX_LEN  
#define JWS_KID_MAX_LEN           JWE_KID_MAX_LEN
#endif

#define JOSE_OK                         0
#define JOSE_UNKNOWN_ERROR              1
#define JOSE_UNSUPPORTED_ALG            2
#define JOSE_UNSUPPORTED_ENC            3
#define JOSE_HEADER_LEN_TOO_SMALL       4
#define JOSE_KID_LEN_TOO_LONG           5
#define JOSE_INAPP_CERT_FAILED          6
#define JOSE_HEADER_LEN_TOO_LARGE       7
#define JOSE_HEADER_UNSUPPORTED_SPPCTY  8

#define JOSE_RSA2048_KEY_LEN            256
#define JOSE_RSA4096_KEY_LEN            512
#define JOSE_RSA3072_KEY_LEN            384
#define JOSE_RSA_KEY_EXP_LEN            3

typedef enum {
	RSA1_5,
	RSA_OAEP,
	RSA_OAEP_256,
	A128KW,
	A192KW,
	A256KW,
	DIRECT,
	ECDH_ES,
	ECDH_ES_A128KW,
	ECDH_ES_A192KW,
	ECDH_ES_A256KW,
	A128GCMKW,
	A192GCMKW,
	A256GCMKW,
	PBES2_HS256_A128KW,
	PBES2_HS384_A192KW,
	PBES2_HS512_A256KW
} jwe_alg_t;

typedef enum {
	A128CBC_HS256,
	A192CBC_HS384,
	A256CBC_HS512,
	A128GCM,
	A192GCM,
	A256GCM
} jwe_enc_t;

typedef enum {
	HS256,
	HS384,
	HS512,
	RS256,
	RS384,
	RS512,
	ES256,
	ES384,
	ES512,
	PS256,
	PS384,
	PS512
} jws_alg_t;

typedef enum{
	JOSE_JWS_FORMAT = 0,
	JOSE_JWE_FORMAT,
	JOSE_UNKNOWN_FORMAT
} jose_format_t;

typedef struct {
	uint8_t modulus[JOSE_RSA2048_KEY_LEN];
	uint32_t modulus_len;
	uint8_t pubexp[JOSE_RSA_KEY_EXP_LEN];
	uint32_t pubexp_len;
	uint8_t privExp[JOSE_RSA2048_KEY_LEN];
	uint32_t privExp_len;
} jose_rsa2048_privinfo_t;

typedef struct jose_rsa2048_pubinfo_ {
	uint8_t modulus[JOSE_RSA2048_KEY_LEN];
	uint32_t modulus_len;
	uint8_t pubexp[JOSE_RSA_KEY_EXP_LEN];
	uint32_t pubexp_len;
} jose_rsa2048_pubinfo_t;

typedef struct jose_rsa3072_pubinfo_ {
	uint8_t modulus[JOSE_RSA3072_KEY_LEN];
	uint32_t modulus_len;
	uint8_t pubexp[JOSE_RSA_KEY_EXP_LEN];
	uint32_t pubexp_len;
} jose_rsa3072_pubinfo_t;

typedef struct jose_rsa4096_pubinfo_ {
	uint8_t modulus[JOSE_RSA4096_KEY_LEN];
	uint32_t modulus_len;
	uint8_t pubexp[JOSE_RSA_KEY_EXP_LEN];
	uint32_t pubexp_len;
} jose_rsa4096_pubinfo_t;

uint32_t jwe_header(uint8_t * header, uint32_t * header_len,
		jwe_alg_t alg,
		uint8_t * kid, uint32_t kid_len,
		jwe_enc_t enc);

uint32_t jws_header(uint8_t * header, uint32_t * header_len,
		jws_alg_t alg,
		uint8_t * kid, uint32_t kid_len);

uint32_t construct_jwe_transaction_info(
		uint8_t * kid, uint32_t kid_len,
		uint8_t * root_modulus, uint32_t root_modulus_len,
		uint8_t * root_pubexp, uint32_t root_pubexp_len,
		uint8_t * intermediate_cert, uint32_t intermediate_cert_len,
		uint8_t * merchant_cert, uint32_t merchant_cert_len,
		uint8_t * transaction_info, uint32_t transaction_info_len,
		uint8_t * jwe_output, uint32_t * jwe_output_len);

uint32_t construct_jws_transaction_info(
		uint8_t * kid, uint32_t kid_len,
		uint8_t * modulus, uint32_t modulus_len,
		uint8_t * exponent, uint32_t exponent_len,	
		uint8_t * private_exponent, uint32_t private_exponent_len,
		uint8_t * root_modulus, uint32_t root_modulus_len,
		uint8_t * root_pubexp, uint32_t root_pubexp_len,
		uint8_t * intermediate_cert, uint32_t intermediate_cert_len,
		uint8_t * merchant_cert, uint32_t merchant_cert_len,
		uint8_t * transaction_info, uint32_t transaction_info_len,
		uint8_t * jws_output, uint32_t * jws_output_len);

uint32_t construct_jws_only_transaction_info(
		uint8_t * kid, uint32_t kid_len,
		uint8_t * modulus, uint32_t modulus_len,
		uint8_t * exponent, uint32_t exponent_len,
		uint8_t * private_exponent, uint32_t private_exponent_len,
		uint8_t * transaction_info, uint32_t transaction_info_len,
		uint8_t * jws_output, uint32_t * jws_output_len);

uint32_t construct_jwe(
		uint8_t * kid, uint32_t kid_len,
		uint8_t isAadNeeded,
		uint8_t * merchant_modulus, uint32_t merchant_modulus_len,
		uint8_t * merchant_pubexp, uint32_t merchant_pubexp_len,
		uint8_t * transaction_info, uint32_t transaction_info_len,
		uint8_t * jwe_output, uint32_t * jwe_output_len);

jose_format_t jose_format_determine(
		uint8_t * in_data, uint32_t in_data_len);

uint32_t jose_decrypt_jwe(
	uint8_t * in_data, uint32_t in_data_len, jose_rsa2048_privinfo_t *device_ecertinfo,
	uint8_t * out_data, uint32_t * out_data_len);

int jose_find_dot(
		uint8_t * in_data, uint32_t in_data_len, uint32_t start_i,
		uint32_t * dot_i);
#endif
