#define NULL ((void *)0)
typedef unsigned long size_t; // Customize by platform.
typedef long intptr_t;
typedef unsigned long uintptr_t;
typedef long scalar_t__; // Either arithmetic or pointer type.
/* By default, we understand bool (as a convenience). */
typedef int bool;
#define false 0
#define true 1

/* Forward declarations */

/* Type definitions */
typedef int uint8_t;
typedef int /*<<< orphan*/ sysid;
typedef int /*<<< orphan*/ new_key;
typedef int /*<<< orphan*/ expect_key;

/* Variables and functions */
int atoi(char *);
int /*<<< orphan*/ keys_equal(int *, int, int *, int);
int nfclock_diversify_key_aes128(int *, int *, char *, int *, int, int *);
int /*<<< orphan*/ pretty_print_key(int *, int);
int /*<<< orphan*/ printf(char *, ...);
int main(int argc, char *argv[]) {
  uint8_t new_key[16];
  uint8_t expect_key[16] = {0xA8, 0xDD, 0x63, 0xA3, 0xB8, 0x9D, 0x54, 0xB3,
                            0x7C, 0xA8, 0x02, 0x47, 0x3F, 0xDA, 0x91, 0x75};
  uint8_t base_key[16] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
                          0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF};
  uint8_t aid[3] = {0x30, 0x42, 0xF5};
  uint8_t sysid[] = {0x4E, 0x58, 0x50, 0x20, 0x41, 0x62, 0x75};
  char uid[] = "04782E21801D80";
  int ret;
  int test_times = 1;
  if (argc == 2) {
    test_times = atoi(argv[1]);
  }
  for (int i = 0; i < test_times; ++i) {
    ret = nfclock_diversify_key_aes128(base_key, aid, uid, sysid, sizeof(sysid),
                                       new_key);
    if (ret != 0) {
      printf("nfclock_diversify_key_aes128 returned %d\n", ret);
      return 1;
    }
    printf("expected: ");
    pretty_print_key(expect_key, sizeof(expect_key));
    printf("got:      ");
    pretty_print_key(new_key, sizeof(new_key));
    if (!keys_equal(new_key, sizeof(new_key), expect_key, sizeof(expect_key))) {
      printf("ERROR: new_key does not match expected key\n");
      return 1;
    }
  }
  return 0;
}


