#include "Stage2.h"

/*
	Client_info
		const char *			cli_ID;
		const char *			pub_file;
		mbedtls_ecp_point *		pub_key;
		int 					Cli_STATUS;
		int 					Cli_CAP;
*/


DIMASTATUS load_nodes(Client_info * Cl_list)
{

	printf("PASS 20\n");
	DIMASTATUS ret = 0;
	int len = 0;

	mbedtls_entropy_context entropy;
	mbedtls_entropy_init(&entropy);

	uint8_t * RAND = calloc(1, sizeof(uint8_t)*NONCE_SIZE);

	if(DEBUG)
	{printf("PASS 21\n");}

	//load from access list? 
	//////////////////////////TODO////////////////////////////
	//Protected accesslist must be unlocked with Alias key
	//Allow access to client list only after successful DICE


	//itrate over client list : perclient
	Client_info		Cl1_ctx;
	Cl1_ctx.cli_ID 		= "Node1";
	Cl1_ctx.pub_file 	= "clientkeys/Client1_pub.pem";
	Cl1_ctx.Cli_STATUS 	= Cl_unverf;
	Cl1_ctx.Cli_CAP 	= DFL_CAP;
	
	//mbedtls_entropy_gather(&entropy);
	ret = mbedtls_entropy_func(&entropy, RAND, sizeof(RAND));
	if(ret < DIMASUCCESS)
	{
		perror("DIMADRBGFAILURE : Failed to gen NONCE\n");
		exit(DIMADRBGFAILURE);
	}

	Cl1_ctx.NONCE 		= RAND;
	
	/*
	if(DEBUG)
	{
		for(int i = 0; i < NONCE_SIZE; i++)
	    	printf("%hhx",Cl1_ctx.NONCE[i]);
	    printf(" :  NONCE inter\n");
	}
	*/

	//add to the client list
	Cl_list[1] 			= Cl1_ctx;

	//end perclient itetration

	mbedtls_entropy_free(&entropy);
	return DIMASUCCESS;
}

/* NOT USING  THIS

DIMASTATUS genNONCE(Client_info * Cl_ctx)
{

//
//1. create new genNONCe session n entropy per client
//2. pass client list iterate over active clients genNONCE for all 
//

	mbedtls_entropy_context entropy;
	mbedtls_entropy_init(&entropy);

	DIMASTATUS ret = 0;

	uint8_t * RAND = calloc(1, sizeof(uint8_t)*NONCE_SIZE);
if(DEBUG)printf("Pass1\n");

	//mbedtls_entropy_gather(&entropy);
	ret = mbedtls_entropy_func(&entropy, RAND, sizeof(RAND));
	if(ret < DIMASUCCESS)
	{
		perror("DIMADRBGFAILURE : Failed to gen NONCE\n");
		exit(DIMADRBGFAILURE);
	}

if(DEBUG)printf("Pass2\n");
	Cl_ctx -> NONCE = RAND;

	if(DEBUG)
	{
		for(int i = 0; i < NONCE_SIZE; i++)
	    	printf("%hhx",RAND[i]);
	    printf(" :  RAND\n");
	}
	if(DEBUG)
	{
		for(int i = 0; i < NONCE_SIZE; i++)
	    	printf("%hhx",Cl_ctx -> NONCE[i]);
	    printf(" :  NONCE\n");
	}

	mbedtls_entropy_free(&entropy);

	return DIMASUCCESS;
}


*/

DIMASTATUS challengeCl( mbedtls_pk_context * pk_ctx, Client_info * Cl_ctx, uint8_t *sign, size_t *signlen)
{

	DIMASTATUS ret = 0;
	uint8_t* dgst = calloc(1,sizeof(uint8_t)*SHA256_DGST_SIZE);
	
	ret = mbedtls_sha256_ret( Cl_ctx->NONCE,NONCE_SIZE,dgst,0 );
	if(ret < DIMASUCCESS)
	{
		perror("DIMASHAFAILURE : could not perfom SHA digest\n");
		return DIMASHAFAILURE;
	}

//	ret = mbedtls_md(mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ),
//					Cl_list[1].NONCE, NONCE_SIZE, hash );

	if(DEBUG)
	{
		for (int i = 0; i < SHA256_DGST_SIZE; i++)
  			printf("%hhx", dgst[i]);
		printf(" :	sha dgst\n" );  	

	}

	//ret = mbedtls_pk_sign( &pk_ctx, MBEDTLS_MD_SHA256, dgst, SHA256_DGST_SIZE, sign, &signlen,
    //                     mbedtls_ctr_drbg_random, &drbgCtx );
	ret = mbedtls_pk_sign( pk_ctx, MBEDTLS_MD_SHA256, dgst, SHA256_DGST_SIZE, sign, signlen,
                         NULL,NULL );

	if(ret < DIMASUCCESS)
	{
		perror("DIMASIGNFAILURE : could not perfom private key signature\n");
		return DIMASIGNFAILURE;
	}

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

	}

	// server : send challenge, cli_info -> cli_fd

	return DIMASUCCESS;

}


DIMASTATUS verifyCl( mbedtls_pk_context * pk_ctx, Client_info * Cl_ctx, uint8_t *sign, size_t signlen)
{

	//Paramer checks
	if(Cl_ctx->Cli_STATUS != Cl_unverf)
	{
		printf("DIMAINFOMISMATCH :Client %s verification already performed. skipping to next client..", Cl_ctx->cli_ID);
		return DIMAINFOMISMATCH;
	}

	//////

	DIMASTATUS ret = 0;
	uint8_t* dgst = calloc(1,sizeof(uint8_t)*SHA256_DGST_SIZE);
	
	ret = mbedtls_sha256_ret( Cl_ctx->NONCE,NONCE_SIZE,dgst,0 );
	if(ret < DIMASUCCESS)
	{
		perror("DIMASHAFAILURE : could not perfom SHA digest\n");
		return DIMASHAFAILURE;
	}

	/*
	if(DEBUG)
	{
		for(int i = 0; i < NONCE_SIZE; i++)
	    	printf("%hhx",Cl_ctx.NONCE[i]);
	    printf(" :  NONCE verf\n");
	}

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

	}
	*/

	ret = mbedtls_pk_verify( pk_ctx, MBEDTLS_MD_SHA256, dgst, 0, sign, signlen );
	if (ret < DIMASUCCESS)
	{
		perror("DIMAVERIFYFAILURE : could not verify signature\n");
		Cl_ctx->Cli_STATUS = Cl_fault;
		return DIMAVERIFYFAILURE;
	}

	Cl_ctx->Cli_STATUS = Cl_verfd;


	return DIMASUCCESS;

}