// File: renzibei[P]TSProxy/aes.cpp
// Function: encode(char*, int, char const*, int, char const (&) [16], char (&) [16], char (&) [16])
int encode(char *dst, int dst_size, const char *src, int src_size, const char (&key)[16], char (&random)[16], char (&mac)[16]) {
	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);

	srand((unsigned int)time((time_t *)NULL));
	// 生成随机计数器初始值
	// char* copy = (char*) malloc((16) * sizeof(char));
	char copy[16];
	int i, j;
	for(i=0; i<16; i++){
		copy[i] = random[i] = (char)rand();
	}
	// 计算h
	// char* h = (char*) malloc((16) * sizeof(char));
	char h[16];
	// strCopy(h, copy);
	memcpy(h, copy, 16);
	aes(h, key);

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

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

// Assembly:
subq $0x88, %rsp
movq 0x90(%rsp), %rax
movq %rdi, 0x78(%rsp)
movl %esi, 0x74(%rsp)
movq %rdx, 0x68(%rsp)
movl %ecx, 0x64(%rsp)
movq %r8, 0x58(%rsp)
movq %r9, 0x50(%rsp)
cmpl $0x0, 0x64(%rsp)
je 0xe203
movl 0x64(%rsp), %eax
movl $0x10, %ecx
cltd
idivl %ecx
cmpl $0x0, %edx
je 0xe227
movl 0x64(%rsp), %edx
xorl %edi, %edi
leaq 0x2d0a(%rip), %rsi      # 0x10f1a
movb $0x0, %al
callq 0x28f0
movl $0xffffffff, 0x84(%rsp) # imm = 0xFFFFFFFF
jmp 0xe4aa
movl 0x74(%rsp), %eax
cmpl 0x64(%rsp), %eax
jge 0xe259
movl 0x74(%rsp), %edx
movl 0x64(%rsp), %ecx
xorl %edi, %edi
leaq 0x2d01(%rip), %rsi      # 0x10f43
movb $0x0, %al
callq 0x28f0
movl $0xfffffffe, 0x84(%rsp) # imm = 0xFFFFFFFE
jmp 0xe4aa
movq 0x78(%rsp), %rdi
movq 0x68(%rsp), %rsi
movslq 0x64(%rsp), %rdx
callq 0x2180
xorl %eax, %eax
movl %eax, %edi
callq 0x21c0
movl %eax, %edi
callq 0x21f0
movl $0x0, 0x3c(%rsp)
cmpl $0x10, 0x3c(%rsp)
jge 0xe2b6
callq 0x20a0
movb %al, %cl
movq 0x50(%rsp), %rax
movslq 0x3c(%rsp), %rdx
movb %cl, (%rax,%rdx)
movslq 0x3c(%rsp), %rax
movb %cl, 0x40(%rsp,%rax)
movl 0x3c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x3c(%rsp)
jmp 0xe285
movq 0x40(%rsp), %rax
movq %rax, 0x20(%rsp)
movq 0x48(%rsp), %rax
movq %rax, 0x28(%rsp)
leaq 0x20(%rsp), %rdi
movq 0x58(%rsp), %rsi
callq 0xd930
movl $0x0, 0x3c(%rsp)
movl 0x3c(%rsp), %eax
movl 0x64(%rsp), %ecx
sarl $0x4, %ecx
cmpl %ecx, %eax
jge 0xe38a
leaq 0x40(%rsp), %rdi
callq 0xe4c0
movq 0x40(%rsp), %rax
movq %rax, 0x10(%rsp)
movq 0x48(%rsp), %rax
movq %rax, 0x18(%rsp)
leaq 0x10(%rsp), %rdi
movq 0x58(%rsp), %rsi
callq 0xd930
movl $0x0, 0x38(%rsp)
cmpl $0x10, 0x38(%rsp)
jge 0xe378
movq 0x78(%rsp), %rax
movl 0x3c(%rsp), %ecx
shll $0x4, %ecx
addl 0x38(%rsp), %ecx
movslq %ecx, %rcx
movsbl (%rax,%rcx), %eax
movslq 0x38(%rsp), %rcx
movsbl 0x10(%rsp,%rcx), %ecx
xorl %ecx, %eax
movb %al, %dl
movq 0x78(%rsp), %rax
movl 0x3c(%rsp), %ecx
shll $0x4, %ecx
addl 0x38(%rsp), %ecx
movslq %ecx, %rcx
movb %dl, (%rax,%rcx)
movl 0x38(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x38(%rsp)
jmp 0xe329
jmp 0xe37a
movl 0x3c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x3c(%rsp)
jmp 0xe2e1
leaq 0x20(%rsp), %rdi
callq 0xe060
movq 0x50(%rsp), %rdi
movq 0x90(%rsp), %rsi
callq 0xe520
movl $0x0, 0x3c(%rsp)
movl 0x3c(%rsp), %eax
movl 0x64(%rsp), %ecx
sarl $0x4, %ecx
cmpl %ecx, %eax
jge 0xe441
movq 0x90(%rsp), %rax
movq (%rax), %rcx
movq %rcx, (%rsp)
movq 0x8(%rax), %rax
movq %rax, 0x8(%rsp)
movl $0x0, 0x38(%rsp)
cmpl $0x10, 0x38(%rsp)
jge 0xe421
movslq 0x38(%rsp), %rax
movsbl (%rsp,%rax), %eax
movq 0x78(%rsp), %rcx
movl 0x3c(%rsp), %edx
shll $0x4, %edx
addl 0x38(%rsp), %edx
movslq %edx, %rdx
movsbl (%rcx,%rdx), %ecx
xorl %ecx, %eax
movb %al, %cl
movslq 0x38(%rsp), %rax
movb %cl, (%rsp,%rax)
movl 0x38(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x38(%rsp)
jmp 0xe3e1
movq 0x90(%rsp), %rsi
movq %rsp, %rdi
callq 0xe520
movl 0x3c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x3c(%rsp)
jmp 0xe3ae
movl $0x0, 0x38(%rsp)
cmpl $0x10, 0x38(%rsp)
jge 0xe48c
movq 0x90(%rsp), %rax
movslq 0x38(%rsp), %rcx
movsbl (%rax,%rcx), %eax
movslq 0x38(%rsp), %rcx
movsbl 0x20(%rsp,%rcx), %ecx
xorl %ecx, %eax
movb %al, %dl
movq 0x90(%rsp), %rax
movslq 0x38(%rsp), %rcx
movb %dl, (%rax,%rcx)
movl 0x38(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x38(%rsp)
jmp 0xe449
movl $0x3, %edi
leaq 0x2afb(%rip), %rsi      # 0x10f93
movb $0x0, %al
callq 0x28f0
movl $0x0, 0x84(%rsp)
movl 0x84(%rsp), %eax
addq $0x88, %rsp
retq
nopl (%rax)