// File: /workspace/github_cpp_makefile_star2_O2/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, %ebx
movl %esi, %eax
testl %ecx, %ecx
setne %cl
testb $0xf, %bl
sete %sil
testb %sil, %cl
je 0x6821
cmpl %ebx, %eax
jge 0x6845
leaq 0x1bee(%rip), %rsi      # 0x83fe
xorl %edi, %edi
movl %eax, %edx
movl %ebx, %ecx
xorl %eax, %eax
callq 0x262c
pushq $-0x2
jmp 0x6835
leaq 0x1bad(%rip), %rsi      # 0x83d5
xorl %edi, %edi
movl %ebx, %edx
xorl %eax, %eax
callq 0x262c
pushq $-0x1
popq %rax
addq $0x68, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %r9, %r13
movq %r8, %r15
movq %rdi, %r14
movslq %ebx, %rax
movq %rdx, %rsi
movq %rax, %rdx
callq 0x2160
movups (%r13), %xmm0
movaps %xmm0, 0x40(%rsp)
movups (%r13), %xmm0
leaq 0x50(%rsp), %r12
movaps %xmm0, (%r12)
movq %r12, %rdi
movq %r15, 0x18(%rsp)
movq %r15, %rsi
callq 0x6130
movq %r12, %rdi
callq 0x6541
movq %rsp, %r12
movq %r13, %rdi
movq %r12, %rsi
callq 0x677d
sarl $0x4, %ebx
xorl %ebp, %ebp
testl %ebx, %ebx
cmovlel %ebp, %ebx
leaq 0x30(%rsp), %r13
movq %r14, %r15
cmpq %rbx, %rbp
je 0x68e4
movaps (%rsp), %xmm0
movaps %xmm0, 0x30(%rsp)
xorl %eax, %eax
cmpq $0x10, %rax
je 0x68d0
movb (%r15,%rax), %cl
xorb %cl, 0x30(%rsp,%rax)
incq %rax
jmp 0x68bd
movq %r13, %rdi
movq %r12, %rsi
callq 0x677d
incq %rbp
addq $0x10, %r15
jmp 0x68ad
xorl %eax, %eax
movq 0x18(%rsp), %r15
movq 0xa0(%rsp), %rsi
cmpq $0x10, %rax
je 0x6905
movb 0x50(%rsp,%rax), %cl
xorb %cl, (%rsp,%rax)
incq %rax
jmp 0x68f3
xorl %eax, %eax
cmpq $0x10, %rax
je 0x6934
movb (%rsp,%rax), %cl
leaq 0x1(%rax), %rdx
cmpb (%rsi,%rax), %cl
movq %rdx, %rax
je 0x6907
leaq 0x1b39(%rip), %rsi      # 0x845c
pushq $0x1
popq %rdi
xorl %eax, %eax
callq 0x262c
pushq $-0x3
jmp 0x6835
leaq 0x1b31(%rip), %rsi      # 0x846c
xorl %ebp, %ebp
pushq $0x3
popq %rdi
xorl %eax, %eax
callq 0x262c
leaq 0x40(%rsp), %r12
leaq 0x20(%rsp), %r13
cmpq %rbx, %rbp
je 0x6991
movq %r12, %rdi
callq 0x676c
movaps 0x40(%rsp), %xmm0
movaps %xmm0, 0x20(%rsp)
movq %r13, %rdi
movq %r15, %rsi
callq 0x6130
xorl %eax, %eax
cmpq $0x10, %rax
je 0x6988
movb 0x20(%rsp,%rax), %cl
xorb %cl, (%r14,%rax)
incq %rax
jmp 0x6975
incq %rbp
addq $0x10, %r14
jmp 0x6951
xorl %eax, %eax
jmp 0x6836