// File: akw0088[P]openssl/aes_upload.cpp
// Function: aes_file_upload(char*, unsigned short, unsigned char*, unsigned char*, unsigned char*)
int aes_file_upload(char *file, unsigned short port, unsigned char *key, unsigned char *iv, unsigned char *public_key_filename)
{
	int			connfd;
	unsigned int		size = sizeof(struct sockaddr_in);
	struct sockaddr_in	servaddr, client;
	time_t			ticks;
	int listenfd;

#ifdef _WIN32
	WSADATA		WSAData;

	WSAStartup(MAKEWORD(2, 0), &WSAData);
#endif

	listenfd = socket(AF_INET, SOCK_STREAM, 0);
	if (listenfd == -1)
	{
		perror("socket error");
		return -1;
	}

	memset(&servaddr, 0, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	servaddr.sin_port = htons(port);

	if ((::bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr))) == -1)
	{
		perror("bind error");
		return 0;
	}

	printf("Server listening on: %s:%d\n", inet_ntoa(servaddr.sin_addr), htons(servaddr.sin_port));

	if (listen(listenfd, 3) == -1)
	{
		perror("listen error");
		return -1;
	}

	for (;;)
	{
		char response[1024] = { 0 };

		printf("listening for connections...\n");
		connfd = accept(listenfd, (struct sockaddr *)&client, (socklen_t *)&size);
		if (connfd == INVALID_SOCKET)
			continue;

		ticks = time(NULL);
		snprintf(response, sizeof(response), "%.24s\r\n", ctime(&ticks));
		printf("Client: %s - %s\r\n", inet_ntoa(client.sin_addr), response);

		unsigned int file_size = 0;
		unsigned char *data = (unsigned char *)get_file(file, &file_size);
		if (data == NULL)
		{
			printf("Error: could not open file %s\r\n", file);
			continue;
		}
		printf("Opened file %s size %d bytes\r\n", file, file_size);

		char file_name[128] = { 0 };

		unsigned char *ciphertext = NULL;
		unsigned int ciphertext_len = 0;

		printf("Performing AES encryptions\r\n");
		aes_encrypt(key, iv, data, file_size, ciphertext, ciphertext_len);

		char rsa_plaintext[1024] = {0};

		sprintf(rsa_plaintext, "%s %s", iv, key);

		int rsa_plaintext_len = strlen(rsa_plaintext);

		unsigned char encrypted[4098] = {0};
		unsigned int encrypted_length = 0;
		unsigned char hash[33] = {0};

		md5sum((char *)data, file_size, (char *)&hash[0]);
		printf("Unencrypted MD5: %s\r\n", hash);
		printf("AES Encrypted size %d\r\n", ciphertext_len);

		printf("Performing RSA encryptions\r\n");
		rsa_encrypt((char *)public_key_filename, (unsigned char *)&rsa_plaintext[0], rsa_plaintext_len, encrypted, encrypted_length);

		delete[] data;
		printf("Encryption complete, sending file\r\n");
		memcpy(file_name, file, MIN(127, strlen(file)));
		send(connfd, (char *)&ciphertext_len, sizeof(int), 0);
		send(connfd, (char *)&file_name, 128, 0);
		send(connfd, (char *)&file_size, sizeof(int), 0);
		send(connfd, (char *)&hash, 32, 0);
		send(connfd, (char *)&encrypted, 256, 0);
		send(connfd, ciphertext, ciphertext_len, 0);
		free((void *)ciphertext);
		closesocket(connfd);
	}
	return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1980, %rsp           # imm = 0x1980
