// File: /workspace/github_c_makefile_star2_O0/mjosaarinen[P]brutus/crypto_aead/aescopav2/ref/encrypt.c
// Function: crypto_aead_encrypt
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
     )
{
	unsigned char* macdata;
	const unsigned char* in = m;
	unsigned char* out = c;
	unsigned long long remaining = mlen;
	int partial;

	block_t V;
	block_t lastblock;
	block_t block, Lup, Ldown;
	block_t checksum = { 0 };
	block_t T;
	block_t LL = { 0 };

	AES_ENCRYPT(LL, LL, k); /* LL = AES(LL) */

	/* last byte is bit P. 
	   P=1 for partial last block, 
	   P=0 otherwise. */
	*clen = (mlen == 0 ? 16 : ((mlen+15)/16)*16) + 16 + 1; 
	partial = (*clen > mlen + 16 + 1);

	/* store bit P */
	c[*clen-1] = partial;

	/* mac AD + nonce */
	macdata = malloc(adlen + 16);
	memcpy(macdata, ad, adlen);
	memcpy(macdata+adlen, npub, 16);
	mac(V, macdata, adlen+16, LL, k);
	free(macdata);

	xor_block(lastblock, LL, V); /* lastblock = LL ^ V */

	gf128_mul3(Lup, LL); /* Lup = 3*LL */
	gf128_mul2(Ldown, LL); /* Ldown = 2*LL */

	while (remaining >= 16) { 
		xor_block(checksum, checksum, in);
		xor_block(block, in, Lup);
		AES_ENCRYPT(block, block, k);

		xor_block(block, block, lastblock);
		copy_block(lastblock, block);

		AES_ENCRYPT(block, block, k);
		xor_block(out, block, Ldown);

		if (remaining != 16) { /* don't double after full last block */
			gf128_mul2(Lup, Lup);
			gf128_mul2(Ldown, Ldown);
		}

		in += 16;
		out += 16;
		remaining -= 16;
	}

	/* if last block is partial */
	if (partial) {
		/* padding */
		block_t padmsg = { 0 };
		unsigned long long i;

		for (i = 0; i < remaining; i++) {
			padmsg[i] = in[i];
		}
		padmsg[i] = 0x80; /* padding */

		gf128_mul7(Lup, Lup);

		xor_block(checksum, checksum, padmsg);
		xor_block(block, padmsg, Lup);
		AES_ENCRYPT(block, block, k);

		xor_block(block, block, lastblock);
		copy_block(lastblock, block);

		AES_ENCRYPT(block, block, k);
		xor_block(out, block, Ldown);

		out += 16;
	}

	/* compute tag */
	gf128_mul3(LL, Lup);
	xor_block(checksum, checksum, LL);
	AES_ENCRYPT(checksum, checksum, k);

	xor_block(checksum, checksum, lastblock);

	AES_ENCRYPT(checksum, checksum, k);
	gf128_mul7(LL, Ldown);
	xor_block(T, checksum, LL);

	copy_block(out, T);

	return 0;
}

