// File: msotoodeh[P]asymmetric-passwords/demo/demo.cpp
// Function: SelfTest()
int SelfTest()
{
    int error_count = 0;
    // HMAC-SHA512 test vector from RFC4231 (test case 2)
    static const uint8_t hmac_sha512_tv1[64] =
    {
        0x16,0x4b,0x7a,0x7b,0xfc,0xf8,0x19,0xe2,0xe3,0x95,0xfb,0xe7,0x3b,0x56,0xe0,0xa3,
        0x87,0xbd,0x64,0x22,0x2e,0x83,0x1f,0xd6,0x10,0x27,0x0c,0xd7,0xea,0x25,0x05,0x54,
        0x97,0x58,0xbf,0x75,0xc0,0x5a,0x99,0x4a,0x6d,0x03,0x4f,0x65,0xf8,0xf0,0xe6,0xfd,
        0xca,0xea,0xb1,0xa3,0x4d,0x4a,0x6b,0x4b,0x63,0x6e,0x07,0x0a,0x38,0xbc,0xe7,0x37
    };

    // PBKDF2 test vectors from: https://github.com/Jither/PBKDF2/blob/master/Jither.PBKDF2.Test/PBKDF2DeriveBytesTest.cs
    static const uint8_t pbkdf2_key1[64] =
    {   // iterations = 1
        0x86,0x7f,0x70,0xcf,0x1a,0xde,0x02,0xcf,0xf3,0x75,0x25,0x99,0xa3,0xa5,0x3d,0xc4,
        0xaf,0x34,0xc7,0xa6,0x69,0x81,0x5a,0xe5,0xd5,0x13,0x55,0x4e,0x1c,0x8c,0xf2,0x52,
        0xc0,0x2d,0x47,0x0a,0x28,0x5a,0x05,0x01,0xba,0xd9,0x99,0xbf,0xe9,0x43,0xc0,0x8f,
        0x05,0x02,0x35,0xd7,0xd6,0x8b,0x1d,0xa5,0x5e,0x63,0xf7,0x3b,0x60,0xa5,0x7f,0xce
    };
    static const uint8_t pbkdf2_key2[64] =
    {   // iterations = 2
        0xe1,0xd9,0xc1,0x6a,0xa6,0x81,0x70,0x8a,0x45,0xf5,0xc7,0xc4,0xe2,0x15,0xce,0xb6,
        0x6e,0x01,0x1a,0x2e,0x9f,0x00,0x40,0x71,0x3f,0x18,0xae,0xfd,0xb8,0x66,0xd5,0x3c,
        0xf7,0x6c,0xab,0x28,0x68,0xa3,0x9b,0x9f,0x78,0x40,0xed,0xce,0x4f,0xef,0x5a,0x82,
        0xbe,0x67,0x33,0x5c,0x77,0xa6,0x06,0x8e,0x04,0x11,0x27,0x54,0xf2,0x7c,0xcf,0x4e
    };
    static const uint8_t pbkdf2_key4096[64] =
    {   // iterations = 4096
        0xd1,0x97,0xb1,0xb3,0x3d,0xb0,0x14,0x3e,0x01,0x8b,0x12,0xf3,0xd1,0xd1,0x47,0x9e,
        0x6c,0xde,0xbd,0xcc,0x97,0xc5,0xc0,0xf8,0x7f,0x69,0x02,0xe0,0x72,0xf4,0x57,0xb5,
        0x14,0x3f,0x30,0x60,0x26,0x41,0xb3,0xd5,0x5c,0xd3,0x35,0x98,0x8c,0xb3,0x6b,0x84,
        0x37,0x60,0x60,0xec,0xd5,0x32,0xe0,0x39,0xb7,0x42,0xa2,0x39,0x43,0x4a,0xf2,0xd5
    };

    uint8_t dk[64], mac[64];
    // HMAC-SHA512: rfc4321 test case 2
    if (APDigest::hmac((const uint8_t*)"Jefe", 4,
        (const uint8_t*)"what do ya want for nothing?", 28, mac, 64) != 64 ||
        memcmp(mac, hmac_sha512_tv1, 64) != 0)
    {
        error_count++;
        printf ("KAT error #%d: HMAC (1) failure.\n", error_count);
    }

    // PBKDF2-HMAC-SHA512
    APDigest::pbkdf2("password", 8, "salt", 4, 1, dk, sizeof(dk));
    if (memcmp(dk, pbkdf2_key1, sizeof(dk)) != 0)
    {
        error_count++;
        printf ("KAT error #%d: PBKDF2 (1) failure.\n", error_count);
    }
    APDigest::pbkdf2("password", 8, "salt", 4, 2, dk, sizeof(dk));
    if (memcmp(dk, pbkdf2_key2, sizeof(dk)) != 0)
    {
        error_count++;
        printf ("KAT error #%d: PBKDF2 (2) failure.\n", error_count);
    }
    APDigest::pbkdf2("password", 8, "salt", 4, 4096, dk, sizeof(dk));
    if (memcmp(dk, pbkdf2_key4096, sizeof(dk)) != 0)
    {
        error_count++;
        printf ("KAT error #%d: PBKDF2 (4096) failure.\n", error_count);
    }
    return error_count;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xa0, %rsp
movl $0x0, -0x4(%rbp)
leaq -0x90(%rbp), %r8
leaq 0x17c2d7(%rip), %rdi    # 0x5815f7
movl $0x4, %esi
leaq 0x17c2d0(%rip), %rdx    # 0x5815fc
movl $0x1c, %ecx
movl $0x40, %r9d
callq 0x407460
cmpq $0x40, %rax
jne 0x40535f
leaq -0x90(%rbp), %rdi
leaq 0x17bd00(%rip), %rsi    # 0x581050
movl $0x40, %edx
callq 0x401028
cmpl $0x0, %eax
je 0x405379
movl -0x4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x4(%rbp)
movl -0x4(%rbp), %esi
leaq 0x17c2a7(%rip), %rdi    # 0x581619
movb $0x0, %al
callq 0x4d79b0
leaq -0x50(%rbp), %r9
leaq 0x17c357(%rip), %rdi    # 0x5816db
movl $0x8, %esi
leaq 0x17c2ab(%rip), %rdx    # 0x58163b
movl $0x4, %ecx
movl $0x1, %r8d
movq $0x40, (%rsp)
callq 0x407870
leaq -0x50(%rbp), %rdi
leaq 0x17bcdd(%rip), %rsi    # 0x581090
movl $0x40, %edx
callq 0x401028
cmpl $0x0, %eax
je 0x4053dc
movl -0x4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x4(%rbp)
movl -0x4(%rbp), %esi
leaq 0x17c26b(%rip), %rdi    # 0x581640
movb $0x0, %al
callq 0x4d79b0
leaq -0x50(%rbp), %r9
leaq 0x17c2f4(%rip), %rdi    # 0x5816db
movl $0x8, %esi
leaq 0x17c248(%rip), %rdx    # 0x58163b
movl $0x4, %ecx
movl $0x2, %r8d
movq $0x40, (%rsp)
callq 0x407870
leaq -0x50(%rbp), %rdi
leaq 0x17bcba(%rip), %rsi    # 0x5810d0
movl $0x40, %edx
callq 0x401028
cmpl $0x0, %eax
je 0x40543f
movl -0x4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x4(%rbp)
movl -0x4(%rbp), %esi
leaq 0x17c22c(%rip), %rdi    # 0x581664
movb $0x0, %al
callq 0x4d79b0
leaq -0x50(%rbp), %r9
leaq 0x17c291(%rip), %rdi    # 0x5816db
movl $0x8, %esi
leaq 0x17c1e5(%rip), %rdx    # 0x58163b
movl $0x4, %ecx
movl $0x1000, %r8d           # imm = 0x1000
movq $0x40, (%rsp)
callq 0x407870
leaq -0x50(%rbp), %rdi
leaq 0x17bc97(%rip), %rsi    # 0x581110
movl $0x40, %edx
callq 0x401028
cmpl $0x0, %eax
je 0x4054a2
movl -0x4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x4(%rbp)
movl -0x4(%rbp), %esi
leaq 0x17c1ed(%rip), %rdi    # 0x581688
movb $0x0, %al
callq 0x4d79b0
movl -0x4(%rbp), %eax
addq $0xa0, %rsp
popq %rbp
retq
nop