int wc_ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen,
                     WC_RNG* rng, ecc_key* key)
{
    int err;
#if !defined(WOLFSSL_ASYNC_CRYPT) || !defined(WC_ASYNC_ENABLE_ECC)
#ifdef WOLFSSL_SMALL_STACK
    mp_int *r = NULL, *s = NULL;
#else
    mp_int r[1], s[1];
#endif
#endif

    if (in == NULL || out == NULL || outlen == NULL || key == NULL ||
                                                                rng == NULL) {
        return ECC_BAD_ARG_E;
    }

#ifdef WOLF_CRYPTO_CB
    if (key->devId != INVALID_DEVID) {
        err = wc_CryptoCb_EccSign(in, inlen, out, outlen, rng, key);
        if (err != CRYPTOCB_UNAVAILABLE)
            return err;
        /* fall-through when unavailable */
    }
#endif

#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC)
    /* handle async cases */
    err = wc_ecc_sign_hash_async(in, inlen, out, outlen, rng, key);
#else

#ifdef WOLFSSL_SMALL_STACK
    r = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC);
    if (r == NULL)
        return MEMORY_E;
    s = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC);
    if (s == NULL) {
        XFREE(r, key->heap, DYNAMIC_TYPE_ECC);
        return MEMORY_E;
    }
#endif
    XMEMSET(r, 0, sizeof(mp_int));
    XMEMSET(s, 0, sizeof(mp_int));

    if ((err = mp_init_multi(r, s, NULL, NULL, NULL, NULL)) != MP_OKAY){
    #ifdef WOLFSSL_SMALL_STACK
        XFREE(s, key->heap, DYNAMIC_TYPE_ECC);
        XFREE(r, key->heap, DYNAMIC_TYPE_ECC);
    #endif
        return err;
    }

/* hardware crypto */
#if defined(WOLFSSL_ATECC508A) || defined(PLUTON_CRYPTO_ECC) || defined(WOLFSSL_CRYPTOCELL)
    err = wc_ecc_sign_hash_hw(in, inlen, r, s, out, outlen, rng, key);
#else
    err = wc_ecc_sign_hash_ex(in, inlen, rng, key, r, s);
#endif
    if (err < 0) {
    #ifdef WOLFSSL_SMALL_STACK
        XFREE(s, key->heap, DYNAMIC_TYPE_ECC);
        XFREE(r, key->heap, DYNAMIC_TYPE_ECC);
    #endif
        return err;
    }

    /* encoded with DSA header */
    err = StoreECC_DSA_Sig(out, outlen, r, s);

    /* cleanup */
    mp_clear(r);
    mp_clear(s);

#ifdef WOLFSSL_SMALL_STACK
    XFREE(s, key->heap, DYNAMIC_TYPE_ECC);
    XFREE(r, key->heap, DYNAMIC_TYPE_ECC);
#endif
#endif /* WOLFSSL_ASYNC_CRYPT */

    return err;
}
int wc_ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen,
                     WC_RNG* rng, ecc_key* key)
{
    int err;
#if !defined(WOLFSSL_ASYNC_CRYPT) || !defined(WC_ASYNC_ENABLE_ECC)
#ifdef WOLFSSL_SMALL_STACK
    mp_int *r = NULL, *s = NULL;
#else
    mp_int r[1], s[1];
#endif
#endif

    if (in == NULL || out == NULL || outlen == NULL || key == NULL ||
                                                                rng == NULL) {
        return ECC_BAD_ARG_E;
    }

#ifdef WOLF_CRYPTO_CB
    if (key->devId != INVALID_DEVID) {
        err = wc_CryptoCb_EccSign(in, inlen, out, outlen, rng, key);
        if (err != CRYPTOCB_UNAVAILABLE)
            return err;
         
    }
#endif

#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC)
     
    err = wc_ecc_sign_hash_async(in, inlen, out, outlen, rng, key);
#else

#ifdef WOLFSSL_SMALL_STACK
    r = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC);
    if (r == NULL)
        return MEMORY_E;
    s = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC);
    if (s == NULL) {
        XFREE(r, key->heap, DYNAMIC_TYPE_ECC);
        return MEMORY_E;
    }
#endif
    XMEMSET(r, 0, sizeof(mp_int));
    XMEMSET(s, 0, sizeof(mp_int));

    if ((err = mp_init_multi(r, s, NULL, NULL, NULL, NULL)) != MP_OKAY){
    #ifdef WOLFSSL_SMALL_STACK
        XFREE(s, key->heap, DYNAMIC_TYPE_ECC);
        XFREE(r, key->heap, DYNAMIC_TYPE_ECC);
    #endif
        return err;
    }

 
#if defined(WOLFSSL_ATECC508A) || defined(PLUTON_CRYPTO_ECC) || defined(WOLFSSL_CRYPTOCELL)
    err = wc_ecc_sign_hash_hw(in, inlen, r, s, out, outlen, rng, key);
#else
    err = wc_ecc_sign_hash_ex(in, inlen, rng, key, r, s);
#endif
    if (err < 0) {
    #ifdef WOLFSSL_SMALL_STACK
        XFREE(s, key->heap, DYNAMIC_TYPE_ECC);
        XFREE(r, key->heap, DYNAMIC_TYPE_ECC);
    #endif
        return err;
    }

     
    err = StoreECC_DSA_Sig(out, outlen, r, s);

     
    mp_clear(r);
    mp_clear(s);

#ifdef WOLFSSL_SMALL_STACK
    XFREE(s, key->heap, DYNAMIC_TYPE_ECC);
    XFREE(r, key->heap, DYNAMIC_TYPE_ECC);
#endif
#endif  

    return err;
}