test/bntest.c:1135: error: BUFFER_OVERRUN_L3
  Offset: [8, +oo] (⇐ [8, +oo] + [0, +oo]) Size: [0, 8388607] by call to `BN_mod_exp_mont_consttime`.
Showing all 23 steps of the trace


test/bntest.c:1131:5: Call
1129.       mont = BN_MONT_CTX_new();
1130.   
1131.       BN_bntest_rand(m, 1024, 0, 1); /* must be odd for montgomery */
            ^
1132.       /* Zero exponent */
1133.       BN_bntest_rand(a, 1024, 0, 0);

crypto/bn/bn_rand.c:210:1: Parameter `*rnd->d`
  208.   }
  209.   
  210. > int BN_bntest_rand(BIGNUM *rnd, int bits, int top, int bottom)
  211.   {
  212.       return bnrand(2, rnd, bits, top, bottom);

crypto/bn/bn_rand.c:212:12: Call
  210.   int BN_bntest_rand(BIGNUM *rnd, int bits, int top, int bottom)
  211.   {
  212.       return bnrand(2, rnd, bits, top, bottom);
                    ^
  213.   }
  214.   

crypto/bn/bn_rand.c:119:1: Parameter `*rnd->d`
    117.   #include <openssl/sha.h>
    118.   
    119. > static int bnrand(int pseudorand, BIGNUM *rnd, int bits, int top, int bottom)
    120.   {
    121.       unsigned char *buf = NULL;

test/bntest.c:1135:10: Call
1133.       BN_bntest_rand(a, 1024, 0, 0);
1134.       BN_zero(p);
1135.       if (!BN_mod_exp_mont_consttime(d, a, p, m, ctx, NULL))
                 ^
1136.           return 0;
1137.       if (!BN_is_one(d)) {

crypto/bn/bn_exp.c:655:1: Parameter `*a->d`
  653.    * http://www.daemonology.net/hyperthreading-considered-harmful/)
  654.    */
  655. > int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
  656.                                 const BIGNUM *m, BN_CTX *ctx,
  657.                                 BN_MONT_CTX *in_mont)

crypto/bn/bn_exp.c:812:17: Call
  810.           if (!BN_to_montgomery(&am, &am, mont, ctx))
  811.               goto err;
  812.       } else if (!BN_to_montgomery(&am, a, mont, ctx))
                         ^
  813.           goto err;
  814.   

crypto/bn/bn_lib.c:924:1: Parameter `*a->d`
    922.   }
    923.   
    924. > int BN_to_montgomery(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont,
    925.                        BN_CTX *ctx)
    926.   {

crypto/bn/bn_lib.c:927:12: Call
    925.                        BN_CTX *ctx)
    926.   {
    927.       return BN_mod_mul_montgomery(r, a, &(mont->RR), mont, ctx);
                      ^
    928.   }
    929.   

crypto/bn/bn_mont.c:128:1: Parameter `*a->d`
      126.   #endif
      127.   
      128. > int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
      129.                             BN_MONT_CTX *mont, BN_CTX *ctx)
      130.   {

crypto/bn/bn_mont.c:158:14: Call
      156.               goto err;
      157.       } else {
      158.           if (!BN_mul(tmp, a, b, ctx))
                          ^
      159.               goto err;
      160.       }

crypto/bn/bn_mul.c:883:1: Parameter `*a->d`
        881.   #endif                          /* BN_RECURSION */
        882.   
        883. > int BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
        884.   {
        885.       int ret = 0;

crypto/bn/bn_mul.c:964:17: Call
        962.                   if (bn_wexpand(rr, k * 4) == NULL)
        963.                       goto err;
        964.                   bn_mul_part_recursive(rr->d, a->d, b->d,
                               ^
        965.                                         j, al - j, bl - j, t->d);
        966.               } else {            /* al <= j || bl <= j */

crypto/bn/bn_mul.c:534:1: Parameter `n`
          532.    */
          533.   /* tnX may not be negative but less than n */
          534. > void bn_mul_part_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n,
          535.                              int tna, int tnb, BN_ULONG *t)
          536.   {

crypto/bn/bn_mul.c:547:10: Call
          545.   
          546.       /* r=(a[0]-a[1])*(b[1]-b[0]) */
          547.       c1 = bn_cmp_part_words(a, &(a[n]), tna, n - tna);
                          ^
          548.       c2 = bn_cmp_part_words(&(b[n]), b, tnb, tnb - n);
          549.       neg = 0;

crypto/bn/bn_lib.c:782:1: Parameter `cl`
            780.    */
            781.   
            782. > int bn_cmp_part_words(const BN_ULONG *a, const BN_ULONG *b, int cl, int dl)
            783.   {
            784.       int n, i;

crypto/bn/bn_lib.c:799:12: Call
            797.           }
            798.       }
            799.       return bn_cmp_words(a, b, cl);
                              ^
            800.   }
            801.   