movw %si, %ax
movq %rdi, -0x10(%rbp)
movw %ax, -0x12(%rbp)
movq %rdx, -0x20(%rbp)
movq %rcx, -0x28(%rbp)
movq %r8, -0x30(%rbp)
movl $0x10, -0x38(%rbp)
movl $0x2, %edi
movl $0x1, %esi
xorl %edx, %edx
callq 0x20b0
movl %eax, -0x64(%rbp)
cmpl $-0x1, -0x64(%rbp)
jne 0x2a2b
leaq 0x6a5(%rip), %rdi       # 0x30bf
callq 0x21e0
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x2e64
leaq -0x48(%rbp), %rdi
xorl %esi, %esi
movl $0x10, %edx
callq 0x2150
movw $0x2, -0x48(%rbp)
xorl %edi, %edi
callq 0x21c0
movl %eax, -0x44(%rbp)
movzwl -0x12(%rbp), %edi
callq 0x2060
movw %ax, -0x46(%rbp)
movl -0x64(%rbp), %edi
leaq -0x48(%rbp), %rsi
movl $0x10, %edx
callq 0x2080
cmpl $-0x1, %eax
jne 0x2a86
leaq 0x657(%rip), %rdi       # 0x30cc
callq 0x21e0
movl $0x0, -0x4(%rbp)
jmp 0x2e64
movl -0x44(%rbp), %eax
movl %eax, -0x68(%rbp)
movl -0x68(%rbp), %edi
callq 0x2110
movq %rax, -0x1958(%rbp)
movzwl -0x46(%rbp), %edi
callq 0x2060
movq -0x1958(%rbp), %rsi
movzwl %ax, %edx
leaq 0x622(%rip), %rdi       # 0x30d7
movb $0x0, %al
callq 0x2050
movl -0x64(%rbp), %edi
movl $0x3, %esi
callq 0x2240
cmpl $-0x1, %eax
jne 0x2ae6
leaq 0x61e(%rip), %rdi       # 0x30f3
callq 0x21e0
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x2e64
jmp 0x2ae8
leaq -0x470(%rbp), %rdi
xorl %esi, %esi
movl $0x400, %edx            # imm = 0x400
callq 0x2150
leaq 0x5fe(%rip), %rdi       # 0x3100
movb $0x0, %al
callq 0x2050
movl -0x64(%rbp), %edi
leaq -0x58(%rbp), %rsi
leaq -0x38(%rbp), %rdx
callq 0x20c0
movl %eax, -0x34(%rbp)
cmpl $-0x1, -0x34(%rbp)
jne 0x2b24
jmp 0x2ae8
xorl %eax, %eax
movl %eax, %edi
callq 0x21f0
movq %rax, -0x60(%rbp)
leaq -0x470(%rbp), %rax
movq %rax, -0x1960(%rbp)
leaq -0x60(%rbp), %rdi
callq 0x20e0
movq -0x1960(%rbp), %rdi
movq %rax, %rcx
movl $0x400, %esi            # imm = 0x400
leaq 0x5c0(%rip), %rdx       # 0x311e
movb $0x0, %al
callq 0x22e0
movl -0x54(%rbp), %eax
movl %eax, -0x474(%rbp)
movl -0x474(%rbp), %edi
callq 0x2110
movq %rax, %rsi
leaq -0x470(%rbp), %rdx
leaq 0x59c(%rip), %rdi       # 0x3126
movb $0x0, %al
callq 0x2050
movl $0x0, -0x478(%rbp)
movq -0x10(%rbp), %rdi
leaq -0x478(%rbp), %rsi
callq 0x24f0
movq %rax, -0x480(%rbp)
cmpq $0x0, -0x480(%rbp)
jne 0x2bd3
movq -0x10(%rbp), %rsi
leaq 0x571(%rip), %rdi       # 0x3138
movb $0x0, %al
callq 0x2050
jmp 0x2ae8
movq -0x10(%rbp), %rsi
movl -0x478(%rbp), %edx
leaq 0x574(%rip), %rdi       # 0x3158
movb $0x0, %al
callq 0x2050
leaq -0x500(%rbp), %rdi
xorl %esi, %esi
movl $0x80, %edx
callq 0x2150
movq $0x0, -0x508(%rbp)
movl $0x0, -0x50c(%rbp)
leaq 0x55d(%rip), %rdi       # 0x3177
movb $0x0, %al
callq 0x2050
movq -0x20(%rbp), %rdi
movq -0x28(%rbp), %rsi
movq -0x480(%rbp), %rdx
movl -0x478(%rbp), %ecx
leaq -0x508(%rbp), %r8
leaq -0x50c(%rbp), %r9
callq 0x2920
leaq -0x910(%rbp), %rdi
xorl %esi, %esi
movl $0x400, %edx            # imm = 0x400
callq 0x2150
leaq -0x910(%rbp), %rdi
movq -0x28(%rbp), %rdx
movq -0x20(%rbp), %rcx
leaq 0x522(%rip), %rsi       # 0x3194
movb $0x0, %al
callq 0x2090
leaq -0x910(%rbp), %rdi
callq 0x2100
movl %eax, -0x914(%rbp)
leaq -0x1920(%rbp), %rdi
xorl %esi, %esi
movl $0x1002, %edx           # imm = 0x1002
callq 0x2150
movl $0x0, -0x1924(%rbp)
leaq -0x1950(%rbp), %rdi
xorl %esi, %esi
movl $0x21, %edx
callq 0x2150
movq -0x480(%rbp), %rdi
movl -0x478(%rbp), %esi
leaq -0x1950(%rbp), %rdx
callq 0x2430
leaq -0x1950(%rbp), %rsi
leaq 0x4b8(%rip), %rdi       # 0x319a
movb $0x0, %al
callq 0x2050
movl -0x50c(%rbp), %esi
leaq 0x4ba(%rip), %rdi       # 0x31b0
movb $0x0, %al
callq 0x2050
leaq 0x4c4(%rip), %rdi       # 0x31c8
movb $0x0, %al
callq 0x2050
movq -0x30(%rbp), %rdi
leaq -0x910(%rbp), %rsi
movl -0x914(%rbp), %edx
leaq -0x1920(%rbp), %rcx
leaq -0x1924(%rbp), %r8
callq 0x26b0
movq -0x480(%rbp), %rax
movq %rax, -0x1968(%rbp)
cmpq $0x0, %rax
je 0x2d4f
movq -0x1968(%rbp), %rdi
callq 0x2280
leaq 0x48f(%rip), %rdi       # 0x31e5
movb $0x0, %al
callq 0x2050
leaq -0x500(%rbp), %rax
movq %rax, -0x1978(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x1970(%rbp)
movq -0x10(%rbp), %rdi
callq 0x2100
movq %rax, %rcx
movl $0x7f, %eax
cmpq %rcx, %rax
jae 0x2d9a
movl $0x7f, %eax
movq %rax, -0x1980(%rbp)
jmp 0x2daa
movq -0x10(%rbp), %rdi
callq 0x2100
movq %rax, -0x1980(%rbp)
movq -0x1970(%rbp), %rsi
movq -0x1978(%rbp), %rdi
movq -0x1980(%rbp), %rdx
callq 0x21d0
movl -0x34(%rbp), %edi
leaq -0x50c(%rbp), %rsi
movl $0x4, %edx
xorl %ecx, %ecx
callq 0x2130
movl -0x34(%rbp), %edi
leaq -0x500(%rbp), %rsi
movl $0x80, %edx
xorl %ecx, %ecx
callq 0x2130
movl -0x34(%rbp), %edi
leaq -0x478(%rbp), %rsi
movl $0x4, %edx
xorl %ecx, %ecx
callq 0x2130
movl -0x34(%rbp), %edi
leaq -0x1950(%rbp), %rsi
movl $0x20, %edx
xorl %ecx, %ecx
callq 0x2130
movl -0x34(%rbp), %edi
leaq -0x1920(%rbp), %rsi
movl $0x100, %edx            # imm = 0x100
xorl %ecx, %ecx
callq 0x2130
movl -0x34(%rbp), %edi
movq -0x508(%rbp), %rsi
movl -0x50c(%rbp), %eax
movl %eax, %edx
xorl %ecx, %ecx
callq 0x2130
movq -0x508(%rbp), %rdi
callq 0x2260
movl -0x34(%rbp), %edi
callq 0x2310
jmp 0x2ae8
movl -0x4(%rbp), %eax
addq $0x1980, %rsp           # imm = 0x1980
popq %rbp
retq