int wc_ecc_check_key(ecc_key* key)
{
    int    err;
#ifndef WOLFSSL_SP_MATH
#if !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_CRYPTOCELL)
    mp_int* b = NULL;
#ifdef USE_ECC_B_PARAM
    DECLARE_CURVE_SPECS(curve, 4);
#else
#ifndef WOLFSSL_SMALL_STACK
    mp_int b_lcl;
#endif
    DECLARE_CURVE_SPECS(curve, 3);
#endif /* USE_ECC_B_PARAM */
#endif /* WOLFSSL_ATECC508A */

    if (key == NULL)
        return BAD_FUNC_ARG;

#if defined(WOLFSSL_ATECC508A) || defined(WOLFSSL_CRYPTOCELL)

    err = 0; /* consider key check success on ATECC508A */

#else
    #ifdef USE_ECC_B_PARAM
        ALLOC_CURVE_SPECS(4);
    #else
        ALLOC_CURVE_SPECS(3);
        #ifndef WOLFSSL_SMALL_STACK
            b = &b_lcl;
        #else
            b = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC);
            if (b == NULL) {
                FREE_CURVE_SPECS();
                return MEMORY_E;
            }
        #endif
        XMEMSET(b, 0, sizeof(mp_int));
    #endif

    /* SP 800-56Ar3, section 5.6.2.3.3, process step 1 */
    /* pubkey point cannot be at infinity */
    if (wc_ecc_point_is_at_infinity(&key->pubkey)) {
    #ifdef WOLFSSL_SMALL_STACK
        XFREE(b, key->heap, DYNAMIC_TYPE_ECC);
    #endif
        FREE_CURVE_SPECS();
        return ECC_INF_E;
    }

    /* load curve info */
    err = wc_ecc_curve_load(key->dp, &curve, (ECC_CURVE_FIELD_PRIME |
            ECC_CURVE_FIELD_AF | ECC_CURVE_FIELD_ORDER
#ifdef USE_ECC_B_PARAM
            | ECC_CURVE_FIELD_BF
#endif
    ));

#ifndef USE_ECC_B_PARAM
    /* load curve b parameter */
    if (err == MP_OKAY)
        err = mp_init(b);
    if (err == MP_OKAY)
        err = mp_read_radix(b, key->dp->Bf, MP_RADIX_HEX);
#else
    if (err == MP_OKAY)
        b = curve->Bf;
#endif

    /* SP 800-56Ar3, section 5.6.2.3.3, process step 2 */
    /* Qx must be in the range [0, p-1] */
    if (err == MP_OKAY) {
        if (mp_cmp(key->pubkey.x, curve->prime) != MP_LT)
            err = ECC_OUT_OF_RANGE_E;
    }

    /* Qy must be in the range [0, p-1] */
    if (err == MP_OKAY) {
        if (mp_cmp(key->pubkey.y, curve->prime) != MP_LT)
            err = ECC_OUT_OF_RANGE_E;
    }

    /* SP 800-56Ar3, section 5.6.2.3.3, process steps 3 */
    /* make sure point is actually on curve */
    if (err == MP_OKAY)
        err = wc_ecc_is_point(&key->pubkey, curve->Af, b, curve->prime);

    /* SP 800-56Ar3, section 5.6.2.3.3, process steps 4 */
    /* pubkey * order must be at infinity */
    if (err == MP_OKAY)
        err = ecc_check_pubkey_order(key, &key->pubkey, curve->Af, curve->prime,
                curve->order);

    /* SP 800-56Ar3, section 5.6.2.1.4, method (b) for ECC */
    /* private * base generator must equal pubkey */
    if (err == MP_OKAY && key->type == ECC_PRIVATEKEY)
        err = ecc_check_privkey_gen(key, curve->Af, curve->prime);

    wc_ecc_curve_free(curve);

#ifndef USE_ECC_B_PARAM
    mp_clear(b);
    #ifdef WOLFSSL_SMALL_STACK
        XFREE(b, key->heap, DYNAMIC_TYPE_ECC);
    #endif
#endif

    FREE_CURVE_SPECS();

#endif /* WOLFSSL_ATECC508A */
#else
    if (key == NULL)
        return BAD_FUNC_ARG;

    /* pubkey point cannot be at infinity */
#ifndef WOLFSSL_SP_NO_256
    if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1) {
        err = sp_ecc_check_key_256(key->pubkey.x, key->pubkey.y, &key->k,
                                                                     key->heap);
    }
    else
#endif
#ifdef WOLFSSL_SP_384
    if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP384R1) {
        err = sp_ecc_check_key_384(key->pubkey.x, key->pubkey.y, &key->k,
                                                                     key->heap);
    }
    else
#endif
    {
        err = WC_KEY_SIZE_E;
    }
#endif

    return err;
}