// Assembly:
subq $0xf8, %rsp
movq 0x110(%rsp), %rax
movq 0x108(%rsp), %rax
movq 0x100(%rsp), %rax
movq %rdi, 0xf0(%rsp)
movq %rsi, 0xe8(%rsp)
movq %rdx, 0xe0(%rsp)
movq %rcx, 0xd8(%rsp)
movq %r8, 0xd0(%rsp)
movq %r9, 0xc8(%rsp)
movq 0xe0(%rsp), %rax
movq %rax, 0xb8(%rsp)
movq 0xf0(%rsp), %rax
movq %rax, 0xb0(%rsp)
movq 0xd8(%rsp), %rax
movq %rax, 0xa8(%rsp)
leaq 0x40(%rsp), %rdi
xorl %esi, %esi
movl $0x10, %edx
callq 0x1060
leaq 0x20(%rsp), %rdi
xorl %esi, %esi
movl $0x10, %edx
callq 0x1060
leaq 0x20(%rsp), %rdi
leaq 0x20(%rsp), %rsi
movq 0x110(%rsp), %rdx
callq 0x1150
cmpq $0x0, 0xd8(%rsp)
jne 0x2b0e
movl $0x10, %eax
movq %rax, (%rsp)
jmp 0x2b26
movq 0xd8(%rsp), %rax
addq $0xf, %rax
shrq $0x4, %rax
shlq $0x4, %rax
movq %rax, (%rsp)
movq (%rsp), %rcx
addq $0x10, %rcx
addq $0x1, %rcx
movq 0xe8(%rsp), %rax
movq %rcx, (%rax)
movq 0xe8(%rsp), %rax
movq (%rax), %rax
movq 0xd8(%rsp), %rcx
addq $0x10, %rcx
addq $0x1, %rcx
cmpq %rcx, %rax
seta %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, 0xa4(%rsp)
movl 0xa4(%rsp), %eax
movb %al, %dl
movq 0xf0(%rsp), %rax
movq 0xe8(%rsp), %rcx
movq (%rcx), %rcx
subq $0x1, %rcx
movb %dl, (%rax,%rcx)
movq 0xc8(%rsp), %rdi
addq $0x10, %rdi
callq 0x1080
movq %rax, 0xc0(%rsp)
movq 0xc0(%rsp), %rdi
movq 0xd0(%rsp), %rsi
movq 0xc8(%rsp), %rdx
callq 0x1130
movq 0xc0(%rsp), %rax
movq 0xc8(%rsp), %rcx
movq 0x108(%rsp), %rdx
movq (%rdx), %rsi
movq %rsi, (%rax,%rcx)
movq 0x8(%rdx), %rdx
movq %rdx, 0x8(%rax,%rcx)
leaq 0x90(%rsp), %rdi
movq 0xc0(%rsp), %rsi
movq 0xc8(%rsp), %rdx
addq $0x10, %rdx
leaq 0x20(%rsp), %rcx
movq 0x110(%rsp), %r8
callq 0x1120
movq 0xc0(%rsp), %rdi
callq 0x10a0
leaq 0x80(%rsp), %rdi
leaq 0x20(%rsp), %rsi
leaq 0x90(%rsp), %rdx
callq 0x2990
leaq 0x60(%rsp), %rdi
leaq 0x20(%rsp), %rsi
callq 0x2950
leaq 0x50(%rsp), %rdi
leaq 0x20(%rsp), %rsi
callq 0x29f0
cmpq $0x10, 0xa8(%rsp)
jb 0x2d73
leaq 0x40(%rsp), %rdi
leaq 0x40(%rsp), %rsi
movq 0xb8(%rsp), %rdx
callq 0x2990
leaq 0x70(%rsp), %rdi
movq 0xb8(%rsp), %rsi
leaq 0x60(%rsp), %rdx
callq 0x2990
leaq 0x70(%rsp), %rdi
leaq 0x70(%rsp), %rsi
movq 0x110(%rsp), %rdx
callq 0x1150
leaq 0x70(%rsp), %rdi
leaq 0x70(%rsp), %rsi
leaq 0x80(%rsp), %rdx
callq 0x2990
leaq 0x80(%rsp), %rdi
leaq 0x70(%rsp), %rsi
callq 0x26d0
leaq 0x70(%rsp), %rdi
leaq 0x70(%rsp), %rsi
movq 0x110(%rsp), %rdx
callq 0x1150
movq 0xb0(%rsp), %rdi
leaq 0x70(%rsp), %rsi
leaq 0x50(%rsp), %rdx
callq 0x2990
cmpq $0x10, 0xa8(%rsp)
je 0x2d32
leaq 0x60(%rsp), %rdi
leaq 0x60(%rsp), %rsi
callq 0x29f0
leaq 0x50(%rsp), %rdi
leaq 0x50(%rsp), %rsi
callq 0x29f0
movq 0xb8(%rsp), %rax
addq $0x10, %rax
movq %rax, 0xb8(%rsp)
movq 0xb0(%rsp), %rax
addq $0x10, %rax
movq %rax, 0xb0(%rsp)
movq 0xa8(%rsp), %rax
subq $0x10, %rax
movq %rax, 0xa8(%rsp)
jmp 0x2c5e
cmpl $0x0, 0xa4(%rsp)
je 0x2e96
leaq 0x10(%rsp), %rdi
xorl %esi, %esi
movl $0x10, %edx
callq 0x1060
movq $0x0, 0x8(%rsp)
movq 0x8(%rsp), %rax
cmpq 0xa8(%rsp), %rax
jae 0x2dd3
movq 0xb8(%rsp), %rax
movq 0x8(%rsp), %rcx
movb (%rax,%rcx), %cl
movq 0x8(%rsp), %rax
movb %cl, 0x10(%rsp,%rax)
movq 0x8(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x8(%rsp)
jmp 0x2d9b
movq 0x8(%rsp), %rax
movb $-0x80, 0x10(%rsp,%rax)
leaq 0x60(%rsp), %rdi
leaq 0x60(%rsp), %rsi
callq 0x2f40
leaq 0x40(%rsp), %rdi
leaq 0x40(%rsp), %rsi
leaq 0x10(%rsp), %rdx
callq 0x2990
leaq 0x70(%rsp), %rdi
leaq 0x10(%rsp), %rsi
leaq 0x60(%rsp), %rdx
callq 0x2990
leaq 0x70(%rsp), %rdi
leaq 0x70(%rsp), %rsi
movq 0x110(%rsp), %rdx
callq 0x1150
leaq 0x70(%rsp), %rdi
leaq 0x70(%rsp), %rsi
leaq 0x80(%rsp), %rdx
callq 0x2990
leaq 0x80(%rsp), %rdi
leaq 0x70(%rsp), %rsi
callq 0x26d0
leaq 0x70(%rsp), %rdi
leaq 0x70(%rsp), %rsi
movq 0x110(%rsp), %rdx
callq 0x1150
movq 0xb0(%rsp), %rdi
leaq 0x70(%rsp), %rsi
leaq 0x50(%rsp), %rdx
callq 0x2990
movq 0xb0(%rsp), %rax
addq $0x10, %rax
movq %rax, 0xb0(%rsp)
leaq 0x20(%rsp), %rdi
leaq 0x60(%rsp), %rsi
callq 0x2950
leaq 0x40(%rsp), %rdi
leaq 0x40(%rsp), %rsi
leaq 0x20(%rsp), %rdx
callq 0x2990
leaq 0x40(%rsp), %rdi
leaq 0x40(%rsp), %rsi
movq 0x110(%rsp), %rdx
callq 0x1150
leaq 0x40(%rsp), %rdi
leaq 0x40(%rsp), %rsi
leaq 0x80(%rsp), %rdx
callq 0x2990
leaq 0x40(%rsp), %rdi
leaq 0x40(%rsp), %rsi
movq 0x110(%rsp), %rdx
callq 0x1150
leaq 0x20(%rsp), %rdi
leaq 0x50(%rsp), %rsi
callq 0x2f40
leaq 0x30(%rsp), %rdi
leaq 0x40(%rsp), %rsi
leaq 0x20(%rsp), %rdx
callq 0x2990
movq 0xb0(%rsp), %rdi
leaq 0x30(%rsp), %rsi
callq 0x26d0
xorl %eax, %eax
addq $0xf8, %rsp
retq
nopl (%rax)