// File: /workspace/github_cpp_makefile_star2_O3/FFY00[P]uicc/include/milenage.h
// Function: milenage_f2345(unsigned char const*, unsigned char const*, unsigned char const*, unsigned char*, unsigned char*, unsigned char*, unsigned char*, unsigned char*)
bool milenage_f2345(const u8 *opc, const u8 *k, const u8 *_rand,
                    u8 *res, u8 *ck, u8 *ik, u8 *ak, u8 *akstar) {
  u8 tmp1[16], tmp2[16], tmp3[16];
  int i;

  /* tmp2 = TEMP = E_K(RAND XOR OP_C) */
  for (i = 0; i < 16; i++)
    tmp1[i] = _rand[i] ^ opc[i];

  aes_128_encrypt_block(k, tmp1, tmp2);

  /* OUT2 = E_K(rot(TEMP XOR OP_C, r2) XOR c2) XOR OP_C */
  /* OUT3 = E_K(rot(TEMP XOR OP_C, r3) XOR c3) XOR OP_C */
  /* OUT4 = E_K(rot(TEMP XOR OP_C, r4) XOR c4) XOR OP_C */
  /* OUT5 = E_K(rot(TEMP XOR OP_C, r5) XOR c5) XOR OP_C */

  /* f2 and f5 */
  /* rotate by r2 (= 0, i.e., NOP) */
  for (i = 0; i < 16; i++)
    tmp1[i] = tmp2[i] ^ opc[i];

  tmp1[15] ^= 1; /* XOR c2 (= ..01) */
  /* f5 || f2 = E_K(tmp1) XOR OP_c */
  aes_128_encrypt_block(k, tmp1, tmp3);

  for (i = 0; i < 16; i++)
    tmp3[i] ^= opc[i];

  if (res)
    memcpy(res, tmp3 + 8, 8); /* f2 */

  if (ak)
    memcpy(ak, tmp3, 6); /* f5 */

  /* f3 */
  if (ck) {
    /* rotate by r3 = 0x20 = 4 bytes */
    for (i = 0; i < 16; i++)
      tmp1[(i + 12) % 16] = tmp2[i] ^ opc[i];

    tmp1[15] ^= 2; /* XOR c3 (= ..02) */
    aes_128_encrypt_block(k, tmp1, ck);

    for (i = 0; i < 16; i++)
      ck[i] ^= opc[i];
  }

  /* f4 */
  if (ik) {
    /* rotate by r4 = 0x40 = 8 bytes */
    for (i = 0; i < 16; i++)
      tmp1[(i + 8) % 16] = tmp2[i] ^ opc[i];

    tmp1[15] ^= 4; /* XOR c4 (= ..04) */
    aes_128_encrypt_block(k, tmp1, ik);

    for (i = 0; i < 16; i++)
      ik[i] ^= opc[i];
  }

  /* f5* */
  if (akstar) {
    /* rotate by r5 = 0x60 = 12 bytes */
    for (i = 0; i < 16; i++)
      tmp1[(i + 4) % 16] = tmp2[i] ^ opc[i];

    tmp1[15] ^= 8; /* XOR c5 (= ..08) */
    aes_128_encrypt_block(k, tmp1, tmp1);

    for (i = 0; i < 6; i++)
      akstar[i] = tmp1[i] ^ opc[i];
  }

  return true;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
movq %r9, %r15
movq %r8, %r12
movq %rcx, %r13
movq %rsi, -0x30(%rbp)
movq %rdi, %rbx
movq 0x18(%rbp), %r14
xorl %eax, %eax
movb (%rbx,%rax), %cl
xorb (%rdx,%rax), %cl
movb %cl, -0x40(%rbp,%rax)
incq %rax
cmpq $0x10, %rax
jne 0x43d8
leaq -0x40(%rbp), %rsi
leaq -0x60(%rbp), %rdx
movq -0x30(%rbp), %rdi
callq 0x4053
xorl %eax, %eax
movb (%rbx,%rax), %cl
xorb -0x60(%rbp,%rax), %cl
movb %cl, -0x40(%rbp,%rax)
incq %rax
cmpq $0x10, %rax
jne 0x43fe
leaq -0x40(%rbp), %rsi
xorb $0x1, 0xf(%rsi)
leaq -0x50(%rbp), %rdx
movq -0x30(%rbp), %rdi
callq 0x4053
xorl %eax, %eax
movb (%rbx,%rax), %cl
xorb %cl, -0x50(%rbp,%rax)
incq %rax
cmpq $0x10, %rax
jne 0x4429
testq %r13, %r13
je 0x4446
movq -0x48(%rbp), %rax
movq %rax, (%r13)
movq 0x10(%rbp), %rcx
testq %rcx, %rcx
je 0x445c
movzwl -0x4c(%rbp), %eax
movw %ax, 0x4(%rcx)
movl -0x50(%rbp), %eax
movl %eax, (%rcx)
testq %r12, %r12
je 0x44a6
movl $0xc, %eax
movb -0xc(%rbx,%rax), %cl
xorb -0x6c(%rbp,%rax), %cl
movl %eax, %edx
andl $0xf, %edx
movb %cl, -0x40(%rbp,%rdx)
incq %rax
cmpq $0x1c, %rax
jne 0x4466
leaq -0x40(%rbp), %rsi
xorb $0x2, 0xf(%rsi)
movq -0x30(%rbp), %rdi
movq %r12, %rdx
callq 0x4053
xorl %eax, %eax
movb (%rbx,%rax), %cl
xorb %cl, (%r12,%rax)
incq %rax
cmpq $0x10, %rax
jne 0x4496
testq %r15, %r15
je 0x44ee
xorl %eax, %eax
movb (%rbx,%rax), %cl
xorb -0x60(%rbp,%rax), %cl
movq %rax, %rdx
xorq $0x8, %rdx
movb %cl, -0x40(%rbp,%rdx)
incq %rax
cmpq $0x10, %rax
jne 0x44ad
leaq -0x40(%rbp), %rsi
xorb $0x4, 0xf(%rsi)
movq -0x30(%rbp), %rdi
movq %r15, %rdx
callq 0x4053
xorl %eax, %eax
movb (%rbx,%rax), %cl
xorb %cl, (%r15,%rax)
incq %rax
cmpq $0x10, %rax
jne 0x44de
testq %r14, %r14
je 0x453c
movl $0x4, %eax
movb -0x4(%rbx,%rax), %cl
xorb -0x64(%rbp,%rax), %cl
movl %eax, %edx
andl $0xf, %edx
movb %cl, -0x40(%rbp,%rdx)
incq %rax
cmpq $0x14, %rax
jne 0x44f8
leaq -0x40(%rbp), %rdx
xorb $0x8, 0xf(%rdx)
movq -0x30(%rbp), %rdi
movq %rdx, %rsi
callq 0x4053
xorl %eax, %eax
movb (%rbx,%rax), %cl
xorb -0x40(%rbp,%rax), %cl
movb %cl, (%r14,%rax)
incq %rax
cmpq $0x6, %rax
jne 0x4528
movb $0x1, %al
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq