// File: simap[P]ecctools/lib/uECC.c
// Function: uECC_sign_with_k(unsigned char const*, unsigned char const*, unsigned int, unsigned long*, unsigned char*, uECC_Curve_t const*)
static int uECC_sign_with_k(const uint8_t *private_key,
                            const uint8_t *message_hash,
                            unsigned hash_size,
                            uECC_word_t *k,
                            uint8_t *signature,
                            uECC_Curve curve) {

    uECC_word_t tmp[uECC_MAX_WORDS];
    uECC_word_t s[uECC_MAX_WORDS];
    uECC_word_t *k2[2] = {tmp, s};
#if uECC_VLI_NATIVE_LITTLE_ENDIAN
    uECC_word_t *p = (uECC_word_t *)signature;
#else
    uECC_word_t p[uECC_MAX_WORDS * 2];
#endif
    uECC_word_t carry;
    wordcount_t num_words = curve->num_words;
    wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
    bitcount_t num_n_bits = curve->num_n_bits;

    /* Make sure 0 < k < curve_n */
    if (uECC_vli_isZero(k, num_words) || uECC_vli_cmp(curve->n, k, num_n_words) != 1) {
        return 0;
    }

    carry = regularize_k(k, tmp, s, curve);
    EccPoint_mult(p, curve->G, k2[!carry], 0, num_n_bits + 1, curve);
    if (uECC_vli_isZero(p, num_words)) {
        return 0;
    }

    /* If an RNG function was specified, get a random number
       to prevent side channel analysis of k. */
    if (!g_rng_function) {
        uECC_vli_clear(tmp, num_n_words);
        tmp[0] = 1;
    } else if (!uECC_generate_random_int(tmp, curve->n, num_n_words)) {
        return 0;
    }

    /* Prevent side channel analysis of uECC_vli_modInv() to determine
       bits of k / the private key by premultiplying by a random number */
    uECC_vli_modMult(k, k, tmp, curve->n, num_n_words); /* k' = rand * k */
    uECC_vli_modInv(k, k, curve->n, num_n_words);       /* k = 1 / k' */
    uECC_vli_modMult(k, k, tmp, curve->n, num_n_words); /* k = 1 / k */

#if uECC_VLI_NATIVE_LITTLE_ENDIAN == 0
    uECC_vli_nativeToBytes(signature, curve->num_bytes, p); /* store r */
#endif

#if uECC_VLI_NATIVE_LITTLE_ENDIAN
    bcopy((uint8_t *) tmp, private_key, BITS_TO_BYTES(curve->num_n_bits));
#else
    uECC_vli_bytesToNative(tmp, private_key, BITS_TO_BYTES(curve->num_n_bits)); /* tmp = d */
#endif

    s[num_n_words - 1] = 0;
    uECC_vli_set(s, p, num_words);
    uECC_vli_modMult(s, tmp, s, curve->n, num_n_words); /* s = r*d */

    bits2int(tmp, message_hash, hash_size, curve);
    uECC_vli_modAdd(s, tmp, s, curve->n, num_n_words); /* s = e + r*d */
    uECC_vli_modMult(s, s, k, curve->n, num_n_words);  /* s = (e + r*d) / k */
    if (uECC_vli_numBits(s, num_n_words) > (bitcount_t)curve->num_bytes * 8) {
        return 0;
    }
#if uECC_VLI_NATIVE_LITTLE_ENDIAN
    bcopy((uint8_t *) signature + curve->num_bytes, (uint8_t *) s, curve->num_bytes);
#else
    uECC_vli_nativeToBytes(signature + curve->num_bytes, curve->num_bytes, s);
#endif    
    return 1;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xe0, %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)
