int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
                size_t num, const EC_POINT *points[], const BIGNUM *scalars[],
                BN_CTX *ctx)
{
    const EC_POINT *generator = NULL;
    EC_POINT *tmp = NULL;
    size_t totalnum;
    size_t blocksize = 0, numblocks = 0;
    size_t pre_points_per_block = 0;
    size_t i, j;
    int k;
    int r_is_inverted = 0;
    int r_is_at_infinity = 1;
    size_t *wsize = NULL;
    signed char **wNAF = NULL;
    size_t *wNAF_len = NULL;
    size_t max_len = 0;
    size_t num_val;
    EC_POINT **val = NULL;
    EC_POINT **v;
    EC_POINT ***val_sub = NULL;
    const EC_PRE_COMP *pre_comp = NULL;
    int num_scalar = 0;
    int ret = 0;
    if (!BN_is_zero(group->order) && !BN_is_zero(group->cofactor)) {
        if ((scalar != group->order) && (scalar != NULL) && (num == 0)) {
            return ec_scalar_mul_ladder(group, r, scalar, NULL, ctx);
        }
        if ((scalar == NULL) && (num == 1) && (scalars[0] != group->order)) {
            return ec_scalar_mul_ladder(group, r, scalars[0], points[0], ctx);
        }
    }
    if (scalar != NULL) {
        generator = EC_GROUP_get0_generator(group);
        if (generator == NULL) {
            ECerr(EC_F_EC_WNAF_MUL, EC_R_UNDEFINED_GENERATOR);
            goto err;
        }
        pre_comp = group->pre_comp.ec;
        if (pre_comp && pre_comp->numblocks
            && (EC_POINT_cmp(group, generator, pre_comp->points[0], ctx) ==
                0)) {
            blocksize = pre_comp->blocksize;
            numblocks = (BN_num_bits(scalar) / blocksize) + 1;
            if (numblocks > pre_comp->numblocks)
                numblocks = pre_comp->numblocks;
            pre_points_per_block = (size_t)1 << (pre_comp->w - 1);
            if (pre_comp->num != (pre_comp->numblocks * pre_points_per_block)) {
                ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
                goto err;
            }
        } else {
            pre_comp = NULL;
            numblocks = 1;
            num_scalar = 1;
        }
    }
    totalnum = num + numblocks;
    wsize = OPENSSL_malloc(totalnum * sizeof(wsize[0]));
    wNAF_len = OPENSSL_malloc(totalnum * sizeof(wNAF_len[0]));
    wNAF = OPENSSL_malloc((totalnum + 1) * sizeof(wNAF[0]));
    val_sub = OPENSSL_malloc(totalnum * sizeof(val_sub[0]));
    if (wNAF != NULL)
        wNAF[0] = NULL;
    if (wsize == NULL || wNAF_len == NULL || wNAF == NULL || val_sub == NULL) {
        ECerr(EC_F_EC_WNAF_MUL, ERR_R_MALLOC_FAILURE);
        goto err;
    }
    num_val = 0;
    for (i = 0; i < num + num_scalar; i++) {
        size_t bits;
        bits = i < num ? BN_num_bits(scalars[i]) : BN_num_bits(scalar);
        wsize[i] = EC_window_bits_for_scalar_size(bits);
        num_val += (size_t)1 << (wsize[i] - 1);
        wNAF[i + 1] = NULL;
        wNAF[i] =
            bn_compute_wNAF((i < num ? scalars[i] : scalar), wsize[i],
                            &wNAF_len[i]);
        if (wNAF[i] == NULL)
            goto err;
        if (wNAF_len[i] > max_len)
            max_len = wNAF_len[i];
    }
    if (numblocks) {
        if (pre_comp == NULL) {
            if (num_scalar != 1) {
                ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
                goto err;
            }
        } else {
            signed char *tmp_wNAF = NULL;
            size_t tmp_len = 0;
            if (num_scalar != 0) {
                ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
                goto err;
            }
            wsize[num] = pre_comp->w;
            tmp_wNAF = bn_compute_wNAF(scalar, wsize[num], &tmp_len);
            if (!tmp_wNAF)
                goto err;
            if (tmp_len <= max_len) {
                numblocks = 1;
                totalnum = num + 1;
                wNAF[num] = tmp_wNAF;
                wNAF[num + 1] = NULL;
                wNAF_len[num] = tmp_len;
                val_sub[num] = pre_comp->points;
            } else {
                signed char *pp;
                EC_POINT **tmp_points;
                if (tmp_len < numblocks * blocksize) {
                    numblocks = (tmp_len + blocksize - 1) / blocksize;
                    if (numblocks > pre_comp->numblocks) {
                        ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
                        OPENSSL_free(tmp_wNAF);
                        goto err;
                    }
                    totalnum = num + numblocks;
                }
                pp = tmp_wNAF;
                tmp_points = pre_comp->points;
                for (i = num; i < totalnum; i++) {
                    if (i < totalnum - 1) {
                        wNAF_len[i] = blocksize;
                        if (tmp_len < blocksize) {
                            ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
                            OPENSSL_free(tmp_wNAF);
                            goto err;
                        }
                        tmp_len -= blocksize;
                    } else
                        wNAF_len[i] = tmp_len;
                    wNAF[i + 1] = NULL;
                    wNAF[i] = OPENSSL_malloc(wNAF_len[i]);
                    if (wNAF[i] == NULL) {
                        ECerr(EC_F_EC_WNAF_MUL, ERR_R_MALLOC_FAILURE);
                        OPENSSL_free(tmp_wNAF);
                        goto err;
                    }
                    memcpy(wNAF[i], pp, wNAF_len[i]);
                    if (wNAF_len[i] > max_len)
                        max_len = wNAF_len[i];
                    if (*tmp_points == NULL) {
                        ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
                        OPENSSL_free(tmp_wNAF);
                        goto err;
                    }
                    val_sub[i] = tmp_points;
                    tmp_points += pre_points_per_block;
                    pp += blocksize;
                }
                OPENSSL_free(tmp_wNAF);
            }
        }
    }
    val = OPENSSL_malloc((num_val + 1) * sizeof(val[0]));
    if (val == NULL) {
        ECerr(EC_F_EC_WNAF_MUL, ERR_R_MALLOC_FAILURE);
        goto err;
    }
    val[num_val] = NULL;
    v = val;
    for (i = 0; i < num + num_scalar; i++) {
        val_sub[i] = v;
        for (j = 0; j < ((size_t)1 << (wsize[i] - 1)); j++) {
            *v = EC_POINT_new(group);
            if (*v == NULL)
                goto err;
            v++;
        }
    }
    if (!(v == val + num_val)) {
        ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
        goto err;
    }
    if ((tmp = EC_POINT_new(group)) == NULL)
        goto err;
    for (i = 0; i < num + num_scalar; i++) {
        if (i < num) {
            if (!EC_POINT_copy(val_sub[i][0], points[i]))
                goto err;
        } else {
            if (!EC_POINT_copy(val_sub[i][0], generator))
                goto err;
        }
        if (wsize[i] > 1) {
            if (!EC_POINT_dbl(group, tmp, val_sub[i][0], ctx))
                goto err;
            for (j = 1; j < ((size_t)1 << (wsize[i] - 1)); j++) {
                if (!EC_POINT_add
                    (group, val_sub[i][j], val_sub[i][j - 1], tmp, ctx))
                    goto err;
            }
        }
    }
    if (!EC_POINTs_make_affine(group, num_val, val, ctx))
        goto err;
    r_is_at_infinity = 1;
    for (k = max_len - 1; k >= 0; k--) {
        if (!r_is_at_infinity) {
            if (!EC_POINT_dbl(group, r, r, ctx))
                goto err;
        }
        for (i = 0; i < totalnum; i++) {
            if (wNAF_len[i] > (size_t)k) {
                int digit = wNAF[i][k];
                int is_neg;
                if (digit) {
                    is_neg = digit < 0;
                    if (is_neg)
                        digit = -digit;
                    if (is_neg != r_is_inverted) {
                        if (!r_is_at_infinity) {
                            if (!EC_POINT_invert(group, r, ctx))
                                goto err;
                        }
                        r_is_inverted = !r_is_inverted;
                    }
                    if (r_is_at_infinity) {
                        if (!EC_POINT_copy(r, val_sub[i][digit >> 1]))
                            goto err;
                        r_is_at_infinity = 0;
                    } else {
                        if (!EC_POINT_add
                            (group, r, r, val_sub[i][digit >> 1], ctx))
                            goto err;
                    }
                }
            }
        }
    }
    if (r_is_at_infinity) {
        if (!EC_POINT_set_to_infinity(group, r))
            goto err;
    } else {
        if (r_is_inverted)
            if (!EC_POINT_invert(group, r, ctx))
                goto err;
    }
    ret = 1;
 err:
    EC_POINT_free(tmp);
    OPENSSL_free(wsize);
    OPENSSL_free(wNAF_len);
    if (wNAF != NULL) {
        signed char **w;
        for (w = wNAF; *w != NULL; w++)
            OPENSSL_free(*w);
        OPENSSL_free(wNAF);
    }
    if (val != NULL) {
        for (v = val; *v != NULL; v++)
            EC_POINT_clear_free(*v);
        OPENSSL_free(val);
    }
    OPENSSL_free(val_sub);
    return ret;
}
['int ecparam_main(int argc, char **argv)\n{\n    ENGINE *e = NULL;\n    BIGNUM *ec_gen = NULL, *ec_order = NULL, *ec_cofactor = NULL;\n    BIGNUM *ec_p = NULL, *ec_a = NULL, *ec_b = NULL;\n    BIO *in = NULL, *out = NULL;\n    EC_GROUP *group = NULL;\n    point_conversion_form_t form = POINT_CONVERSION_UNCOMPRESSED;\n    char *curve_name = NULL;\n    char *infile = NULL, *outfile = NULL, *prog;\n    unsigned char *buffer = NULL;\n    OPTION_CHOICE o;\n    int asn1_flag = OPENSSL_EC_NAMED_CURVE, new_asn1_flag = 0;\n    int informat = FORMAT_PEM, outformat = FORMAT_PEM, noout = 0, C = 0;\n    int ret = 1, private = 0;\n    int list_curves = 0, no_seed = 0, check = 0, new_form = 0;\n    int text = 0, i, genkey = 0, check_named = 0;\n    prog = opt_init(argc, argv, ecparam_options);\n    while ((o = opt_next()) != OPT_EOF) {\n        switch (o) {\n        case OPT_EOF:\n        case OPT_ERR:\n opthelp:\n            BIO_printf(bio_err, "%s: Use -help for summary.\\n", prog);\n            goto end;\n        case OPT_HELP:\n            opt_help(ecparam_options);\n            ret = 0;\n            goto end;\n        case OPT_INFORM:\n            if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat))\n                goto opthelp;\n            break;\n        case OPT_IN:\n            infile = opt_arg();\n            break;\n        case OPT_OUTFORM:\n            if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat))\n                goto opthelp;\n            break;\n        case OPT_OUT:\n            outfile = opt_arg();\n            break;\n        case OPT_TEXT:\n            text = 1;\n            break;\n        case OPT_C:\n            C = 1;\n            break;\n        case OPT_CHECK:\n            check = 1;\n            break;\n        case OPT_CHECK_NAMED:\n            check_named = 1;\n            break;\n        case OPT_LIST_CURVES:\n            list_curves = 1;\n            break;\n        case OPT_NO_SEED:\n            no_seed = 1;\n            break;\n        case OPT_NOOUT:\n            noout = 1;\n            break;\n        case OPT_NAME:\n            curve_name = opt_arg();\n            break;\n        case OPT_CONV_FORM:\n            if (!opt_pair(opt_arg(), forms, &new_form))\n                goto opthelp;\n            form = new_form;\n            new_form = 1;\n            break;\n        case OPT_PARAM_ENC:\n            if (!opt_pair(opt_arg(), encodings, &asn1_flag))\n                goto opthelp;\n            new_asn1_flag = 1;\n            break;\n        case OPT_GENKEY:\n            genkey = 1;\n            break;\n        case OPT_R_CASES:\n            if (!opt_rand(o))\n                goto end;\n            break;\n        case OPT_ENGINE:\n            e = setup_engine(opt_arg(), 0);\n            break;\n        }\n    }\n    argc = opt_num_rest();\n    if (argc != 0)\n        goto opthelp;\n    private = genkey ? 1 : 0;\n    in = bio_open_default(infile, \'r\', informat);\n    if (in == NULL)\n        goto end;\n    out = bio_open_owner(outfile, outformat, private);\n    if (out == NULL)\n        goto end;\n    if (list_curves) {\n        EC_builtin_curve *curves = NULL;\n        size_t crv_len = EC_get_builtin_curves(NULL, 0);\n        size_t n;\n        curves = app_malloc((int)sizeof(*curves) * crv_len, "list curves");\n        if (!EC_get_builtin_curves(curves, crv_len)) {\n            OPENSSL_free(curves);\n            goto end;\n        }\n        for (n = 0; n < crv_len; n++) {\n            const char *comment;\n            const char *sname;\n            comment = curves[n].comment;\n            sname = OBJ_nid2sn(curves[n].nid);\n            if (comment == NULL)\n                comment = "CURVE DESCRIPTION NOT AVAILABLE";\n            if (sname == NULL)\n                sname = "";\n            BIO_printf(out, "  %-10s: ", sname);\n            BIO_printf(out, "%s\\n", comment);\n        }\n        OPENSSL_free(curves);\n        ret = 0;\n        goto end;\n    }\n    if (curve_name != NULL) {\n        int nid;\n        if (strcmp(curve_name, "secp192r1") == 0) {\n            BIO_printf(bio_err, "using curve name prime192v1 "\n                       "instead of secp192r1\\n");\n            nid = NID_X9_62_prime192v1;\n        } else if (strcmp(curve_name, "secp256r1") == 0) {\n            BIO_printf(bio_err, "using curve name prime256v1 "\n                       "instead of secp256r1\\n");\n            nid = NID_X9_62_prime256v1;\n        } else {\n            nid = OBJ_sn2nid(curve_name);\n        }\n        if (nid == 0)\n            nid = EC_curve_nist2nid(curve_name);\n        if (nid == 0) {\n            BIO_printf(bio_err, "unknown curve name (%s)\\n", curve_name);\n            goto end;\n        }\n        group = EC_GROUP_new_by_curve_name(nid);\n        if (group == NULL) {\n            BIO_printf(bio_err, "unable to create curve (%s)\\n", curve_name);\n            goto end;\n        }\n        EC_GROUP_set_asn1_flag(group, asn1_flag);\n        EC_GROUP_set_point_conversion_form(group, form);\n    } else if (informat == FORMAT_ASN1) {\n        group = d2i_ECPKParameters_bio(in, NULL);\n    } else {\n        group = PEM_read_bio_ECPKParameters(in, NULL, NULL, NULL);\n    }\n    if (group == NULL) {\n        BIO_printf(bio_err, "unable to load elliptic curve parameters\\n");\n        ERR_print_errors(bio_err);\n        goto end;\n    }\n    if (new_form)\n        EC_GROUP_set_point_conversion_form(group, form);\n    if (new_asn1_flag)\n        EC_GROUP_set_asn1_flag(group, asn1_flag);\n    if (no_seed) {\n        EC_GROUP_set_seed(group, NULL, 0);\n    }\n    if (text) {\n        if (!ECPKParameters_print(out, group, 0))\n            goto end;\n    }\n    if (check_named) {\n        BIO_printf(bio_err, "validating named elliptic curve parameters: ");\n        if (EC_GROUP_check_named_curve(group, 0) <= 0) {\n            BIO_printf(bio_err, "failed\\n");\n            ERR_print_errors(bio_err);\n            goto end;\n        }\n        BIO_printf(bio_err, "ok\\n");\n    }\n    if (check) {\n        BIO_printf(bio_err, "checking elliptic curve parameters: ");\n        if (!EC_GROUP_check(group, NULL)) {\n            BIO_printf(bio_err, "failed\\n");\n            ERR_print_errors(bio_err);\n            goto end;\n        }\n        BIO_printf(bio_err, "ok\\n");\n    }\n    if (C) {\n        size_t buf_len = 0, tmp_len = 0;\n        const EC_POINT *point;\n        int is_prime, len = 0;\n        const EC_METHOD *meth = EC_GROUP_method_of(group);\n        if ((ec_p = BN_new()) == NULL\n                || (ec_a = BN_new()) == NULL\n                || (ec_b = BN_new()) == NULL\n                || (ec_gen = BN_new()) == NULL\n                || (ec_order = BN_new()) == NULL\n                || (ec_cofactor = BN_new()) == NULL) {\n            perror("Can\'t allocate BN");\n            goto end;\n        }\n        is_prime = (EC_METHOD_get_field_type(meth) == NID_X9_62_prime_field);\n        if (!is_prime) {\n            BIO_printf(bio_err, "Can only handle X9.62 prime fields\\n");\n            goto end;\n        }\n        if (!EC_GROUP_get_curve(group, ec_p, ec_a, ec_b, NULL))\n            goto end;\n        if ((point = EC_GROUP_get0_generator(group)) == NULL)\n            goto end;\n        if (!EC_POINT_point2bn(group, point,\n                               EC_GROUP_get_point_conversion_form(group),\n                               ec_gen, NULL))\n            goto end;\n        if (!EC_GROUP_get_order(group, ec_order, NULL))\n            goto end;\n        if (!EC_GROUP_get_cofactor(group, ec_cofactor, NULL))\n            goto end;\n        if (!ec_p || !ec_a || !ec_b || !ec_gen || !ec_order || !ec_cofactor)\n            goto end;\n        len = BN_num_bits(ec_order);\n        if ((tmp_len = (size_t)BN_num_bytes(ec_p)) > buf_len)\n            buf_len = tmp_len;\n        if ((tmp_len = (size_t)BN_num_bytes(ec_a)) > buf_len)\n            buf_len = tmp_len;\n        if ((tmp_len = (size_t)BN_num_bytes(ec_b)) > buf_len)\n            buf_len = tmp_len;\n        if ((tmp_len = (size_t)BN_num_bytes(ec_gen)) > buf_len)\n            buf_len = tmp_len;\n        if ((tmp_len = (size_t)BN_num_bytes(ec_order)) > buf_len)\n            buf_len = tmp_len;\n        if ((tmp_len = (size_t)BN_num_bytes(ec_cofactor)) > buf_len)\n            buf_len = tmp_len;\n        buffer = app_malloc(buf_len, "BN buffer");\n        BIO_printf(out, "EC_GROUP *get_ec_group_%d(void)\\n{\\n", len);\n        print_bignum_var(out, ec_p, "ec_p", len, buffer);\n        print_bignum_var(out, ec_a, "ec_a", len, buffer);\n        print_bignum_var(out, ec_b, "ec_b", len, buffer);\n        print_bignum_var(out, ec_gen, "ec_gen", len, buffer);\n        print_bignum_var(out, ec_order, "ec_order", len, buffer);\n        print_bignum_var(out, ec_cofactor, "ec_cofactor", len, buffer);\n        BIO_printf(out, "    int ok = 0;\\n"\n                        "    EC_GROUP *group = NULL;\\n"\n                        "    EC_POINT *point = NULL;\\n"\n                        "    BIGNUM *tmp_1 = NULL;\\n"\n                        "    BIGNUM *tmp_2 = NULL;\\n"\n                        "    BIGNUM *tmp_3 = NULL;\\n"\n                        "\\n");\n        BIO_printf(out, "    if ((tmp_1 = BN_bin2bn(ec_p_%d, sizeof(ec_p_%d), NULL)) == NULL)\\n"\n                        "        goto err;\\n", len, len);\n        BIO_printf(out, "    if ((tmp_2 = BN_bin2bn(ec_a_%d, sizeof(ec_a_%d), NULL)) == NULL)\\n"\n                        "        goto err;\\n", len, len);\n        BIO_printf(out, "    if ((tmp_3 = BN_bin2bn(ec_b_%d, sizeof(ec_b_%d), NULL)) == NULL)\\n"\n                        "        goto err;\\n", len, len);\n        BIO_printf(out, "    if ((group = EC_GROUP_new_curve_GFp(tmp_1, tmp_2, tmp_3, NULL)) == NULL)\\n"\n                        "        goto err;\\n"\n                        "\\n");\n        BIO_printf(out, "    /* build generator */\\n");\n        BIO_printf(out, "    if ((tmp_1 = BN_bin2bn(ec_gen_%d, sizeof(ec_gen_%d), tmp_1)) == NULL)\\n"\n                        "        goto err;\\n", len, len);\n        BIO_printf(out, "    point = EC_POINT_bn2point(group, tmp_1, NULL, NULL);\\n");\n        BIO_printf(out, "    if (point == NULL)\\n"\n                        "        goto err;\\n");\n        BIO_printf(out, "    if ((tmp_2 = BN_bin2bn(ec_order_%d, sizeof(ec_order_%d), tmp_2)) == NULL)\\n"\n                        "        goto err;\\n", len, len);\n        BIO_printf(out, "    if ((tmp_3 = BN_bin2bn(ec_cofactor_%d, sizeof(ec_cofactor_%d), tmp_3)) == NULL)\\n"\n                        "        goto err;\\n", len, len);\n        BIO_printf(out, "    if (!EC_GROUP_set_generator(group, point, tmp_2, tmp_3))\\n"\n                        "        goto err;\\n"\n                        "ok = 1;"\n                        "\\n");\n        BIO_printf(out, "err:\\n"\n                        "    BN_free(tmp_1);\\n"\n                        "    BN_free(tmp_2);\\n"\n                        "    BN_free(tmp_3);\\n"\n                        "    EC_POINT_free(point);\\n"\n                        "    if (!ok) {\\n"\n                        "        EC_GROUP_free(group);\\n"\n                        "        return NULL;\\n"\n                        "    }\\n"\n                        "    return (group);\\n"\n                        "}\\n");\n    }\n    if (outformat == FORMAT_ASN1 && genkey)\n        noout = 1;\n    if (!noout) {\n        if (outformat == FORMAT_ASN1)\n            i = i2d_ECPKParameters_bio(out, group);\n        else\n            i = PEM_write_bio_ECPKParameters(out, group);\n        if (!i) {\n            BIO_printf(bio_err, "unable to write elliptic "\n                       "curve parameters\\n");\n            ERR_print_errors(bio_err);\n            goto end;\n        }\n    }\n    if (genkey) {\n        EC_KEY *eckey = EC_KEY_new();\n        if (eckey == NULL)\n            goto end;\n        if (EC_KEY_set_group(eckey, group) == 0) {\n            BIO_printf(bio_err, "unable to set group when generating key\\n");\n            EC_KEY_free(eckey);\n            ERR_print_errors(bio_err);\n            goto end;\n        }\n        if (new_form)\n            EC_KEY_set_conv_form(eckey, form);\n        if (!EC_KEY_generate_key(eckey)) {\n            BIO_printf(bio_err, "unable to generate key\\n");\n            EC_KEY_free(eckey);\n            ERR_print_errors(bio_err);\n            goto end;\n        }\n        assert(private);\n        if (outformat == FORMAT_ASN1)\n            i = i2d_ECPrivateKey_bio(out, eckey);\n        else\n            i = PEM_write_bio_ECPrivateKey(out, eckey, NULL,\n                                           NULL, 0, NULL, NULL);\n        EC_KEY_free(eckey);\n    }\n    ret = 0;\n end:\n    BN_free(ec_p);\n    BN_free(ec_a);\n    BN_free(ec_b);\n    BN_free(ec_gen);\n    BN_free(ec_order);\n    BN_free(ec_cofactor);\n    OPENSSL_free(buffer);\n    EC_GROUP_free(group);\n    release_engine(e);\n    BIO_free(in);\n    BIO_free_all(out);\n    return ret;\n}', 'int EC_GROUP_check(const EC_GROUP *group, BN_CTX *ctx)\n{\n#ifdef FIPS_MODE\n    return EC_GROUP_check_named_curve(group, 1) >= 0 ? 1 : 0;\n#else\n    int ret = 0;\n    const BIGNUM *order;\n    BN_CTX *new_ctx = NULL;\n    EC_POINT *point = NULL;\n    if (group == NULL || group->meth == NULL) {\n        ECerr(EC_F_EC_GROUP_CHECK, ERR_R_PASSED_NULL_PARAMETER);\n        return 0;\n    }\n    if ((group->meth->flags & EC_FLAGS_CUSTOM_CURVE) != 0)\n        return 1;\n    if (ctx == NULL) {\n        ctx = new_ctx = BN_CTX_new();\n        if (ctx == NULL) {\n            ECerr(EC_F_EC_GROUP_CHECK, ERR_R_MALLOC_FAILURE);\n            goto err;\n        }\n    }\n    if (!EC_GROUP_check_discriminant(group, ctx)) {\n        ECerr(EC_F_EC_GROUP_CHECK, EC_R_DISCRIMINANT_IS_ZERO);\n        goto err;\n    }\n    if (group->generator == NULL) {\n        ECerr(EC_F_EC_GROUP_CHECK, EC_R_UNDEFINED_GENERATOR);\n        goto err;\n    }\n    if (EC_POINT_is_on_curve(group, group->generator, ctx) <= 0) {\n        ECerr(EC_F_EC_GROUP_CHECK, EC_R_POINT_IS_NOT_ON_CURVE);\n        goto err;\n    }\n    if ((point = EC_POINT_new(group)) == NULL)\n        goto err;\n    order = EC_GROUP_get0_order(group);\n    if (order == NULL)\n        goto err;\n    if (BN_is_zero(order)) {\n        ECerr(EC_F_EC_GROUP_CHECK, EC_R_UNDEFINED_ORDER);\n        goto err;\n    }\n    if (!EC_POINT_mul(group, point, order, NULL, NULL, ctx))\n        goto err;\n    if (!EC_POINT_is_at_infinity(group, point)) {\n        ECerr(EC_F_EC_GROUP_CHECK, EC_R_INVALID_GROUP_ORDER);\n        goto err;\n    }\n    ret = 1;\n err:\n    BN_CTX_free(new_ctx);\n    EC_POINT_free(point);\n    return ret;\n#endif\n}', 'int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,\n                 const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx)\n{\n    const EC_POINT *points[1];\n    const BIGNUM *scalars[1];\n    points[0] = point;\n    scalars[0] = p_scalar;\n    return EC_POINTs_mul(group, r, g_scalar,\n                         (point != NULL\n                          && p_scalar != NULL), points, scalars, ctx);\n}', 'int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,\n                  size_t num, const EC_POINT *points[],\n                  const BIGNUM *scalars[], BN_CTX *ctx)\n{\n    int ret = 0;\n    size_t i = 0;\n    BN_CTX *new_ctx = NULL;\n    if ((scalar == NULL) && (num == 0)) {\n        return EC_POINT_set_to_infinity(group, r);\n    }\n    if (!ec_point_is_compat(r, group)) {\n        ECerr(EC_F_EC_POINTS_MUL, EC_R_INCOMPATIBLE_OBJECTS);\n        return 0;\n    }\n    for (i = 0; i < num; i++) {\n        if (!ec_point_is_compat(points[i], group)) {\n            ECerr(EC_F_EC_POINTS_MUL, EC_R_INCOMPATIBLE_OBJECTS);\n            return 0;\n        }\n    }\n    if (ctx == NULL && (ctx = new_ctx = BN_CTX_secure_new()) == NULL) {\n        ECerr(EC_F_EC_POINTS_MUL, ERR_R_INTERNAL_ERROR);\n        return 0;\n    }\n    if (group->meth->mul != NULL)\n        ret = group->meth->mul(group, r, scalar, num, points, scalars, ctx);\n    else\n        ret = ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);\n    BN_CTX_free(new_ctx);\n    return ret;\n}', 'int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,\n                size_t num, const EC_POINT *points[], const BIGNUM *scalars[],\n                BN_CTX *ctx)\n{\n    const EC_POINT *generator = NULL;\n    EC_POINT *tmp = NULL;\n    size_t totalnum;\n    size_t blocksize = 0, numblocks = 0;\n    size_t pre_points_per_block = 0;\n    size_t i, j;\n    int k;\n    int r_is_inverted = 0;\n    int r_is_at_infinity = 1;\n    size_t *wsize = NULL;\n    signed char **wNAF = NULL;\n    size_t *wNAF_len = NULL;\n    size_t max_len = 0;\n    size_t num_val;\n    EC_POINT **val = NULL;\n    EC_POINT **v;\n    EC_POINT ***val_sub = NULL;\n    const EC_PRE_COMP *pre_comp = NULL;\n    int num_scalar = 0;\n    int ret = 0;\n    if (!BN_is_zero(group->order) && !BN_is_zero(group->cofactor)) {\n        if ((scalar != group->order) && (scalar != NULL) && (num == 0)) {\n            return ec_scalar_mul_ladder(group, r, scalar, NULL, ctx);\n        }\n        if ((scalar == NULL) && (num == 1) && (scalars[0] != group->order)) {\n            return ec_scalar_mul_ladder(group, r, scalars[0], points[0], ctx);\n        }\n    }\n    if (scalar != NULL) {\n        generator = EC_GROUP_get0_generator(group);\n        if (generator == NULL) {\n            ECerr(EC_F_EC_WNAF_MUL, EC_R_UNDEFINED_GENERATOR);\n            goto err;\n        }\n        pre_comp = group->pre_comp.ec;\n        if (pre_comp && pre_comp->numblocks\n            && (EC_POINT_cmp(group, generator, pre_comp->points[0], ctx) ==\n                0)) {\n            blocksize = pre_comp->blocksize;\n            numblocks = (BN_num_bits(scalar) / blocksize) + 1;\n            if (numblocks > pre_comp->numblocks)\n                numblocks = pre_comp->numblocks;\n            pre_points_per_block = (size_t)1 << (pre_comp->w - 1);\n            if (pre_comp->num != (pre_comp->numblocks * pre_points_per_block)) {\n                ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);\n                goto err;\n            }\n        } else {\n            pre_comp = NULL;\n            numblocks = 1;\n            num_scalar = 1;\n        }\n    }\n    totalnum = num + numblocks;\n    wsize = OPENSSL_malloc(totalnum * sizeof(wsize[0]));\n    wNAF_len = OPENSSL_malloc(totalnum * sizeof(wNAF_len[0]));\n    wNAF = OPENSSL_malloc((totalnum + 1) * sizeof(wNAF[0]));\n    val_sub = OPENSSL_malloc(totalnum * sizeof(val_sub[0]));\n    if (wNAF != NULL)\n        wNAF[0] = NULL;\n    if (wsize == NULL || wNAF_len == NULL || wNAF == NULL || val_sub == NULL) {\n        ECerr(EC_F_EC_WNAF_MUL, ERR_R_MALLOC_FAILURE);\n        goto err;\n    }\n    num_val = 0;\n    for (i = 0; i < num + num_scalar; i++) {\n        size_t bits;\n        bits = i < num ? BN_num_bits(scalars[i]) : BN_num_bits(scalar);\n        wsize[i] = EC_window_bits_for_scalar_size(bits);\n        num_val += (size_t)1 << (wsize[i] - 1);\n        wNAF[i + 1] = NULL;\n        wNAF[i] =\n            bn_compute_wNAF((i < num ? scalars[i] : scalar), wsize[i],\n                            &wNAF_len[i]);\n        if (wNAF[i] == NULL)\n            goto err;\n        if (wNAF_len[i] > max_len)\n            max_len = wNAF_len[i];\n    }\n    if (numblocks) {\n        if (pre_comp == NULL) {\n            if (num_scalar != 1) {\n                ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);\n                goto err;\n            }\n        } else {\n            signed char *tmp_wNAF = NULL;\n            size_t tmp_len = 0;\n            if (num_scalar != 0) {\n                ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);\n                goto err;\n            }\n            wsize[num] = pre_comp->w;\n            tmp_wNAF = bn_compute_wNAF(scalar, wsize[num], &tmp_len);\n            if (!tmp_wNAF)\n                goto err;\n            if (tmp_len <= max_len) {\n                numblocks = 1;\n                totalnum = num + 1;\n                wNAF[num] = tmp_wNAF;\n                wNAF[num + 1] = NULL;\n                wNAF_len[num] = tmp_len;\n                val_sub[num] = pre_comp->points;\n            } else {\n                signed char *pp;\n                EC_POINT **tmp_points;\n                if (tmp_len < numblocks * blocksize) {\n                    numblocks = (tmp_len + blocksize - 1) / blocksize;\n                    if (numblocks > pre_comp->numblocks) {\n                        ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);\n                        OPENSSL_free(tmp_wNAF);\n                        goto err;\n                    }\n                    totalnum = num + numblocks;\n                }\n                pp = tmp_wNAF;\n                tmp_points = pre_comp->points;\n                for (i = num; i < totalnum; i++) {\n                    if (i < totalnum - 1) {\n                        wNAF_len[i] = blocksize;\n                        if (tmp_len < blocksize) {\n                            ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);\n                            OPENSSL_free(tmp_wNAF);\n                            goto err;\n                        }\n                        tmp_len -= blocksize;\n                    } else\n                        wNAF_len[i] = tmp_len;\n                    wNAF[i + 1] = NULL;\n                    wNAF[i] = OPENSSL_malloc(wNAF_len[i]);\n                    if (wNAF[i] == NULL) {\n                        ECerr(EC_F_EC_WNAF_MUL, ERR_R_MALLOC_FAILURE);\n                        OPENSSL_free(tmp_wNAF);\n                        goto err;\n                    }\n                    memcpy(wNAF[i], pp, wNAF_len[i]);\n                    if (wNAF_len[i] > max_len)\n                        max_len = wNAF_len[i];\n                    if (*tmp_points == NULL) {\n                        ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);\n                        OPENSSL_free(tmp_wNAF);\n                        goto err;\n                    }\n                    val_sub[i] = tmp_points;\n                    tmp_points += pre_points_per_block;\n                    pp += blocksize;\n                }\n                OPENSSL_free(tmp_wNAF);\n            }\n        }\n    }\n    val = OPENSSL_malloc((num_val + 1) * sizeof(val[0]));\n    if (val == NULL) {\n        ECerr(EC_F_EC_WNAF_MUL, ERR_R_MALLOC_FAILURE);\n        goto err;\n    }\n    val[num_val] = NULL;\n    v = val;\n    for (i = 0; i < num + num_scalar; i++) {\n        val_sub[i] = v;\n        for (j = 0; j < ((size_t)1 << (wsize[i] - 1)); j++) {\n            *v = EC_POINT_new(group);\n            if (*v == NULL)\n                goto err;\n            v++;\n        }\n    }\n    if (!(v == val + num_val)) {\n        ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);\n        goto err;\n    }\n    if ((tmp = EC_POINT_new(group)) == NULL)\n        goto err;\n    for (i = 0; i < num + num_scalar; i++) {\n        if (i < num) {\n            if (!EC_POINT_copy(val_sub[i][0], points[i]))\n                goto err;\n        } else {\n            if (!EC_POINT_copy(val_sub[i][0], generator))\n                goto err;\n        }\n        if (wsize[i] > 1) {\n            if (!EC_POINT_dbl(group, tmp, val_sub[i][0], ctx))\n                goto err;\n            for (j = 1; j < ((size_t)1 << (wsize[i] - 1)); j++) {\n                if (!EC_POINT_add\n                    (group, val_sub[i][j], val_sub[i][j - 1], tmp, ctx))\n                    goto err;\n            }\n        }\n    }\n    if (!EC_POINTs_make_affine(group, num_val, val, ctx))\n        goto err;\n    r_is_at_infinity = 1;\n    for (k = max_len - 1; k >= 0; k--) {\n        if (!r_is_at_infinity) {\n            if (!EC_POINT_dbl(group, r, r, ctx))\n                goto err;\n        }\n        for (i = 0; i < totalnum; i++) {\n            if (wNAF_len[i] > (size_t)k) {\n                int digit = wNAF[i][k];\n                int is_neg;\n                if (digit) {\n                    is_neg = digit < 0;\n                    if (is_neg)\n                        digit = -digit;\n                    if (is_neg != r_is_inverted) {\n                        if (!r_is_at_infinity) {\n                            if (!EC_POINT_invert(group, r, ctx))\n                                goto err;\n                        }\n                        r_is_inverted = !r_is_inverted;\n                    }\n                    if (r_is_at_infinity) {\n                        if (!EC_POINT_copy(r, val_sub[i][digit >> 1]))\n                            goto err;\n                        r_is_at_infinity = 0;\n                    } else {\n                        if (!EC_POINT_add\n                            (group, r, r, val_sub[i][digit >> 1], ctx))\n                            goto err;\n                    }\n                }\n            }\n        }\n    }\n    if (r_is_at_infinity) {\n        if (!EC_POINT_set_to_infinity(group, r))\n            goto err;\n    } else {\n        if (r_is_inverted)\n            if (!EC_POINT_invert(group, r, ctx))\n                goto err;\n    }\n    ret = 1;\n err:\n    EC_POINT_free(tmp);\n    OPENSSL_free(wsize);\n    OPENSSL_free(wNAF_len);\n    if (wNAF != NULL) {\n        signed char **w;\n        for (w = wNAF; *w != NULL; w++)\n            OPENSSL_free(*w);\n        OPENSSL_free(wNAF);\n    }\n    if (val != NULL) {\n        for (v = val; *v != NULL; v++)\n            EC_POINT_clear_free(*v);\n        OPENSSL_free(val);\n    }\n    OPENSSL_free(val_sub);\n    return ret;\n}']