// File: simap[P]ecctools/lib/uECC.c
// Function: uECC_shared_secret
int uECC_shared_secret(const uint8_t *public_key,
                       const uint8_t *private_key,
                       uint8_t *secret,
                       uECC_Curve curve) {
    uECC_word_t _public[uECC_MAX_WORDS * 2];
    uECC_word_t _private[uECC_MAX_WORDS];

    uECC_word_t tmp[uECC_MAX_WORDS];
    uECC_word_t *p2[2] = {_private, tmp};
    uECC_word_t *initial_Z = 0;
    uECC_word_t carry;
    wordcount_t num_words = curve->num_words;
    wordcount_t num_bytes = curve->num_bytes;

#if uECC_VLI_NATIVE_LITTLE_ENDIAN
    bcopy((uint8_t *) _private, private_key, num_bytes);
    bcopy((uint8_t *) _public, public_key, num_bytes*2);
#else
    uECC_vli_bytesToNative(_private, private_key, BITS_TO_BYTES(curve->num_n_bits));
    uECC_vli_bytesToNative(_public, public_key, num_bytes);
    uECC_vli_bytesToNative(_public + num_words, public_key + num_bytes, num_bytes);
#endif

    /* Regularize the bitcount for the private key so that attackers cannot use a side channel
       attack to learn the number of leading zeros. */
    carry = regularize_k(_private, _private, tmp, curve);

    /* If an RNG function was specified, try to get a random initial Z value to improve
       protection against side-channel attacks. */
    if (g_rng_function) {
        if (!uECC_generate_random_int(p2[carry], curve->p, num_words)) {
            return 0;
        }
        initial_Z = p2[carry];
    }

    EccPoint_mult(_public, _public, p2[!carry], initial_Z, curve->num_n_bits + 1, curve);
#if uECC_VLI_NATIVE_LITTLE_ENDIAN
    bcopy((uint8_t *) secret, (uint8_t *) _public, num_bytes);
#else
    uECC_vli_nativeToBytes(secret, num_bytes, _public);
#endif
    return !EccPoint_isZero(_public, curve);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xe0, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movq %rcx, -0x28(%rbp)
leaq -0x90(%rbp), %rax
movq %rax, -0xc0(%rbp)
leaq -0xb0(%rbp), %rax
movq %rax, -0xb8(%rbp)
movq $0x0, -0xc8(%rbp)
movq -0x28(%rbp), %rax
movb (%rax), %al
movb %al, -0xd1(%rbp)
movq -0x28(%rbp), %rax
movb 0x1(%rax), %al
movb %al, -0xd2(%rbp)
leaq -0x90(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0x28(%rbp), %rax
movswl 0x2(%rax), %eax
addl $0x7, %eax
movl $0x8, %ecx
cltd
idivl %ecx
movl %eax, %edx
callq 0x1d90
leaq -0x70(%rbp), %rdi
movq -0x10(%rbp), %rsi
movsbl -0xd2(%rbp), %edx
callq 0x1d90
leaq -0x70(%rbp), %rdi
movsbl -0xd1(%rbp), %eax
cltq
shlq $0x3, %rax
addq %rax, %rdi
movq -0x10(%rbp), %rsi
movsbl -0xd2(%rbp), %eax
cltq
addq %rax, %rsi
movsbl -0xd2(%rbp), %edx
callq 0x1d90
leaq -0x90(%rbp), %rdi
leaq -0x90(%rbp), %rsi
leaq -0xb0(%rbp), %rdx
movq -0x28(%rbp), %rcx
callq 0x1e20
movq %rax, -0xd0(%rbp)
cmpq $0x0, 0x9407(%rip)      # 0xb0b8
je 0x1cfd
movq -0xd0(%rbp), %rax
movq -0xc0(%rbp,%rax,8), %rdi
movq -0x28(%rbp), %rsi
addq $0x8, %rsi
movsbl -0xd1(%rbp), %edx
callq 0x1980
cmpl $0x0, %eax
jne 0x1ce7
movl $0x0, -0x4(%rbp)
jmp 0x1d78
movq -0xd0(%rbp), %rax
movq -0xc0(%rbp,%rax,8), %rax
movq %rax, -0xc8(%rbp)
leaq -0x70(%rbp), %rdi
leaq -0x70(%rbp), %rsi
cmpq $0x0, -0xd0(%rbp)
setne %al
xorb $-0x1, %al
andb $0x1, %al
movzbl %al, %eax
movq -0xc0(%rbp,%rax,8), %rdx
movq -0xc8(%rbp), %rcx
movq -0x28(%rbp), %rax
movswl 0x2(%rax), %eax
addl $0x1, %eax
movq -0x28(%rbp), %r9
movswl %ax, %r8d
callq 0x1ef0
movq -0x20(%rbp), %rdi
movsbl -0xd2(%rbp), %esi
leaq -0x70(%rbp), %rdx
callq 0x1b50
leaq -0x70(%rbp), %rdi
movq -0x28(%rbp), %rax
movsbl (%rax), %eax
shll %eax
movsbl %al, %esi
callq 0x22e0
cmpq $0x0, %rax
setne %al
xorb $-0x1, %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0xe0, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)