x86 assembly (clang, -O0):
<main>:
push   %rbp
mov    %rsp,%rbp
sub    $0x120,%rsp
movl   $0x0,-0x4(%rbp)
mov    %edi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
lea    -0x90(%rbp),%rdi
lea    0xe79(%rip),%rsi
mov    $0x40,%edx
call   1060 <memcpy@plt>
lea    -0xd0(%rbp),%rdi
lea    0xea1(%rip),%rsi
mov    $0x40,%edx
call   1060 <memcpy@plt>
mov    0xed0(%rip),%rax
mov    %rax,-0xdc(%rbp)
mov    0xecb(%rip),%eax
mov    %eax,-0xd4(%rbp)
mov    0xec6(%rip),%rax
mov    %rax,-0x100(%rbp)
mov    0xec0(%rip),%rax
mov    %rax,-0xf8(%rbp)
mov    0xeba(%rip),%rax
mov    %rax,-0xf0(%rbp)
mov    0xeb5(%rip),%eax
mov    %eax,-0xe8(%rbp)
mov    0xeac(%rip),%rax
mov    %rax,-0x10f(%rbp)
mov    0xea7(%rip),%eax
mov    %eax,-0x107(%rbp)
mov    0xe9e(%rip),%ax
mov    %ax,-0x103(%rbp)
mov    0xe93(%rip),%al
mov    %al,-0x101(%rbp)
movl   $0x1,-0x118(%rbp)
cmpl   $0x2,-0x8(%rbp)
jne    1254 <main+0xf4>
mov    -0x10(%rbp),%rax
mov    0x8(%rax),%rdi
call   1080 <atoi@plt>
mov    %eax,-0x118(%rbp)
movl   $0x0,-0x11c(%rbp)
mov    -0x11c(%rbp),%eax
cmp    -0x118(%rbp),%eax
jge    135c <main+0x1fc>
lea    -0xd0(%rbp),%rdi
lea    -0xdc(%rbp),%rsi
lea    -0x10f(%rbp),%rdx
lea    -0x100(%rbp),%rcx
lea    -0x50(%rbp),%r9
mov    $0x1c,%r8d
call   1070 <nfclock_diversify_key_aes128@plt>
mov    %eax,-0x114(%rbp)
cmpl   $0x0,-0x114(%rbp)
je     12ce <main+0x16e>
mov    -0x114(%rbp),%esi
lea    0xe00(%rip),%rdi
mov    $0x0,%al
call   1030 <printf@plt>
movl   $0x1,-0x4(%rbp)
jmp    1363 <main+0x203>
lea    0xe10(%rip),%rdi
mov    $0x0,%al
call   1030 <printf@plt>
lea    -0x90(%rbp),%rdi
mov    $0x40,%esi
call   1040 <pretty_print_key@plt>
lea    0xdfc(%rip),%rdi
mov    $0x0,%al
call   1030 <printf@plt>
lea    -0x50(%rbp),%rdi
mov    $0x40,%esi
call   1040 <pretty_print_key@plt>
lea    -0x50(%rbp),%rdi
lea    -0x90(%rbp),%rdx
mov    $0x40,%ecx
mov    %ecx,%esi
call   1050 <keys_equal@plt>
cmp    $0x0,%eax
jne    1343 <main+0x1e3>
lea    0xdcb(%rip),%rdi
mov    $0x0,%al
call   1030 <printf@plt>
movl   $0x1,-0x4(%rbp)
jmp    1363 <main+0x203>
jmp    1348 <main+0x1e8>
mov    -0x11c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x11c(%rbp)
jmp    125e <main+0xfe>
movl   $0x0,-0x4(%rbp)
mov    -0x4(%rbp),%eax
add    $0x120,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<main>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
sub    $0x108,%rsp
movaps 0xeb8(%rip),%xmm0
movaps %xmm0,0xb0(%rsp)
movaps 0xe99(%rip),%xmm0
movaps %xmm0,0xa0(%rsp)
movaps 0xe7a(%rip),%xmm0
movaps %xmm0,0x90(%rsp)
movaps 0xe5b(%rip),%xmm0
movaps %xmm0,0x80(%rsp)
movaps 0xebc(%rip),%xmm0
movaps %xmm0,0x70(%rsp)
movaps 0xea0(%rip),%xmm0
movaps %xmm0,0x60(%rsp)
movaps 0xe84(%rip),%xmm0
movaps %xmm0,0x50(%rsp)
movaps 0xe68(%rip),%xmm0
movaps %xmm0,0x40(%rsp)
mov    0xea5(%rip),%eax
mov    %eax,0x8(%rsp)
mov    0xe92(%rip),%rax
mov    %rax,(%rsp)
movups 0xea3(%rip),%xmm0
movups %xmm0,0x2c(%rsp)
movaps 0xe8b(%rip),%xmm0
movaps %xmm0,0x20(%rsp)
movabs $0x30384431303831,%rax
mov    %rax,0x17(%rsp)
movabs $0x3132453238373430,%rax
45 32 31
mov    %rax,0x10(%rsp)
mov    $0x1,%ebx
cmp    $0x2,%edi
jne    1245 <main+0xe5>
mov    0x8(%rsi),%rdi
call   1080 <atoi@plt>
mov    %eax,%ebx
test   %eax,%eax
jle    12de <main+0x17e>
lea    0x20(%rsp),%r13
lea    0xc0(%rsp),%rbp
lea    0xe8c(%rip),%r14
lea    0x80(%rsp),%r15
lea    0xe88(%rip),%r12
nopl   0x0(%rax,%rax,1)
lea    0x40(%rsp),%rdi
mov    %rsp,%rsi
lea    0x10(%rsp),%rdx
mov    %r13,%rcx
mov    $0x1c,%r8d
mov    %rbp,%r9
call   1070 <nfclock_diversify_key_aes128@plt>
test   %eax,%eax
jne    12e2 <main+0x182>
mov    %r14,%rdi
xor    %eax,%eax
call   1040 <printf@plt>
mov    %r15,%rdi
mov    $0x40,%esi
call   1050 <pretty_print_key@plt>
mov    %r12,%rdi
xor    %eax,%eax
call   1040 <printf@plt>
mov    %rbp,%rdi
mov    $0x40,%esi
call   1050 <pretty_print_key@plt>
mov    %rbp,%rdi
mov    $0x40,%esi
mov    %r15,%rdx
mov    $0x40,%ecx
call   1060 <keys_equal@plt>
test   %eax,%eax
je     12f4 <main+0x194>
add    $0xffffffff,%ebx
jne    1270 <main+0x110>
xor    %eax,%eax
jmp    1305 <main+0x1a5>
lea    0xdd2(%rip),%rdi
mov    %eax,%esi
xor    %eax,%eax
call   1040 <printf@plt>
jmp    1300 <main+0x1a0>
lea    0xe00(%rip),%rdi
call   1030 <puts@plt>
mov    $0x1,%eax
add    $0x108,%rsp
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
@__const.main.expect_key = [16 x i32] [i32 168, i32 221, i32 99, i32 163, i32 184, i32 157, i32 84, i32 179, i32 124, i32 168, i32 2, i32 71, i32 63, i32 218, i32 145, i32 117]
@__const.main.base_key = [16 x i32] [i32 0, i32 17, i32 34, i32 51, i32 68, i32 85, i32 102, i32 119, i32 136, i32 153, i32 170, i32 187, i32 204, i32 221, i32 238, i32 255]
@__const.main.aid = [3 x i32] [i32 48, i32 66, i32 245]
@__const.main.sysid = [7 x i32] [i32 78, i32 88, i32 80, i32 32, i32 65, i32 98, i32 117]
@__const.main.uid = [15 x i8] c"04782E21801D80\00"
@.str = [42 x i8] c"nfclock_diversify_key_aes128 returned %d\0A\00"
@.str.1 = [11 x i8] c"expected: \00"
@.str.2 = [11 x i8] c"got: \00"
@.str.3 = [44 x i8] c"ERROR: new_key does not match expected key\0A\00"
define i32 @main(i32 %0, i8** %1) {
%3 = alloca i32
%4 = alloca i32
%5 = alloca i8**
%6 = alloca [16 x i32]
%7 = alloca [16 x i32]
%8 = alloca [16 x i32]
%9 = alloca [3 x i32]
%10 = alloca [7 x i32]
%11 = alloca [15 x i8]
%12 = alloca i32
%13 = alloca i32
%14 = alloca i32
store i32 0, i32* %3
store i32 %0, i32* %4
store i8** %1, i8*** %5
%15 = bitcast [16 x i32]* %7 to i8*
%16 = bitcast [16 x i32]* %8 to i8*
%17 = bitcast [3 x i32]* %9 to i8*
%18 = bitcast [7 x i32]* %10 to i8*
%19 = bitcast [15 x i8]* %11 to i8*
store i32 1, i32* %13
%20 = load i32, i32* %4
%21 = icmp eq i32 %20, 2
br i1 %21, label %22, label %27
22: ; preds = %2
%23 = load i8**, i8*** %5
%24 = getelementptr inbounds i8*, i8** %23, i64 1
%25 = load i8*, i8** %24
%26 = call i32 @atoi(i8* %25)
store i32 %26, i32* %13
br label %27
27: ; preds = %22, %2
store i32 0, i32* %14
br label %28
28: ; preds = %58, %27
%29 = load i32, i32* %14
%30 = load i32, i32* %13
%31 = icmp slt i32 %29, %30
br i1 %31, label %32, label %61
32: ; preds = %28
%33 = getelementptr inbounds [16 x i32], [16 x i32]* %8, i64 0, i64 0
%34 = getelementptr inbounds [3 x i32], [3 x i32]* %9, i64 0, i64 0
%35 = getelementptr inbounds [15 x i8], [15 x i8]* %11, i64 0, i64 0
%36 = getelementptr inbounds [7 x i32], [7 x i32]* %10, i64 0, i64 0
%37 = getelementptr inbounds [16 x i32], [16 x i32]* %6, i64 0, i64 0
%38 = call i32 @nfclock_diversify_key_aes128(i32* %33, i32* %34, i8* %35, i32* %36, i32 28, i32* %37)
store i32 %38, i32* %12
%39 = load i32, i32* %12
%40 = icmp ne i32 %39, 0
br i1 %40, label %41, label %44
41: ; preds = %32
%42 = load i32, i32* %12
%43 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([42 x i8], [42 x i8]* @.str, i64 0, i64 0), i32 %42)
store i32 1, i32* %3
br label %62
44: ; preds = %32
%45 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.1, i64 0, i64 0))
%46 = getelementptr inbounds [16 x i32], [16 x i32]* %7, i64 0, i64 0
%47 = call i32 @pretty_print_key(i32* %46, i32 64)
%48 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.2, i64 0, i64 0))
%49 = getelementptr inbounds [16 x i32], [16 x i32]* %6, i64 0, i64 0
%50 = call i32 @pretty_print_key(i32* %49, i32 64)
%51 = getelementptr inbounds [16 x i32], [16 x i32]* %6, i64 0, i64 0
%52 = getelementptr inbounds [16 x i32], [16 x i32]* %7, i64 0, i64 0
%53 = call i32 @keys_equal(i32* %51, i32 64, i32* %52, i32 64)
%54 = icmp ne i32 %53, 0
br i1 %54, label %57, label %55
55: ; preds = %44
%56 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([44 x i8], [44 x i8]* @.str.3, i64 0, i64 0))
store i32 1, i32* %3
br label %62
57: ; preds = %44
br label %58
58: ; preds = %57
%59 = load i32, i32* %14
%60 = add nsw i32 %59, 1
store i32 %60, i32* %14
br label %28
61: ; preds = %28
store i32 0, i32* %3
br label %62
62: ; preds = %61, %55, %41
%63 = load i32, i32* %3
ret i32 %63
}

