// File: simap[P]ecctools/lib/uECC.c
// Function: uECC_sign_deterministic
int uECC_sign_deterministic(const uint8_t *private_key,
                            const uint8_t *message_hash,
                            unsigned hash_size,
                            const uECC_HashContext *hash_context,
                            uint8_t *signature,
                            uECC_Curve curve) {
    uint8_t *K = hash_context->tmp;
    uint8_t *V = K + hash_context->result_size;
    wordcount_t num_bytes = curve->num_bytes;
    wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
    bitcount_t num_n_bits = curve->num_n_bits;
    uECC_word_t tries;
    unsigned i;
    for (i = 0; i < hash_context->result_size; ++i) {
        V[i] = 0x01;
        K[i] = 0;
    }

    /* K = HMAC_K(V || 0x00 || int2octets(x) || h(m)) */
    HMAC_init(hash_context, K);
    V[hash_context->result_size] = 0x00;
    HMAC_update(hash_context, V, hash_context->result_size + 1);
    HMAC_update(hash_context, private_key, num_bytes);
    HMAC_update(hash_context, message_hash, hash_size);
    HMAC_finish(hash_context, K, K);

    update_V(hash_context, K, V);

    /* K = HMAC_K(V || 0x01 || int2octets(x) || h(m)) */
    HMAC_init(hash_context, K);
    V[hash_context->result_size] = 0x01;
    HMAC_update(hash_context, V, hash_context->result_size + 1);
    HMAC_update(hash_context, private_key, num_bytes);
    HMAC_update(hash_context, message_hash, hash_size);
    HMAC_finish(hash_context, K, K);

    update_V(hash_context, K, V);

    for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) {
        uECC_word_t T[uECC_MAX_WORDS];
        uint8_t *T_ptr = (uint8_t *)T;
        wordcount_t T_bytes = 0;
        for (;;) {
            update_V(hash_context, K, V);
            for (i = 0; i < hash_context->result_size; ++i) {
                T_ptr[T_bytes++] = V[i];
                if (T_bytes >= num_n_words * uECC_WORD_SIZE) {
                    goto filled;
                }
            }
        }
    filled:
        if ((bitcount_t)num_n_words * uECC_WORD_SIZE * 8 > num_n_bits) {
            uECC_word_t mask = (uECC_word_t)-1;
            T[num_n_words - 1] &=
                mask >> ((bitcount_t)(num_n_words * uECC_WORD_SIZE * 8 - num_n_bits));
        }

        if (uECC_sign_with_k(private_key, message_hash, hash_size, T, signature, curve)) {
            return 1;
        }

        /* K = HMAC_K(V || 0x00) */
        HMAC_init(hash_context, K);
        V[hash_context->result_size] = 0x00;
        HMAC_update(hash_context, V, hash_context->result_size + 1);
        HMAC_finish(hash_context, K, K);

        update_V(hash_context, K, V);
    }
    return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xa0, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movl %edx, -0x1c(%rbp)
movq %rcx, -0x28(%rbp)
movq %r8, -0x30(%rbp)
movq %r9, -0x38(%rbp)
movq -0x28(%rbp), %rax
movq 0x20(%rax), %rax
movq %rax, -0x40(%rbp)
movq -0x40(%rbp), %rax
movq -0x28(%rbp), %rcx
movl 0x1c(%rcx), %ecx
addq %rcx, %rax
movq %rax, -0x48(%rbp)
movq -0x38(%rbp), %rax
movb 0x1(%rax), %al
movb %al, -0x49(%rbp)
movq -0x38(%rbp), %rax
movswl 0x2(%rax), %eax
addl $0x3f, %eax
movl $0x40, %ecx
cltd
idivl %ecx
movb %al, -0x4a(%rbp)
movq -0x38(%rbp), %rax
movw 0x2(%rax), %ax
movw %ax, -0x4c(%rbp)
movl $0x0, -0x5c(%rbp)
movl -0x5c(%rbp), %eax
movq -0x28(%rbp), %rcx
cmpl 0x1c(%rcx), %eax
jae 0x2dd0
movq -0x48(%rbp), %rax
movl -0x5c(%rbp), %ecx
movb $0x1, (%rax,%rcx)
movq -0x40(%rbp), %rax
movl -0x5c(%rbp), %ecx
movb $0x0, (%rax,%rcx)
movl -0x5c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x5c(%rbp)
jmp 0x2da3
movq -0x28(%rbp), %rdi
movq -0x40(%rbp), %rsi
callq 0x3050
movq -0x48(%rbp), %rax
movq -0x28(%rbp), %rcx
movl 0x1c(%rcx), %ecx
movb $0x0, (%rax,%rcx)
movq -0x28(%rbp), %rdi
movq -0x48(%rbp), %rsi
movq -0x28(%rbp), %rax
movl 0x1c(%rax), %edx
addl $0x1, %edx
callq 0x3110
movq -0x28(%rbp), %rdi
movq -0x10(%rbp), %rsi
movsbl -0x49(%rbp), %edx
callq 0x3110
movq -0x28(%rbp), %rdi
movq -0x18(%rbp), %rsi
movl -0x1c(%rbp), %edx
callq 0x3110
movq -0x28(%rbp), %rdi
movq -0x40(%rbp), %rsi
movq -0x40(%rbp), %rdx
callq 0x3140
movq -0x28(%rbp), %rdi
movq -0x40(%rbp), %rsi
movq -0x48(%rbp), %rdx
callq 0x3240
movq -0x28(%rbp), %rdi
movq -0x40(%rbp), %rsi
callq 0x3050
movq -0x48(%rbp), %rax
movq -0x28(%rbp), %rcx
movl 0x1c(%rcx), %ecx
movb $0x1, (%rax,%rcx)
movq -0x28(%rbp), %rdi
movq -0x48(%rbp), %rsi
movq -0x28(%rbp), %rax
movl 0x1c(%rax), %edx
addl $0x1, %edx
callq 0x3110
movq -0x28(%rbp), %rdi
movq -0x10(%rbp), %rsi
movsbl -0x49(%rbp), %edx
callq 0x3110
movq -0x28(%rbp), %rdi
movq -0x18(%rbp), %rsi
movl -0x1c(%rbp), %edx
callq 0x3110
movq -0x28(%rbp), %rdi
movq -0x40(%rbp), %rsi
movq -0x40(%rbp), %rdx
callq 0x3140
movq -0x28(%rbp), %rdi
movq -0x40(%rbp), %rsi
movq -0x48(%rbp), %rdx
callq 0x3240
movq $0x0, -0x58(%rbp)
cmpq $0x40, -0x58(%rbp)
jae 0x3037
leaq -0x80(%rbp), %rax
movq %rax, -0x88(%rbp)
movb $0x0, -0x89(%rbp)
movq -0x28(%rbp), %rdi
movq -0x40(%rbp), %rsi
movq -0x48(%rbp), %rdx
callq 0x3240
movl $0x0, -0x5c(%rbp)
movl -0x5c(%rbp), %eax
movq -0x28(%rbp), %rcx
cmpl 0x1c(%rcx), %eax
jae 0x2f52
movq -0x48(%rbp), %rax
movl -0x5c(%rbp), %ecx
movb (%rax,%rcx), %dl
movq -0x88(%rbp), %rax
movb -0x89(%rbp), %cl
movb %cl, %sil
addb $0x1, %sil
movb %sil, -0x89(%rbp)
movsbq %cl, %rcx
movb %dl, (%rax,%rcx)
movsbl -0x89(%rbp), %eax
movsbl -0x4a(%rbp), %ecx
shll $0x3, %ecx
cmpl %ecx, %eax
jl 0x2f45
jmp 0x2f54
jmp 0x2f47
movl -0x5c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x5c(%rbp)
jmp 0x2ef9
jmp 0x2ee1
movsbl -0x4a(%rbp), %eax
cwtl
shll $0x3, %eax
shll $0x3, %eax
movswl -0x4c(%rbp), %ecx
cmpl %ecx, %eax
jle 0x2fa7
movq $-0x1, -0x98(%rbp)
movq -0x98(%rbp), %rax
movsbl -0x4a(%rbp), %ecx
shll $0x3, %ecx
shll $0x3, %ecx
movswl -0x4c(%rbp), %edx
subl %edx, %ecx
movswl %cx, %ecx
movl %ecx, %ecx
shrq %cl, %rax
movq %rax, %rcx
movsbl -0x4a(%rbp), %eax
subl $0x1, %eax
cltq
andq -0x80(%rbp,%rax,8), %rcx
movq %rcx, -0x80(%rbp,%rax,8)
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
movl -0x1c(%rbp), %edx
leaq -0x80(%rbp), %rcx
movq -0x30(%rbp), %r8
movq -0x38(%rbp), %r9
callq 0x2a10
cmpl $0x0, %eax
je 0x2fd1
movl $0x1, -0x4(%rbp)
jmp 0x303e
movq -0x28(%rbp), %rdi
movq -0x40(%rbp), %rsi
callq 0x3050
movq -0x48(%rbp), %rax
movq -0x28(%rbp), %rcx
movl 0x1c(%rcx), %ecx
movb $0x0, (%rax,%rcx)
movq -0x28(%rbp), %rdi
movq -0x48(%rbp), %rsi
movq -0x28(%rbp), %rax
movl 0x1c(%rax), %edx
addl $0x1, %edx
callq 0x3110
movq -0x28(%rbp), %rdi
movq -0x40(%rbp), %rsi
movq -0x40(%rbp), %rdx
callq 0x3140
movq -0x28(%rbp), %rdi
movq -0x40(%rbp), %rsi
movq -0x48(%rbp), %rdx
callq 0x3240
movq -0x58(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x58(%rbp)
jmp 0x2ec4
movl $0x0, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0xa0, %rsp
popq %rbp
retq
nopw (%rax,%rax)