leaq -0x60(%rbp), %rax
movq %rax, -0x90(%rbp)
leaq -0x80(%rbp), %rax
movq %rax, -0x88(%rbp)
movq -0x38(%rbp), %rax
movb (%rax), %al
movb %al, -0xd9(%rbp)
movq -0x38(%rbp), %rax
movswl 0x2(%rax), %eax
addl $0x3f, %eax
movl $0x40, %ecx
cltd
idivl %ecx
movb %al, -0xda(%rbp)
movq -0x38(%rbp), %rax
movw 0x2(%rax), %ax
movw %ax, -0xdc(%rbp)
movq -0x28(%rbp), %rdi
movsbl -0xd9(%rbp), %esi
callq 0x22e0
cmpq $0x0, %rax
jne 0x2ab2
movq -0x38(%rbp), %rdi
addq $0x28, %rdi
movq -0x28(%rbp), %rsi
movsbl -0xda(%rbp), %edx
callq 0x28f0
movsbl %al, %eax
cmpl $0x1, %eax
je 0x2abe
movl $0x0, -0x4(%rbp)
jmp 0x2d20
movq -0x28(%rbp), %rdi
leaq -0x60(%rbp), %rsi
leaq -0x80(%rbp), %rdx
movq -0x38(%rbp), %rcx
callq 0x1e20
movq %rax, -0xd8(%rbp)
leaq -0xd0(%rbp), %rdi
movq -0x38(%rbp), %rsi
addq $0x48, %rsi
cmpq $0x0, -0xd8(%rbp)
setne %al
xorb $-0x1, %al
andb $0x1, %al
movzbl %al, %eax
movq -0x90(%rbp,%rax,8), %rdx
movswl -0xdc(%rbp), %eax
addl $0x1, %eax
movq -0x38(%rbp), %r9
xorl %ecx, %ecx
movswl %ax, %r8d
callq 0x1ef0
leaq -0xd0(%rbp), %rdi
movsbl -0xd9(%rbp), %esi
callq 0x22e0
cmpq $0x0, %rax
je 0x2b41
movl $0x0, -0x4(%rbp)
jmp 0x2d20
cmpq $0x0, 0x856f(%rip)      # 0xb0b8
jne 0x2b65
leaq -0x60(%rbp), %rdi
movsbl -0xda(%rbp), %esi
callq 0x4170
movq $0x1, -0x60(%rbp)
jmp 0x2b90
leaq -0x60(%rbp), %rdi
movq -0x38(%rbp), %rsi
addq $0x28, %rsi
movsbl -0xda(%rbp), %edx
callq 0x1980
cmpl $0x0, %eax
jne 0x2b8e
movl $0x0, -0x4(%rbp)
jmp 0x2d20
jmp 0x2b90
movq -0x28(%rbp), %rdi
movq -0x28(%rbp), %rsi
leaq -0x60(%rbp), %rdx
movq -0x38(%rbp), %rcx
addq $0x28, %rcx
movsbl -0xda(%rbp), %r8d
callq 0x3d60
movq -0x28(%rbp), %rdi
movq -0x28(%rbp), %rsi
movq -0x38(%rbp), %rdx
addq $0x28, %rdx
movsbl -0xda(%rbp), %ecx
callq 0x39c0
movq -0x28(%rbp), %rdi
movq -0x28(%rbp), %rsi
leaq -0x60(%rbp), %rdx
movq -0x38(%rbp), %rcx
addq $0x28, %rcx
movsbl -0xda(%rbp), %r8d
callq 0x3d60
movq -0x30(%rbp), %rdi
movq -0x38(%rbp), %rax
movsbl 0x1(%rax), %esi
leaq -0xd0(%rbp), %rdx
callq 0x1b50
leaq -0x60(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x38(%rbp), %rax
movswl 0x2(%rax), %eax
addl $0x7, %eax
movl $0x8, %ecx
cltd
idivl %ecx
movl %eax, %edx
callq 0x1d90
movsbl -0xda(%rbp), %eax
subl $0x1, %eax
cltq
movq $0x0, -0x80(%rbp,%rax,8)
leaq -0x80(%rbp), %rdi
leaq -0xd0(%rbp), %rsi
movsbl -0xd9(%rbp), %edx
callq 0x3db0
leaq -0x80(%rbp), %rdi
leaq -0x60(%rbp), %rsi
leaq -0x80(%rbp), %rdx
movq -0x38(%rbp), %rcx
addq $0x28, %rcx
movsbl -0xda(%rbp), %r8d
callq 0x3d60
leaq -0x60(%rbp), %rdi
movq -0x18(%rbp), %rsi
movl -0x1c(%rbp), %edx
movq -0x38(%rbp), %rcx
callq 0x3c10
leaq -0x80(%rbp), %rdi
leaq -0x60(%rbp), %rsi
leaq -0x80(%rbp), %rdx
movq -0x38(%rbp), %rcx
addq $0x28, %rcx
movsbl -0xda(%rbp), %r8d
callq 0x4840
leaq -0x80(%rbp), %rdi
leaq -0x80(%rbp), %rsi
movq -0x28(%rbp), %rdx
movq -0x38(%rbp), %rcx
addq $0x28, %rcx
movsbl -0xda(%rbp), %r8d
callq 0x3d60
leaq -0x80(%rbp), %rdi
movsbl -0xda(%rbp), %esi
callq 0x40a0
cwtl
movq -0x38(%rbp), %rcx
movsbl 0x1(%rcx), %ecx
movswl %cx, %ecx
shll $0x3, %ecx
cmpl %ecx, %eax
jle 0x2cf7
movl $0x0, -0x4(%rbp)
jmp 0x2d20
movq -0x30(%rbp), %rdi
movq -0x38(%rbp), %rax
movsbl 0x1(%rax), %eax
cltq
addq %rax, %rdi
movq -0x38(%rbp), %rax
movsbl 0x1(%rax), %esi
leaq -0x80(%rbp), %rdx
callq 0x1b50
movl $0x1, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0xe0, %rsp
popq %rbp
retq
nopl (%rax)