// File: /workspace/github_c_makefile_star2_O1/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 $0x168, %rsp            # imm = 0x168
movq %r9, %r13
movq %r8, 0x20(%rsp)
movq %rcx, %r15
movq %rdx, %r12
movq %rsi, 0x50(%rsp)
movq %rdi, %rbx
movq 0x1b0(%rsp), %rdi
vxorps %xmm0, %xmm0, %xmm0
vmovaps %xmm0, 0x60(%rsp)
leaq 0x90(%rsp), %r14
vmovaps %xmm0, (%r14)
leaq 0xb0(%rsp), %rsi
callq 0x10c0
leaq 0x30(%rsp), %rbp
movq %r14, %rdi
movq %rbp, %rsi
leaq 0xb0(%rsp), %rdx
callq 0x10b0
vmovaps (%rbp), %xmm0
vmovaps %xmm0, (%r14)
leaq 0xf(%r15), %rax
andq $-0x10, %rax
addq $0x10, %rax
testq %r15, %r15
movl $0x20, %ecx
cmovneq %rax, %rcx
leaq 0x1(%rcx), %rax
movq 0x50(%rsp), %rdx
movq %rax, (%rdx)
leaq 0x11(%r15), %rax
movq %rax, 0x80(%rsp)
cmpq %rax, %rcx
movq %rcx, 0x88(%rsp)
setae (%rbx,%rcx)
leaq 0x10(%r13), %rbp
movq %rbp, %rdi
callq 0x1050
movq %rax, %r14
movq %rax, %rdi
movq 0x20(%rsp), %rsi
movq %r13, %rdx
callq 0x10e0
movq 0x1a8(%rsp), %rax
vmovups (%rax), %xmm0
vmovups %xmm0, (%r14,%r13)
leaq 0xa0(%rsp), %r13
movq %r13, %rdi
movq %r14, %rsi
movq %rbp, %rdx
leaq 0x90(%rsp), %rbp
movq %rbp, %rcx
movq 0x1b0(%rsp), %r8
callq 0x10d0
movq %r14, %rdi
callq 0x1070
vmovaps (%rbp), %xmm0
vmovaps %xmm0, 0x50(%rsp)
vxorps (%r13), %xmm0, %xmm0
vmovaps %xmm0, 0x20(%rsp)
leaq 0x10(%rsp), %rdi
movq %rbp, %rsi
callq 0x1d8f
movw $0x7fff, %ax            # imm = 0x7FFF
kmovd %eax, %k1
vmovdqu8 0x1(%rbp), %xmm0 {%k1} {z}
vpsrlw $0x7, %xmm0, %xmm0
vmovdqa 0x50(%rsp), %xmm1
vpaddw %xmm1, %xmm1, %xmm1
vpternlogd $0xe4, 0x18d5(%rip){1to4}, %xmm0, %xmm1 # 0x3830
movb (%rbp), %al
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, %r15
jb 0x20f1
movq %r12, 0x50(%rsp)
vmovups (%r12), %xmm0
vxorps 0x60(%rsp), %xmm0, %xmm1
vmovaps %xmm1, 0x60(%rsp)
vxorps 0x10(%rsp), %xmm0, %xmm0
vmovaps %xmm0, 0x40(%rsp)
movq 0x1b0(%rsp), %rbp
movq %rbp, %rdi
movq %rbx, %r12
leaq 0xb0(%rsp), %rbx
movq %rbx, %rsi
callq 0x10c0
leaq 0x40(%rsp), %r14
movq %r14, %rdi
leaq 0x30(%rsp), %r13
movq %r13, %rsi
movq %rbx, %rdx
callq 0x10b0
vmovdqa 0x30(%rsp), %xmm0
vmovdqa %xmm0, 0x40(%rsp)
vmovdqa 0x20(%rsp), %xmm1
vpxor %xmm0, %xmm1, %xmm1
vmovdqa %xmm1, 0x20(%rsp)
vmovdqa %xmm1, 0x40(%rsp)
movq %rbp, %rdi
movq %rbx, %rsi
callq 0x10c0
movq %r14, %rdi
movq %r13, %rsi
movq %rbx, %rdx
movq %r12, %rbx
callq 0x10b0
vmovdqa 0x30(%rsp), %xmm0
vmovdqa %xmm0, 0x40(%rsp)
vpxor (%rsp), %xmm0, %xmm0
vmovdqu %xmm0, (%r12)
cmpq $0x10, %r15
je 0x20d6
vmovdqa 0x10(%rsp), %xmm0
movw $0x7fff, %ax            # imm = 0x7FFF
kmovd %eax, %k1
leaq 0x11(%rsp), %rax
vmovdqu8 (%rax), %xmm1 {%k1} {z}
vpsrlw $0x7, %xmm1, %xmm1
vpaddw %xmm0, %xmm0, %xmm0
vpbroadcastd 0x17c7(%rip), %xmm2 # 0x3830
vpternlogd $0xe2, %xmm1, %xmm2, %xmm0
movb 0x10(%rsp), %al
vmovdqu8 %xmm0, 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)
vmovdqa (%rsp), %xmm0
leaq 0x1(%rsp), %rax
vmovdqu8 (%rax), %xmm1 {%k1} {z}
vpsrlw $0x7, %xmm1, %xmm1
vpaddw %xmm0, %xmm0, %xmm0
vpternlogd $0xe2, %xmm1, %xmm2, %xmm0
movb (%rsp), %al
vmovdqu8 %xmm0, (%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)
movq 0x50(%rsp), %r12
addq $0x10, %r12
addq $0x10, %rbx
addq $-0x10, %r15
cmpq $0xf, %r15
ja 0x1f86
movq 0x80(%rsp), %rax
cmpq %rax, 0x88(%rsp)
jb 0x21fc
vpxor %xmm0, %xmm0, %xmm0
vmovdqa %xmm0, 0x70(%rsp)
testq %r15, %r15
je 0x212a
xorl %eax, %eax
movb (%r12,%rax), %cl
movb %cl, 0x70(%rsp,%rax)
incq %rax
cmpq %rax, %r15
jne 0x2118
jmp 0x212d
xorl %r15d, %r15d
movb $-0x80, 0x70(%rsp,%r15)
leaq 0x10(%rsp), %r14
movq %r14, %rdi
movq %r14, %rsi
callq 0x22de
vmovaps 0x70(%rsp), %xmm0
vxorps 0x60(%rsp), %xmm0, %xmm1
vmovaps %xmm1, 0x60(%rsp)
vxorps (%r14), %xmm0, %xmm0
leaq 0x40(%rsp), %r14
vmovaps %xmm0, (%r14)
leaq 0xb0(%rsp), %r15
movq 0x1b0(%rsp), %r13
movq %r13, %rdi
movq %r15, %rsi
callq 0x10c0
leaq 0x30(%rsp), %r12
movq %r14, %rdi
movq %r12, %rsi
movq %r15, %rdx
callq 0x10b0
vmovdqa (%r12), %xmm0
vmovdqa %xmm0, (%r14)
vmovdqa 0x20(%rsp), %xmm1
vpxor %xmm0, %xmm1, %xmm1
vmovdqa %xmm1, 0x20(%rsp)
vmovdqa %xmm1, (%r14)
leaq 0xb0(%rsp), %r15
movq %r13, %rdi
movq %r15, %rsi
callq 0x10c0
leaq 0x30(%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 0x40(%rsp,%rax), %cl
movb %cl, (%rbx,%rax)
incq %rax
cmpq $0x10, %rax
jne 0x21e5
addq $0x10, %rbx
leaq 0x90(%rsp), %r14
leaq 0x10(%rsp), %rsi
movq %r14, %rdi
callq 0x1d8f
vmovaps (%r14), %xmm0
leaq 0x60(%rsp), %r15
vxorps (%r15), %xmm0, %xmm0
vmovaps %xmm0, (%r15)
leaq 0xb0(%rsp), %r12
movq 0x1b0(%rsp), %rbp
movq %rbp, %rdi
movq %r12, %rsi
callq 0x10c0
leaq 0x30(%rsp), %r13
movq %r15, %rdi
movq %r13, %rsi
movq %r12, %rdx
callq 0x10b0
vmovaps (%r13), %xmm0
vmovaps %xmm0, (%r15)
vxorps 0x20(%rsp), %xmm0, %xmm0
vmovaps %xmm0, (%r15)
leaq 0xb0(%rsp), %r12
movq %rbp, %rdi
movq %r12, %rsi
callq 0x10c0
leaq 0x30(%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 0x22de
vmovaps (%r14), %xmm0
vxorps (%r15), %xmm0, %xmm0
vmovaps %xmm0, (%r12)
xorl %eax, %eax
movb 0xb0(%rsp,%rax), %cl
movb %cl, (%rbx,%rax)
incq %rax
cmpq $0x10, %rax
jne 0x22b7
xorl %eax, %eax
addq $0x168, %rsp            # imm = 0x168
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq