// File: /workspace/github_cpp_makefile_star2_O3/renzibei[P]TSProxy/aes.cpp
// Function: decode(char*, int, char const*, int, char const (&) [16], char const (&) [16], char const (&) [16])
int decode(char *dst, int dst_size, const char *src, int src_size, const char (&key)[16], const char (&random)[16], const char (&mac)[16]) {
	// 利用计数器初始值计算h
	// char* copy = (char*) malloc((16) * sizeof(char));

	if(src_size == 0 || src_size % 16 != 0) {
		// printf("data len should be 16*n");
		LogHelper::log(Error, "src len should be 16*n, but src_size: %d", src_size);
		return -1;
	}

	if (dst_size < src_size) {
		LogHelper::log(Error, "dst_size should be at least the same as src_size, but dst_size: %, src_size: %d", dst_size, src_size);
		return -2;
	}
	memcpy(dst, src, src_size);

	char copy[16];
	// strCopy(copy, random);
	memcpy(copy, random, sizeof(copy));
	int i, j;
	// 计算h
	// char* h = (char*) malloc((16) * sizeof(char));
	char h[16];
	// strCopy(h, copy);
	memcpy(h, copy, sizeof(h));
	aes(h, key);

	// mac 值校验
	compute_hh((Uchar16 &)h);
	// char* result = (char*) malloc((16) * sizeof(char));
	char result[16];
	// 第一次GF乘法
	mult_h((Uchar16 &)random, (Uchar16 &)result);
	
	char lastResult[16];
	// 对每组密文进行一次
	for(i=0; i < (src_size >> 4); i++){
		// char* lastResult = (char*) malloc((16) * sizeof(char));
		// strCopy(lastResult, result);
		memcpy(lastResult, result, sizeof(lastResult));
		// 对该组密文的16个字节分别进行异或操作
		for(j=0; j<16; j++){
			lastResult[j] = lastResult[j] ^ dst[ (i << 4) + j];
		}
		mult_h((Uchar16 &)lastResult, (Uchar16 &)result);
	}
	// 与h进行异或操作
	for(j=0; j<16; j++){
		result[j] = result[j] ^ h[j];
	}
	// 校对
	for(j=0; j<16; j++){
		if(result[j] != mac[j]){
			// printf("mac error!\n");
			LogHelper::log(Warn, "mac check error");
			// exit(0);
			return -3;
		}
	}
	// printf("mac check ok\n");
	LogHelper::log(Debug, "mac check ok");

	char ctr[16];
	// 解密 len/16 组数据，得到数据
	for(i=0; i< (src_size >> 4) ; i++){
		ctrAdd(copy);	// 计数器 +1
		// char* ctr = (char*) malloc((16) * sizeof(char));
		// strCopy(ctr, copy);
		memcpy(ctr, copy, sizeof(ctr));
		aes(ctr, key);
		// 对该组数据的16个字节分别进行异或操作
		for(j=0; j<16; j++){
			dst[(i << 4) + j] = dst[(i << 4) + j] ^ ctr[j];
		}
	}
	// printf("finish decode\n");
	
	return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x68, %rsp
movl %ecx, %ebp
movl %esi, %eax
testl %ecx, %ecx
setne %cl
testb $0xf, %bpl
sete %sil
testb %sil, %cl
je 0x67c3
cmpl %ebp, %eax
jge 0x67e0
leaq 0x1c53(%rip), %rsi      # 0x83fe
xorl %edi, %edi
movl %eax, %edx
movl %ebp, %ecx
xorl %eax, %eax
callq 0x273c
movl $0xfffffffe, %r15d      # imm = 0xFFFFFFFE
jmp 0x6930
leaq 0x1c0b(%rip), %rsi      # 0x83d5
xorl %edi, %edi
movl %ebp, %edx
xorl %eax, %eax
callq 0x273c
movl $0xffffffff, %r15d      # imm = 0xFFFFFFFF
jmp 0x6930
movq %r9, %r15
movq %r8, %rbx
movq %rdi, %r14
movslq %ebp, %rax
movq %rdx, %rsi
movq %rax, %rdx
callq 0x2150
movups (%r15), %xmm0
movaps %xmm0, 0x10(%rsp)
movups (%r15), %xmm0
leaq 0x50(%rsp), %r12
movaps %xmm0, (%r12)
movq %r12, %rdi
movq %rbx, 0x28(%rsp)
movq %rbx, %rsi
callq 0x60a0
movq %r12, %rdi
callq 0x64de
movq %rsp, %rsi
movq %r15, %rdi
callq 0x672f
sarl $0x4, %ebp
testl %ebp, %ebp
jle 0x6873
movl %ebp, %r13d
shlq $0x4, %r13
xorl %ebx, %ebx
leaq 0x40(%rsp), %r15
movq %rsp, %r12
movaps (%rsp), %xmm0
movaps %xmm0, 0x40(%rsp)
movups (%r14,%rbx), %xmm1
xorps %xmm0, %xmm1
movaps %xmm1, 0x40(%rsp)
movq %r15, %rdi
movq %r12, %rsi
callq 0x672f
addq $0x10, %rbx
cmpq %rbx, %r13
jne 0x6849
movq 0xa0(%rsp), %rax
movaps 0x50(%rsp), %xmm0
xorps (%rsp), %xmm0
movaps %xmm0, (%rsp)
xorl %ecx, %ecx
movb (%rsp,%rcx), %dl
cmpb (%rax,%rcx), %dl
jne 0x6917
incq %rcx
cmpq $0x10, %rcx
jne 0x688a
leaq 0x1bc6(%rip), %rsi      # 0x846c
xorl %r15d, %r15d
movl $0x3, %edi
xorl %eax, %eax
callq 0x273c
testl %ebp, %ebp
movq 0x28(%rsp), %rbx
jle 0x6930
movl %ebp, %r13d
xorl %ebp, %ebp
leaq 0x30(%rsp), %r12
movl $0xf, %eax
movl %eax, %edx
movb 0x10(%rsp,%rdx), %cl
incb %cl
movb %cl, 0x10(%rsp,%rdx)
subl $0x1, %eax
jb 0x68e2
testb %cl, %cl
je 0x68cd
movaps 0x10(%rsp), %xmm0
movaps %xmm0, 0x30(%rsp)
movq %r12, %rdi
movq %rbx, %rsi
callq 0x60a0
movq %rbp, %rax
shlq $0x4, %rax
movups (%r14,%rax), %xmm0
xorps 0x30(%rsp), %xmm0
movups %xmm0, (%r14,%rax)
incq %rbp
cmpq %r13, %rbp
jne 0x68c8
jmp 0x6930
leaq 0x1b3e(%rip), %rsi      # 0x845c
movl $0x1, %edi
xorl %eax, %eax
callq 0x273c
movl $0xfffffffd, %r15d      # imm = 0xFFFFFFFD
movl %r15d, %eax
addq $0x68, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq