void BN_consttime_swap(BN_ULONG condition, BIGNUM *a, BIGNUM *b, int nwords)
{
    BN_ULONG t;
    int i;
    bn_wcheck_size(a, nwords);
    bn_wcheck_size(b, nwords);
    assert(a != b);
    assert((condition & (condition - 1)) == 0);
    assert(sizeof(BN_ULONG) >= sizeof(int));
    condition = ((condition - 1) >> (BN_BITS2 - 1)) - 1;
    t = (a->top ^ b->top) & condition;
    a->top ^= t;
    b->top ^= t;
#define BN_CONSTTIME_SWAP(ind) \
        do { \
                t = (a->d[ind] ^ b->d[ind]) & condition; \
                a->d[ind] ^= t; \
                b->d[ind] ^= t; \
        } while (0)
    switch (nwords) {
    default:
        for (i = 10; i < nwords; i++)
            BN_CONSTTIME_SWAP(i);
    case 10:
        BN_CONSTTIME_SWAP(9);
    case 9:
        BN_CONSTTIME_SWAP(8);
    case 8:
        BN_CONSTTIME_SWAP(7);
    case 7:
        BN_CONSTTIME_SWAP(6);
    case 6:
        BN_CONSTTIME_SWAP(5);
    case 5:
        BN_CONSTTIME_SWAP(4);
    case 4:
        BN_CONSTTIME_SWAP(3);
    case 3:
        BN_CONSTTIME_SWAP(2);
    case 2:
        BN_CONSTTIME_SWAP(1);
    case 1:
        BN_CONSTTIME_SWAP(0);
    }
#undef BN_CONSTTIME_SWAP
}
['static int ec_GF2m_montgomery_point_multiply(const EC_GROUP *group,\n                                             EC_POINT *r,\n                                             const BIGNUM *scalar,\n                                             const EC_POINT *point,\n                                             BN_CTX *ctx)\n{\n    BIGNUM *x1, *x2, *z1, *z2;\n    int ret = 0, i, group_top;\n    BN_ULONG mask, word;\n    if (r == point) {\n        ECerr(EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY, EC_R_INVALID_ARGUMENT);\n        return 0;\n    }\n    if ((scalar == NULL) || BN_is_zero(scalar) || (point == NULL) ||\n        EC_POINT_is_at_infinity(group, point)) {\n        return EC_POINT_set_to_infinity(group, r);\n    }\n    if (!point->Z_is_one)\n        return 0;\n    BN_CTX_start(ctx);\n    x1 = BN_CTX_get(ctx);\n    z1 = BN_CTX_get(ctx);\n    if (z1 == NULL)\n        goto err;\n    x2 = r->X;\n    z2 = r->Y;\n    group_top = bn_get_top(group->field);\n    if (bn_wexpand(x1, group_top) == NULL\n        || bn_wexpand(z1, group_top) == NULL\n        || bn_wexpand(x2, group_top) == NULL\n        || bn_wexpand(z2, group_top) == NULL)\n        goto err;\n    if (!BN_GF2m_mod_arr(x1, point->X, group->poly))\n        goto err;\n    if (!BN_one(z1))\n        goto err;\n    if (!group->meth->field_sqr(group, z2, x1, ctx))\n        goto err;\n    if (!group->meth->field_sqr(group, x2, z2, ctx))\n        goto err;\n    if (!BN_GF2m_add(x2, x2, group->b))\n        goto err;\n    i = bn_get_top(scalar) - 1;\n    mask = BN_TBIT;\n    word = bn_get_words(scalar)[i];\n    while (!(word & mask))\n        mask >>= 1;\n    mask >>= 1;\n    if (!mask) {\n        i--;\n        mask = BN_TBIT;\n    }\n    for (; i >= 0; i--) {\n        word = bn_get_words(scalar)[i];\n        while (mask) {\n            BN_consttime_swap(word & mask, x1, x2, group_top);\n            BN_consttime_swap(word & mask, z1, z2, group_top);\n            if (!gf2m_Madd(group, point->X, x2, z2, x1, z1, ctx))\n                goto err;\n            if (!gf2m_Mdouble(group, x1, z1, ctx))\n                goto err;\n            BN_consttime_swap(word & mask, x1, x2, group_top);\n            BN_consttime_swap(word & mask, z1, z2, group_top);\n            mask >>= 1;\n        }\n        mask = BN_TBIT;\n    }\n    i = gf2m_Mxy(group, point->X, point->Y, x1, z1, x2, z2, ctx);\n    if (i == 0)\n        goto err;\n    else if (i == 1) {\n        if (!EC_POINT_set_to_infinity(group, r))\n            goto err;\n    } else {\n        if (!BN_one(r->Z))\n            goto err;\n        r->Z_is_one = 1;\n    }\n    BN_set_negative(r->X, 0);\n    BN_set_negative(r->Y, 0);\n    ret = 1;\n err:\n    BN_CTX_end(ctx);\n    return ret;\n}', 'static int gf2m_Madd(const EC_GROUP *group, const BIGNUM *x, BIGNUM *x1,\n                     BIGNUM *z1, const BIGNUM *x2, const BIGNUM *z2,\n                     BN_CTX *ctx)\n{\n    BIGNUM *t1, *t2;\n    int ret = 0;\n    BN_CTX_start(ctx);\n    t1 = BN_CTX_get(ctx);\n    t2 = BN_CTX_get(ctx);\n    if (t2 == NULL)\n        goto err;\n    if (!BN_copy(t1, x))\n        goto err;\n    if (!group->meth->field_mul(group, x1, x1, z2, ctx))\n        goto err;\n    if (!group->meth->field_mul(group, z1, z1, x2, ctx))\n        goto err;\n    if (!group->meth->field_mul(group, t2, x1, z1, ctx))\n        goto err;\n    if (!BN_GF2m_add(z1, z1, x1))\n        goto err;\n    if (!group->meth->field_sqr(group, z1, z1, ctx))\n        goto err;\n    if (!group->meth->field_mul(group, x1, z1, t1, ctx))\n        goto err;\n    if (!BN_GF2m_add(x1, x1, t2))\n        goto err;\n    ret = 1;\n err:\n    BN_CTX_end(ctx);\n    return ret;\n}', 'void BN_consttime_swap(BN_ULONG condition, BIGNUM *a, BIGNUM *b, int nwords)\n{\n    BN_ULONG t;\n    int i;\n    bn_wcheck_size(a, nwords);\n    bn_wcheck_size(b, nwords);\n    assert(a != b);\n    assert((condition & (condition - 1)) == 0);\n    assert(sizeof(BN_ULONG) >= sizeof(int));\n    condition = ((condition - 1) >> (BN_BITS2 - 1)) - 1;\n    t = (a->top ^ b->top) & condition;\n    a->top ^= t;\n    b->top ^= t;\n#define BN_CONSTTIME_SWAP(ind) \\\n        do { \\\n                t = (a->d[ind] ^ b->d[ind]) & condition; \\\n                a->d[ind] ^= t; \\\n                b->d[ind] ^= t; \\\n        } while (0)\n    switch (nwords) {\n    default:\n        for (i = 10; i < nwords; i++)\n            BN_CONSTTIME_SWAP(i);\n    case 10:\n        BN_CONSTTIME_SWAP(9);\n    case 9:\n        BN_CONSTTIME_SWAP(8);\n    case 8:\n        BN_CONSTTIME_SWAP(7);\n    case 7:\n        BN_CONSTTIME_SWAP(6);\n    case 6:\n        BN_CONSTTIME_SWAP(5);\n    case 5:\n        BN_CONSTTIME_SWAP(4);\n    case 4:\n        BN_CONSTTIME_SWAP(3);\n    case 3:\n        BN_CONSTTIME_SWAP(2);\n    case 2:\n        BN_CONSTTIME_SWAP(1);\n    case 1:\n        BN_CONSTTIME_SWAP(0);\n    }\n#undef BN_CONSTTIME_SWAP\n}']