int wc_ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, int curve_id)
{
    int err;
#if !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_CRYPTOCELL)
#ifndef WOLFSSL_SP_MATH
    DECLARE_CURVE_SPECS(curve, ECC_CURVE_FIELD_COUNT);
#endif
#endif /* !WOLFSSL_ATECC508A */
#if defined(WOLFSSL_CRYPTOCELL) && !defined(WOLFSSL_ATECC508A)
    const CRYS_ECPKI_Domain_t*  pDomain;
    CRYS_ECPKI_KG_TempData_t    tempBuff;
    CRYS_ECPKI_KG_FipsContext_t fipsCtx;
    byte ucompressed_key[ECC_MAX_CRYPTO_HW_SIZE*2 + 1];
    word32 raw_size = 0;
#endif
    if (key == NULL || rng == NULL) {
        return BAD_FUNC_ARG;
    }

    /* make sure required variables are reset */
    wc_ecc_reset(key);

    err = wc_ecc_set_curve(key, keysize, curve_id);
    if (err != 0) {
        return err;
    }

#ifdef WOLF_CRYPTO_CB
    if (key->devId != INVALID_DEVID) {
        err = wc_CryptoCb_MakeEccKey(rng, keysize, key, curve_id);
        if (err != CRYPTOCB_UNAVAILABLE)
            return err;
        /* fall-through when unavailable */
    }
#endif

#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC)
    if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) {
    #ifdef HAVE_CAVIUM
        /* TODO: Not implemented */
    #elif defined(HAVE_INTEL_QA)
        /* TODO: Not implemented */
    #else
        if (wc_AsyncTestInit(&key->asyncDev, ASYNC_TEST_ECC_MAKE)) {
            WC_ASYNC_TEST* testDev = &key->asyncDev.test;
            testDev->eccMake.rng = rng;
            testDev->eccMake.key = key;
            testDev->eccMake.size = keysize;
            testDev->eccMake.curve_id = curve_id;
            return WC_PENDING_E;
        }
    #endif
    }
#endif /* WOLFSSL_ASYNC_CRYPT && WC_ASYNC_ENABLE_ECC */

#ifdef WOLFSSL_ATECC508A
   if (key->dp->id == ECC_SECP256R1) {
       key->type = ECC_PRIVATEKEY;
       key->slot = atmel_ecc_alloc(ATMEL_SLOT_ECDHE);
       err = atmel_ecc_create_key(key->slot, key->pubkey_raw);

       /* populate key->pubkey */
       if (err == 0
       #ifdef ALT_ECC_SIZE
          && key->pubkey.x
       #endif
       ) {
           err = mp_read_unsigned_bin(key->pubkey.x, key->pubkey_raw,
                                      ECC_MAX_CRYPTO_HW_SIZE);
       }
       if (err == 0
       #ifdef ALT_ECC_SIZE
          && key->pubkey.y
       #endif
       ) {
           err = mp_read_unsigned_bin(key->pubkey.y,
                                      key->pubkey_raw + ECC_MAX_CRYPTO_HW_SIZE,
                                      ECC_MAX_CRYPTO_HW_SIZE);
       }
   }
   else {
      err = NOT_COMPILED_IN;
   }
#elif defined(WOLFSSL_CRYPTOCELL)

    pDomain = CRYS_ECPKI_GetEcDomain(cc310_mapCurve(curve_id));
    raw_size = (word32)(key->dp->size)*2 + 1;

    /* generate first key pair */
    err = CRYS_ECPKI_GenKeyPair(&wc_rndState,
                                wc_rndGenVectFunc,
                                pDomain,
                                &key->ctx.privKey,
                                &key->ctx.pubKey,
                                &tempBuff,
                                &fipsCtx);

    if (err != SA_SILIB_RET_OK){
        WOLFSSL_MSG("CRYS_ECPKI_GenKeyPair for key pair failed");
        return err;
    }
    key->type = ECC_PRIVATEKEY;

    err = CRYS_ECPKI_ExportPublKey(&key->ctx.pubKey,
                                   CRYS_EC_PointUncompressed,
                                   &ucompressed_key[0],
                                   &raw_size);

    if (err == SA_SILIB_RET_OK && key->pubkey.x && key->pubkey.y) {
        err = mp_read_unsigned_bin(key->pubkey.x,
                                   &ucompressed_key[1], key->dp->size);
        if (err == MP_OKAY) {
            err = mp_read_unsigned_bin(key->pubkey.y,
                            &ucompressed_key[1+key->dp->size],key->dp->size);
        }
    }
    raw_size = key->dp->size;
    if (err == MP_OKAY) {
        err = CRYS_ECPKI_ExportPrivKey(&key->ctx.privKey,
                                       ucompressed_key,
                                       &raw_size);
    }

    if (err == SA_SILIB_RET_OK) {
        err = mp_read_unsigned_bin(&key->k, ucompressed_key, raw_size);
    }

#else

#ifdef WOLFSSL_HAVE_SP_ECC
#ifndef WOLFSSL_SP_NO_256
    if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1) {
        err = sp_ecc_make_key_256(rng, &key->k, &key->pubkey, key->heap);
        if (err == MP_OKAY) {
            key->type = ECC_PRIVATEKEY;
        }
    }
    else
#endif
#ifdef WOLFSSL_SP_384
    if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP384R1) {
        err = sp_ecc_make_key_384(rng, &key->k, &key->pubkey, key->heap);
        if (err == MP_OKAY) {
            key->type = ECC_PRIVATEKEY;
        }
    }
    else
#endif
#endif /* WOLFSSL_HAVE_SP_ECC */

   { /* software key gen */
#ifdef WOLFSSL_SP_MATH
        err = WC_KEY_SIZE_E;
#else

        /* setup the key variables */
        err = mp_init(&key->k);

        /* load curve info */
        if (err == MP_OKAY) {
            ALLOC_CURVE_SPECS(ECC_CURVE_FIELD_COUNT);
            err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ALL);
        }

        /* generate k */
        if (err == MP_OKAY)
            err = wc_ecc_gen_k(rng, key->dp->size, &key->k, curve->order);

        /* generate public key from k */
        if (err == MP_OKAY)
            err = wc_ecc_make_pub_ex(key, curve, NULL);

        if (err == MP_OKAY)
            key->type = ECC_PRIVATEKEY;

        /* cleanup these on failure case only */
        if (err != MP_OKAY) {
            /* clean up */
            mp_forcezero(&key->k);
        }

        /* cleanup allocations */
        wc_ecc_curve_free(curve);
        FREE_CURVE_SPECS();
#endif /* WOLFSSL_SP_MATH */
    }

#ifdef HAVE_WOLF_BIGINT
    if (err == MP_OKAY)
         err = wc_mp_to_bigint(&key->k, &key->k.raw);
    if (err == MP_OKAY)
         err = wc_mp_to_bigint(key->pubkey.x, &key->pubkey.x->raw);
    if (err == MP_OKAY)
         err = wc_mp_to_bigint(key->pubkey.y, &key->pubkey.y->raw);
    if (err == MP_OKAY)
         err = wc_mp_to_bigint(key->pubkey.z, &key->pubkey.z->raw);
#endif

#endif /* WOLFSSL_ATECC508A */

    return err;
}