#include "ROMprotocol.h"
#include "Stage2.h"

int main()
{
	printf("Hello World!\n");
	
	DIMASTATUS ret = 0;

	/*lock all resources, no interruptons*/ 
	/*unlock Secure Storage to read UDS and write DID Priv key*/

	ret = ROMprotocol();
	
	/*lock Secure Storage*/
	

	//ALIAS and session keys, firmware execution

	//measure firmware.bin
	//measure firmware.conf
	//measure ....
	//calculate FW_ID - composite hash of all above measurements
	//create ALIAS KD_ctx
	//keygen
	//publish keys



	//Session key creation
	//receive session nonce from verifier?
	//placeholder 
	char * PERS = "session1";

	KeyDrv_context SSN1_ctx;
	SSN1_ctx.ENT_MODE = SW_PRNG;				//non determ, gen new key for every session
	SSN1_ctx.PKC_MODE = DFL_PKC;
	SSN1_ctx.seed = NULL;					
	SSN1_ctx.phrase = PERS;
	SSN1_ctx.KEY_FORM = DFL_FORM;

	printf("Generating Session keys\n");

	ret = AsymmKeyGen(&SSN1_ctx);
	if(ret < DIMASUCCESS)
	{
		perror("DIMAFAILURE : SESSION key gen failed\n");
		exit(DIMAFAILURE);
	}


	/////////////////KEY gen protocol ends here
	/////////////////DID Priv key is purged/secure, other keys are available for use

	/////////////////////DICE END//////////////////////////


	//////////////////////Now STAGE 2 protocols///////////////////
	//read verifier signing key
	//load connected nodes information
	//wait for connection init
	//recv prover info
	//load prover Pubkey
	//challenge NONCE N
	//sign N with Aik
	//Encrypt N with Pub-Prv
	//sendNonce()
	//wait
	//recv Resp R
	//Decrypt R with Aik
	//Verify signature with Pub-prv
	//verify N
	//issue ACK
	//close conn.


	mbedtls_pk_context pk_ctx;
	mbedtls_pk_init(&pk_ctx);

	//mbedtls_entropy_context entropyCtx;
	//mbedtls_entropy_init(&entropyCtx);

	//mbedtls_ctr_drbg_context drbgCtx;
	//mbedtls_ctr_drbg_init(&drbgCtx);

	//ret = mbedtls_ctr_drbg_seed(&drbgCtx, mbedtls_entropy_func, &entropyCtx, NULL, 0);
	if(ret < DIMASUCCESS)
	{
		perror("DIMAFAILURE : CRT DRBG failed\n");
		exit(DIMAFAILURE);
	}

	if(DEBUG) {printf("Loading signing key\n");}
	ret = mbedtls_pk_parse_keyfile( &pk_ctx, "keys/Alias_priv.pem", "" );
	if(ret < DIMASUCCESS)
	{
		perror("DIMAPKFAILURE : Failed to load signing key\n");
		exit(DIMAPKFAILURE);
	}

////////////// Key capability check ///////////
	ret = mbedtls_pk_can_do(&pk_ctx, MBEDTLS_PK_ECKEY);			//1 - can; 0 - cannot
	if(!ret)
	{
		perror("DIMAPKFAILURE : This key cannot perform EC Key operations\n");

	}
	if (DEBUG) {printf("successful load signing key\n");}
	ret = mbedtls_pk_can_do(&pk_ctx, MBEDTLS_PK_ECDSA);
	if(!ret)
	{
		perror("DIMAPKFAILURE : This key cannot perform ECDSA operations\n");

	}
	ret = mbedtls_pk_can_do(&pk_ctx, MBEDTLS_PK_ECKEY_DH);
	if(!ret)
	{
		perror("DIMAPKFAILURE : This key cannot perform EC DHM operations\n");

	}
////////////// Key check end ///////////

////////////// load client info ////////
	Client_info * Cl_list = calloc(1, sizeof(Client_info)*CL_NOS);

	ret = load_nodes(Cl_list);

	printf("Client list complete, waiting for Client to init..\n");


////////////// wait for conn init //////


	/* 
	server : bind socket
	Client : load server info
	client : connect
	server : accept
	client : send CLI_ID
	server : recv, add cli_fd into appropriate Cli_info
	server : challengeCl()
				send
	*/

////////////// active clients /////////
	printf("client ID : %s\n", Cl_list[1].cli_ID);
	printf("client Pubkey at : %s\n", Cl_list[1].pub_file);


	//for each active client
	//sign NONCE
	//send NONCE and sig

	//cacl hash

	uint8_t* sign = calloc(1,sizeof(uint8_t)*MBEDTLS_MPI_MAX_SIZE);//MBEDTLS_ECDSA_MAX_LEN);
	size_t signlen = 0;

	ret = challengeCl( &pk_ctx, &Cl_list[1], sign, &signlen);
/*
	if(DEBUG)
	{
		for(int i = 0; i < NONCE_SIZE; i++)
	    	printf("%hhx",Cl_list[1].NONCE[i]);
	    printf(" :  NONCE main\n");
	}

	if(DEBUG)
	{
		for (int i = 0; i < signlen; i++)
  			printf("%hhx", sign[i]);
		printf(" :signature main\n" );  	

	}
*/

/////////////////// client actions ////////////
	/*
		client : recv challenge
		store in chall/resp ctx?
		verf signature
		N = N+1?
		calloc sign
		responSer(priv key ctx, resp ctx, sign, signlen)
				send
	*/

//////////////////////////////////////////////////

	//net recv (response)

	//verify
	//ret = verify(&Cl_list[1], &response);

/*		self verification 	*/

	mbedtls_pk_context pubk_ctx;
	mbedtls_pk_init( &pubk_ctx );
	

	ret = mbedtls_pk_parse_public_keyfile( &pubk_ctx, "keys/Alias_pub.pem" );
	if(ret < DIMASUCCESS)
	{
        perror("DIMAPKFAILURE : Public key failure");
        return DIMAPKFAILURE;
    }

/////////////////verification/////////////
    /*
    	server : recv resp ctx
    	verifycl(cli ctx, resp ctx, sign, siglen)
    	send (ack)
    	cli_inf set "verified"
    	
    	client : free(), clear server info 
    	server : free(), clear client info
	*/


    ret = verifyCl( &pubk_ctx, &Cl_list[1], sign, signlen);
    if (ret < DIMASUCCESS)
	{
		perror("DIMAVERIFYFAILURE : could not verify client\n");
		return DIMAVERIFYFAILURE;
	}


	if(Cl_list[1].Cli_STATUS == Cl_verfd)
    {	printf( "\n  . OK (the signature is valid)\n\n" );	}




	/*release resources, pass control to firmware, etc */

	printf("Successful exit\n");

	return 1;
}
