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

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

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

	/* verify that we have 16*x+1 bytes */
	if (clen % 16 != 1) {
		return -1;
	}

	/* Verify bit P */
	if (c[clen-1] > 1) {
		return -1;
	} else {
		partial = c[clen-1];
	}

	*mlen = clen - 16 - 1; /* provisional, will be adjusted later for incomplete last block */

	/* 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 */

	remaining = *mlen;
	while (remaining > 16) {
		xor_block(block, in, Ldown);
		AES_DECRYPT(newlastblock, block, k);

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

		AES_DECRYPT(block, block, k);
		xor_block(out, block, Lup);
		xor_block(checksum, checksum, out);

		gf128_mul2(Lup, Lup);
		gf128_mul2(Ldown, Ldown);

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

	/* verify correct length */
	if ((!partial && remaining != 16) || (partial && remaining == 0)) {
		return -1;
	}

	if (!partial) { /* full last block, normal processing */
		xor_block(block, in, Ldown);
		AES_DECRYPT(newlastblock, block, k);

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

		AES_DECRYPT(block, block, k);
		xor_block(out, block, Lup);
		xor_block(checksum, checksum, out);

		in += 16;
		out += 16;
		remaining -= 16;
	} else { /* last partial block remaining */
		int i, j;

		xor_block(block, in, Ldown);
		AES_DECRYPT(newlastblock, block, k);

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

		AES_DECRYPT(block, block, k);
		gf128_mul7(Lup, Lup);
		xor_block(newlastblock, block, Lup);
		xor_block(checksum, checksum, newlastblock);

		i = 15;
		while (i > 0 && newlastblock[i] == 0)
			--i;
		if ((newlastblock[i] != 0x80)) {
			return -1;
		}
		for (j = 0; j < i; j++) {
			out[j] = newlastblock[j];
		}

		/* adjust mlen */
		*mlen -= 16-i;

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

	/* 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(tag, checksum, LL);

	if (memcmp(tag, in, 16) == 0) {
		return 0;
	} else {
		return -1;
	}
}

// Assembly:
subq $0x108, %rsp            # imm = 0x108
movq 0x120(%rsp), %rax
movq 0x118(%rsp), %rax
movq 0x110(%rsp), %rax
movq %rdi, 0xf8(%rsp)
movq %rsi, 0xf0(%rsp)
movq %rdx, 0xe8(%rsp)
movq %rcx, 0xe0(%rsp)
movq %r8, 0xd8(%rsp)
movq %r9, 0xd0(%rsp)
movq 0xe0(%rsp), %rax
movq %rax, 0xc0(%rsp)
movq 0xf8(%rsp), %rax
movq %rax, 0xb8(%rsp)
leaq 0x60(%rsp), %rdi
xorl %esi, %esi
movl $0x10, %edx
callq 0x1060
leaq 0x10(%rsp), %rdi
xorl %esi, %esi
movl $0x10, %edx
callq 0x1060
leaq 0x10(%rsp), %rdi
leaq 0x10(%rsp), %rsi
movq 0x120(%rsp), %rdx
callq 0x1150
movq 0xd8(%rsp), %rax
andq $0xf, %rax
cmpq $0x1, %rax
je 0x306a
movl $0xffffffff, 0x104(%rsp) # imm = 0xFFFFFFFF
jmp 0x3658
movq 0xe0(%rsp), %rax
movq 0xd8(%rsp), %rcx
subq $0x1, %rcx
movzbl (%rax,%rcx), %eax
cmpl $0x1, %eax
jle 0x3097
movl $0xffffffff, 0x104(%rsp) # imm = 0xFFFFFFFF
jmp 0x3658
movq 0xe0(%rsp), %rax
movq 0xd8(%rsp), %rcx
subq $0x1, %rcx
movzbl (%rax,%rcx), %eax
movl %eax, 0xac(%rsp)
movq 0xd8(%rsp), %rcx
subq $0x10, %rcx
subq $0x1, %rcx
movq 0xf0(%rsp), %rax
movq %rcx, (%rax)
movq 0x110(%rsp), %rdi
addq $0x10, %rdi
callq 0x1080
movq %rax, 0xc8(%rsp)
movq 0xc8(%rsp), %rdi
movq 0xd0(%rsp), %rsi
movq 0x110(%rsp), %rdx
callq 0x1130
movq 0xc8(%rsp), %rax
movq 0x110(%rsp), %rcx
movq 0x118(%rsp), %rdx
movq (%rdx), %rsi
movq %rsi, (%rax,%rcx)
movq 0x8(%rdx), %rdx
movq %rdx, 0x8(%rax,%rcx)
leaq 0x90(%rsp), %rdi
movq 0xc8(%rsp), %rsi
movq 0x110(%rsp), %rdx
addq $0x10, %rdx
leaq 0x10(%rsp), %rcx
movq 0x120(%rsp), %r8
callq 0x1120
movq 0xc8(%rsp), %rdi
callq 0x10a0
leaq 0x80(%rsp), %rdi
leaq 0x10(%rsp), %rsi
leaq 0x90(%rsp), %rdx
callq 0x2990
leaq 0x30(%rsp), %rdi
leaq 0x10(%rsp), %rsi
callq 0x2950
leaq 0x20(%rsp), %rdi
leaq 0x10(%rsp), %rsi
callq 0x29f0
movq 0xf0(%rsp), %rax
movq (%rax), %rax
movq %rax, 0xb0(%rsp)
cmpq $0x10, 0xb0(%rsp)
jbe 0x32bf
leaq 0x40(%rsp), %rdi
movq 0xc0(%rsp), %rsi
leaq 0x20(%rsp), %rdx
callq 0x2990
leaq 0x70(%rsp), %rdi
leaq 0x40(%rsp), %rsi
movq 0x120(%rsp), %rdx
callq 0x1140
leaq 0x40(%rsp), %rdi
leaq 0x70(%rsp), %rsi
leaq 0x80(%rsp), %rdx
callq 0x2990
leaq 0x80(%rsp), %rdi
leaq 0x70(%rsp), %rsi
callq 0x26d0
leaq 0x40(%rsp), %rdi
leaq 0x40(%rsp), %rsi
movq 0x120(%rsp), %rdx
callq 0x1140
movq 0xb8(%rsp), %rdi
leaq 0x40(%rsp), %rsi
leaq 0x30(%rsp), %rdx
callq 0x2990
leaq 0x60(%rsp), %rdi
leaq 0x60(%rsp), %rsi
movq 0xb8(%rsp), %rdx
callq 0x2990
leaq 0x30(%rsp), %rdi
leaq 0x30(%rsp), %rsi
callq 0x29f0
leaq 0x20(%rsp), %rdi
leaq 0x20(%rsp), %rsi
callq 0x29f0
movq 0xc0(%rsp), %rax
addq $0x10, %rax
movq %rax, 0xc0(%rsp)
movq 0xb8(%rsp), %rax
addq $0x10, %rax
movq %rax, 0xb8(%rsp)
movq 0xb0(%rsp), %rax
subq $0x10, %rax
movq %rax, 0xb0(%rsp)
jmp 0x31b5
cmpl $0x0, 0xac(%rsp)
jne 0x32d4
cmpq $0x10, 0xb0(%rsp)
jne 0x32e9
cmpl $0x0, 0xac(%rsp)
je 0x32f9
cmpq $0x0, 0xb0(%rsp)
jne 0x32f9
movl $0xffffffff, 0x104(%rsp) # imm = 0xFFFFFFFF
jmp 0x3658
cmpl $0x0, 0xac(%rsp)
jne 0x33e4
leaq 0x40(%rsp), %rdi
movq 0xc0(%rsp), %rsi
leaq 0x20(%rsp), %rdx
callq 0x2990
leaq 0x70(%rsp), %rdi
leaq 0x40(%rsp), %rsi
movq 0x120(%rsp), %rdx
callq 0x1140
leaq 0x40(%rsp), %rdi
leaq 0x70(%rsp), %rsi
leaq 0x80(%rsp), %rdx
callq 0x2990
leaq 0x80(%rsp), %rdi
leaq 0x70(%rsp), %rsi
callq 0x26d0
leaq 0x40(%rsp), %rdi
leaq 0x40(%rsp), %rsi
movq 0x120(%rsp), %rdx
callq 0x1140
movq 0xb8(%rsp), %rdi
leaq 0x40(%rsp), %rsi
leaq 0x30(%rsp), %rdx
callq 0x2990
leaq 0x60(%rsp), %rdi
leaq 0x60(%rsp), %rsi
movq 0xb8(%rsp), %rdx
callq 0x2990
movq 0xc0(%rsp), %rax
addq $0x10, %rax
movq %rax, 0xc0(%rsp)
movq 0xb8(%rsp), %rax
addq $0x10, %rax
movq %rax, 0xb8(%rsp)
movq 0xb0(%rsp), %rax
subq $0x10, %rax
movq %rax, 0xb0(%rsp)
jmp 0x358c
leaq 0x40(%rsp), %rdi
movq 0xc0(%rsp), %rsi
leaq 0x20(%rsp), %rdx
callq 0x2990
leaq 0x70(%rsp), %rdi
leaq 0x40(%rsp), %rsi
movq 0x120(%rsp), %rdx
callq 0x1140
leaq 0x40(%rsp), %rdi
leaq 0x70(%rsp), %rsi
leaq 0x80(%rsp), %rdx
callq 0x2990
leaq 0x80(%rsp), %rdi
leaq 0x70(%rsp), %rsi
callq 0x26d0
leaq 0x40(%rsp), %rdi
leaq 0x40(%rsp), %rsi
movq 0x120(%rsp), %rdx
callq 0x1140
leaq 0x30(%rsp), %rdi
leaq 0x30(%rsp), %rsi
callq 0x2f40
leaq 0x70(%rsp), %rdi
leaq 0x40(%rsp), %rsi
leaq 0x30(%rsp), %rdx
callq 0x2990
leaq 0x60(%rsp), %rdi
leaq 0x60(%rsp), %rsi
leaq 0x70(%rsp), %rdx
callq 0x2990
movl $0xf, 0xc(%rsp)
xorl %eax, %eax
cmpl $0x0, 0xc(%rsp)
movb %al, 0x7(%rsp)
jle 0x34b2
movslq 0xc(%rsp), %rax
movzbl 0x70(%rsp,%rax), %eax
cmpl $0x0, %eax
sete %al
movb %al, 0x7(%rsp)
movb 0x7(%rsp), %al
testb $0x1, %al
jne 0x34bc
jmp 0x34c9
movl 0xc(%rsp), %eax
addl $-0x1, %eax
movl %eax, 0xc(%rsp)
jmp 0x3491
movslq 0xc(%rsp), %rax
movzbl 0x70(%rsp,%rax), %eax
cmpl $0x80, %eax
je 0x34ea
movl $0xffffffff, 0x104(%rsp) # imm = 0xFFFFFFFF
jmp 0x3658
movl $0x0, 0x8(%rsp)
movl 0x8(%rsp), %eax
cmpl 0xc(%rsp), %eax
jge 0x3522
movslq 0x8(%rsp), %rax
movb 0x70(%rsp,%rax), %dl
movq 0xb8(%rsp), %rax
movslq 0x8(%rsp), %rcx
movb %dl, (%rax,%rcx)
movl 0x8(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x8(%rsp)
jmp 0x34f2
movl $0x10, %eax
subl 0xc(%rsp), %eax
movslq %eax, %rdx
movq 0xf0(%rsp), %rax
movq (%rax), %rcx
subq %rdx, %rcx
movq %rcx, (%rax)
movq 0xb0(%rsp), %rax
addq 0xc0(%rsp), %rax
movq %rax, 0xc0(%rsp)
movl 0xc(%rsp), %ecx
movq 0xb8(%rsp), %rax
movslq %ecx, %rcx
addq %rcx, %rax
movq %rax, 0xb8(%rsp)
movq 0xb0(%rsp), %rcx
movq 0xb0(%rsp), %rax
subq %rcx, %rax
movq %rax, 0xb0(%rsp)
leaq 0x10(%rsp), %rdi
leaq 0x30(%rsp), %rsi
callq 0x2950
leaq 0x60(%rsp), %rdi
leaq 0x60(%rsp), %rsi
leaq 0x10(%rsp), %rdx
callq 0x2990
leaq 0x60(%rsp), %rdi
leaq 0x60(%rsp), %rsi
movq 0x120(%rsp), %rdx
callq 0x1150
leaq 0x60(%rsp), %rdi
leaq 0x60(%rsp), %rsi
leaq 0x80(%rsp), %rdx
callq 0x2990
leaq 0x60(%rsp), %rdi
leaq 0x60(%rsp), %rsi
movq 0x120(%rsp), %rdx
callq 0x1150
leaq 0x10(%rsp), %rdi
leaq 0x20(%rsp), %rsi
callq 0x2f40
leaq 0x50(%rsp), %rdi
leaq 0x60(%rsp), %rsi
leaq 0x10(%rsp), %rdx
callq 0x2990
leaq 0x50(%rsp), %rax
movq 0xc0(%rsp), %rcx
vmovdqu (%rcx), %xmm1
vmovdqu (%rax), %xmm0
vpxor %xmm1, %xmm0, %xmm0
vptest %xmm0, %xmm0
setne %al
movzbl %al, %eax
cmpl $0x0, %eax
jne 0x364d
movl $0x0, 0x104(%rsp)
jmp 0x3658
movl $0xffffffff, 0x104(%rsp) # imm = 0xFFFFFFFF
movl 0x104(%rsp), %eax
addq $0x108, %rsp            # imm = 0x108
retq
nopw (%rax,%rax)