// File: /workspace/github_c_makefile_star2_O0/mjosaarinen[P]brutus/crypto_aead/paeq160/ref/encrypt.cpp
// Function: GenerateNonce(unsigned char*, unsigned char const*, unsigned long long, unsigned char const*, unsigned long long, unsigned char const*)
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;

}

// Assembly:
subq $0x138, %rsp            # imm = 0x138
movq %rdi, 0x130(%rsp)
movq %rsi, 0x128(%rsp)
movq %rdx, 0x120(%rsp)
movq %rcx, 0x118(%rsp)
movq %r8, 0x110(%rsp)
movq %r9, 0x108(%rsp)
leaq 0xc0(%rsp), %rdi
xorl %esi, %esi
movl $0x40, %edx
callq 0x1030
movl $0x0, 0x4c(%rsp)
cmpl $0xc, 0x4c(%rsp)
jae 0x1a9d
movl 0x4c(%rsp), %eax
cmpq $0x8, %rax
jae 0x1a75
movq 0x120(%rsp), %rax
movl 0x4c(%rsp), %ecx
shll $0x3, %ecx
movl %ecx, %ecx
shrq %cl, %rax
andq $0xff, %rax
movq %rax, 0x10(%rsp)
jmp 0x1a7e
xorl %eax, %eax
movq %rax, 0x10(%rsp)
jmp 0x1a7e
movq 0x10(%rsp), %rax
movb %al, %cl
movl 0x4c(%rsp), %eax
movb %cl, 0x90(%rsp,%rax)
movl 0x4c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x4c(%rsp)
jmp 0x1a43
movl $0x0, 0x48(%rsp)
cmpl $0xc, 0x48(%rsp)
jae 0x1b04
movl 0x48(%rsp), %eax
cmpq $0x8, %rax
jae 0x1ad7
movq 0x110(%rsp), %rax
movl 0x48(%rsp), %ecx
shll $0x3, %ecx
movl %ecx, %ecx
shrq %cl, %rax
andq $0xff, %rax
movq %rax, 0x8(%rsp)
jmp 0x1ae0
xorl %eax, %eax
movq %rax, 0x8(%rsp)
jmp 0x1ae0
movq 0x8(%rsp), %rax
movb %al, %cl
movl 0x48(%rsp), %eax
addl $0xc, %eax
movl %eax, %eax
movb %cl, 0x90(%rsp,%rax)
movl 0x48(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x48(%rsp)
jmp 0x1aa5
movb $0x14, 0xa8(%rsp)
movb $0x14, 0xa9(%rsp)
movl $0x0, 0x44(%rsp)
cmpl $0x14, 0x44(%rsp)
jae 0x1b52
movq 0x108(%rsp), %rax
movl 0x44(%rsp), %ecx
movb (%rax,%rcx), %cl
movl 0x44(%rsp), %eax
addl $0x18, %eax
addl $0x2, %eax
movl %eax, %eax
movb %cl, 0x90(%rsp,%rax)
movl 0x44(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x44(%rsp)
jmp 0x1b1c
movl $0x0, 0x40(%rsp)
movq $0x0, 0x38(%rsp)
movq $0x0, 0x30(%rsp)
movl $0x0, 0x2c(%rsp)
cmpl $0x2e, 0x2c(%rsp)
jae 0x1c0f
movl 0x2c(%rsp), %eax
movzbl 0x90(%rsp,%rax), %edx
movl 0x40(%rsp), %eax
movzbl 0xc0(%rsp,%rax), %ecx
xorl %edx, %ecx
movb %cl, 0xc0(%rsp,%rax)
movl 0x40(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x40(%rsp)
cmpl $0x18, 0x40(%rsp)
jne 0x1bfd
leaq 0xc0(%rsp), %rdi
leaq 0x50(%rsp), %rsi
callq 0x1090
movl $0x0, 0x40(%rsp)
movl $0x0, 0x28(%rsp)
cmpl $0x40, 0x28(%rsp)
jae 0x1bfb
movl 0x28(%rsp), %eax
movb 0x50(%rsp,%rax), %cl
movl 0x28(%rsp), %eax
movb %cl, 0xc0(%rsp,%rax)
movl 0x28(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x28(%rsp)
jmp 0x1bd4
jmp 0x1bfd
jmp 0x1bff
movl 0x2c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x2c(%rsp)
jmp 0x1b74
jmp 0x1c11
cmpq $0x0, 0x120(%rsp)
jbe 0x1cca
movq 0x128(%rsp), %rax
movq 0x38(%rsp), %rcx
movzbl (%rax,%rcx), %edx
movl 0x40(%rsp), %eax
movzbl 0xc0(%rsp,%rax), %ecx
xorl %edx, %ecx
movb %cl, 0xc0(%rsp,%rax)
movl 0x40(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x40(%rsp)
movq 0x38(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x38(%rsp)
movq 0x120(%rsp), %rax
addq $-0x1, %rax
movq %rax, 0x120(%rsp)
cmpl $0x18, 0x40(%rsp)
jne 0x1cc5
leaq 0xc0(%rsp), %rdi
leaq 0x50(%rsp), %rsi
callq 0x1090
movl $0x0, 0x40(%rsp)
movl $0x0, 0x24(%rsp)
cmpl $0x40, 0x24(%rsp)
jae 0x1cc3
movl 0x24(%rsp), %eax
movb 0x50(%rsp,%rax), %cl
movl 0x24(%rsp), %eax
movb %cl, 0xc0(%rsp,%rax)
movl 0x24(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x24(%rsp)
jmp 0x1c9c
jmp 0x1cc5
jmp 0x1c11
jmp 0x1ccc
cmpq $0x0, 0x110(%rsp)
jbe 0x1d85
movq 0x118(%rsp), %rax
movq 0x30(%rsp), %rcx
movzbl (%rax,%rcx), %edx
movl 0x40(%rsp), %eax
movzbl 0xc0(%rsp,%rax), %ecx
xorl %edx, %ecx
movb %cl, 0xc0(%rsp,%rax)
movl 0x40(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x40(%rsp)
movq 0x30(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x30(%rsp)
movq 0x110(%rsp), %rax
addq $-0x1, %rax
movq %rax, 0x110(%rsp)
cmpl $0x18, 0x40(%rsp)
jne 0x1d80
leaq 0xc0(%rsp), %rdi
leaq 0x50(%rsp), %rsi
callq 0x1090
movl $0x0, 0x40(%rsp)
movl $0x0, 0x20(%rsp)
cmpl $0x40, 0x20(%rsp)
jae 0x1d7e
movl 0x20(%rsp), %eax
movb 0x50(%rsp,%rax), %cl
movl 0x20(%rsp), %eax
movb %cl, 0xc0(%rsp,%rax)
movl 0x20(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x20(%rsp)
jmp 0x1d57
jmp 0x1d80
jmp 0x1ccc
movl 0x40(%rsp), %eax
movzbl 0xc0(%rsp,%rax), %ecx
xorl $0x1, %ecx
movb %cl, 0xc0(%rsp,%rax)
cmpl $0x18, 0x40(%rsp)
jne 0x1ded
leaq 0xc0(%rsp), %rdi
leaq 0x50(%rsp), %rsi
callq 0x1090
movl $0x0, 0x40(%rsp)
movl $0x0, 0x1c(%rsp)
cmpl $0x40, 0x1c(%rsp)
jae 0x1deb
movl 0x1c(%rsp), %eax
movb 0x50(%rsp,%rax), %cl
movl 0x1c(%rsp), %eax
movb %cl, 0xc0(%rsp,%rax)
movl 0x1c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x1c(%rsp)
jmp 0x1dc4
jmp 0x1ded
jmp 0x1def
cmpl $0x17, 0x40(%rsp)
jae 0x1e19
movl 0x40(%rsp), %eax
movzbl 0xc0(%rsp,%rax), %ecx
xorl $0x0, %ecx
movb %cl, 0xc0(%rsp,%rax)
movl 0x40(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x40(%rsp)
jmp 0x1def
movl 0x40(%rsp), %eax
movzbl 0xc0(%rsp,%rax), %ecx
xorl $0x1, %ecx
movb %cl, 0xc0(%rsp,%rax)
leaq 0xc0(%rsp), %rdi
leaq 0x50(%rsp), %rsi
callq 0x1090
movl $0x0, 0x18(%rsp)
cmpl $0x14, 0x18(%rsp)
jae 0x1e74
movl 0x18(%rsp), %eax
movb 0x50(%rsp,%rax), %dl
movq 0x130(%rsp), %rax
movl 0x18(%rsp), %ecx
movb %dl, (%rax,%rcx)
movl 0x18(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x18(%rsp)
jmp 0x1e49
xorl %eax, %eax
addq $0x138, %rsp            # imm = 0x138
retq
nop