// File: msotoodeh[P]asymmetric-passwords/client/APKeyDerivation.cpp
// Function: APDigest::hmac(unsigned char const*, unsigned long, unsigned char const*, unsigned long, unsigned char*, unsigned long)
size_t APDigest::hmac(
    const uint8_t* key, size_t key_size, 
    const uint8_t* msg, size_t msg_size,
    uint8_t* mac, size_t mac_size)
{
    uint32_t i;
    uint8_t i_pad[BLOCK_SIZE], o_pad[BLOCK_SIZE];
    if (key_size > BLOCK_SIZE)
    {
        APDigest h((void*)key, key_size);
        for (i = 0; i < DIGEST_SIZE; i++)
        {
            o_pad[i] = h.m_Digest[i] ^ 0x5c;
            i_pad[i] = h.m_Digest[i] ^ 0x36;
        }
    }
    else
    {
        for (i = 0; i < key_size; i++)
        {
            o_pad[i] = key[i] ^ 0x5c;
            i_pad[i] = key[i] ^ 0x36;
        }
    }

    while (i < BLOCK_SIZE)
    {
        o_pad[i] = 0x5c;
        i_pad[i] = 0x36;
        i++;
    }

    APDigest inner_hash;
    inner_hash.update((void*)&i_pad[0], sizeof(i_pad));
    inner_hash.update((void*)msg, msg_size);
    inner_hash.finish();

    APDigest outer_hash;
    outer_hash.update((void*)&o_pad[0], sizeof(o_pad));
    outer_hash.update((void*)&inner_hash.m_Digest[0], sizeof(inner_hash.m_Digest));
    return outer_hash.finish((void*)mac, mac_size);
}

// Assembly:
subq $0x4a8, %rsp            # imm = 0x4A8
movq %rdi, 0x4a0(%rsp)
movq %rsi, 0x498(%rsp)
movq %rdx, 0x490(%rsp)
movq %rcx, 0x488(%rsp)
movq %r8, 0x480(%rsp)
movq %r9, 0x478(%rsp)
cmpq $0x80, 0x498(%rsp)
jbe 0x407541
movq 0x4a0(%rsp), %rsi
movq 0x498(%rsp), %rdx
leaq 0x258(%rsp), %rdi
callq 0x407300
movl $0x0, 0x474(%rsp)
cmpl $0x40, 0x474(%rsp)
jae 0x407532
movl 0x474(%rsp), %eax
movzbl 0x330(%rsp,%rax), %eax
xorl $0x5c, %eax
movb %al, %cl
movl 0x474(%rsp), %eax
movb %cl, 0x370(%rsp,%rax)
movl 0x474(%rsp), %eax
movzbl 0x330(%rsp,%rax), %eax
xorl $0x36, %eax
movb %al, %cl
movl 0x474(%rsp), %eax
movb %cl, 0x3f0(%rsp,%rax)
movl 0x474(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x474(%rsp)
jmp 0x4074d1
leaq 0x258(%rsp), %rdi
callq 0x407400
jmp 0x4075be
movl $0x0, 0x474(%rsp)
movl 0x474(%rsp), %eax
cmpq 0x498(%rsp), %rax
jae 0x4075bc
movq 0x4a0(%rsp), %rax
movl 0x474(%rsp), %ecx
movzbl (%rax,%rcx), %eax
xorl $0x5c, %eax
movb %al, %cl
movl 0x474(%rsp), %eax
movb %cl, 0x370(%rsp,%rax)
movq 0x4a0(%rsp), %rax
movl 0x474(%rsp), %ecx
movzbl (%rax,%rcx), %eax
xorl $0x36, %eax
movb %al, %cl
movl 0x474(%rsp), %eax
movb %cl, 0x3f0(%rsp,%rax)
movl 0x474(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x474(%rsp)
jmp 0x40754c
jmp 0x4075be
jmp 0x4075c0
cmpl $0x80, 0x474(%rsp)
jae 0x4075fe
movl 0x474(%rsp), %eax
movb $0x5c, 0x370(%rsp,%rax)
movl 0x474(%rsp), %eax
movb $0x36, 0x3f0(%rsp,%rax)
movl 0x474(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x474(%rsp)
jmp 0x4075c0
leaq 0x140(%rsp), %rdi
movq %rdi, 0x10(%rsp)
callq 0x4072e0
movq 0x10(%rsp), %rdi
leaq 0x3f0(%rsp), %rsi
movl $0x80, %edx
callq 0x407360
jmp 0x407629
movq 0x490(%rsp), %rsi
movq 0x488(%rsp), %rdx
leaq 0x140(%rsp), %rdi
callq 0x407360
jmp 0x407648
leaq 0x140(%rsp), %rdi
callq 0x407440
jmp 0x407657
leaq 0x18(%rsp), %rdi
callq 0x4072e0
jmp 0x407663
leaq 0x18(%rsp), %rdi
leaq 0x370(%rsp), %rsi
movl $0x80, %edx
callq 0x407360
jmp 0x40767c
leaq 0x218(%rsp), %rsi
leaq 0x18(%rsp), %rdi
movl $0x40, %edx
callq 0x407360
jmp 0x407695
movq 0x480(%rsp), %rsi
movq 0x478(%rsp), %rdx
leaq 0x18(%rsp), %rdi
callq 0x407390
movq %rax, 0x8(%rsp)
jmp 0x4076b6
leaq 0x18(%rsp), %rdi
callq 0x407400
leaq 0x140(%rsp), %rdi
callq 0x407400
movq 0x8(%rsp), %rax
addq $0x4a8, %rsp            # imm = 0x4A8
retq
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x138(%rsp)
movl %eax, 0x134(%rsp)
jmp 0x40770e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x138(%rsp)
movl %eax, 0x134(%rsp)
leaq 0x18(%rsp), %rdi
callq 0x407400
leaq 0x140(%rsp), %rdi
callq 0x407400
movq 0x138(%rsp), %rdi
callq 0x4b0e70
nopl (%rax,%rax)