user: Translate the below assembly code into C programming language:

```asm
<dh_get_secret>:
  endbr64
  push   %r15
  movswl %si,%esi
  mov    %rcx,%r15
  push   %r14
  mov    %rdx,%r14
  xor    %edx,%edx
  push   %r13
  push   %r12
  push   %rbp
  push   %rbx
  mov    %r8,%rbx
  sub    $0x18,%rsp
  movq   $0x0,(%r8)
  mov    %r9,0x8(%rsp)
  call   <BN_bin2bn@plt>
  test   %rax,%rax
  je     L55
  mov    %rax,%rbp
  xor    %eax,%eax
  call   <BN_new@plt>
  mov    %rax,%r12
  test   %rax,%rax
  je     L118
  xor    %eax,%eax
  call   <BN_CTX_new@plt>
  mov    %rax,%r13
  test   %rax,%rax
  je     L92
  mov    %rax,%r8
  mov    %r15,%rcx
  mov    %r14,%rdx
  mov    %rbp,%rsi
  mov    %r12,%rdi
  call   <BN_mod_exp@plt>
  test   %eax,%eax
  je     L92
  mov    %r12,%rdi
  call   <BN_num_bytes@plt>
  mov    0x8(%rsp),%r14
  mov    %eax,%edi
  mov    %eax,(%r14)
  call   <malloc@plt>
  mov    %rax,(%rbx)
  mov    %rax,%rsi
  test   %rax,%rax
  je     L44
  mov    %r12,%rdi
  call   <BN_bn2bin@plt>
  cmp    %eax,(%r14)
  je     L18
L92:
  mov    (%rbx),%rdi
  test   %rdi,%rdi
  je     L44
  call   <free@plt>
L44:
  mov    %rbp,%rdi
  call   <BN_free@plt>
  mov    %r12,%rdi
  call   <BN_free@plt>
  test   %r13,%r13
  je     L86
  mov    %r13,%rdi
  call   <BN_CTX_free@plt>
L86:
  movq   $0x0,(%rbx)
  add    $0x18,%rsp
  mov    $0x5,%eax
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  pop    %r15
  ret
  nopl   0x0(%rax,%rax,1)
L18:
  mov    %rbp,%rdi
  call   <BN_free@plt>
  mov    %r12,%rdi
  call   <BN_free@plt>
  mov    %r13,%rdi
  call   <BN_CTX_free@plt>
  add    $0x18,%rsp
  xor    %eax,%eax
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  pop    %r15
  ret
  nopl   0x0(%rax)
L55:
  mov    (%rbx),%rdi
  test   %rdi,%rdi
  je     L86
  call   <free@plt>
  jmp    L86
  nop
L118:
  mov    (%rbx),%rdi
  test   %rdi,%rdi
  je     L70
  call   <free@plt>
  mov    %rbp,%rdi
  call   <BN_free@plt>
  jmp    L86
  nopw   0x0(%rax,%rax,1)
L70:
  mov    %rbp,%rdi
  call   <BN_free@plt>
  jmp    L86
```

assistant: ```c
int dh_get_secret(const unsigned char *public, short public_len, BIGNUM *bn_private, BIGNUM *bn_prime, unsigned char **psecret_key, int *psecret_key_len) {
  int err, len;
  BIGNUM *bn_public = NULL;
  BIGNUM *bn_secret = NULL;
  BN_CTX *ctx = NULL;
  *psecret_key = NULL;
  bn_public = BN_bin2bn(public, public_len, NULL);
  if (!bn_public) {
    err = 5;
    goto ret_err;
  }
  bn_secret = BN_new();
  if (!bn_secret) {
    err = 5;
    goto ret_err;
  }
  ctx = BN_CTX_new();
  if (!ctx) {
    err = 5;
    goto ret_err;
  }
  if (!BN_mod_exp(bn_secret, bn_public, bn_private, bn_prime, ctx)) {
    err = 5;
    goto ret_err;
  }
  *psecret_key_len = BN_num_bytes(bn_secret);
  *psecret_key = (unsigned char *)malloc(*psecret_key_len);
  if (!*psecret_key) {
    err = 5;
    goto ret_err;
  }
  len = BN_bn2bin(bn_secret, *psecret_key);
  if (len != *psecret_key_len) {
    err = 5;
    goto ret_err;
  }
  BN_free(bn_public);
  BN_free(bn_secret);
  BN_CTX_free(ctx);
  return 0;
ret_err:;
  if (*psecret_key)
    free(*psecret_key);
  if (bn_public)
    BN_free(bn_public);
  if (bn_secret)
    BN_free(bn_secret);
  if (ctx)
    BN_CTX_free(ctx);
  *psecret_key = NULL;
  return err;
}
```