test/ectest.c:801: error: INTEGER_OVERFLOW_L2
  ([0, +oo] - 1):unsigned64 by call to `EC_POINTs_mul`.
Showing all 11 steps of the trace


test/ectest.c:467:5: Call
465.       fprintf(stdout, " ok\n");
466.   
467.       group_order_tests(group);
           ^
468.   
469.       if ((P_160 = EC_GROUP_new(EC_GROUP_method_of(group))) == NULL)

test/ectest.c:139:10: Call
  137.       fprintf(stdout, ".");
  138.       fflush(stdout);
  139.       if (!EC_GROUP_precompute_mult(group, ctx))
                  ^
  140.           ABORT;
  141.       if (!EC_POINT_mul(group, Q, order, NULL, NULL, ctx))

crypto/ec/ec_lib.c:934:16: Call
    932.       if (group->meth->mul == 0)
    933.           /* use default */
    934.           return ec_wNAF_precompute_mult(group, ctx);
                          ^
    935.   
    936.       if (group->meth->precompute_mult != 0)

crypto/ec/ec_mult.c:601:5: Assignment
      599.        */
      600.       blocksize = 8;
      601.       w = 4;
                 ^
      602.       if (EC_window_bits_for_scalar_size(bits) > w) {
      603.           /* let's not make the window too small ... */

crypto/ec/ec_mult.c:683:5: Assignment
      681.       pre_comp->blocksize = blocksize;
      682.       pre_comp->numblocks = numblocks;
      683.       pre_comp->w = w;
                 ^
      684.       pre_comp->points = points;
      685.       points = NULL;

test/ectest.c:801:14: Call
799.   
800.           /* z is still the group order */
801.           if (!EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx))
                    ^
802.               ABORT;
803.           if (!EC_POINTs_mul(group, R, z, 2, points, scalars, ctx))

crypto/ec/ec_lib.c:903:1: Parameter `group->pre_comp.ec->w`
  901.    */
  902.   
  903. > int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
  904.                     size_t num, const EC_POINT *points[],
  905.                     const BIGNUM *scalars[], BN_CTX *ctx)

crypto/ec/ec_lib.c:909:16: Call
  907.       if (group->meth->mul == 0)
  908.           /* use default */
  909.           return ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
                        ^
  910.   
  911.       return group->meth->mul(group, r, scalar, num, points, scalars, ctx);

crypto/ec/ec_mult.c:154:1: <LHS trace>
152.    * in the addition if scalar != NULL
153.    */
154. > int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
155.                   size_t num, const EC_POINT *points[], const BIGNUM *scalars[],
156.                   BN_CTX *ctx)

crypto/ec/ec_mult.c:154:1: Parameter `group->pre_comp.ec->w`
    152.    * in the addition if scalar != NULL
    153.    */
    154. > int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
    155.                   size_t num, const EC_POINT *points[], const BIGNUM *scalars[],
    156.                   BN_CTX *ctx)

