Example #1
0
     int crypto_aead_decrypt(
       unsigned char *m,unsigned long long *mlen,
       unsigned char *nsec,
       const unsigned char *c,unsigned long long clen,
       const unsigned char *ad,unsigned long long adlen,
       const unsigned char *npub,
       const unsigned char *k
     )
     {
       Init();//Initializing GF(256) multiplication table for AES

		 if(mlen==NULL)
			 return -1;
		 if((clen==0) && (adlen==0))
		 {
			 *mlen=0;
			 return 0;
		 }

		 //Here we do decryption and/or authentication so we need a key and a plaintext pointer valid
		 if( (k==NULL) || (m==NULL) )
			 return -2;

		 //Minimum tag length verification
		 if (clen < CRYPTO_ABYTES)
			 return -1;

		 //Initializing constants
		unsigned char D0[2];
		D0[0] = CRYPTO_NPUBBYTES*8; //nonce length in bits
		D0[1] = CRYPTO_KEYBYTES*8; //key length in bits
		(*mlen)=0;
		 
		 //Initializing the last input to F
		 unsigned char BlockLastInput[64];  //Z1 - input to the last call of F
		 memset(BlockLastInput,0,64);
		 unsigned char Tag[64]; //Tag output
		 for(unsigned i=0; i<CRYPTO_KEYBYTES; ++i) //Key to the Z input
			BlockLastInput[64-CRYPTO_KEYBYTES+i] = k[i];
		 BlockLastInput[0] = D0[0]+6;
		 BlockLastInput[1] = D0[1];

		 unsigned long long decrypted_bytes=0;//Encrypted bytes counter
		 

		 //Encryption part
		 if(clen!=CRYPTO_ABYTES) //Ciphertext is more than just a tag
		 {
			 if(c==NULL)
				 return -3;
			 unsigned char BlockInput[64];  //V1 - input to the first layer call of F
			 unsigned char BlockMiddle[64];  //W1 - output of the first layer call of F
			 unsigned char BlockOutput[64];  //Y1 - output of the second layer call of F
			 unsigned long long mblock_counter=1;   //Message block counter
			 
			 while((clen>CRYPTO_ABYTES))
			 {
				 /* I. First layer */

				 //1. Domain-separation constant
				 BlockInput[1] = D0[1]; 
				 if(clen>= (CRYPTO_MBLOCK+CRYPTO_ABYTES))
					 BlockInput[0] = D0[0];
				 else //Last incomplete block
					 BlockInput[0] = D0[0]+1;

				 //2. Counter
				 for(unsigned i=0; i<CRYPTO_COUNTERBYTES; ++i)
				 {
					 BlockInput[i+2] = (i<sizeof(mblock_counter))?(mblock_counter>>(8*i))&0xff :0;//copying counter bytewise
				 }
				 
				 //3. Nonce
				 for(unsigned i=0; i<CRYPTO_NPUBBYTES; ++i) 
				 {
					 BlockInput[i+2+CRYPTO_COUNTERBYTES] = npub[i];
				 }

				 //4. Key
				 for(unsigned i=0; i<CRYPTO_KEYBYTES; ++i) 
				 {
					 BlockInput[i+2+CRYPTO_COUNTERBYTES+CRYPTO_NPUBBYTES] = k[i];
				 }	 

				 //5. Permutation call
				 FPerm(BlockInput, BlockMiddle); //First layer call to F

				 /* II. Encryption*/

				 if(clen>=CRYPTO_MBLOCK+CRYPTO_ABYTES)//Full block encryption
				 {
					 for(unsigned i=0; i<CRYPTO_MBLOCK; ++i)
					 {
						 m[decrypted_bytes] = BlockMiddle[i+2]^c[decrypted_bytes];
						 BlockMiddle[i+2] = c[decrypted_bytes];
						 decrypted_bytes++;
						 
					 }
					 BlockMiddle[1] =  D0[1];
					 BlockMiddle[0] = D0[0]+2;  //New Di constant

				 }

				 else //Last incomplete block
				 {
					 for(unsigned i=0; i<(unsigned)clen-CRYPTO_ABYTES; ++i)//Incomplete block Encryption
					 {
						  m[decrypted_bytes] = BlockMiddle[i+2]^c[decrypted_bytes];
						 BlockMiddle[i+2] = c[decrypted_bytes];
						 decrypted_bytes++;
					 }
					 for(unsigned i=(unsigned)clen-CRYPTO_ABYTES; i<CRYPTO_MBLOCK; ++i)
					 {
						 BlockMiddle[i+2] ^=  (unsigned char)(clen-CRYPTO_ABYTES);  //Extra Padding: extra bytes filled with the last block length in bytes
					 }

					 BlockMiddle[1] =  D0[1];
					 BlockMiddle[0] = D0[0]+3;  //New Di constant
				 }

				 //III. Second permutation call
				 //1. Call
				 FPerm(BlockMiddle, BlockOutput); //Second layer call to F
				 
				 //2. Buffer update
				 for(unsigned i=0; i<64-2-CRYPTO_KEYBYTES; ++i)//Adding the output to tag preparation buffer
				 {
					 BlockLastInput[i+2] ^= BlockOutput[i+2];
				 }


				 //Counters increment
				 mblock_counter++;
				 if(clen>=CRYPTO_MBLOCK+CRYPTO_ABYTES)
					 clen-=CRYPTO_MBLOCK;
				 
				 else 
				 	 clen=CRYPTO_ABYTES;
				 (*mlen) = decrypted_bytes;
			 }
		 }

		//Associated data part	  
		if(adlen!=0)
		{
			if(ad==NULL)
				return -4;

			unsigned char BlockInput[64];  //V1 - input to the first layer call of F
			 unsigned char BlockOutput[64];  //Y1 - output of the second layer call of F
			 unsigned long long adblock_counter=1;   //AD block counter
			 unsigned long long auth_bytes=0;

			while(adlen>0)
			{
				//1. Constant
				BlockInput[1] = D0[1];
				if(adlen>= CRYPTO_ADBLOCK)
					 BlockInput[0] = D0[0]+4;
				 else //Last incomplete block
					 BlockInput[0] = D0[0]+5;


				//2. Counter
				for(unsigned i=0; i<CRYPTO_KEYBYTES; ++i)
					BlockInput[i+2] = (i<sizeof(adblock_counter))? (adblock_counter>>(8*i))&0xff:0;//copying counter bytewise

				//3. AD block
				if(adlen >= CRYPTO_ADBLOCK) //Filling AD block
				{
					for(unsigned i=0; i<CRYPTO_ADBLOCK; ++i)
						BlockInput[i+2+CRYPTO_KEYBYTES] = ad[auth_bytes+i];
					
				}
				else //Last incomplete block
				{
					for(unsigned i=0; i<adlen; ++i)
						BlockInput[i+2+CRYPTO_KEYBYTES] = ad[auth_bytes+i];
					for(unsigned i=(unsigned)adlen; i<CRYPTO_ADBLOCK; ++i)
						BlockInput[i+2+CRYPTO_KEYBYTES] = (unsigned char)adlen;
				}

				//4. Key
				for(unsigned i=0; i<CRYPTO_KEYBYTES; ++i) 
				{
					 BlockInput[i+CRYPTO_ADBLOCK+CRYPTO_KEYBYTES+2] = k[i];
				}
				

				//5.Call to the F permutation

				FPerm(BlockInput,BlockOutput);//Call to the F permutation

				 for(unsigned i=0; i<64-2-CRYPTO_KEYBYTES; ++i)//Adding the output to Z
				 {
					 BlockLastInput[i+2] ^= BlockOutput[i+2];
				 }

				//Counters increment
				 adblock_counter++;
				 if(adlen>=CRYPTO_ADBLOCK)
				 {
					 auth_bytes += CRYPTO_ADBLOCK;
					 adlen-=CRYPTO_ADBLOCK;
				 }
				 else 
				 {
					 auth_bytes += adlen;
					 adlen=0;
				 }
			}
		}

		// Tag production 

		//1. Permutation call
		FPerm(BlockLastInput,Tag);
		//2. Key injection
		for(unsigned i=0; i<CRYPTO_KEYBYTES; ++i) 
		{
				Tag[64-CRYPTO_KEYBYTES+i] ^= k[i];
		}

		//3. Truncation
		if(clen!=CRYPTO_ABYTES)//Incorrect tag length
			return -1;

		for(unsigned i=0; i<CRYPTO_ABYTES; ++i)
		{
			if(c[(*mlen)+i] != Tag[i])
			{
				for(unsigned j=0; j< (*mlen); ++j)//Erasing decryption result
					m[j]=0;
				return -1; //Invalid
			}
		}
       return 0;
     }