LLVM IR (-O2):
@__const.main.expect_key = [16 x i32] [i32 168, i32 221, i32 99, i32 163, i32 184, i32 157, i32 84, i32 179, i32 124, i32 168, i32 2, i32 71, i32 63, i32 218, i32 145, i32 117]
@__const.main.base_key = [16 x i32] [i32 0, i32 17, i32 34, i32 51, i32 68, i32 85, i32 102, i32 119, i32 136, i32 153, i32 170, i32 187, i32 204, i32 221, i32 238, i32 255]
@__const.main.aid = [3 x i32] [i32 48, i32 66, i32 245]
@__const.main.sysid = [7 x i32] [i32 78, i32 88, i32 80, i32 32, i32 65, i32 98, i32 117]
@__const.main.uid = [15 x i8] c"04782E21801D80\00"
@.str = [42 x i8] c"nfclock_diversify_key_aes128 returned %d\0A\00"
@.str.1 = [11 x i8] c"expected: \00"
@.str.2 = [11 x i8] c"got: \00"
@str = [43 x i8] c"ERROR: new_key does not match expected key\00"
define i32 @main(i32 %0, i8** nocapture %1) {
%3 = alloca [16 x i32]
%4 = alloca [16 x i32]
%5 = alloca [16 x i32]
%6 = alloca [3 x i32]
%7 = alloca [7 x i32]
%8 = alloca [15 x i8]
%9 = bitcast [16 x i32]* %3 to i8*
%10 = bitcast [16 x i32]* %4 to i8*
%11 = bitcast [16 x i32]* %5 to i8*
%12 = bitcast [3 x i32]* %6 to i8*
%13 = bitcast [7 x i32]* %7 to i8*
%14 = getelementptr inbounds [15 x i8], [15 x i8]* %8, i64 0, i64 0
%15 = icmp eq i32 %0, 2
br i1 %15, label %16, label %21
16: ; preds = %2
%17 = getelementptr inbounds i8*, i8** %1, i64 1
%18 = load i8*, i8** %17
%19 = tail call i32 @atoi(i8* %18)
%20 = icmp sgt i32 %19, 0
br i1 %20, label %21, label %46
21: ; preds = %2, %16
%22 = phi i32 [ %19, %16 ], [ 1, %2 ]
%23 = getelementptr inbounds [16 x i32], [16 x i32]* %5, i64 0, i64 0
%24 = getelementptr inbounds [3 x i32], [3 x i32]* %6, i64 0, i64 0
%25 = getelementptr inbounds [7 x i32], [7 x i32]* %7, i64 0, i64 0
%26 = getelementptr inbounds [16 x i32], [16 x i32]* %3, i64 0, i64 0
%27 = getelementptr inbounds [16 x i32], [16 x i32]* %4, i64 0, i64 0
br label %30
28: ; preds = %36
%29 = icmp eq i32 %43, %22
br i1 %29, label %46, label %30
30: ; preds = %21, %28
%31 = phi i32 [ 0, %21 ], [ %43, %28 ]
%32 = call i32 @nfclock_diversify_key_aes128(i32* %23, i32* %24, i8* %14, i32* %25, i32 28, i32* %26)
%33 = icmp eq i32 %32, 0
br i1 %33, label %36, label %34
34: ; preds = %30
%35 = call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([42 x i8], [42 x i8]* @.str, i64 0, i64 0), i32 %32)
br label %46
36: ; preds = %30
%37 = call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([11 x i8], [11 x i8]* @.str.1, i64 0, i64 0))
%38 = call i32 @pretty_print_key(i32* %27, i32 64)
%39 = call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([11 x i8], [11 x i8]* @.str.2, i64 0, i64 0))
%40 = call i32 @pretty_print_key(i32* %26, i32 64)
%41 = call i32 @keys_equal(i32* %26, i32 64, i32* %27, i32 64)
%42 = icmp eq i32 %41, 0
%43 = add nuw nsw i32 %31, 1
br i1 %42, label %44, label %28
44: ; preds = %36
%45 = call i32 @puts(i8* dereferenceable(1) getelementptr inbounds ([43 x i8], [43 x i8]* @str, i64 0, i64 0))
br label %46
46: ; preds = %28, %16, %44, %34
%47 = phi i32 [ 1, %34 ], [ 1, %44 ], [ 0, %16 ], [ 0, %28 ]
ret i32 %47
}