crypto/ec/ec_mult.c:232:13: Binary operation: ([0, +oo] - 1):unsigned64 by call to `EC_POINTs_mul` 
    230.                   numblocks = pre_comp->numblocks;
    231.   
    232.               pre_points_per_block = (size_t)1 << (pre_comp->w - 1);
                       ^
    233.   
    234.               /* check that pre_comp looks sane */

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)
{
    BN_CTX *new_ctx = NULL;
    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 (group->meth != r->meth) {
        ECerr(EC_F_EC_WNAF_MUL, EC_R_INCOMPATIBLE_OBJECTS);
        return 0;
    }
    if ((scalar == NULL) && (num == 0)) {
        return EC_POINT_set_to_infinity(group, r);
    }
    for (i = 0; i < num; i++) {
        if (group->meth != points[i]->meth) {
            ECerr(EC_F_EC_WNAF_MUL, EC_R_INCOMPATIBLE_OBJECTS);
            return 0;
        }
    }
    if (ctx == NULL) {
        ctx = new_ctx = BN_CTX_new();
        if (ctx == NULL)
            goto err;
    }
    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;
                if (tmp_len > max_len)
                    max_len = 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);
                        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);
                            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:
    BN_CTX_free(new_ctx);
    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;
}
['static void prime_field_tests(void)\n{\n    BN_CTX *ctx = NULL;\n    BIGNUM *p, *a, *b;\n    EC_GROUP *group;\n    EC_GROUP *P_160 = NULL, *P_192 = NULL, *P_224 = NULL, *P_256 =\n        NULL, *P_384 = NULL, *P_521 = NULL;\n    EC_POINT *P, *Q, *R;\n    BIGNUM *x, *y, *z;\n    unsigned char buf[100];\n    size_t i, len;\n    int k;\n    ctx = BN_CTX_new();\n    if (!ctx)\n        ABORT;\n    p = BN_new();\n    a = BN_new();\n    b = BN_new();\n    if (!p || !a || !b)\n        ABORT;\n    if (!BN_hex2bn(&p, "17"))\n        ABORT;\n    if (!BN_hex2bn(&a, "1"))\n        ABORT;\n    if (!BN_hex2bn(&b, "1"))\n        ABORT;\n    group = EC_GROUP_new(EC_GFp_mont_method());\n    if (!group)\n        ABORT;\n    if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx))\n        ABORT;\n    {\n        EC_GROUP *tmp;\n        tmp = EC_GROUP_new(EC_GROUP_method_of(group));\n        if (!tmp)\n            ABORT;\n        if (!EC_GROUP_copy(tmp, group))\n            ABORT;\n        EC_GROUP_free(group);\n        group = tmp;\n    }\n    if (!EC_GROUP_get_curve_GFp(group, p, a, b, ctx))\n        ABORT;\n    fprintf(stdout,\n            "Curve defined by Weierstrass equation\\n     y^2 = x^3 + a*x + b  (mod 0x");\n    BN_print_fp(stdout, p);\n    fprintf(stdout, ")\\n     a = 0x");\n    BN_print_fp(stdout, a);\n    fprintf(stdout, "\\n     b = 0x");\n    BN_print_fp(stdout, b);\n    fprintf(stdout, "\\n");\n    P = EC_POINT_new(group);\n    Q = EC_POINT_new(group);\n    R = EC_POINT_new(group);\n    if (!P || !Q || !R)\n        ABORT;\n    if (!EC_POINT_set_to_infinity(group, P))\n        ABORT;\n    if (!EC_POINT_is_at_infinity(group, P))\n        ABORT;\n    buf[0] = 0;\n    if (!EC_POINT_oct2point(group, Q, buf, 1, ctx))\n        ABORT;\n    if (!EC_POINT_add(group, P, P, Q, ctx))\n        ABORT;\n    if (!EC_POINT_is_at_infinity(group, P))\n        ABORT;\n    x = BN_new();\n    y = BN_new();\n    z = BN_new();\n    if (!x || !y || !z)\n        ABORT;\n    if (!BN_hex2bn(&x, "D"))\n        ABORT;\n    if (!EC_POINT_set_compressed_coordinates_GFp(group, Q, x, 1, ctx))\n        ABORT;\n    if (EC_POINT_is_on_curve(group, Q, ctx) <= 0) {\n        if (!EC_POINT_get_affine_coordinates_GFp(group, Q, x, y, ctx))\n            ABORT;\n        fprintf(stderr, "Point is not on curve: x = 0x");\n        BN_print_fp(stderr, x);\n        fprintf(stderr, ", y = 0x");\n        BN_print_fp(stderr, y);\n        fprintf(stderr, "\\n");\n        ABORT;\n    }\n    fprintf(stdout, "A cyclic subgroup:\\n");\n    k = 100;\n    do {\n        if (k-- == 0)\n            ABORT;\n        if (EC_POINT_is_at_infinity(group, P))\n            fprintf(stdout, "     point at infinity\\n");\n        else {\n            if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx))\n                ABORT;\n            fprintf(stdout, "     x = 0x");\n            BN_print_fp(stdout, x);\n            fprintf(stdout, ", y = 0x");\n            BN_print_fp(stdout, y);\n            fprintf(stdout, "\\n");\n        }\n        if (!EC_POINT_copy(R, P))\n            ABORT;\n        if (!EC_POINT_add(group, P, P, Q, ctx))\n            ABORT;\n    }\n    while (!EC_POINT_is_at_infinity(group, P));\n    if (!EC_POINT_add(group, P, Q, R, ctx))\n        ABORT;\n    if (!EC_POINT_is_at_infinity(group, P))\n        ABORT;\n    len =\n        EC_POINT_point2oct(group, Q, POINT_CONVERSION_COMPRESSED, buf,\n                           sizeof buf, ctx);\n    if (len == 0)\n        ABORT;\n    if (!EC_POINT_oct2point(group, P, buf, len, ctx))\n        ABORT;\n    if (0 != EC_POINT_cmp(group, P, Q, ctx))\n        ABORT;\n    fprintf(stdout, "Generator as octet string, compressed form:\\n     ");\n    for (i = 0; i < len; i++)\n        fprintf(stdout, "%02X", buf[i]);\n    len =\n        EC_POINT_point2oct(group, Q, POINT_CONVERSION_UNCOMPRESSED, buf,\n                           sizeof buf, ctx);\n    if (len == 0)\n        ABORT;\n    if (!EC_POINT_oct2point(group, P, buf, len, ctx))\n        ABORT;\n    if (0 != EC_POINT_cmp(group, P, Q, ctx))\n        ABORT;\n    fprintf(stdout, "\\nGenerator as octet string, uncompressed form:\\n     ");\n    for (i = 0; i < len; i++)\n        fprintf(stdout, "%02X", buf[i]);\n    len =\n        EC_POINT_point2oct(group, Q, POINT_CONVERSION_HYBRID, buf, sizeof buf,\n                           ctx);\n    if (len == 0)\n        ABORT;\n    if (!EC_POINT_oct2point(group, P, buf, len, ctx))\n        ABORT;\n    if (0 != EC_POINT_cmp(group, P, Q, ctx))\n        ABORT;\n    fprintf(stdout, "\\nGenerator as octet string, hybrid form:\\n     ");\n    for (i = 0; i < len; i++)\n        fprintf(stdout, "%02X", buf[i]);\n    if (!EC_POINT_get_Jprojective_coordinates_GFp(group, R, x, y, z, ctx))\n        ABORT;\n    fprintf(stdout,\n            "\\nA representation of the inverse of that generator in\\nJacobian projective coordinates:\\n     X = 0x");\n    BN_print_fp(stdout, x);\n    fprintf(stdout, ", Y = 0x");\n    BN_print_fp(stdout, y);\n    fprintf(stdout, ", Z = 0x");\n    BN_print_fp(stdout, z);\n    fprintf(stdout, "\\n");\n    if (!EC_POINT_invert(group, P, ctx))\n        ABORT;\n    if (0 != EC_POINT_cmp(group, P, R, ctx))\n        ABORT;\n    if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF"))\n        ABORT;\n    if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL))\n        ABORT;\n    if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC"))\n        ABORT;\n    if (!BN_hex2bn(&b, "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45"))\n        ABORT;\n    if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx))\n        ABORT;\n    if (!BN_hex2bn(&x, "4A96B5688EF573284664698968C38BB913CBFC82"))\n        ABORT;\n    if (!BN_hex2bn(&y, "23a628553168947d59dcc912042351377ac5fb32"))\n        ABORT;\n    if (!EC_POINT_set_affine_coordinates_GFp(group, P, x, y, ctx))\n        ABORT;\n    if (EC_POINT_is_on_curve(group, P, ctx) <= 0)\n        ABORT;\n    if (!BN_hex2bn(&z, "0100000000000000000001F4C8F927AED3CA752257"))\n        ABORT;\n    if (!EC_GROUP_set_generator(group, P, z, BN_value_one()))\n        ABORT;\n    if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx))\n        ABORT;\n    fprintf(stdout, "\\nSEC2 curve secp160r1 -- Generator:\\n     x = 0x");\n    BN_print_fp(stdout, x);\n    fprintf(stdout, "\\n     y = 0x");\n    BN_print_fp(stdout, y);\n    fprintf(stdout, "\\n");\n    if (!BN_hex2bn(&z, "23a628553168947d59dcc912042351377ac5fb32"))\n        ABORT;\n    if (0 != BN_cmp(y, z))\n        ABORT;\n    fprintf(stdout, "verify degree ...");\n    if (EC_GROUP_get_degree(group) != 160)\n        ABORT;\n    fprintf(stdout, " ok\\n");\n    group_order_tests(group);\n    if ((P_160 = EC_GROUP_new(EC_GROUP_method_of(group))) == NULL)\n        ABORT;\n    if (!EC_GROUP_copy(P_160, group))\n        ABORT;\n    if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF"))\n        ABORT;\n    if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL))\n        ABORT;\n    if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC"))\n        ABORT;\n    if (!BN_hex2bn(&b, "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1"))\n        ABORT;\n    if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx))\n        ABORT;\n    if (!BN_hex2bn(&x, "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012"))\n        ABORT;\n    if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 1, ctx))\n        ABORT;\n    if (EC_POINT_is_on_curve(group, P, ctx) <= 0)\n        ABORT;\n    if (!BN_hex2bn(&z, "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831"))\n        ABORT;\n    if (!EC_GROUP_set_generator(group, P, z, BN_value_one()))\n        ABORT;\n    if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx))\n        ABORT;\n    fprintf(stdout, "\\nNIST curve P-192 -- Generator:\\n     x = 0x");\n    BN_print_fp(stdout, x);\n    fprintf(stdout, "\\n     y = 0x");\n    BN_print_fp(stdout, y);\n    fprintf(stdout, "\\n");\n    if (!BN_hex2bn(&z, "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811"))\n        ABORT;\n    if (0 != BN_cmp(y, z))\n        ABORT;\n    fprintf(stdout, "verify degree ...");\n    if (EC_GROUP_get_degree(group) != 192)\n        ABORT;\n    fprintf(stdout, " ok\\n");\n    group_order_tests(group);\n    if ((P_192 = EC_GROUP_new(EC_GROUP_method_of(group))) == NULL)\n        ABORT;\n    if (!EC_GROUP_copy(P_192, group))\n        ABORT;\n    if (!BN_hex2bn\n        (&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001"))\n        ABORT;\n    if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL))\n        ABORT;\n    if (!BN_hex2bn\n        (&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE"))\n        ABORT;\n    if (!BN_hex2bn\n        (&b, "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4"))\n        ABORT;\n    if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx))\n        ABORT;\n    if (!BN_hex2bn\n        (&x, "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21"))\n        ABORT;\n    if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 0, ctx))\n        ABORT;\n    if (EC_POINT_is_on_curve(group, P, ctx) <= 0)\n        ABORT;\n    if (!BN_hex2bn\n        (&z, "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D"))\n        ABORT;\n    if (!EC_GROUP_set_generator(group, P, z, BN_value_one()))\n        ABORT;\n    if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx))\n        ABORT;\n    fprintf(stdout, "\\nNIST curve P-224 -- Generator:\\n     x = 0x");\n    BN_print_fp(stdout, x);\n    fprintf(stdout, "\\n     y = 0x");\n    BN_print_fp(stdout, y);\n    fprintf(stdout, "\\n");\n    if (!BN_hex2bn\n        (&z, "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34"))\n        ABORT;\n    if (0 != BN_cmp(y, z))\n        ABORT;\n    fprintf(stdout, "verify degree ...");\n    if (EC_GROUP_get_degree(group) != 224)\n        ABORT;\n    fprintf(stdout, " ok\\n");\n    group_order_tests(group);\n    if ((P_224 = EC_GROUP_new(EC_GROUP_method_of(group))) == NULL)\n        ABORT;\n    if (!EC_GROUP_copy(P_224, group))\n        ABORT;\n    if (!BN_hex2bn\n        (&p,\n         "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF"))\n        ABORT;\n    if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL))\n        ABORT;\n    if (!BN_hex2bn\n        (&a,\n         "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC"))\n        ABORT;\n    if (!BN_hex2bn\n        (&b,\n         "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B"))\n        ABORT;\n    if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx))\n        ABORT;\n    if (!BN_hex2bn\n        (&x,\n         "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296"))\n        ABORT;\n    if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 1, ctx))\n        ABORT;\n    if (EC_POINT_is_on_curve(group, P, ctx) <= 0)\n        ABORT;\n    if (!BN_hex2bn(&z, "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E"\n                   "84F3B9CAC2FC632551"))\n        ABORT;\n    if (!EC_GROUP_set_generator(group, P, z, BN_value_one()))\n        ABORT;\n    if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx))\n        ABORT;\n    fprintf(stdout, "\\nNIST curve P-256 -- Generator:\\n     x = 0x");\n    BN_print_fp(stdout, x);\n    fprintf(stdout, "\\n     y = 0x");\n    BN_print_fp(stdout, y);\n    fprintf(stdout, "\\n");\n    if (!BN_hex2bn\n        (&z,\n         "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5"))\n        ABORT;\n    if (0 != BN_cmp(y, z))\n        ABORT;\n    fprintf(stdout, "verify degree ...");\n    if (EC_GROUP_get_degree(group) != 256)\n        ABORT;\n    fprintf(stdout, " ok\\n");\n    group_order_tests(group);\n    if ((P_256 = EC_GROUP_new(EC_GROUP_method_of(group))) == NULL)\n        ABORT;\n    if (!EC_GROUP_copy(P_256, group))\n        ABORT;\n    if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"\n                   "FFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF"))\n        ABORT;\n    if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL))\n        ABORT;\n    if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"\n                   "FFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC"))\n        ABORT;\n    if (!BN_hex2bn(&b, "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141"\n                   "120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF"))\n        ABORT;\n    if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx))\n        ABORT;\n    if (!BN_hex2bn(&x, "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B"\n                   "9859F741E082542A385502F25DBF55296C3A545E3872760AB7"))\n        ABORT;\n    if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 1, ctx))\n        ABORT;\n    if (EC_POINT_is_on_curve(group, P, ctx) <= 0)\n        ABORT;\n    if (!BN_hex2bn(&z, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"\n                   "FFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973"))\n        ABORT;\n    if (!EC_GROUP_set_generator(group, P, z, BN_value_one()))\n        ABORT;\n    if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx))\n        ABORT;\n    fprintf(stdout, "\\nNIST curve P-384 -- Generator:\\n     x = 0x");\n    BN_print_fp(stdout, x);\n    fprintf(stdout, "\\n     y = 0x");\n    BN_print_fp(stdout, y);\n    fprintf(stdout, "\\n");\n    if (!BN_hex2bn(&z, "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A14"\n                   "7CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F"))\n        ABORT;\n    if (0 != BN_cmp(y, z))\n        ABORT;\n    fprintf(stdout, "verify degree ...");\n    if (EC_GROUP_get_degree(group) != 384)\n        ABORT;\n    fprintf(stdout, " ok\\n");\n    group_order_tests(group);\n    if ((P_384 = EC_GROUP_new(EC_GROUP_method_of(group))) == NULL)\n        ABORT;\n    if (!EC_GROUP_copy(P_384, group))\n        ABORT;\n    if (!BN_hex2bn(&p, "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"\n                   "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"\n                   "FFFFFFFFFFFFFFFFFFFFFFFFFFFF"))\n        ABORT;\n    if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL))\n        ABORT;\n    if (!BN_hex2bn(&a, "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"\n                   "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"\n                   "FFFFFFFFFFFFFFFFFFFFFFFFFFFC"))\n        ABORT;\n    if (!BN_hex2bn(&b, "051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B"\n                   "315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573"\n                   "DF883D2C34F1EF451FD46B503F00"))\n        ABORT;\n    if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx))\n        ABORT;\n    if (!BN_hex2bn(&x, "C6858E06B70404E9CD9E3ECB662395B4429C648139053F"\n                   "B521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B"\n                   "3C1856A429BF97E7E31C2E5BD66"))\n        ABORT;\n    if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 0, ctx))\n        ABORT;\n    if (EC_POINT_is_on_curve(group, P, ctx) <= 0)\n        ABORT;\n    if (!BN_hex2bn(&z, "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"\n                   "FFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5"\n                   "C9B8899C47AEBB6FB71E91386409"))\n        ABORT;\n    if (!EC_GROUP_set_generator(group, P, z, BN_value_one()))\n        ABORT;\n    if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx))\n        ABORT;\n    fprintf(stdout, "\\nNIST curve P-521 -- Generator:\\n     x = 0x");\n    BN_print_fp(stdout, x);\n    fprintf(stdout, "\\n     y = 0x");\n    BN_print_fp(stdout, y);\n    fprintf(stdout, "\\n");\n    if (!BN_hex2bn(&z, "11839296A789A3BC0045C8A5FB42C7D1BD998F54449579"\n                   "B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C"\n                   "7086A272C24088BE94769FD16650"))\n        ABORT;\n    if (0 != BN_cmp(y, z))\n        ABORT;\n    fprintf(stdout, "verify degree ...");\n    if (EC_GROUP_get_degree(group) != 521)\n        ABORT;\n    fprintf(stdout, " ok\\n");\n    group_order_tests(group);\n    if ((P_521 = EC_GROUP_new(EC_GROUP_method_of(group))) == NULL)\n        ABORT;\n    if (!EC_GROUP_copy(P_521, group))\n        ABORT;\n    if (!EC_POINT_copy(Q, P))\n        ABORT;\n    if (EC_POINT_is_at_infinity(group, Q))\n        ABORT;\n    if (!EC_POINT_dbl(group, P, P, ctx))\n        ABORT;\n    if (EC_POINT_is_on_curve(group, P, ctx) <= 0)\n        ABORT;\n    if (!EC_POINT_invert(group, Q, ctx))\n        ABORT;\n    if (!EC_POINT_add(group, R, P, Q, ctx))\n        ABORT;\n    if (!EC_POINT_add(group, R, R, Q, ctx))\n        ABORT;\n    if (!EC_POINT_is_at_infinity(group, R))\n        ABORT;\n    {\n        const EC_POINT *points[4];\n        const BIGNUM *scalars[4];\n        BIGNUM *scalar3;\n        if (EC_POINT_is_at_infinity(group, Q))\n            ABORT;\n        points[0] = Q;\n        points[1] = Q;\n        points[2] = Q;\n        points[3] = Q;\n        if (!EC_GROUP_get_order(group, z, ctx))\n            ABORT;\n        if (!BN_add(y, z, BN_value_one()))\n            ABORT;\n        if (BN_is_odd(y))\n            ABORT;\n        if (!BN_rshift1(y, y))\n            ABORT;\n        scalars[0] = y;\n        scalars[1] = y;\n        fprintf(stdout, "combined multiplication ...");\n        fflush(stdout);\n        if (!EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx))\n            ABORT;\n        if (!EC_POINTs_mul(group, R, z, 2, points, scalars, ctx))\n            ABORT;\n        if (0 != EC_POINT_cmp(group, P, R, ctx))\n            ABORT;\n        if (0 != EC_POINT_cmp(group, R, Q, ctx))\n            ABORT;\n        fprintf(stdout, ".");\n        fflush(stdout);\n        if (!BN_pseudo_rand(y, BN_num_bits(y), 0, 0))\n            ABORT;\n        if (!BN_add(z, z, y))\n            ABORT;\n        BN_set_negative(z, 1);\n        scalars[0] = y;\n        scalars[1] = z;\n        if (!EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx))\n            ABORT;\n        if (!EC_POINT_is_at_infinity(group, P))\n            ABORT;\n        fprintf(stdout, ".");\n        fflush(stdout);\n        if (!BN_pseudo_rand(x, BN_num_bits(y) - 1, 0, 0))\n            ABORT;\n        if (!BN_add(z, x, y))\n            ABORT;\n        BN_set_negative(z, 1);\n        scalars[0] = x;\n        scalars[1] = y;\n        scalars[2] = z;\n        scalar3 = BN_new();\n        if (!scalar3)\n            ABORT;\n        BN_zero(scalar3);\n        scalars[3] = scalar3;\n        if (!EC_POINTs_mul(group, P, NULL, 4, points, scalars, ctx))\n            ABORT;\n        if (!EC_POINT_is_at_infinity(group, P))\n            ABORT;\n        fprintf(stdout, " ok\\n\\n");\n        BN_free(scalar3);\n    }\n    BN_CTX_free(ctx);\n    BN_free(p);\n    BN_free(a);\n    BN_free(b);\n    EC_GROUP_free(group);\n    EC_POINT_free(P);\n    EC_POINT_free(Q);\n    EC_POINT_free(R);\n    BN_free(x);\n    BN_free(y);\n    BN_free(z);\n    EC_GROUP_free(P_160);\n    EC_GROUP_free(P_192);\n    EC_GROUP_free(P_224);\n    EC_GROUP_free(P_256);\n    EC_GROUP_free(P_384);\n    EC_GROUP_free(P_521);\n}', 'static void group_order_tests(EC_GROUP *group)\n{\n    BIGNUM *n1, *n2, *order;\n    EC_POINT *P = EC_POINT_new(group);\n    EC_POINT *Q = EC_POINT_new(group);\n    BN_CTX *ctx = BN_CTX_new();\n    int i;\n    n1 = BN_new();\n    n2 = BN_new();\n    order = BN_new();\n    fprintf(stdout, "verify group order ...");\n    fflush(stdout);\n    if (!EC_GROUP_get_order(group, order, ctx))\n        ABORT;\n    if (!EC_POINT_mul(group, Q, order, NULL, NULL, ctx))\n        ABORT;\n    if (!EC_POINT_is_at_infinity(group, Q))\n        ABORT;\n    fprintf(stdout, ".");\n    fflush(stdout);\n    if (!EC_GROUP_precompute_mult(group, ctx))\n        ABORT;\n    if (!EC_POINT_mul(group, Q, order, NULL, NULL, ctx))\n        ABORT;\n    if (!EC_POINT_is_at_infinity(group, Q))\n        ABORT;\n    fprintf(stdout, " ok\\n");\n    fprintf(stdout, "long/negative scalar tests ");\n    for (i = 1; i <= 2; i++) {\n        const BIGNUM *scalars[6];\n        const EC_POINT *points[6];\n        fprintf(stdout, i == 1 ?\n                "allowing precomputation ... " :\n                "without precomputation ... ");\n        if (!BN_set_word(n1, i))\n            ABORT;\n        if (!EC_POINT_mul(group, P, n1, NULL, NULL, ctx))\n            ABORT;\n        if (!BN_one(n1))\n            ABORT;\n        if (!BN_sub(n1, n1, order))\n            ABORT;\n        if (!EC_POINT_mul(group, Q, NULL, P, n1, ctx))\n            ABORT;\n        if (0 != EC_POINT_cmp(group, Q, P, ctx))\n            ABORT;\n        if (!BN_add(n2, order, BN_value_one()))\n            ABORT;\n        if (!EC_POINT_mul(group, Q, NULL, P, n2, ctx))\n            ABORT;\n        if (0 != EC_POINT_cmp(group, Q, P, ctx))\n            ABORT;\n        if (!BN_mul(n2, n1, n2, ctx))\n            ABORT;\n        if (!EC_POINT_mul(group, Q, NULL, P, n2, ctx))\n            ABORT;\n        if (0 != EC_POINT_cmp(group, Q, P, ctx))\n            ABORT;\n        BN_set_negative(n2, 0);\n        if (!EC_POINT_mul(group, Q, NULL, P, n2, ctx))\n            ABORT;\n        if (!EC_POINT_add(group, Q, Q, P, ctx))\n            ABORT;\n        if (!EC_POINT_is_at_infinity(group, Q))\n            ABORT;\n        if (EC_POINT_is_at_infinity(group, P))\n            ABORT;\n        scalars[0] = n1;\n        points[0] = Q;\n        scalars[1] = n2;\n        points[1] = P;\n        scalars[2] = n1;\n        points[2] = Q;\n        scalars[3] = n2;\n        points[3] = Q;\n        scalars[4] = n1;\n        points[4] = P;\n        scalars[5] = n2;\n        points[5] = Q;\n        if (!EC_POINTs_mul(group, P, NULL, 6, points, scalars, ctx))\n            ABORT;\n        if (!EC_POINT_is_at_infinity(group, P))\n            ABORT;\n    }\n    fprintf(stdout, "ok\\n");\n    EC_POINT_free(P);\n    EC_POINT_free(Q);\n    BN_free(n1);\n    BN_free(n2);\n    BN_free(order);\n    BN_CTX_free(ctx);\n}', 'int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx)\n{\n    if (group->meth->mul == 0)\n        return ec_wNAF_precompute_mult(group, ctx);\n    if (group->meth->precompute_mult != 0)\n        return group->meth->precompute_mult(group, ctx);\n    else\n        return 1;\n}', 'int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *ctx)\n{\n    const EC_POINT *generator;\n    EC_POINT *tmp_point = NULL, *base = NULL, **var;\n    BN_CTX *new_ctx = NULL;\n    BIGNUM *order;\n    size_t i, bits, w, pre_points_per_block, blocksize, numblocks, num;\n    EC_POINT **points = NULL;\n    EC_PRE_COMP *pre_comp;\n    int ret = 0;\n    EC_ec_pre_comp_free(group->pre_comp.ec);\n    if ((pre_comp = ec_pre_comp_new(group)) == NULL)\n        return 0;\n    generator = EC_GROUP_get0_generator(group);\n    if (generator == NULL) {\n        ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, EC_R_UNDEFINED_GENERATOR);\n        goto err;\n    }\n    if (ctx == NULL) {\n        ctx = new_ctx = BN_CTX_new();\n        if (ctx == NULL)\n            goto err;\n    }\n    BN_CTX_start(ctx);\n    order = BN_CTX_get(ctx);\n    if (order == NULL)\n        goto err;\n    if (!EC_GROUP_get_order(group, order, ctx))\n        goto err;\n    if (BN_is_zero(order)) {\n        ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, EC_R_UNKNOWN_ORDER);\n        goto err;\n    }\n    bits = BN_num_bits(order);\n    blocksize = 8;\n    w = 4;\n    if (EC_window_bits_for_scalar_size(bits) > w) {\n        w = EC_window_bits_for_scalar_size(bits);\n    }\n    numblocks = (bits + blocksize - 1) / blocksize;\n    pre_points_per_block = (size_t)1 << (w - 1);\n    num = pre_points_per_block * numblocks;\n    points = OPENSSL_malloc(sizeof(*points) * (num + 1));\n    if (points == NULL) {\n        ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_MALLOC_FAILURE);\n        goto err;\n    }\n    var = points;\n    var[num] = NULL;\n    for (i = 0; i < num; i++) {\n        if ((var[i] = EC_POINT_new(group)) == NULL) {\n            ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_MALLOC_FAILURE);\n            goto err;\n        }\n    }\n    if ((tmp_point = EC_POINT_new(group)) == NULL\n        || (base = EC_POINT_new(group)) == NULL) {\n        ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_MALLOC_FAILURE);\n        goto err;\n    }\n    if (!EC_POINT_copy(base, generator))\n        goto err;\n    for (i = 0; i < numblocks; i++) {\n        size_t j;\n        if (!EC_POINT_dbl(group, tmp_point, base, ctx))\n            goto err;\n        if (!EC_POINT_copy(*var++, base))\n            goto err;\n        for (j = 1; j < pre_points_per_block; j++, var++) {\n            if (!EC_POINT_add(group, *var, tmp_point, *(var - 1), ctx))\n                goto err;\n        }\n        if (i < numblocks - 1) {\n            size_t k;\n            if (blocksize <= 2) {\n                ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_INTERNAL_ERROR);\n                goto err;\n            }\n            if (!EC_POINT_dbl(group, base, tmp_point, ctx))\n                goto err;\n            for (k = 2; k < blocksize; k++) {\n                if (!EC_POINT_dbl(group, base, base, ctx))\n                    goto err;\n            }\n        }\n    }\n    if (!EC_POINTs_make_affine(group, num, points, ctx))\n        goto err;\n    pre_comp->group = group;\n    pre_comp->blocksize = blocksize;\n    pre_comp->numblocks = numblocks;\n    pre_comp->w = w;\n    pre_comp->points = points;\n    points = NULL;\n    pre_comp->num = num;\n    SETPRECOMP(group, ec, pre_comp);\n    pre_comp = NULL;\n    ret = 1;\n err:\n    if (ctx != NULL)\n        BN_CTX_end(ctx);\n    BN_CTX_free(new_ctx);\n    EC_ec_pre_comp_free(pre_comp);\n    if (points) {\n        EC_POINT **p;\n        for (p = points; *p != NULL; p++)\n            EC_POINT_free(*p);\n        OPENSSL_free(points);\n    }\n    EC_POINT_free(tmp_point);\n    EC_POINT_free(base);\n    return ret;\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    if (group->meth->mul == 0)\n        return ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);\n    return group->meth->mul(group, r, scalar, num, points, scalars, ctx);\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    BN_CTX *new_ctx = NULL;\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 (group->meth != r->meth) {\n        ECerr(EC_F_EC_WNAF_MUL, EC_R_INCOMPATIBLE_OBJECTS);\n        return 0;\n    }\n    if ((scalar == NULL) && (num == 0)) {\n        return EC_POINT_set_to_infinity(group, r);\n    }\n    for (i = 0; i < num; i++) {\n        if (group->meth != points[i]->meth) {\n            ECerr(EC_F_EC_WNAF_MUL, EC_R_INCOMPATIBLE_OBJECTS);\n            return 0;\n        }\n    }\n    if (ctx == NULL) {\n        ctx = new_ctx = BN_CTX_new();\n        if (ctx == NULL)\n            goto err;\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                if (tmp_len > max_len)\n                    max_len = 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                        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                            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    BN_CTX_free(new_ctx);\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}']