crypto/bn/bn_lib.c:755:1: <Offset trace>
753.   }
754.   
755. > int bn_cmp_words(const BN_ULONG *a, const BN_ULONG *b, int n)
756.   {
757.       int i;

crypto/bn/bn_lib.c:755:1: Parameter `n`
              753.   }
              754.   
              755. > int bn_cmp_words(const BN_ULONG *a, const BN_ULONG *b, int n)
              756.   {
              757.       int i;

crypto/bn/bn_lib.c:764:10: Assignment
              762.       if (aa != bb)
              763.           return ((aa > bb) ? 1 : -1);
              764.       for (i = n - 2; i >= 0; i--) {
                              ^
              765.           aa = a[i];
              766.           bb = b[i];

crypto/bn/bn_lib.c:755:1: <Length trace>
753.   }
754.   
755. > int bn_cmp_words(const BN_ULONG *a, const BN_ULONG *b, int n)
756.   {
757.       int i;

crypto/bn/bn_lib.c:755:1: Parameter `*b`
              753.   }
              754.   
              755. > int bn_cmp_words(const BN_ULONG *a, const BN_ULONG *b, int n)
              756.   {
              757.       int i;

crypto/bn/bn_lib.c:766:14: Array access: Offset: [8, +oo] (⇐ [8, +oo] + [0, +oo]) Size: [0, 8388607] by call to `BN_mod_exp_mont_consttime` 
              764.       for (i = n - 2; i >= 0; i--) {
              765.           aa = a[i];
              766.           bb = b[i];
                                  ^
              767.           if (aa != bb)
              768.               return ((aa > bb) ? 1 : -1);

int bn_cmp_words(const BN_ULONG *a, const BN_ULONG *b, int n)
{
    int i;
    BN_ULONG aa, bb;
    aa = a[n - 1];
    bb = b[n - 1];
    if (aa != bb)
        return ((aa > bb) ? 1 : -1);
    for (i = n - 2; i >= 0; i--) {
        aa = a[i];
        bb = b[i];
        if (aa != bb)
            return ((aa > bb) ? 1 : -1);
    }
    return (0);
}
['int test_mod_exp_mont5(BIO *bp, BN_CTX *ctx)\n{\n    BIGNUM *a, *p, *m, *d, *e;\n    BN_MONT_CTX *mont;\n    a = BN_new();\n    p = BN_new();\n    m = BN_new();\n    d = BN_new();\n    e = BN_new();\n    mont = BN_MONT_CTX_new();\n    BN_bntest_rand(m, 1024, 0, 1);\n    BN_bntest_rand(a, 1024, 0, 0);\n    BN_zero(p);\n    if (!BN_mod_exp_mont_consttime(d, a, p, m, ctx, NULL))\n        return 0;\n    if (!BN_is_one(d)) {\n        fprintf(stderr, "Modular exponentiation test failed!\\n");\n        return 0;\n    }\n    BN_bntest_rand(p, 1024, 0, 0);\n    BN_zero(a);\n    if (!BN_mod_exp_mont_consttime(d, a, p, m, ctx, NULL))\n        return 0;\n    if (!BN_is_zero(d)) {\n        fprintf(stderr, "Modular exponentiation test failed!\\n");\n        return 0;\n    }\n    BN_one(a);\n    BN_MONT_CTX_set(mont, m, ctx);\n    if (!BN_from_montgomery(e, a, mont, ctx))\n        return 0;\n    if (!BN_mod_exp_mont_consttime(d, e, p, m, ctx, NULL))\n        return 0;\n    if (!BN_mod_exp_simple(a, e, p, m, ctx))\n        return 0;\n    if (BN_cmp(a, d) != 0) {\n        fprintf(stderr, "Modular exponentiation test failed!\\n");\n        return 0;\n    }\n    BN_bntest_rand(e, 1024, 0, 0);\n    if (!BN_mod_exp_mont_consttime(d, e, p, m, ctx, NULL))\n        return 0;\n    if (!BN_mod_exp_simple(a, e, p, m, ctx))\n        return 0;\n    if (BN_cmp(a, d) != 0) {\n        fprintf(stderr, "Modular exponentiation test failed!\\n");\n        return 0;\n    }\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    return (1);\n}', 'int BN_bntest_rand(BIGNUM *rnd, int bits, int top, int bottom)\n{\n    return bnrand(2, rnd, bits, top, bottom);\n}', 'static int bnrand(int pseudorand, BIGNUM *rnd, int bits, int top, int bottom)\n{\n    unsigned char *buf = NULL;\n    int ret = 0, bit, bytes, mask;\n    time_t tim;\n    if (bits < 0 || (bits == 1 && top > 0)) {\n        BNerr(BN_F_BNRAND, BN_R_BITS_TOO_SMALL);\n        return 0;\n    }\n    if (bits == 0) {\n        BN_zero(rnd);\n        return 1;\n    }\n    bytes = (bits + 7) / 8;\n    bit = (bits - 1) % 8;\n    mask = 0xff << (bit + 1);\n    buf = OPENSSL_malloc(bytes);\n    if (buf == NULL) {\n        BNerr(BN_F_BNRAND, ERR_R_MALLOC_FAILURE);\n        goto err;\n    }\n    time(&tim);\n    RAND_add(&tim, sizeof(tim), 0.0);\n    if (pseudorand) {\n        if (RAND_bytes(buf, bytes) <= 0)\n            goto err;\n    } else {\n        if (RAND_bytes(buf, bytes) <= 0)\n            goto err;\n    }\n    if (pseudorand == 2) {\n        int i;\n        unsigned char c;\n        for (i = 0; i < bytes; i++) {\n            if (RAND_bytes(&c, 1) <= 0)\n                goto err;\n            if (c >= 128 && i > 0)\n                buf[i] = buf[i - 1];\n            else if (c < 42)\n                buf[i] = 0;\n            else if (c < 84)\n                buf[i] = 255;\n        }\n    }\n    if (top >= 0) {\n        if (top) {\n            if (bit == 0) {\n                buf[0] = 1;\n                buf[1] |= 0x80;\n            } else {\n                buf[0] |= (3 << (bit - 1));\n            }\n        } else {\n            buf[0] |= (1 << bit);\n        }\n    }\n    buf[0] &= ~mask;\n    if (bottom)\n        buf[bytes - 1] |= 1;\n    if (!BN_bin2bn(buf, bytes, rnd))\n        goto err;\n    ret = 1;\n err:\n    OPENSSL_clear_free(buf, bytes);\n    bn_check_top(rnd);\n    return (ret);\n}', 'int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,\n                              const BIGNUM *m, BN_CTX *ctx,\n                              BN_MONT_CTX *in_mont)\n{\n    int i, bits, ret = 0, window, wvalue;\n    int top;\n    BN_MONT_CTX *mont = NULL;\n    int numPowers;\n    unsigned char *powerbufFree = NULL;\n    int powerbufLen = 0;\n    unsigned char *powerbuf = NULL;\n    BIGNUM tmp, am;\n#if defined(SPARC_T4_MONT)\n    unsigned int t4 = 0;\n#endif\n    bn_check_top(a);\n    bn_check_top(p);\n    bn_check_top(m);\n    if (!BN_is_odd(m)) {\n        BNerr(BN_F_BN_MOD_EXP_MONT_CONSTTIME, BN_R_CALLED_WITH_EVEN_MODULUS);\n        return (0);\n    }\n    top = m->top;\n    bits = BN_num_bits(p);\n    if (bits == 0) {\n        if (BN_is_one(m)) {\n            ret = 1;\n            BN_zero(rr);\n        } else {\n            ret = BN_one(rr);\n        }\n        return ret;\n    }\n    BN_CTX_start(ctx);\n    if (in_mont != NULL)\n        mont = in_mont;\n    else {\n        if ((mont = BN_MONT_CTX_new()) == NULL)\n            goto err;\n        if (!BN_MONT_CTX_set(mont, m, ctx))\n            goto err;\n    }\n#ifdef RSAZ_ENABLED\n    if ((16 == a->top) && (16 == p->top) && (BN_num_bits(m) == 1024)\n        && rsaz_avx2_eligible()) {\n        if (NULL == bn_wexpand(rr, 16))\n            goto err;\n        RSAZ_1024_mod_exp_avx2(rr->d, a->d, p->d, m->d, mont->RR.d,\n                               mont->n0[0]);\n        rr->top = 16;\n        rr->neg = 0;\n        bn_correct_top(rr);\n        ret = 1;\n        goto err;\n    } else if ((8 == a->top) && (8 == p->top) && (BN_num_bits(m) == 512)) {\n        if (NULL == bn_wexpand(rr, 8))\n            goto err;\n        RSAZ_512_mod_exp(rr->d, a->d, p->d, m->d, mont->n0[0], mont->RR.d);\n        rr->top = 8;\n        rr->neg = 0;\n        bn_correct_top(rr);\n        ret = 1;\n        goto err;\n    }\n#endif\n    window = BN_window_bits_for_ctime_exponent_size(bits);\n#if defined(SPARC_T4_MONT)\n    if (window >= 5 && (top & 15) == 0 && top <= 64 &&\n        (OPENSSL_sparcv9cap_P[1] & (CFR_MONTMUL | CFR_MONTSQR)) ==\n        (CFR_MONTMUL | CFR_MONTSQR) && (t4 = OPENSSL_sparcv9cap_P[0]))\n        window = 5;\n    else\n#endif\n#if defined(OPENSSL_BN_ASM_MONT5)\n    if (window >= 5) {\n        window = 5;\n        if ((top & 7) == 0)\n            powerbufLen += 2 * top * sizeof(m->d[0]);\n    }\n#endif\n    (void)0;\n    numPowers = 1 << window;\n    powerbufLen += sizeof(m->d[0]) * (top * numPowers +\n                                      ((2 * top) >\n                                       numPowers ? (2 * top) : numPowers));\n#ifdef alloca\n    if (powerbufLen < 3072)\n        powerbufFree =\n            alloca(powerbufLen + MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH);\n    else\n#endif\n        if ((powerbufFree =\n             OPENSSL_malloc(powerbufLen + MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH))\n            == NULL)\n        goto err;\n    powerbuf = MOD_EXP_CTIME_ALIGN(powerbufFree);\n    memset(powerbuf, 0, powerbufLen);\n#ifdef alloca\n    if (powerbufLen < 3072)\n        powerbufFree = NULL;\n#endif\n    tmp.d = (BN_ULONG *)(powerbuf + sizeof(m->d[0]) * top * numPowers);\n    am.d = tmp.d + top;\n    tmp.top = am.top = 0;\n    tmp.dmax = am.dmax = top;\n    tmp.neg = am.neg = 0;\n    tmp.flags = am.flags = BN_FLG_STATIC_DATA;\n#if 1\n    if (m->d[top - 1] & (((BN_ULONG)1) << (BN_BITS2 - 1))) {\n        tmp.d[0] = (0 - m->d[0]) & BN_MASK2;\n        for (i = 1; i < top; i++)\n            tmp.d[i] = (~m->d[i]) & BN_MASK2;\n        tmp.top = top;\n    } else\n#endif\n    if (!BN_to_montgomery(&tmp, BN_value_one(), mont, ctx))\n        goto err;\n    if (a->neg || BN_ucmp(a, m) >= 0) {\n        if (!BN_mod(&am, a, m, ctx))\n            goto err;\n        if (!BN_to_montgomery(&am, &am, mont, ctx))\n            goto err;\n    } else if (!BN_to_montgomery(&am, a, mont, ctx))\n        goto err;\n#if defined(SPARC_T4_MONT)\n    if (t4) {\n        typedef int (*bn_pwr5_mont_f) (BN_ULONG *tp, const BN_ULONG *np,\n                                       const BN_ULONG *n0, const void *table,\n                                       int power, int bits);\n        int bn_pwr5_mont_t4_8(BN_ULONG *tp, const BN_ULONG *np,\n                              const BN_ULONG *n0, const void *table,\n                              int power, int bits);\n        int bn_pwr5_mont_t4_16(BN_ULONG *tp, const BN_ULONG *np,\n                               const BN_ULONG *n0, const void *table,\n                               int power, int bits);\n        int bn_pwr5_mont_t4_24(BN_ULONG *tp, const BN_ULONG *np,\n                               const BN_ULONG *n0, const void *table,\n                               int power, int bits);\n        int bn_pwr5_mont_t4_32(BN_ULONG *tp, const BN_ULONG *np,\n                               const BN_ULONG *n0, const void *table,\n                               int power, int bits);\n        static const bn_pwr5_mont_f pwr5_funcs[4] = {\n            bn_pwr5_mont_t4_8, bn_pwr5_mont_t4_16,\n            bn_pwr5_mont_t4_24, bn_pwr5_mont_t4_32\n        };\n        bn_pwr5_mont_f pwr5_worker = pwr5_funcs[top / 16 - 1];\n        typedef int (*bn_mul_mont_f) (BN_ULONG *rp, const BN_ULONG *ap,\n                                      const void *bp, const BN_ULONG *np,\n                                      const BN_ULONG *n0);\n        int bn_mul_mont_t4_8(BN_ULONG *rp, const BN_ULONG *ap, const void *bp,\n                             const BN_ULONG *np, const BN_ULONG *n0);\n        int bn_mul_mont_t4_16(BN_ULONG *rp, const BN_ULONG *ap,\n                              const void *bp, const BN_ULONG *np,\n                              const BN_ULONG *n0);\n        int bn_mul_mont_t4_24(BN_ULONG *rp, const BN_ULONG *ap,\n                              const void *bp, const BN_ULONG *np,\n                              const BN_ULONG *n0);\n        int bn_mul_mont_t4_32(BN_ULONG *rp, const BN_ULONG *ap,\n                              const void *bp, const BN_ULONG *np,\n                              const BN_ULONG *n0);\n        static const bn_mul_mont_f mul_funcs[4] = {\n            bn_mul_mont_t4_8, bn_mul_mont_t4_16,\n            bn_mul_mont_t4_24, bn_mul_mont_t4_32\n        };\n        bn_mul_mont_f mul_worker = mul_funcs[top / 16 - 1];\n        void bn_mul_mont_vis3(BN_ULONG *rp, const BN_ULONG *ap,\n                              const void *bp, const BN_ULONG *np,\n                              const BN_ULONG *n0, int num);\n        void bn_mul_mont_t4(BN_ULONG *rp, const BN_ULONG *ap,\n                            const void *bp, const BN_ULONG *np,\n                            const BN_ULONG *n0, int num);\n        void bn_mul_mont_gather5_t4(BN_ULONG *rp, const BN_ULONG *ap,\n                                    const void *table, const BN_ULONG *np,\n                                    const BN_ULONG *n0, int num, int power);\n        void bn_flip_n_scatter5_t4(const BN_ULONG *inp, size_t num,\n                                   void *table, size_t power);\n        void bn_gather5_t4(BN_ULONG *out, size_t num,\n                           void *table, size_t power);\n        void bn_flip_t4(BN_ULONG *dst, BN_ULONG *src, size_t num);\n        BN_ULONG *np = mont->N.d, *n0 = mont->n0;\n        int stride = 5 * (6 - (top / 16 - 1));\n        for (i = am.top; i < top; i++)\n            am.d[i] = 0;\n        for (i = tmp.top; i < top; i++)\n            tmp.d[i] = 0;\n        bn_flip_n_scatter5_t4(tmp.d, top, powerbuf, 0);\n        bn_flip_n_scatter5_t4(am.d, top, powerbuf, 1);\n        if (!(*mul_worker) (tmp.d, am.d, am.d, np, n0) &&\n            !(*mul_worker) (tmp.d, am.d, am.d, np, n0))\n            bn_mul_mont_vis3(tmp.d, am.d, am.d, np, n0, top);\n        bn_flip_n_scatter5_t4(tmp.d, top, powerbuf, 2);\n        for (i = 3; i < 32; i++) {\n            if (!(*mul_worker) (tmp.d, tmp.d, am.d, np, n0) &&\n                !(*mul_worker) (tmp.d, tmp.d, am.d, np, n0))\n                bn_mul_mont_vis3(tmp.d, tmp.d, am.d, np, n0, top);\n            bn_flip_n_scatter5_t4(tmp.d, top, powerbuf, i);\n        }\n        np = alloca(top * sizeof(BN_ULONG));\n        top /= 2;\n        bn_flip_t4(np, mont->N.d, top);\n        bits--;\n        for (wvalue = 0, i = bits % 5; i >= 0; i--, bits--)\n            wvalue = (wvalue << 1) + BN_is_bit_set(p, bits);\n        bn_gather5_t4(tmp.d, top, powerbuf, wvalue);\n        while (bits >= 0) {\n            if (bits < stride)\n                stride = bits + 1;\n            bits -= stride;\n            wvalue = bn_get_bits(p, bits + 1);\n            if ((*pwr5_worker) (tmp.d, np, n0, powerbuf, wvalue, stride))\n                continue;\n            if ((*pwr5_worker) (tmp.d, np, n0, powerbuf, wvalue, stride))\n                continue;\n            bits += stride - 5;\n            wvalue >>= stride - 5;\n            wvalue &= 31;\n            bn_mul_mont_t4(tmp.d, tmp.d, tmp.d, np, n0, top);\n            bn_mul_mont_t4(tmp.d, tmp.d, tmp.d, np, n0, top);\n            bn_mul_mont_t4(tmp.d, tmp.d, tmp.d, np, n0, top);\n            bn_mul_mont_t4(tmp.d, tmp.d, tmp.d, np, n0, top);\n            bn_mul_mont_t4(tmp.d, tmp.d, tmp.d, np, n0, top);\n            bn_mul_mont_gather5_t4(tmp.d, tmp.d, powerbuf, np, n0, top,\n                                   wvalue);\n        }\n        bn_flip_t4(tmp.d, tmp.d, top);\n        top *= 2;\n        tmp.top = top;\n        bn_correct_top(&tmp);\n        OPENSSL_cleanse(np, top * sizeof(BN_ULONG));\n    } else\n#endif\n#if defined(OPENSSL_BN_ASM_MONT5)\n    if (window == 5 && top > 1) {\n        void bn_mul_mont_gather5(BN_ULONG *rp, const BN_ULONG *ap,\n                                 const void *table, const BN_ULONG *np,\n                                 const BN_ULONG *n0, int num, int power);\n        void bn_scatter5(const BN_ULONG *inp, size_t num,\n                         void *table, size_t power);\n        void bn_gather5(BN_ULONG *out, size_t num, void *table, size_t power);\n        void bn_power5(BN_ULONG *rp, const BN_ULONG *ap,\n                       const void *table, const BN_ULONG *np,\n                       const BN_ULONG *n0, int num, int power);\n        int bn_get_bits5(const BN_ULONG *ap, int off);\n        int bn_from_montgomery(BN_ULONG *rp, const BN_ULONG *ap,\n                               const BN_ULONG *not_used, const BN_ULONG *np,\n                               const BN_ULONG *n0, int num);\n        BN_ULONG *np = mont->N.d, *n0 = mont->n0, *np2;\n        for (i = am.top; i < top; i++)\n            am.d[i] = 0;\n        for (i = tmp.top; i < top; i++)\n            tmp.d[i] = 0;\n        if (top & 7)\n            np2 = np;\n        else\n            for (np2 = am.d + top, i = 0; i < top; i++)\n                np2[2 * i] = np[i];\n        bn_scatter5(tmp.d, top, powerbuf, 0);\n        bn_scatter5(am.d, am.top, powerbuf, 1);\n        bn_mul_mont(tmp.d, am.d, am.d, np, n0, top);\n        bn_scatter5(tmp.d, top, powerbuf, 2);\n# if 0\n        for (i = 3; i < 32; i++) {\n            bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np2, n0, top, i - 1);\n            bn_scatter5(tmp.d, top, powerbuf, i);\n        }\n# else\n        for (i = 4; i < 32; i *= 2) {\n            bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top);\n            bn_scatter5(tmp.d, top, powerbuf, i);\n        }\n        for (i = 3; i < 8; i += 2) {\n            int j;\n            bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np2, n0, top, i - 1);\n            bn_scatter5(tmp.d, top, powerbuf, i);\n            for (j = 2 * i; j < 32; j *= 2) {\n                bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top);\n                bn_scatter5(tmp.d, top, powerbuf, j);\n            }\n        }\n        for (; i < 16; i += 2) {\n            bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np2, n0, top, i - 1);\n            bn_scatter5(tmp.d, top, powerbuf, i);\n            bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top);\n            bn_scatter5(tmp.d, top, powerbuf, 2 * i);\n        }\n        for (; i < 32; i += 2) {\n            bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np2, n0, top, i - 1);\n            bn_scatter5(tmp.d, top, powerbuf, i);\n        }\n# endif\n        bits--;\n        for (wvalue = 0, i = bits % 5; i >= 0; i--, bits--)\n            wvalue = (wvalue << 1) + BN_is_bit_set(p, bits);\n        bn_gather5(tmp.d, top, powerbuf, wvalue);\n        if (top & 7)\n            while (bits >= 0) {\n                for (wvalue = 0, i = 0; i < 5; i++, bits--)\n                    wvalue = (wvalue << 1) + BN_is_bit_set(p, bits);\n                bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top);\n                bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top);\n                bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top);\n                bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top);\n                bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top);\n                bn_mul_mont_gather5(tmp.d, tmp.d, powerbuf, np, n0, top,\n                                    wvalue);\n        } else {\n            while (bits >= 0) {\n                wvalue = bn_get_bits5(p->d, bits - 4);\n                bits -= 5;\n                bn_power5(tmp.d, tmp.d, powerbuf, np2, n0, top, wvalue);\n            }\n        }\n        ret = bn_from_montgomery(tmp.d, tmp.d, NULL, np2, n0, top);\n        tmp.top = top;\n        bn_correct_top(&tmp);\n        if (ret) {\n            if (!BN_copy(rr, &tmp))\n                ret = 0;\n            goto err;\n        }\n    } else\n#endif\n    {\n        if (!MOD_EXP_CTIME_COPY_TO_PREBUF(&tmp, top, powerbuf, 0, numPowers))\n            goto err;\n        if (!MOD_EXP_CTIME_COPY_TO_PREBUF(&am, top, powerbuf, 1, numPowers))\n            goto err;\n        if (window > 1) {\n            if (!BN_mod_mul_montgomery(&tmp, &am, &am, mont, ctx))\n                goto err;\n            if (!MOD_EXP_CTIME_COPY_TO_PREBUF\n                (&tmp, top, powerbuf, 2, numPowers))\n                goto err;\n            for (i = 3; i < numPowers; i++) {\n                if (!BN_mod_mul_montgomery(&tmp, &am, &tmp, mont, ctx))\n                    goto err;\n                if (!MOD_EXP_CTIME_COPY_TO_PREBUF\n                    (&tmp, top, powerbuf, i, numPowers))\n                    goto err;\n            }\n        }\n        bits--;\n        for (wvalue = 0, i = bits % window; i >= 0; i--, bits--)\n            wvalue = (wvalue << 1) + BN_is_bit_set(p, bits);\n        if (!MOD_EXP_CTIME_COPY_FROM_PREBUF\n            (&tmp, top, powerbuf, wvalue, numPowers))\n            goto err;\n        while (bits >= 0) {\n            wvalue = 0;\n            for (i = 0; i < window; i++, bits--) {\n                if (!BN_mod_mul_montgomery(&tmp, &tmp, &tmp, mont, ctx))\n                    goto err;\n                wvalue = (wvalue << 1) + BN_is_bit_set(p, bits);\n            }\n            if (!MOD_EXP_CTIME_COPY_FROM_PREBUF\n                (&am, top, powerbuf, wvalue, numPowers))\n                goto err;\n            if (!BN_mod_mul_montgomery(&tmp, &tmp, &am, mont, ctx))\n                goto err;\n        }\n    }\n#if defined(SPARC_T4_MONT)\n    if (OPENSSL_sparcv9cap_P[0] & (SPARCV9_VIS3 | SPARCV9_PREFER_FPU)) {\n        am.d[0] = 1;\n        for (i = 1; i < top; i++)\n            am.d[i] = 0;\n        if (!BN_mod_mul_montgomery(rr, &tmp, &am, mont, ctx))\n            goto err;\n    } else\n#endif\n    if (!BN_from_montgomery(rr, &tmp, mont, ctx))\n        goto err;\n    ret = 1;\n err:\n    if (in_mont == NULL)\n        BN_MONT_CTX_free(mont);\n    if (powerbuf != NULL) {\n        OPENSSL_cleanse(powerbuf, powerbufLen);\n        OPENSSL_free(powerbufFree);\n    }\n    BN_CTX_end(ctx);\n    return (ret);\n}', 'int BN_to_montgomery(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont,\n                     BN_CTX *ctx)\n{\n    return BN_mod_mul_montgomery(r, a, &(mont->RR), mont, ctx);\n}', 'int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,\n                          BN_MONT_CTX *mont, BN_CTX *ctx)\n{\n    BIGNUM *tmp;\n    int ret = 0;\n#if defined(OPENSSL_BN_ASM_MONT) && defined(MONT_WORD)\n    int num = mont->N.top;\n    if (num > 1 && a->top == num && b->top == num) {\n        if (bn_wexpand(r, num) == NULL)\n            return (0);\n        if (bn_mul_mont(r->d, a->d, b->d, mont->N.d, mont->n0, num)) {\n            r->neg = a->neg ^ b->neg;\n            r->top = num;\n            bn_correct_top(r);\n            return (1);\n        }\n    }\n#endif\n    BN_CTX_start(ctx);\n    tmp = BN_CTX_get(ctx);\n    if (tmp == NULL)\n        goto err;\n    bn_check_top(tmp);\n    if (a == b) {\n        if (!BN_sqr(tmp, a, ctx))\n            goto err;\n    } else {\n        if (!BN_mul(tmp, a, b, ctx))\n            goto err;\n    }\n#ifdef MONT_WORD\n    if (!BN_from_montgomery_word(r, tmp, mont))\n        goto err;\n#else\n    if (!BN_from_montgomery(r, tmp, mont, ctx))\n        goto err;\n#endif\n    bn_check_top(r);\n    ret = 1;\n err:\n    BN_CTX_end(ctx);\n    return (ret);\n}', 'int BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)\n{\n    int ret = 0;\n    int top, al, bl;\n    BIGNUM *rr;\n#if defined(BN_MUL_COMBA) || defined(BN_RECURSION)\n    int i;\n#endif\n#ifdef BN_RECURSION\n    BIGNUM *t = NULL;\n    int j = 0, k;\n#endif\n    bn_check_top(a);\n    bn_check_top(b);\n    bn_check_top(r);\n    al = a->top;\n    bl = b->top;\n    if ((al == 0) || (bl == 0)) {\n        BN_zero(r);\n        return (1);\n    }\n    top = al + bl;\n    BN_CTX_start(ctx);\n    if ((r == a) || (r == b)) {\n        if ((rr = BN_CTX_get(ctx)) == NULL)\n            goto err;\n    } else\n        rr = r;\n    rr->neg = a->neg ^ b->neg;\n#if defined(BN_MUL_COMBA) || defined(BN_RECURSION)\n    i = al - bl;\n#endif\n#ifdef BN_MUL_COMBA\n    if (i == 0) {\n# if 0\n        if (al == 4) {\n            if (bn_wexpand(rr, 8) == NULL)\n                goto err;\n            rr->top = 8;\n            bn_mul_comba4(rr->d, a->d, b->d);\n            goto end;\n        }\n# endif\n        if (al == 8) {\n            if (bn_wexpand(rr, 16) == NULL)\n                goto err;\n            rr->top = 16;\n            bn_mul_comba8(rr->d, a->d, b->d);\n            goto end;\n        }\n    }\n#endif\n#ifdef BN_RECURSION\n    if ((al >= BN_MULL_SIZE_NORMAL) && (bl >= BN_MULL_SIZE_NORMAL)) {\n        if (i >= -1 && i <= 1) {\n            if (i >= 0) {\n                j = BN_num_bits_word((BN_ULONG)al);\n            }\n            if (i == -1) {\n                j = BN_num_bits_word((BN_ULONG)bl);\n            }\n            j = 1 << (j - 1);\n            assert(j <= al || j <= bl);\n            k = j + j;\n            t = BN_CTX_get(ctx);\n            if (t == NULL)\n                goto err;\n            if (al > j || bl > j) {\n                if (bn_wexpand(t, k * 4) == NULL)\n                    goto err;\n                if (bn_wexpand(rr, k * 4) == NULL)\n                    goto err;\n                bn_mul_part_recursive(rr->d, a->d, b->d,\n                                      j, al - j, bl - j, t->d);\n            } else {\n                if (bn_wexpand(t, k * 2) == NULL)\n                    goto err;\n                if (bn_wexpand(rr, k * 2) == NULL)\n                    goto err;\n                bn_mul_recursive(rr->d, a->d, b->d, j, al - j, bl - j, t->d);\n            }\n            rr->top = top;\n            goto end;\n        }\n# if 0\n        if (i == 1 && !BN_get_flags(b, BN_FLG_STATIC_DATA)) {\n            BIGNUM *tmp_bn = (BIGNUM *)b;\n            if (bn_wexpand(tmp_bn, al) == NULL)\n                goto err;\n            tmp_bn->d[bl] = 0;\n            bl++;\n            i--;\n        } else if (i == -1 && !BN_get_flags(a, BN_FLG_STATIC_DATA)) {\n            BIGNUM *tmp_bn = (BIGNUM *)a;\n            if (bn_wexpand(tmp_bn, bl) == NULL)\n                goto err;\n            tmp_bn->d[al] = 0;\n            al++;\n            i++;\n        }\n        if (i == 0) {\n            j = BN_num_bits_word((BN_ULONG)al);\n            j = 1 << (j - 1);\n            k = j + j;\n            t = BN_CTX_get(ctx);\n            if (al == j) {\n                if (bn_wexpand(t, k * 2) == NULL)\n                    goto err;\n                if (bn_wexpand(rr, k * 2) == NULL)\n                    goto err;\n                bn_mul_recursive(rr->d, a->d, b->d, al, t->d);\n            } else {\n                if (bn_wexpand(t, k * 4) == NULL)\n                    goto err;\n                if (bn_wexpand(rr, k * 4) == NULL)\n                    goto err;\n                bn_mul_part_recursive(rr->d, a->d, b->d, al - j, j, t->d);\n            }\n            rr->top = top;\n            goto end;\n        }\n# endif\n    }\n#endif\n    if (bn_wexpand(rr, top) == NULL)\n        goto err;\n    rr->top = top;\n    bn_mul_normal(rr->d, a->d, al, b->d, bl);\n#if defined(BN_MUL_COMBA) || defined(BN_RECURSION)\n end:\n#endif\n    bn_correct_top(rr);\n    if (r != rr)\n        BN_copy(r, rr);\n    ret = 1;\n err:\n    bn_check_top(r);\n    BN_CTX_end(ctx);\n    return (ret);\n}', 'void bn_mul_part_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n,\n                           int tna, int tnb, BN_ULONG *t)\n{\n    int i, j, n2 = n * 2;\n    int c1, c2, neg;\n    BN_ULONG ln, lo, *p;\n    if (n < 8) {\n        bn_mul_normal(r, a, n + tna, b, n + tnb);\n        return;\n    }\n    c1 = bn_cmp_part_words(a, &(a[n]), tna, n - tna);\n    c2 = bn_cmp_part_words(&(b[n]), b, tnb, tnb - n);\n    neg = 0;\n    switch (c1 * 3 + c2) {\n    case -4:\n        bn_sub_part_words(t, &(a[n]), a, tna, tna - n);\n        bn_sub_part_words(&(t[n]), b, &(b[n]), tnb, n - tnb);\n        break;\n    case -3:\n    case -2:\n        bn_sub_part_words(t, &(a[n]), a, tna, tna - n);\n        bn_sub_part_words(&(t[n]), &(b[n]), b, tnb, tnb - n);\n        neg = 1;\n        break;\n    case -1:\n    case 0:\n    case 1:\n    case 2:\n        bn_sub_part_words(t, a, &(a[n]), tna, n - tna);\n        bn_sub_part_words(&(t[n]), b, &(b[n]), tnb, n - tnb);\n        neg = 1;\n        break;\n    case 3:\n    case 4:\n        bn_sub_part_words(t, a, &(a[n]), tna, n - tna);\n        bn_sub_part_words(&(t[n]), &(b[n]), b, tnb, tnb - n);\n        break;\n    }\n# if 0\n    if (n == 4) {\n        bn_mul_comba4(&(t[n2]), t, &(t[n]));\n        bn_mul_comba4(r, a, b);\n        bn_mul_normal(&(r[n2]), &(a[n]), tn, &(b[n]), tn);\n        memset(&r[n2 + tn * 2], 0, sizeof(*r) * (n2 - tn * 2));\n    } else\n# endif\n    if (n == 8) {\n        bn_mul_comba8(&(t[n2]), t, &(t[n]));\n        bn_mul_comba8(r, a, b);\n        bn_mul_normal(&(r[n2]), &(a[n]), tna, &(b[n]), tnb);\n        memset(&r[n2 + tna + tnb], 0, sizeof(*r) * (n2 - tna - tnb));\n    } else {\n        p = &(t[n2 * 2]);\n        bn_mul_recursive(&(t[n2]), t, &(t[n]), n, 0, 0, p);\n        bn_mul_recursive(r, a, b, n, 0, 0, p);\n        i = n / 2;\n        if (tna > tnb)\n            j = tna - i;\n        else\n            j = tnb - i;\n        if (j == 0) {\n            bn_mul_recursive(&(r[n2]), &(a[n]), &(b[n]),\n                             i, tna - i, tnb - i, p);\n            memset(&r[n2 + i * 2], 0, sizeof(*r) * (n2 - i * 2));\n        } else if (j > 0) {\n            bn_mul_part_recursive(&(r[n2]), &(a[n]), &(b[n]),\n                                  i, tna - i, tnb - i, p);\n            memset(&(r[n2 + tna + tnb]), 0,\n                   sizeof(BN_ULONG) * (n2 - tna - tnb));\n        } else {\n            memset(&r[n2], 0, sizeof(*r) * n2);\n            if (tna < BN_MUL_RECURSIVE_SIZE_NORMAL\n                && tnb < BN_MUL_RECURSIVE_SIZE_NORMAL) {\n                bn_mul_normal(&(r[n2]), &(a[n]), tna, &(b[n]), tnb);\n            } else {\n                for (;;) {\n                    i /= 2;\n                    if (i < tna || i < tnb) {\n                        bn_mul_part_recursive(&(r[n2]),\n                                              &(a[n]), &(b[n]),\n                                              i, tna - i, tnb - i, p);\n                        break;\n                    } else if (i == tna || i == tnb) {\n                        bn_mul_recursive(&(r[n2]),\n                                         &(a[n]), &(b[n]),\n                                         i, tna - i, tnb - i, p);\n                        break;\n                    }\n                }\n            }\n        }\n    }\n    c1 = (int)(bn_add_words(t, r, &(r[n2]), n2));\n    if (neg) {\n        c1 -= (int)(bn_sub_words(&(t[n2]), t, &(t[n2]), n2));\n    } else {\n        c1 += (int)(bn_add_words(&(t[n2]), &(t[n2]), t, n2));\n    }\n    c1 += (int)(bn_add_words(&(r[n]), &(r[n]), &(t[n2]), n2));\n    if (c1) {\n        p = &(r[n + n2]);\n        lo = *p;\n        ln = (lo + c1) & BN_MASK2;\n        *p = ln;\n        if (ln < (BN_ULONG)c1) {\n            do {\n                p++;\n                lo = *p;\n                ln = (lo + 1) & BN_MASK2;\n                *p = ln;\n            } while (ln == 0);\n        }\n    }\n}', 'int bn_cmp_part_words(const BN_ULONG *a, const BN_ULONG *b, int cl, int dl)\n{\n    int n, i;\n    n = cl - 1;\n    if (dl < 0) {\n        for (i = dl; i < 0; i++) {\n            if (b[n - i] != 0)\n                return -1;\n        }\n    }\n    if (dl > 0) {\n        for (i = dl; i > 0; i--) {\n            if (a[n + i] != 0)\n                return 1;\n        }\n    }\n    return bn_cmp_words(a, b, cl);\n}', 'int bn_cmp_words(const BN_ULONG *a, const BN_ULONG *b, int n)\n{\n    int i;\n    BN_ULONG aa, bb;\n    aa = a[n - 1];\n    bb = b[n - 1];\n    if (aa != bb)\n        return ((aa > bb) ? 1 : -1);\n    for (i = n - 2; i >= 0; i--) {\n        aa = a[i];\n        bb = b[i];\n        if (aa != bb)\n            return ((aa > bb) ? 1 : -1);\n    }\n    return (0);\n}']