Example #2
0
int crypto_aead_encrypt(
       unsigned char *c,unsigned long long *clen,
       const unsigned char *m,unsigned long long mlen,
       const unsigned char *ad,unsigned long long adlen,
       const unsigned char *nsec,
       const unsigned char *npub,
       const unsigned char *k
     )

     {
		 Init();//Initializing GF(256) multiplication table for AES

		 if(clen==NULL)
			 return -1;
		 if((mlen==0) && (adlen==0))
		 {
			 *clen=0;
			 return 0;
		 }

		 //Assume that we do encryption and/or authentication so we need a key and a ciphertext pointer valid
		 if( (k==NULL) || (c==NULL) )
			 return -2;

		 if(npub==NULL)
			 return -7;

		 //Initializing constants
		unsigned char D0[2];
		D0[0] = CRYPTO_NPUBBYTES*8; //nonce length in bits, zero for 256-bit nonce
		D0[1] = CRYPTO_KEYBYTES*8; //key length in bits
		(*clen)=0;
		 
		 //Block variables
		 unsigned char BlockInput[64];  //V1 - input to the first layer call of F
			 unsigned char BlockMiddle[64];  //W1 - output of the first layer call of F
			 unsigned char BlockOutput[64];  //Y1 - output of the second layer call of F
			
		 unsigned char BlockLastInput[64];  //Z1 - input to the last call of F
		 memset(BlockLastInput,0,64);
		 unsigned char Tag[64]; //Tag output
		 
		 unsigned long long encrypted_bytes=0;//Encrypted bytes counter
		 

		 //Encryption part
		 if(mlen!=0)
		 {
			 if(m==NULL)
			 {
				 //Clearing variables
				for(unsigned i=0; i<64; ++i)
					BlockInput[i] = BlockMiddle[i] = BlockOutput[i] = BlockLastInput[i] = 0;
				return -3;
			 }
				 
			 unsigned long long mblock_counter=1;   //Message block counter
			 
			 while((mlen>0))
			 {
				 /* I. First layer */

				 //1. Domain-separation constant
				 BlockInput[1] = D0[1]; 
				 if(mlen>= CRYPTO_MBLOCK)
					 BlockInput[0] = D0[0];
				 else //Last incomplete block
					 BlockInput[0] = D0[0]+1;

				 //2. Counter
				 for(unsigned i=0; i<CRYPTO_COUNTERBYTES; ++i)
				 {
					 BlockInput[i+2] = (i<sizeof(mblock_counter))?(mblock_counter>>(8*i))&0xff :0;//copying counter bytewise
				 }
				 
				 //3. Nonce
				 for(unsigned i=0; i<CRYPTO_NPUBBYTES; ++i) 
				 {
					 BlockInput[i+2+CRYPTO_COUNTERBYTES] = npub[i];
				 }

				 //4. Key
				 for(unsigned i=0; i<CRYPTO_KEYBYTES; ++i) 
				 {
					 BlockInput[i+2+CRYPTO_COUNTERBYTES+CRYPTO_NPUBBYTES] = k[i];
				 }	 

				 //5. Permutation call
				 FPerm(BlockInput, BlockMiddle); //First layer call to F

				

				 /* II. Encryption*/

				 if(mlen>=CRYPTO_MBLOCK)//Full block encryption
				 {
					 for(unsigned i=0; i<CRYPTO_MBLOCK; ++i)
					 {
						 BlockMiddle[i+2] ^= m[encrypted_bytes+i];
						 c[encrypted_bytes+i] = BlockMiddle[i+2];
						 
					 }
					 BlockMiddle[1] =  D0[1];
					 BlockMiddle[0] = D0[0]+2;  //New Di constant

				 }

				 else //Last incomplete block
				 {
					 for(unsigned i=0; i<(unsigned)mlen; ++i)//Incomplete block Encryption
					 {
						 BlockMiddle[i+2] ^= m[encrypted_bytes+i];
						 c[encrypted_bytes+i] = BlockMiddle[i+2];						 
					 }
					 for(unsigned i=(unsigned)mlen; i<CRYPTO_MBLOCK; ++i)
					 {
						 BlockMiddle[i+2] ^=  (unsigned char)mlen;  //Extra Padding: extra bytes filled with the last block length in bytes
					 }

					 BlockMiddle[1] =  D0[1];
					 BlockMiddle[0] = D0[0]+3;  //New Di constant
				 }

				 //III. Second permutation call
				 //1. Call
				 FPerm(BlockMiddle, BlockOutput); //Second layer call to F
				 
				 //2. Buffer update
				 for(unsigned i=0; i<64-2-CRYPTO_KEYBYTES; ++i)//Adding the output to tag preparation buffer
				 {
					 BlockLastInput[i+2] ^= BlockOutput[i+2];
				 }


				 //Counters increment
				 mblock_counter++;
				 if(mlen>=CRYPTO_MBLOCK)
				 {					 
					 encrypted_bytes += CRYPTO_MBLOCK;
					 mlen-=CRYPTO_MBLOCK;
				 }
				 else 
				 {
					 encrypted_bytes += mlen;
					 mlen=0;
				 }
				 (*clen) = encrypted_bytes;
			 }
		 }

		//Associated data part	  
		if(adlen!=0)
		{
			if(ad==NULL)
			{
				//Clearing variables
				for(unsigned i=0; i<64; ++i)
					BlockInput[i] = BlockMiddle[i] = BlockOutput[i] = BlockLastInput[i] = 0;
				return -4;
			}

			 unsigned long long adblock_counter=1;   //AD block counter
			 unsigned long long auth_bytes=0;

			while(adlen>0)
			{
				//1. Constant
				BlockInput[1] = D0[1];
				if(adlen>= CRYPTO_ADBLOCK)
					 BlockInput[0] = D0[0]+4;
				 else //Last incomplete block
					 BlockInput[0] = D0[0]+5;


				//2. Counter
				for(unsigned i=0; i<CRYPTO_KEYBYTES; ++i)
					BlockInput[i+2] =  (i<sizeof(adblock_counter))? (adblock_counter>>(8*i))&0xff:0;//copying counter bytewise

				//3. AD block
				if(adlen >= CRYPTO_ADBLOCK) //Filling AD block
				{
					for(unsigned i=0; i<CRYPTO_ADBLOCK; ++i)
						BlockInput[i+2+CRYPTO_KEYBYTES] = ad[auth_bytes+i];
					
				}
				else //Last incomplete block
				{
					for(unsigned i=0; i<adlen; ++i)
						BlockInput[i+2+CRYPTO_KEYBYTES] = ad[auth_bytes+i];
					for(unsigned i=(unsigned)adlen; i<CRYPTO_ADBLOCK; ++i)
						BlockInput[i+2+CRYPTO_KEYBYTES] = (unsigned char)adlen;
				}

				//4. Key
				for(unsigned i=0; i<CRYPTO_KEYBYTES; ++i) 
				{
					 BlockInput[i+CRYPTO_ADBLOCK+CRYPTO_KEYBYTES+2] = k[i];
				}
				

				//5.Call to the F permutation

				FPerm(BlockInput,BlockOutput);//Call to the F permutation

				 for(unsigned i=0; i<64-2-CRYPTO_KEYBYTES; ++i)//Adding the output to Z
				 {
					 BlockLastInput[i+2] ^= BlockOutput[i+2];
				 }

				//Counters increment
				 adblock_counter++;
				 if(adlen>=CRYPTO_ADBLOCK)
				 {
					 auth_bytes += CRYPTO_ADBLOCK;
					 adlen-=CRYPTO_ADBLOCK;
				 }
				 else 
				 {
					 auth_bytes += adlen;
					 adlen=0;
				 }
			}
		}

		// Tag production 
		for(unsigned i=0; i<CRYPTO_KEYBYTES; ++i) //Key to the Z input
			BlockLastInput[64-CRYPTO_KEYBYTES+i] = k[i];
		 BlockLastInput[0] = D0[0]+6;
		 BlockLastInput[1] = D0[1];

		//1. Permutation call
		FPerm(BlockLastInput,Tag);
		//2. Key injection
		for(unsigned i=0; i<CRYPTO_KEYBYTES; ++i) 
		{
				Tag[64-CRYPTO_KEYBYTES+i] ^= k[i];
		}

		//3. Truncation
		for(unsigned i=0; i<CRYPTO_ABYTES; ++i)
			c[(*clen)+i] = Tag[i];
		*clen += CRYPTO_ABYTES;


		//Clearing variables
		for(unsigned i=0; i<64; ++i)
			BlockInput[i] = BlockMiddle[i] = BlockOutput[i] = BlockLastInput[i] = 0;
		

	   
		return 0;
     }
