static int test_modexp_mont5(void)
{
    BIGNUM *a = NULL, *p = NULL, *m = NULL, *d = NULL, *e = NULL;
    BIGNUM *b = NULL, *n = NULL, *c = NULL;
    BN_MONT_CTX *mont = NULL;
    int st = 0;
    if (!TEST_ptr(a = BN_new())
            || !TEST_ptr(p = BN_new())
            || !TEST_ptr(m = BN_new())
            || !TEST_ptr(d = BN_new())
            || !TEST_ptr(e = BN_new())
            || !TEST_ptr(b = BN_new())
            || !TEST_ptr(n = BN_new())
            || !TEST_ptr(c = BN_new())
            || !TEST_ptr(mont = BN_MONT_CTX_new()))
        goto err;
    BN_bntest_rand(m, 1024, 0, 1);
    BN_bntest_rand(a, 1024, 0, 0);
    BN_zero(p);
    if (!TEST_true(BN_mod_exp_mont_consttime(d, a, p, m, ctx, NULL)))
        goto err;
    if (!TEST_BN_eq_one(d))
        goto err;
    BN_hex2bn(&a,
        "7878787878787878787878787878787878787878787878787878787878787878"
        "7878787878787878787878787878787878787878787878787878787878787878"
        "7878787878787878787878787878787878787878787878787878787878787878"
        "7878787878787878787878787878787878787878787878787878787878787878");
    BN_hex2bn(&b,
        "095D72C08C097BA488C5E439C655A192EAFB6380073D8C2664668EDDB4060744"
        "E16E57FB4EDB9AE10A0CEFCDC28A894F689A128379DB279D48A2E20849D68593"
        "9B7803BCF46CEBF5C533FB0DD35B080593DE5472E3FE5DB951B8BFF9B4CB8F03"
        "9CC638A5EE8CDD703719F8000E6A9F63BEED5F2FCD52FF293EA05A251BB4AB81");
    BN_hex2bn(&n,
        "D78AF684E71DB0C39CFF4E64FB9DB567132CB9C50CC98009FEB820B26F2DED9B"
        "91B9B5E2B83AE0AE4EB4E0523CA726BFBE969B89FD754F674CE99118C3F2D1C5"
        "D81FDC7C54E02B60262B241D53C040E99E45826ECA37A804668E690E1AFC1CA4"
        "2C9A15D84D4954425F0B7642FC0BD9D7B24E2618D2DCC9B729D944BADACFDDAF");
    BN_MONT_CTX_set(mont, n, ctx);
    BN_mod_mul_montgomery(c, a, b, mont, ctx);
    BN_mod_mul_montgomery(d, b, a, mont, ctx);
    if (!TEST_BN_eq(c, d))
        goto err;
    parse_bigBN(&n, bn1strings);
    parse_bigBN(&a, bn2strings);
    BN_free(b);
    b = BN_dup(a);
    BN_MONT_CTX_set(mont, n, ctx);
    BN_mod_mul_montgomery(c, a, a, mont, ctx);
    BN_mod_mul_montgomery(d, a, b, mont, ctx);
    if (!TEST_BN_eq(c, d))
        goto err;
    {
        static const char *ahex[] = {
                      "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
            "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
            "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
            "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
            "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8FFEADBCFC4DAE7FFF908E92820306B",
            "9544D954000000006C0000000000000000000000000000000000000000000000",
            "00000000000000000000FF030202FFFFF8FFEBDBCFC4DAE7FFF908E92820306B",
            "9544D954000000006C000000FF0302030000000000FFFFFFFFFFFFFFFFFFFFFF",
            "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF01FC00FF02FFFFFFFF",
            "00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00FCFD",
            "FCFFFFFFFFFF000000000000000000FF0302030000000000FFFFFFFFFFFFFFFF",
            "FF00FCFDFDFF030202FF00000000FFFFFFFFFFFFFFFFFF00FCFDFCFFFFFFFFFF",
            NULL
        };
        static const char *nhex[] = {
                      "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
            "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
            "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
            "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
            "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8F8F8F8000000",
            "00000010000000006C0000000000000000000000000000000000000000000000",
            "00000000000000000000000000000000000000FFFFFFFFFFFFF8F8F8F8000000",
            "00000010000000006C000000000000000000000000FFFFFFFFFFFFFFFFFFFFFF",
            "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
            "00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
            "FFFFFFFFFFFF000000000000000000000000000000000000FFFFFFFFFFFFFFFF",
            "FFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
            NULL
        };
        parse_bigBN(&a, ahex);
        parse_bigBN(&n, nhex);
    }
    BN_free(b);
    b = BN_dup(a);
    BN_MONT_CTX_set(mont, n, ctx);
    BN_mod_mul_montgomery(c, a, a, mont, ctx);
    BN_mod_mul_montgomery(d, a, b, mont, ctx);
    if (!TEST_BN_eq(c, d))
        goto err;
    BN_hex2bn(&a,
        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2020202020DF");
    BN_hex2bn(&b,
        "2020202020202020202020202020202020202020202020202020202020202020"
        "2020202020202020202020202020202020202020202020202020202020202020"
        "20202020202020FF202020202020202020202020202020202020202020202020"
        "2020202020202020202020202020202020202020202020202020202020202020");
    BN_hex2bn(&n,
        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2020202020FF");
    BN_MONT_CTX_set(mont, n, ctx);
    BN_mod_exp_mont_consttime(c, a, b, n, ctx, mont);
    BN_mod_exp_mont(d, a, b, n, ctx, mont);
    if (!TEST_BN_eq(c, d))
        goto err;
    BN_bntest_rand(p, 1024, 0, 0);
    BN_zero(a);
    if (!TEST_true(BN_mod_exp_mont_consttime(d, a, p, m, ctx, NULL))
            || !TEST_BN_eq_zero(d))
        goto err;
    BN_one(a);
    BN_MONT_CTX_set(mont, m, ctx);
    if (!TEST_true(BN_from_montgomery(e, a, mont, ctx))
            || !TEST_true(BN_mod_exp_mont_consttime(d, e, p, m, ctx, NULL))
            || !TEST_true(BN_mod_exp_simple(a, e, p, m, ctx))
            || !TEST_BN_eq(a, d))
        goto err;
    BN_bntest_rand(e, 1024, 0, 0);
    if (!TEST_true(BN_mod_exp_mont_consttime(d, e, p, m, ctx, NULL))
            || !TEST_true(BN_mod_exp_simple(a, e, p, m, ctx))
            || !TEST_BN_eq(a, d))
        goto err;
    st = 1;
err:
    BN_MONT_CTX_free(mont);
    BN_free(a);
    BN_free(p);
    BN_free(m);
    BN_free(d);
    BN_free(e);
    BN_free(b);
    BN_free(n);
    BN_free(c);
    return st;
}
['static int test_modexp_mont5(void)\n{\n    BIGNUM *a = NULL, *p = NULL, *m = NULL, *d = NULL, *e = NULL;\n    BIGNUM *b = NULL, *n = NULL, *c = NULL;\n    BN_MONT_CTX *mont = NULL;\n    int st = 0;\n    if (!TEST_ptr(a = BN_new())\n            || !TEST_ptr(p = BN_new())\n            || !TEST_ptr(m = BN_new())\n            || !TEST_ptr(d = BN_new())\n            || !TEST_ptr(e = BN_new())\n            || !TEST_ptr(b = BN_new())\n            || !TEST_ptr(n = BN_new())\n            || !TEST_ptr(c = BN_new())\n            || !TEST_ptr(mont = BN_MONT_CTX_new()))\n        goto err;\n    BN_bntest_rand(m, 1024, 0, 1);\n    BN_bntest_rand(a, 1024, 0, 0);\n    BN_zero(p);\n    if (!TEST_true(BN_mod_exp_mont_consttime(d, a, p, m, ctx, NULL)))\n        goto err;\n    if (!TEST_BN_eq_one(d))\n        goto err;\n    BN_hex2bn(&a,\n        "7878787878787878787878787878787878787878787878787878787878787878"\n        "7878787878787878787878787878787878787878787878787878787878787878"\n        "7878787878787878787878787878787878787878787878787878787878787878"\n        "7878787878787878787878787878787878787878787878787878787878787878");\n    BN_hex2bn(&b,\n        "095D72C08C097BA488C5E439C655A192EAFB6380073D8C2664668EDDB4060744"\n        "E16E57FB4EDB9AE10A0CEFCDC28A894F689A128379DB279D48A2E20849D68593"\n        "9B7803BCF46CEBF5C533FB0DD35B080593DE5472E3FE5DB951B8BFF9B4CB8F03"\n        "9CC638A5EE8CDD703719F8000E6A9F63BEED5F2FCD52FF293EA05A251BB4AB81");\n    BN_hex2bn(&n,\n        "D78AF684E71DB0C39CFF4E64FB9DB567132CB9C50CC98009FEB820B26F2DED9B"\n        "91B9B5E2B83AE0AE4EB4E0523CA726BFBE969B89FD754F674CE99118C3F2D1C5"\n        "D81FDC7C54E02B60262B241D53C040E99E45826ECA37A804668E690E1AFC1CA4"\n        "2C9A15D84D4954425F0B7642FC0BD9D7B24E2618D2DCC9B729D944BADACFDDAF");\n    BN_MONT_CTX_set(mont, n, ctx);\n    BN_mod_mul_montgomery(c, a, b, mont, ctx);\n    BN_mod_mul_montgomery(d, b, a, mont, ctx);\n    if (!TEST_BN_eq(c, d))\n        goto err;\n    parse_bigBN(&n, bn1strings);\n    parse_bigBN(&a, bn2strings);\n    BN_free(b);\n    b = BN_dup(a);\n    BN_MONT_CTX_set(mont, n, ctx);\n    BN_mod_mul_montgomery(c, a, a, mont, ctx);\n    BN_mod_mul_montgomery(d, a, b, mont, ctx);\n    if (!TEST_BN_eq(c, d))\n        goto err;\n    {\n        static const char *ahex[] = {\n                      "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",\n            "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",\n            "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",\n            "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",\n            "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8FFEADBCFC4DAE7FFF908E92820306B",\n            "9544D954000000006C0000000000000000000000000000000000000000000000",\n            "00000000000000000000FF030202FFFFF8FFEBDBCFC4DAE7FFF908E92820306B",\n            "9544D954000000006C000000FF0302030000000000FFFFFFFFFFFFFFFFFFFFFF",\n            "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF01FC00FF02FFFFFFFF",\n            "00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00FCFD",\n            "FCFFFFFFFFFF000000000000000000FF0302030000000000FFFFFFFFFFFFFFFF",\n            "FF00FCFDFDFF030202FF00000000FFFFFFFFFFFFFFFFFF00FCFDFCFFFFFFFFFF",\n            NULL\n        };\n        static const char *nhex[] = {\n                      "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",\n            "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",\n            "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",\n            "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",\n            "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8F8F8F8000000",\n            "00000010000000006C0000000000000000000000000000000000000000000000",\n            "00000000000000000000000000000000000000FFFFFFFFFFFFF8F8F8F8000000",\n            "00000010000000006C000000000000000000000000FFFFFFFFFFFFFFFFFFFFFF",\n            "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",\n            "00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",\n            "FFFFFFFFFFFF000000000000000000000000000000000000FFFFFFFFFFFFFFFF",\n            "FFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",\n            NULL\n        };\n        parse_bigBN(&a, ahex);\n        parse_bigBN(&n, nhex);\n    }\n    BN_free(b);\n    b = BN_dup(a);\n    BN_MONT_CTX_set(mont, n, ctx);\n    BN_mod_mul_montgomery(c, a, a, mont, ctx);\n    BN_mod_mul_montgomery(d, a, b, mont, ctx);\n    if (!TEST_BN_eq(c, d))\n        goto err;\n    BN_hex2bn(&a,\n        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"\n        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"\n        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"\n        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2020202020DF");\n    BN_hex2bn(&b,\n        "2020202020202020202020202020202020202020202020202020202020202020"\n        "2020202020202020202020202020202020202020202020202020202020202020"\n        "20202020202020FF202020202020202020202020202020202020202020202020"\n        "2020202020202020202020202020202020202020202020202020202020202020");\n    BN_hex2bn(&n,\n        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"\n        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"\n        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"\n        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2020202020FF");\n    BN_MONT_CTX_set(mont, n, ctx);\n    BN_mod_exp_mont_consttime(c, a, b, n, ctx, mont);\n    BN_mod_exp_mont(d, a, b, n, ctx, mont);\n    if (!TEST_BN_eq(c, d))\n        goto err;\n    BN_bntest_rand(p, 1024, 0, 0);\n    BN_zero(a);\n    if (!TEST_true(BN_mod_exp_mont_consttime(d, a, p, m, ctx, NULL))\n            || !TEST_BN_eq_zero(d))\n        goto err;\n    BN_one(a);\n    BN_MONT_CTX_set(mont, m, ctx);\n    if (!TEST_true(BN_from_montgomery(e, a, mont, ctx))\n            || !TEST_true(BN_mod_exp_mont_consttime(d, e, p, m, ctx, NULL))\n            || !TEST_true(BN_mod_exp_simple(a, e, p, m, ctx))\n            || !TEST_BN_eq(a, d))\n        goto err;\n    BN_bntest_rand(e, 1024, 0, 0);\n    if (!TEST_true(BN_mod_exp_mont_consttime(d, e, p, m, ctx, NULL))\n            || !TEST_true(BN_mod_exp_simple(a, e, p, m, ctx))\n            || !TEST_BN_eq(a, d))\n        goto err;\n    st = 1;\nerr:\n    BN_MONT_CTX_free(mont);\n    BN_free(a);\n    BN_free(p);\n    BN_free(m);\n    BN_free(d);\n    BN_free(e);\n    BN_free(b);\n    BN_free(n);\n    BN_free(c);\n    return st;\n}', 'int test_ptr(const char *file, int line, const char *s, const void *p)\n{\n    if (p != NULL)\n        return 1;\n    test_fail_message(NULL, file, line, "ptr", s, "NULL", "!=", "%p", p);\n    return 0;\n}', 'BN_MONT_CTX *BN_MONT_CTX_new(void)\n{\n    BN_MONT_CTX *ret;\n    if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL)\n        return NULL;\n    BN_MONT_CTX_init(ret);\n    ret->flags = BN_FLG_MALLOCED;\n    return ret;\n}', 'void *CRYPTO_malloc(size_t num, const char *file, int line)\n{\n    void *ret = NULL;\n    INCREMENT(malloc_count);\n    if (malloc_impl != NULL && malloc_impl != CRYPTO_malloc)\n        return malloc_impl(num, file, line);\n    if (num == 0)\n        return NULL;\n    FAILTEST();\n    if (allow_customize) {\n        allow_customize = 0;\n    }\n#ifndef OPENSSL_NO_CRYPTO_MDEBUG\n    if (call_malloc_debug) {\n        CRYPTO_mem_debug_malloc(NULL, num, 0, file, line);\n        ret = malloc(num);\n        CRYPTO_mem_debug_malloc(ret, num, 1, file, line);\n    } else {\n        ret = malloc(num);\n    }\n#else\n    (void)(file); (void)(line);\n    ret = malloc(num);\n#endif\n    return ret;\n}', 'void BN_MONT_CTX_init(BN_MONT_CTX *ctx)\n{\n    ctx->ri = 0;\n    bn_init(&(ctx->RR));\n    bn_init(&(ctx->N));\n    bn_init(&(ctx->Ni));\n    ctx->n0[0] = ctx->n0[1] = 0;\n    ctx->flags = 0;\n}', 'int BN_bntest_rand(BIGNUM *rnd, int bits, int top, int bottom)\n{\n    return bnrand(TESTING, rnd, bits, top, bottom);\n}', 'int test_true(const char *file, int line, const char *s, int b)\n{\n    if (b)\n        return 1;\n    test_fail_message(NULL, file, line, "bool", s, "true", "==", "false");\n    return 0;\n}', 'int test_BN_eq_one(const char *file, int line, const char *s, const BIGNUM *a)\n{\n    if (a != NULL && BN_is_one(a))\n        return 1;\n    test_fail_bignum_mono_message(NULL, file, line, "BIGNUM", s, "1", "==", a);\n    return 0;\n}', 'int BN_is_one(const BIGNUM *a)\n{\n    return BN_abs_is_word(a, 1) && !a->neg;\n}', 'int BN_abs_is_word(const BIGNUM *a, const BN_ULONG w)\n{\n    return ((a->top == 1) && (a->d[0] == w)) || ((w == 0) && (a->top == 0));\n}', 'void test_fail_bignum_mono_message(const char *prefix, const char *file,\n                                   int line, const char *type,\n                                   const char *left, const char *right,\n                                   const char *op, const BIGNUM *bn)\n{\n    test_fail_bignum_common(prefix, file, line, type, left, right, op, bn, bn);\n    test_printf_stderr("\\n");\n}', 'void BN_MONT_CTX_free(BN_MONT_CTX *mont)\n{\n    BN_clear_free(&(mont->RR));\n    BN_clear_free(&(mont->N));\n    BN_clear_free(&(mont->Ni));\n    if (mont->flags & BN_FLG_MALLOCED)\n        OPENSSL_free(mont);\n}']