// File: /workspace/github_c_makefile_star2_O3/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:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x178, %rsp            # imm = 0x178
movq %r9, %r13
movq %r8, 0x30(%rsp)
movq %rcx, %r12
movq %rdx, %r15
movq %rsi, 0x48(%rsp)
movq %rdi, %rbx
movq 0x1c0(%rsp), %rdi
vxorps %xmm0, %xmm0, %xmm0
vmovaps %xmm0, 0x60(%rsp)
leaq 0xa0(%rsp), %r14
vmovaps %xmm0, (%r14)
leaq 0xc0(%rsp), %rsi
callq 0x10c0
leaq 0x20(%rsp), %rbp
movq %r14, %rdi
movq %rbp, %rsi
leaq 0xc0(%rsp), %rdx
callq 0x10b0
vmovaps (%rbp), %xmm0
vmovaps %xmm0, (%r14)
leaq 0xf(%r12), %rax
andq $-0x10, %rax
addq $0x10, %rax
testq %r12, %r12
movl $0x20, %ecx
cmovneq %rax, %rcx
leaq 0x1(%rcx), %rax
movq 0x48(%rsp), %rdx
movq %rax, (%rdx)
leaq 0x11(%r12), %rax
movq %rax, 0x90(%rsp)
cmpq %rax, %rcx
movq %rcx, 0x98(%rsp)
setae (%rbx,%rcx)
leaq 0x10(%r13), %rbp
movq %rbp, %rdi
callq 0x1050
movq %rax, %r14
movq %rax, %rdi
movq 0x30(%rsp), %rsi
movq %r13, %rdx
callq 0x10e0
movq 0x1b8(%rsp), %rax
vmovups (%rax), %xmm0
vmovups %xmm0, (%r14,%r13)
leaq 0xb0(%rsp), %r13
movq %r13, %rdi
movq %r14, %rsi
movq %rbp, %rdx
leaq 0xa0(%rsp), %rbp
movq %rbp, %rcx
movq 0x1c0(%rsp), %r8
callq 0x10d0
movq %r14, %rdi
callq 0x1070
vmovaps (%r13), %xmm0
vxorps (%rbp), %xmm0, %xmm0
vmovaps %xmm0, 0x30(%rsp)
leaq 0x10(%rsp), %rdi
movq %rbp, %rsi
callq 0x1dac
movb (%rbp), %al
vmovd %eax, %xmm0
movw $0x7fff, %cx            # imm = 0x7FFF
kmovd %ecx, %k1
vmovdqu8 0x1(%rbp), %xmm1 {%k1} {z}
vpbroadcastb %xmm0, %xmm0
vpalignr $0xf, %xmm0, %xmm1, %xmm0 # xmm0 = xmm0[15],xmm1[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14]
vpaddw %xmm0, %xmm0, %xmm0
vpsrlw $0x7, %xmm1, %xmm1
vpternlogd $0xd8, 0x18a7(%rip){1to4}, %xmm0, %xmm1 # 0x3830
vmovdqu8 %xmm1, (%rsp) {%k1}
movb 0xf(%rbp), %cl
addb %cl, %cl
movzbl %cl, %edx
xorb $-0x79, %cl
testb %al, %al
movzbl %cl, %eax
cmovnsl %edx, %eax
movb %al, 0xf(%rsp)
cmpq $0x10, %r12
jb 0x2171
movq %r12, 0x70(%rsp)
leaq -0x10(%r12), %rax
movq %rax, 0x48(%rsp)
xorl %ebp, %ebp
xorl %r14d, %r14d
movq %r15, 0x78(%rsp)
vmovups (%r15,%r14), %xmm0
vxorps 0x60(%rsp), %xmm0, %xmm1
vmovaps %xmm1, 0x60(%rsp)
vxorps 0x10(%rsp), %xmm0, %xmm0
vmovaps %xmm0, 0x50(%rsp)
movq 0x1c0(%rsp), %r15
movq %r15, %rdi
movq %rbx, %r12
leaq 0xc0(%rsp), %rbx
movq %rbx, %rsi
callq 0x10c0
leaq 0x50(%rsp), %r13
movq %r13, %rdi
leaq 0x20(%rsp), %rsi
movq %rbx, %rdx
callq 0x10b0
vmovaps 0x20(%rsp), %xmm0
vmovaps %xmm0, 0x50(%rsp)
vmovaps 0x30(%rsp), %xmm1
vxorps %xmm0, %xmm1, %xmm1
vmovaps %xmm1, 0x30(%rsp)
vmovaps %xmm1, 0x50(%rsp)
movq %r15, %rdi
movq %rbx, %rsi
callq 0x10c0
movq %r13, %rdi
leaq 0x20(%rsp), %rsi
movq %rbx, %rdx
movq %r12, %rbx
callq 0x10b0
vmovaps 0x20(%rsp), %xmm0
vmovaps %xmm0, 0x50(%rsp)
vxorps (%rsp), %xmm0, %xmm0
vmovups %xmm0, (%r12,%r14)
cmpq %r14, 0x48(%rsp)
je 0x215b
movb 0x10(%rsp), %al
vmovd %eax, %xmm0
vpbroadcastb %xmm0, %xmm0
movw $0x7fff, %cx            # imm = 0x7FFF
kmovd %ecx, %k1
leaq 0x11(%rsp), %rcx
vmovdqu8 (%rcx), %xmm1 {%k1} {z}
vpalignr $0xf, %xmm0, %xmm1, %xmm0 # xmm0 = xmm0[15],xmm1[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14]
vpaddw %xmm0, %xmm0, %xmm0
vpsrlw $0x7, %xmm1, %xmm1
vpbroadcastd 0x177b(%rip), %xmm2 # 0x3830
vpternlogd $0xb8, %xmm0, %xmm2, %xmm1
vmovdqu8 %xmm1, 0x10(%rsp) {%k1}
movb 0x1f(%rsp), %cl
addb %cl, %cl
movzbl %cl, %edx
xorb $-0x79, %cl
testb %al, %al
movzbl %cl, %eax
cmovnsl %edx, %eax
movb %al, 0x1f(%rsp)
movb (%rsp), %al
vmovd %eax, %xmm0
vpbroadcastb %xmm0, %xmm0
leaq 0x1(%rsp), %rcx
vmovdqu8 (%rcx), %xmm1 {%k1} {z}
vpalignr $0xf, %xmm0, %xmm1, %xmm0 # xmm0 = xmm0[15],xmm1[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14]
vpaddw %xmm0, %xmm0, %xmm0
vpsrlw $0x7, %xmm1, %xmm1
vpternlogd $0xb8, %xmm0, %xmm2, %xmm1
vmovdqu8 %xmm1, (%rsp) {%k1}
movb 0xf(%rsp), %cl
addb %cl, %cl
movzbl %cl, %edx
xorb $-0x79, %cl
testb %al, %al
movzbl %cl, %eax
cmovnsl %edx, %eax
movb %al, 0xf(%rsp)
addq $0x10, %r14
movq 0x70(%rsp), %rax
addq %rbp, %rax
addq $-0x10, %rax
addq $-0x10, %rbp
cmpq $0xf, %rax
movq 0x78(%rsp), %r15
ja 0x1fca
addq %r14, %r15
movq 0x70(%rsp), %r12
addq %rbp, %r12
addq %r14, %rbx
jmp 0x2171
movq 0x78(%rsp), %r15
addq %r14, %r15
addq $0x10, %r15
addq %r14, %rbx
addq $0x10, %rbx
xorl %r12d, %r12d
movq 0x90(%rsp), %rax
cmpq %rax, 0x98(%rsp)
jb 0x2283
vpxor %xmm0, %xmm0, %xmm0
vmovdqa %xmm0, 0x80(%rsp)
testq %r12, %r12
je 0x21ae
xorl %eax, %eax
movb (%r15,%rax), %cl
movb %cl, 0x80(%rsp,%rax)
incq %rax
cmpq %rax, %r12
jne 0x219b
movb $-0x80, 0x80(%rsp,%r12)
leaq 0x10(%rsp), %r14
movq %r14, %rdi
movq %r14, %rsi
callq 0x2365
vmovaps 0x80(%rsp), %xmm0
vxorps 0x60(%rsp), %xmm0, %xmm1
vmovaps %xmm1, 0x60(%rsp)
vxorps (%r14), %xmm0, %xmm0
leaq 0x50(%rsp), %r14
vmovaps %xmm0, (%r14)
leaq 0xc0(%rsp), %r15
movq 0x1c0(%rsp), %r13
movq %r13, %rdi
movq %r15, %rsi
callq 0x10c0
leaq 0x20(%rsp), %r12
movq %r14, %rdi
movq %r12, %rsi
movq %r15, %rdx
callq 0x10b0
vmovdqa (%r12), %xmm0
vmovdqa %xmm0, (%r14)
vmovdqa 0x30(%rsp), %xmm1
vpxor %xmm0, %xmm1, %xmm1
vmovdqa %xmm1, 0x30(%rsp)
vmovdqa %xmm1, (%r14)
leaq 0xc0(%rsp), %r15
movq %r13, %rdi
movq %r15, %rsi
callq 0x10c0
leaq 0x20(%rsp), %r12
movq %r14, %rdi
movq %r12, %rsi
movq %r15, %rdx
callq 0x10b0
vmovdqa (%r12), %xmm0
vmovdqa %xmm0, (%r14)
xorl %eax, %eax
movb (%rsp,%rax), %cl
xorb 0x50(%rsp,%rax), %cl
movb %cl, (%rbx,%rax)
incq %rax
cmpq $0x10, %rax
jne 0x226c
addq $0x10, %rbx
leaq 0xa0(%rsp), %r14
leaq 0x10(%rsp), %rsi
movq %r14, %rdi
callq 0x1dac
vmovaps (%r14), %xmm0
leaq 0x60(%rsp), %r15
vxorps (%r15), %xmm0, %xmm0
vmovaps %xmm0, (%r15)
leaq 0xc0(%rsp), %r12
movq 0x1c0(%rsp), %rbp
movq %rbp, %rdi
movq %r12, %rsi
callq 0x10c0
leaq 0x20(%rsp), %r13
movq %r15, %rdi
movq %r13, %rsi
movq %r12, %rdx
callq 0x10b0
vmovaps (%r13), %xmm0
vmovaps %xmm0, (%r15)
vxorps 0x30(%rsp), %xmm0, %xmm0
vmovaps %xmm0, (%r15)
leaq 0xc0(%rsp), %r12
movq %rbp, %rdi
movq %r12, %rsi
callq 0x10c0
leaq 0x20(%rsp), %r13
movq %r15, %rdi
movq %r13, %rsi
movq %r12, %rdx
callq 0x10b0
vmovaps (%r13), %xmm0
vmovaps %xmm0, (%r15)
movq %rsp, %rsi
movq %r14, %rdi
callq 0x2365
vmovaps (%r14), %xmm0
vxorps (%r15), %xmm0, %xmm0
vmovaps %xmm0, (%r12)
xorl %eax, %eax
movb 0xc0(%rsp,%rax), %cl
movb %cl, (%rbx,%rax)
incq %rax
cmpq $0x10, %rax
jne 0x233e
xorl %eax, %eax
addq $0x178, %rsp            # imm = 0x178
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq