// File: FFY00[P]uicc/include/milenage.h
// Function: milenage_check(unsigned char const*, unsigned char const*, unsigned char const*, unsigned char const*, unsigned char const*, unsigned char*, unsigned char*, unsigned char*, unsigned long*, unsigned char*)
int milenage_check(const u8 *opc, const u8 *k, const u8 *sqn, const u8 *_rand,
                   const u8 *autn, u8 *ik, u8 *ck, u8 *res, size_t *res_len,
                   u8 *auts) {
  int i;
  u8 mac_a[8], ak[6], rx_sqn[6];
  const u8 *amf;

  if (milenage_f2345(opc, k, _rand, res, ck, ik, ak, NULL))
    return -1;

  *res_len = 8;

  /* AUTN = (SQN ^ AK) || AMF || MAC */
  for (i = 0; i < 6; i++)
    rx_sqn[i] = autn[i] ^ ak[i];

  if (memcmp(rx_sqn, sqn, 6) <= 0) {
    u8 auts_amf[2] = { 0x00, 0x00 }; /* TS 33.102 v7.0.0, 6.3.3 */

    if (milenage_f2345(opc, k, _rand, NULL, NULL, NULL, NULL, ak))
      return -1;

    for (i = 0; i < 6; i++)
      auts[i] = sqn[i] ^ ak[i];

    if (milenage_f1(opc, k, _rand, sqn, auts_amf, NULL, auts + 6))
      return -1;

    return -2;
  }

  amf = autn + 6;

  if (milenage_f1(opc, k, _rand, rx_sqn, amf, mac_a, NULL))
    return -1;

  if (memcmp(mac_a, autn + 8, 8) != 0) {
    printf( "Milenage: MAC mismatch\n");
    return -1;
  }

  return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x70, %rsp
movq 0x28(%rbp), %rax
movq 0x20(%rbp), %rax
movq 0x18(%rbp), %rax
movq 0x10(%rbp), %rax
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movq %rcx, -0x28(%rbp)
movq %r8, -0x30(%rbp)
movq %r9, -0x38(%rbp)
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0x28(%rbp), %rdx
movq 0x18(%rbp), %rcx
movq 0x10(%rbp), %r8
movq -0x38(%rbp), %r9
leaq -0x4a(%rbp), %rax
xorl %r10d, %r10d
movq %rax, (%rsp)
movq $0x0, 0x8(%rsp)
callq 0x3840
testb $0x1, %al
jne 0x3ee7
jmp 0x3ef3
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x40a3
movq 0x20(%rbp), %rax
movq $0x8, (%rax)
movl $0x0, -0x3c(%rbp)
cmpl $0x6, -0x3c(%rbp)
jge 0x3f37
movq -0x30(%rbp), %rax
movslq -0x3c(%rbp), %rcx
movzbl (%rax,%rcx), %eax
movslq -0x3c(%rbp), %rcx
movzbl -0x4a(%rbp,%rcx), %ecx
xorl %ecx, %eax
movb %al, %cl
movslq -0x3c(%rbp), %rax
movb %cl, -0x50(%rbp,%rax)
movl -0x3c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x3c(%rbp)
jmp 0x3f05
leaq -0x50(%rbp), %rdi
movq -0x20(%rbp), %rsi
movl $0x6, %edx
callq 0x3130
cmpl $0x0, %eax
jg 0x4023
leaq -0x5a(%rbp), %rdi
xorl %esi, %esi
movl $0x2, %edx
callq 0x3160
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0x28(%rbp), %rdx
leaq -0x4a(%rbp), %rax
xorl %ecx, %ecx
movl %ecx, %r9d
movq %r9, %rcx
movq %r9, %r8
movq $0x0, (%rsp)
movq %rax, 0x8(%rsp)
callq 0x3840
testb $0x1, %al
jne 0x3f95
jmp 0x3fa1
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x40a3
movl $0x0, -0x3c(%rbp)
cmpl $0x6, -0x3c(%rbp)
jge 0x3fdd
movq -0x20(%rbp), %rax
movslq -0x3c(%rbp), %rcx
movzbl (%rax,%rcx), %eax
movslq -0x3c(%rbp), %rcx
movzbl -0x4a(%rbp,%rcx), %ecx
xorl %ecx, %eax
movb %al, %dl
movq 0x28(%rbp), %rax
movslq -0x3c(%rbp), %rcx
movb %dl, (%rax,%rcx)
movl -0x3c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x3c(%rbp)
jmp 0x3fa8
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0x28(%rbp), %rdx
movq -0x20(%rbp), %rcx
leaq -0x5a(%rbp), %r8
movq 0x28(%rbp), %rax
addq $0x6, %rax
xorl %r9d, %r9d
movq %rax, (%rsp)
callq 0x3670
testb $0x1, %al
jne 0x400b
jmp 0x4017
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x40a3
movl $0xfffffffe, -0x4(%rbp) # imm = 0xFFFFFFFE
jmp 0x40a3
movq -0x30(%rbp), %rax
addq $0x6, %rax
movq %rax, -0x58(%rbp)
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0x28(%rbp), %rdx
leaq -0x50(%rbp), %rcx
movq -0x58(%rbp), %r8
leaq -0x44(%rbp), %r9
xorl %eax, %eax
movq $0x0, (%rsp)
callq 0x3670
testb $0x1, %al
jne 0x405c
jmp 0x4065
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x40a3
leaq -0x44(%rbp), %rax
movq -0x30(%rbp), %rcx
addq $0x8, %rcx
movq (%rcx), %rcx
movq (%rax), %rax
subq %rcx, %rax
setne %al
movzbl %al, %eax
cmpl $0x0, %eax
je 0x409c
leaq 0x1f256(%rip), %rdi     # 0x232e2
movb $0x0, %al
callq 0x3050
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x40a3
movl $0x0, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x70, %rsp
popq %rbp
retq
nopl (%rax)