Example #3
0
int genKAT(unsigned long long plaintext_length, unsigned long long ad_length)
{
	if((plaintext_length > (1<<31)) || (ad_length> (1<<31)))
		return 1;
	Init();   //For generating plaintext
	unsigned char *key = (unsigned char*)malloc(crypto_aead_KEYBYTES);  
	unsigned char *nonce = (unsigned char*)malloc(crypto_aead_NPUBBYTES);

 	unsigned char *ciphertext;
	unsigned long long ciphertext_length;
	unsigned long long decrypted_length;

	unsigned char *plaintext = (unsigned char*)malloc((size_t)plaintext_length);
	unsigned char *plaintext_decrypted = (unsigned char*)malloc((size_t)plaintext_length);
	plaintext_length = (size_t)plaintext_length;
	if(plaintext==NULL || plaintext_decrypted==NULL)
		return 1;

	unsigned char *associated_data = (unsigned char*)malloc((size_t)ad_length);
	if(associated_data==NULL)
	{
		free(plaintext);
		free(plaintext_decrypted);
		return 1;
	}

	//Plaintext initialization
	unsigned char StateIn[64];
	memset(StateIn,0,64);
	unsigned char StateOut[64];
	int counter= (int)plaintext_length;
	unsigned char *dest_pointer = plaintext;
	while(counter>0)
	{
		FPerm(StateIn,StateOut);
		unsigned to_copy = (counter<64)?counter:64;
		memcpy(dest_pointer,StateOut,to_copy);
		dest_pointer += to_copy;
		(*((unsigned*)StateIn))++;
		counter-= to_copy;
	}

	//AD initialization
	counter= (int)
		ad_length;
	dest_pointer = associated_data;
	while(counter>0)
	{
		FPerm(StateIn,StateOut);
		unsigned to_copy = (counter<64)?counter:64;
		memcpy(dest_pointer,StateOut,to_copy);
		dest_pointer += to_copy;
		(*((unsigned*)StateIn))++;
		counter-= to_copy;
	}

	//Key setting
	FPerm(StateIn,StateOut);
	memcpy(key,StateOut,crypto_aead_KEYBYTES);
	(*((unsigned*)StateIn))++;

	//Nonce setting
	FPerm(StateIn,StateOut);
	memcpy(nonce,StateOut,crypto_aead_NPUBBYTES);
	(*((unsigned*)StateIn))++;

	//Ciphertext memory allocation
	ciphertext = (unsigned char*)malloc((size_t)(plaintext_length+crypto_aead_ABYTES));
	if(ciphertext==NULL)
	{
		free(plaintext);
		free(plaintext_decrypted);
		free(associated_data);
		return 1;
	}

	//Writing input
	FILE *fp=fopen("out.log","w+");
	fprintf(fp, "PLAINTEXT (%llu bytes):\n",plaintext_length);
	for(unsigned i=0; i<plaintext_length; ++i)
	{
		fprintf(fp, "0x%.02x ",plaintext[i]);
		if(i%20==19)
			fprintf(fp, "\n");
	}

	fprintf(fp, "\nASSOCIATED DATA  (%llu bytes):\n", ad_length);
	for(unsigned i=0; i<ad_length; ++i)
	{
		fprintf(fp, "0x%.02x ",associated_data[i]);
		if(i%20==19)
			fprintf(fp, "\n");
	}
	fprintf(fp, "\n");
		fprintf(fp, "\nKEY  (%d bytes):\n", crypto_aead_KEYBYTES);
	for(unsigned i=0; i<crypto_aead_KEYBYTES; ++i)
		fprintf(fp, "0x%.02x ",key[i]);
	fprintf(fp, "\n");
		 

	//Encryption and decryption
#ifdef EXTRANONCE 	//ExtraNonce
	crypto_aead_encrypt_no_nonce(ciphertext,&ciphertext_length,plaintext,plaintext_length,associated_data, ad_length,NULL,nonce,key);

	int result = crypto_aead_decrypt(plaintext_decrypted,&decrypted_length,NULL,ciphertext,ciphertext_length,associated_data, ad_length,nonce,key);
	
#else	   	//Normal nonce
	crypto_aead_encrypt(ciphertext,&ciphertext_length,plaintext,plaintext_length,associated_data, ad_length,NULL,nonce,key);
	int result = crypto_aead_decrypt(plaintext_decrypted,&decrypted_length,NULL,ciphertext,ciphertext_length,associated_data, ad_length,nonce,key);
	
#endif

	if(decrypted_length != plaintext_length)
		printf("Plaintext length mismatch\n");

	//Writing outputs
	fprintf(fp, "\nNONCE  (%d bytes):\n", crypto_aead_NPUBBYTES);
	for(unsigned i=0; i<crypto_aead_NPUBBYTES; ++i)
		fprintf(fp, "0x%.02x ",nonce[i]);
	fprintf(fp, ".\n");
	printf("Decryption result: %d\n",result);

	  
	fprintf(fp, "\nCIPHERTEXT (%llu bytes):\n", ciphertext_length);
	for(unsigned i=0; i<ciphertext_length; ++i)
	{
		fprintf(fp, "0x%.02x ",ciphertext[i]);
		if(i%20==19)
			fprintf(fp, "\n");
		if(i == ciphertext_length - crypto_aead_ABYTES-1)
			fprintf(fp, " || ");
	}
	fprintf(fp, ".\n");

	fprintf(fp, "\nDECRYPTED PLAINTEXT  (%llu bytes):\n", decrypted_length);
	for(unsigned i=0; i<decrypted_length; ++i)
	{
		fprintf(fp, "0x%.02x ",plaintext_decrypted[i]);
		if(i%20==19)
			fprintf(fp, "\n");
	}
	fprintf(fp, ".\n");
	fclose(fp);


	free(plaintext);
	free(ciphertext);
	free(plaintext_decrypted);
	free(associated_data);
		return 0;



}
Example #4
0
int GenerateNonce(unsigned char* output, const unsigned char *m,unsigned long long mlen,
       const unsigned char *ad,unsigned long long adlen,
       const unsigned char *k)
	   //Generate a nonce as a hash of the plaintext & AD by the AESQ-sponge function
{
	//Does not work for keys longer than 192 bits
	if(CRYPTO_KEYBYTES >24)
	{
		memset(output,0,CRYPTO_NPUBBYTES);
		return -1;
	}

	unsigned char State[64];
	unsigned char Buffer[CRYPTO_KEYBYTES+2+2*CRYPTO_LENGTH];
	unsigned char StateOut[64];
	memset(State,0,64);

	//Plaintext length
	for(unsigned i=0; i<CRYPTO_LENGTH; ++i)
		Buffer[i] = (i<sizeof(mlen))? (mlen>>(8*i))&0xff:0;

	//Associated data length
	for(unsigned i=0; i<CRYPTO_LENGTH; ++i)
		Buffer[i+CRYPTO_LENGTH] =  (i<sizeof(adlen))?(adlen>>(8*i))&0xff:0;

	//Key length
	Buffer[2*CRYPTO_LENGTH] = CRYPTO_KEYBYTES;

	//Nonce length
	Buffer[2*CRYPTO_LENGTH+1] = CRYPTO_NPUBBYTES;

	//Add key 
	for(unsigned i=0; i<CRYPTO_KEYBYTES; ++i)
		Buffer[i+CRYPTO_LENGTH*2+2] = k[i];

	unsigned state_index=0;
	unsigned long long message_index=0;
	unsigned long long ad_index=0;
	
	for(unsigned i=0; (i<CRYPTO_KEYBYTES+2+2*CRYPTO_LENGTH); ++i)//Feeding buffer
	{
		State[state_index] ^= Buffer[i];
		state_index++;
		if(state_index==64-2*CRYPTO_KEYBYTES)//end of state
		{
			FPerm(State,StateOut);
			state_index = 0;
			for(unsigned j=0; j<64; ++j) State[j] = StateOut[j];
		}
	}

	while(mlen>0)//Feeding plaintext
	{
		State[state_index] ^= m[message_index];
		state_index++;
		message_index++;
		mlen--;
		if(state_index==64-2*CRYPTO_KEYBYTES)//end of state
		{
			FPerm(State,StateOut);
			state_index = 0;
			for(unsigned j=0; j<64; ++j) State[j] = StateOut[j];
		}
	}
	while(adlen>0) //Filling AD
	{
		State[state_index] ^= ad[ad_index];
		state_index++;
		ad_index++;
		adlen--;
		if(state_index==64-2*CRYPTO_KEYBYTES)//end of state
		{
			FPerm(State,StateOut);
			state_index = 0;
			for(unsigned j=0; j<64; ++j) State[j] = StateOut[j];
		}
	}
	//end of data
	//Padding 10*1
	State[state_index] ^= 1;
	if(state_index==64-2*CRYPTO_KEYBYTES)//end of state
	{
		FPerm(State,StateOut);
		state_index = 0;
		for(unsigned j=0; j<64; ++j) State[j] = StateOut[j];
	}
	while(state_index <63-2*CRYPTO_KEYBYTES)
	{
		State[state_index] ^= 0;
		state_index++;
	}
	State[state_index] ^= 1;//state_index must be =63 - 2*CRYPTO_KEYBYTES
	FPerm(State,StateOut);
	for(unsigned j=0; j<CRYPTO_NPUBBYTES; ++j)
		output[j] = StateOut[j];

	return 0;

}
Example #5
0
int benchmark(unsigned long long plaintext_length, unsigned long long ad_length)
{
	if ((plaintext_length >(1 << 31)) || (ad_length> (1 << 31)))
		return 1;
	Init();   //For generating plaintext
	unsigned char *key = (unsigned char*)malloc(key_bytes);
	unsigned char *nonce = (unsigned char*)malloc(nonce_bytes);

	unsigned char *ciphertext;
	unsigned long long ciphertext_length;
	unsigned long long decrypted_length;

	unsigned char *plaintext = (unsigned char*)malloc((size_t)plaintext_length);
	unsigned char *plaintext_decrypted = (unsigned char*)malloc((size_t)plaintext_length);
	plaintext_length = (size_t)plaintext_length;
	if (plaintext == NULL || plaintext_decrypted == NULL)
		return 1;

	unsigned char *associated_data = (unsigned char*)malloc((size_t)ad_length);
	if (associated_data == NULL)
	{
		free(plaintext);
		free(plaintext_decrypted);
		return 1;
	}

	//Plaintext initialization
	unsigned char StateIn[64];
	memset(StateIn, 0, 64);
	unsigned char StateOut[64];
	int counter = (int)plaintext_length;
	unsigned char *dest_pointer = plaintext;
	while (counter>0)
	{
		FPerm(StateIn, StateOut);
		unsigned to_copy = (counter<64) ? counter : 64;
		memcpy(dest_pointer, StateOut, to_copy);
		dest_pointer += to_copy;
		(*((unsigned*)StateIn))++;
		counter -= to_copy;
	}

	//AD initialization
	counter = (int)
		ad_length;
	dest_pointer = associated_data;
	while (counter>0)
	{
		FPerm(StateIn, StateOut);
		unsigned to_copy = (counter<64) ? counter : 64;
		memcpy(dest_pointer, StateOut, to_copy);
		dest_pointer += to_copy;
		(*((unsigned*)StateIn))++;
		counter -= to_copy;
	}

	//Key setting
	FPerm(StateIn, StateOut);
	memcpy(key, StateOut, key_bytes);
	(*((unsigned*)StateIn))++;

	//Nonce setting
	FPerm(StateIn, StateOut);
	memcpy(nonce, StateOut, nonce_bytes);
	(*((unsigned*)StateIn))++;

	//Ciphertext memory allocation
	ciphertext = (unsigned char*)malloc((size_t)(plaintext_length + tag_bytes));
	if (ciphertext == NULL)
	{
		free(plaintext);
		free(plaintext_decrypted);
		free(associated_data);
		return 1;
	}

	uint64_t start_time, mid_time, end_time;
	uint32_t start_ptr, mid_ptr, end_ptr;

	start_time = __rdtscp(&start_ptr);
#ifdef EXTRANONCE 	//ExtraNonce
	crypto_aead_encrypt_no_nonce(ciphertext, &ciphertext_length, plaintext, plaintext_length, associated_data, ad_length, NULL, nonce, key);
#else
	crypto_aead_encrypt(ciphertext, &ciphertext_length, plaintext, plaintext_length, associated_data, ad_length, NULL, nonce, key);
#endif
	mid_time = __rdtscp(&mid_ptr);
	float speed = (float)(mid_time - start_time) / (plaintext_length + ad_length);
	printf("PAEQ-128: %d bytes encrypted, %2.2f cpb\n", (uint32_t)(plaintext_length + ad_length), speed);
	mid_time = __rdtscp(&mid_ptr);
	int result = crypto_aead_decrypt(plaintext_decrypted, &decrypted_length, NULL, ciphertext, ciphertext_length, associated_data, ad_length, nonce, key);
	end_time = __rdtscp(&end_ptr);
	speed = (float)(end_time - mid_time) / (plaintext_length + ad_length);
	printf("PAEQ-128: %d bytes decrypted, %2.2f cpb\n", (uint32_t)(plaintext_length + ad_length), speed);

	if (decrypted_length != plaintext_length)
		printf("Plaintext length mismatch\n");
	if (result!=0)
		printf("Decryption result: %d\n", result);

	free(ciphertext);
	free(plaintext_decrypted);
	free(associated_data);
	return 0;
}