crypto/rsa/rsa_ossl.c:888: error: BUFFER_OVERRUN_L3
  Offset: [8, +oo] (⇐ [8, +oo] + [0, +oo]) Size: [0, 8388607] by call to `BN_mod_exp_mont`.
Showing all 25 steps of the trace


crypto/rsa/rsa_ossl.c:687:17: Call
685.                                         ctx)
686.               /* r0 = r1 * q + m1 */
687.               || !bn_mul_fixed_top(r0, r1, rsa->q, ctx)
                       ^
688.               || !bn_mod_add_fixed_top(r0, r0, m1, rsa->n))
689.               goto err;

crypto/bn/bn_mul.c:507:1: Parameter `*r->d`
  505.   }
  506.   
  507. > int bn_mul_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
  508.   {
  509.       int ret = 0;

crypto/rsa/rsa_ossl.c:688:17: Call
686.               /* r0 = r1 * q + m1 */
687.               || !bn_mul_fixed_top(r0, r1, rsa->q, ctx)
688.               || !bn_mod_add_fixed_top(r0, r0, m1, rsa->n))
                       ^
689.               goto err;
690.   

crypto/bn/bn_mod.c:48:1: Parameter `*a->d`
  46.    * move depending on whether or not subtraction borrowed.
  47.    */
  48. > int bn_mod_add_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
  49.                            const BIGNUM *m)
  50.   {

crypto/rsa/rsa_ossl.c:888:18: Call
886.       if (rsa->e && rsa->n) {
887.           if (rsa->meth->bn_mod_exp == BN_mod_exp_mont) {
888.               if (!BN_mod_exp_mont(vrfy, r0, rsa->e, rsa->n, ctx,
                        ^
889.                                    rsa->_method_mod_n))
890.                   goto err;

crypto/bn/bn_exp.c:296:1: Parameter `*a->d`
  294.   }
  295.   
  296. > int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
  297.                       const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont)
  298.   {

crypto/bn/bn_exp.c:310:16: Call
  308.               || BN_get_flags(a, BN_FLG_CONSTTIME) != 0
  309.               || BN_get_flags(m, BN_FLG_CONSTTIME) != 0) {
  310.           return BN_mod_exp_mont_consttime(rr, a, p, m, ctx, in_mont);
                        ^
  311.       }
  312.   

crypto/bn/bn_exp.c:592:1: Parameter `*a->d`
    590.    * http://www.daemonology.net/hyperthreading-considered-harmful/)
    591.    */
    592. > int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
    593.                                 const BIGNUM *m, BN_CTX *ctx,
    594.                                 BN_MONT_CTX *in_mont)

crypto/bn/bn_exp.c:757:10: Call
    755.   
    756.       /* prepare a^1 in Montgomery domain */
    757.       if (!bn_to_mont_fixed_top(&am, a, mont, ctx))
                    ^
    758.           goto err;
    759.   

crypto/bn/bn_mont.c:222:1: Parameter `*a->d`
      220.   }
      221.   
      222. > int bn_to_mont_fixed_top(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont,
      223.                            BN_CTX *ctx)
      224.   {

crypto/bn/bn_mont.c:225:12: Call
      223.                            BN_CTX *ctx)
      224.   {
      225.       return bn_mul_mont_fixed_top(r, a, &(mont->RR), mont, ctx);
                        ^
      226.   }
      227.   

crypto/bn/bn_mont.c:37:1: Parameter `*a->d`
        35.   }
        36.   
        37. > int bn_mul_mont_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
        38.                             BN_MONT_CTX *mont, BN_CTX *ctx)
        39.   {

crypto/bn/bn_mont.c:70:14: Call
        68.               goto err;
        69.       } else {
        70.           if (!bn_mul_fixed_top(tmp, a, b, ctx))
                           ^
        71.               goto err;
        72.       }

crypto/bn/bn_mul.c:507:1: Parameter `*a->d`
          505.   }
          506.   
          507. > int bn_mul_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
          508.   {
          509.       int ret = 0;

crypto/bn/bn_mul.c:587:17: Call
          585.                   if (bn_wexpand(rr, k * 4) == NULL)
          586.                       goto err;
          587.                   bn_mul_part_recursive(rr->d, a->d, b->d,
                                 ^
          588.                                         j, al - j, bl - j, t->d);
          589.               } else {            /* al <= j || bl <= j */

crypto/bn/bn_mul.c:322:1: Parameter `n`
            320.    */
            321.   /* tnX may not be negative but less than n */
            322. > void bn_mul_part_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n,
            323.                              int tna, int tnb, BN_ULONG *t)
            324.   {

crypto/bn/bn_mul.c:335:10: Call
            333.   
            334.       /* r=(a[0]-a[1])*(b[1]-b[0]) */
            335.       c1 = bn_cmp_part_words(a, &(a[n]), tna, n - tna);
                            ^
            336.       c2 = bn_cmp_part_words(&(b[n]), b, tnb, tnb - n);
            337.       neg = 0;

crypto/bn/bn_lib.c:720:1: Parameter `cl`
              718.    */
              719.   
              720. > int bn_cmp_part_words(const BN_ULONG *a, const BN_ULONG *b, int cl, int dl)
              721.   {
              722.       int n, i;

crypto/bn/bn_lib.c:737:12: Call
              735.           }
              736.       }
              737.       return bn_cmp_words(a, b, cl);
                                ^
              738.   }
              739.   

crypto/bn/bn_lib.c:693:1: <Offset trace>
691.   }
692.   
693. > int bn_cmp_words(const BN_ULONG *a, const BN_ULONG *b, int n)
694.   {
695.       int i;

crypto/bn/bn_lib.c:693:1: Parameter `n`
                691.   }
                692.   
                693. > int bn_cmp_words(const BN_ULONG *a, const BN_ULONG *b, int n)
                694.   {
                695.       int i;

crypto/bn/bn_lib.c:702:10: Assignment
                700.       if (aa != bb)
                701.           return ((aa > bb) ? 1 : -1);
                702.       for (i = n - 2; i >= 0; i--) {
                                ^
                703.           aa = a[i];
                704.           bb = b[i];

crypto/bn/bn_lib.c:693:1: <Length trace>
691.   }
692.   
693. > int bn_cmp_words(const BN_ULONG *a, const BN_ULONG *b, int n)
694.   {
695.       int i;

crypto/bn/bn_lib.c:693:1: Parameter `*b`
                691.   }
                692.   
                693. > int bn_cmp_words(const BN_ULONG *a, const BN_ULONG *b, int n)
                694.   {
                695.       int i;

crypto/bn/bn_lib.c:704:14: Array access: Offset: [8, +oo] (⇐ [8, +oo] + [0, +oo]) Size: [0, 8388607] by call to `BN_mod_exp_mont` 
                702.       for (i = n - 2; i >= 0; i--) {
                703.           aa = a[i];
                704.           bb = b[i];
                                    ^
                705.           if (aa != bb)
                706.               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;
}
['static int rsa_ossl_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)\n{\n    BIGNUM *r1, *m1, *vrfy, *r2, *m[RSA_MAX_PRIME_NUM - 2];\n    int ret = 0, i, ex_primes = 0, smooth = 0;\n    RSA_PRIME_INFO *pinfo;\n    BN_CTX_start(ctx);\n    r1 = BN_CTX_get(ctx);\n    r2 = BN_CTX_get(ctx);\n    m1 = BN_CTX_get(ctx);\n    vrfy = BN_CTX_get(ctx);\n    if (vrfy == NULL)\n        goto err;\n    if (rsa->version == RSA_ASN1_VERSION_MULTI\n        && ((ex_primes = sk_RSA_PRIME_INFO_num(rsa->prime_infos)) <= 0\n             || ex_primes > RSA_MAX_PRIME_NUM - 2))\n        goto err;\n    if (rsa->flags & RSA_FLAG_CACHE_PRIVATE) {\n        BIGNUM *factor = BN_new();\n        if (factor == NULL)\n            goto err;\n        if (!(BN_with_flags(factor, rsa->p, BN_FLG_CONSTTIME),\n              BN_MONT_CTX_set_locked(&rsa->_method_mod_p, rsa->lock,\n                                     factor, ctx))\n            || !(BN_with_flags(factor, rsa->q, BN_FLG_CONSTTIME),\n                 BN_MONT_CTX_set_locked(&rsa->_method_mod_q, rsa->lock,\n                                        factor, ctx))) {\n            BN_free(factor);\n            goto err;\n        }\n        for (i = 0; i < ex_primes; i++) {\n            pinfo = sk_RSA_PRIME_INFO_value(rsa->prime_infos, i);\n            BN_with_flags(factor, pinfo->r, BN_FLG_CONSTTIME);\n            if (!BN_MONT_CTX_set_locked(&pinfo->m, rsa->lock, factor, ctx)) {\n                BN_free(factor);\n                goto err;\n            }\n        }\n        BN_free(factor);\n        smooth = (ex_primes == 0)\n                 && (rsa->meth->bn_mod_exp == BN_mod_exp_mont)\n                 && (BN_num_bits(rsa->q) == BN_num_bits(rsa->p));\n    }\n    if (rsa->flags & RSA_FLAG_CACHE_PUBLIC)\n        if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, rsa->lock,\n                                    rsa->n, ctx))\n            goto err;\n    if (smooth) {\n        if (\n            !bn_from_mont_fixed_top(m1, I, rsa->_method_mod_q, ctx)\n            || !bn_to_mont_fixed_top(m1, m1, rsa->_method_mod_q, ctx)\n            || !BN_mod_exp_mont_consttime(m1, m1, rsa->dmq1, rsa->q, ctx,\n                                          rsa->_method_mod_q)\n            || !bn_from_mont_fixed_top(r1, I, rsa->_method_mod_p, ctx)\n            || !bn_to_mont_fixed_top(r1, r1, rsa->_method_mod_p, ctx)\n            || !BN_mod_exp_mont_consttime(r1, r1, rsa->dmp1, rsa->p, ctx,\n                                          rsa->_method_mod_p)\n            || !bn_mod_sub_fixed_top(r1, r1, m1, rsa->p)\n            || !bn_to_mont_fixed_top(r1, r1, rsa->_method_mod_p, ctx)\n            || !bn_mul_mont_fixed_top(r1, r1, rsa->iqmp, rsa->_method_mod_p,\n                                      ctx)\n            || !bn_mul_fixed_top(r0, r1, rsa->q, ctx)\n            || !bn_mod_add_fixed_top(r0, r0, m1, rsa->n))\n            goto err;\n        goto tail;\n    }\n    {\n        BIGNUM *c = BN_new();\n        if (c == NULL)\n            goto err;\n        BN_with_flags(c, I, BN_FLG_CONSTTIME);\n        if (!BN_mod(r1, c, rsa->q, ctx)) {\n            BN_free(c);\n            goto err;\n        }\n        {\n            BIGNUM *dmq1 = BN_new();\n            if (dmq1 == NULL) {\n                BN_free(c);\n                goto err;\n            }\n            BN_with_flags(dmq1, rsa->dmq1, BN_FLG_CONSTTIME);\n            if (!rsa->meth->bn_mod_exp(m1, r1, dmq1, rsa->q, ctx,\n                                       rsa->_method_mod_q)) {\n                BN_free(c);\n                BN_free(dmq1);\n                goto err;\n            }\n            BN_free(dmq1);\n        }\n        if (!BN_mod(r1, c, rsa->p, ctx)) {\n            BN_free(c);\n            goto err;\n        }\n        BN_free(c);\n    }\n    {\n        BIGNUM *dmp1 = BN_new();\n        if (dmp1 == NULL)\n            goto err;\n        BN_with_flags(dmp1, rsa->dmp1, BN_FLG_CONSTTIME);\n        if (!rsa->meth->bn_mod_exp(r0, r1, dmp1, rsa->p, ctx,\n                                   rsa->_method_mod_p)) {\n            BN_free(dmp1);\n            goto err;\n        }\n        BN_free(dmp1);\n    }\n    if (ex_primes > 0) {\n        BIGNUM *di = BN_new(), *cc = BN_new();\n        if (cc == NULL || di == NULL) {\n            BN_free(cc);\n            BN_free(di);\n            goto err;\n        }\n        for (i = 0; i < ex_primes; i++) {\n            if ((m[i] = BN_CTX_get(ctx)) == NULL) {\n                BN_free(cc);\n                BN_free(di);\n                goto err;\n            }\n            pinfo = sk_RSA_PRIME_INFO_value(rsa->prime_infos, i);\n            BN_with_flags(cc, I, BN_FLG_CONSTTIME);\n            BN_with_flags(di, pinfo->d, BN_FLG_CONSTTIME);\n            if (!BN_mod(r1, cc, pinfo->r, ctx)) {\n                BN_free(cc);\n                BN_free(di);\n                goto err;\n            }\n            if (!rsa->meth->bn_mod_exp(m[i], r1, di, pinfo->r, ctx, pinfo->m)) {\n                BN_free(cc);\n                BN_free(di);\n                goto err;\n            }\n        }\n        BN_free(cc);\n        BN_free(di);\n    }\n    if (!BN_sub(r0, r0, m1))\n        goto err;\n    if (BN_is_negative(r0))\n        if (!BN_add(r0, r0, rsa->p))\n            goto err;\n    if (!BN_mul(r1, r0, rsa->iqmp, ctx))\n        goto err;\n    {\n        BIGNUM *pr1 = BN_new();\n        if (pr1 == NULL)\n            goto err;\n        BN_with_flags(pr1, r1, BN_FLG_CONSTTIME);\n        if (!BN_mod(r0, pr1, rsa->p, ctx)) {\n            BN_free(pr1);\n            goto err;\n        }\n        BN_free(pr1);\n    }\n    if (BN_is_negative(r0))\n        if (!BN_add(r0, r0, rsa->p))\n            goto err;\n    if (!BN_mul(r1, r0, rsa->q, ctx))\n        goto err;\n    if (!BN_add(r0, r1, m1))\n        goto err;\n    if (ex_primes > 0) {\n        BIGNUM *pr2 = BN_new();\n        if (pr2 == NULL)\n            goto err;\n        for (i = 0; i < ex_primes; i++) {\n            pinfo = sk_RSA_PRIME_INFO_value(rsa->prime_infos, i);\n            if (!BN_sub(r1, m[i], r0)) {\n                BN_free(pr2);\n                goto err;\n            }\n            if (!BN_mul(r2, r1, pinfo->t, ctx)) {\n                BN_free(pr2);\n                goto err;\n            }\n            BN_with_flags(pr2, r2, BN_FLG_CONSTTIME);\n            if (!BN_mod(r1, pr2, pinfo->r, ctx)) {\n                BN_free(pr2);\n                goto err;\n            }\n            if (BN_is_negative(r1))\n                if (!BN_add(r1, r1, pinfo->r)) {\n                    BN_free(pr2);\n                    goto err;\n                }\n            if (!BN_mul(r1, r1, pinfo->pp, ctx)) {\n                BN_free(pr2);\n                goto err;\n            }\n            if (!BN_add(r0, r0, r1)) {\n                BN_free(pr2);\n                goto err;\n            }\n        }\n        BN_free(pr2);\n    }\n tail:\n    if (rsa->e && rsa->n) {\n        if (rsa->meth->bn_mod_exp == BN_mod_exp_mont) {\n            if (!BN_mod_exp_mont(vrfy, r0, rsa->e, rsa->n, ctx,\n                                 rsa->_method_mod_n))\n                goto err;\n        } else {\n            bn_correct_top(r0);\n            if (!rsa->meth->bn_mod_exp(vrfy, r0, rsa->e, rsa->n, ctx,\n                                       rsa->_method_mod_n))\n                goto err;\n        }\n        if (!BN_sub(vrfy, vrfy, I))\n            goto err;\n        if (BN_is_zero(vrfy)) {\n            bn_correct_top(r0);\n            ret = 1;\n            goto err;\n        }\n        if (!BN_mod(vrfy, vrfy, rsa->n, ctx))\n            goto err;\n        if (BN_is_negative(vrfy))\n            if (!BN_add(vrfy, vrfy, rsa->n))\n                goto err;\n        if (!BN_is_zero(vrfy)) {\n            BIGNUM *d = BN_new();\n            if (d == NULL)\n                goto err;\n            BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);\n            if (!rsa->meth->bn_mod_exp(r0, I, d, rsa->n, ctx,\n                                       rsa->_method_mod_n)) {\n                BN_free(d);\n                goto err;\n            }\n            BN_free(d);\n        }\n    }\n    bn_correct_top(r0);\n    ret = 1;\n err:\n    BN_CTX_end(ctx);\n    return ret;\n}', 'int bn_mul_fixed_top(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#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    }\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    rr->neg = a->neg ^ b->neg;\n    rr->flags |= BN_FLG_FIXED_TOP;\n    if (r != rr && BN_copy(r, rr) == NULL)\n        goto err;\n    ret = 1;\n err:\n    bn_check_top(r);\n    BN_CTX_end(ctx);\n    return ret;\n}', 'int bn_mod_add_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,\n                         const BIGNUM *m)\n{\n    size_t i, ai, bi, mtop = m->top;\n    BN_ULONG storage[1024 / BN_BITS2];\n    BN_ULONG carry, temp, mask, *rp, *tp = storage;\n    const BN_ULONG *ap, *bp;\n    if (bn_wexpand(r, mtop) == NULL)\n        return 0;\n    if (mtop > sizeof(storage) / sizeof(storage[0])\n        && (tp = OPENSSL_malloc(mtop * sizeof(BN_ULONG))) == NULL)\n        return 0;\n    ap = a->d != NULL ? a->d : tp;\n    bp = b->d != NULL ? b->d : tp;\n    for (i = 0, ai = 0, bi = 0, carry = 0; i < mtop;) {\n        mask = (BN_ULONG)0 - ((i - a->top) >> (8 * sizeof(i) - 1));\n        temp = ((ap[ai] & mask) + carry) & BN_MASK2;\n        carry = (temp < carry);\n        mask = (BN_ULONG)0 - ((i - b->top) >> (8 * sizeof(i) - 1));\n        tp[i] = ((bp[bi] & mask) + temp) & BN_MASK2;\n        carry += (tp[i] < temp);\n        i++;\n        ai += (i - a->dmax) >> (8 * sizeof(i) - 1);\n        bi += (i - b->dmax) >> (8 * sizeof(i) - 1);\n    }\n    rp = r->d;\n    carry -= bn_sub_words(rp, tp, m->d, mtop);\n    for (i = 0; i < mtop; i++) {\n        rp[i] = (carry & tp[i]) | (~carry & rp[i]);\n        ((volatile BN_ULONG *)tp)[i] = 0;\n    }\n    r->top = mtop;\n    r->flags |= BN_FLG_FIXED_TOP;\n    r->neg = 0;\n    if (tp != storage)\n        OPENSSL_free(tp);\n    return 1;\n}', 'int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,\n                    const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont)\n{\n    int i, j, bits, ret = 0, wstart, wend, window, wvalue;\n    int start = 1;\n    BIGNUM *d, *r;\n    const BIGNUM *aa;\n    BIGNUM *val[TABLE_SIZE];\n    BN_MONT_CTX *mont = NULL;\n    if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0\n            || BN_get_flags(a, BN_FLG_CONSTTIME) != 0\n            || BN_get_flags(m, BN_FLG_CONSTTIME) != 0) {\n        return BN_mod_exp_mont_consttime(rr, a, p, m, ctx, in_mont);\n    }\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, BN_R_CALLED_WITH_EVEN_MODULUS);\n        return 0;\n    }\n    bits = BN_num_bits(p);\n    if (bits == 0) {\n        if (BN_abs_is_word(m, 1)) {\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    d = BN_CTX_get(ctx);\n    r = BN_CTX_get(ctx);\n    val[0] = BN_CTX_get(ctx);\n    if (val[0] == NULL)\n        goto err;\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    if (a->neg || BN_ucmp(a, m) >= 0) {\n        if (!BN_nnmod(val[0], a, m, ctx))\n            goto err;\n        aa = val[0];\n    } else\n        aa = a;\n    if (!bn_to_mont_fixed_top(val[0], aa, mont, ctx))\n        goto err;\n    window = BN_window_bits_for_exponent_size(bits);\n    if (window > 1) {\n        if (!bn_mul_mont_fixed_top(d, val[0], val[0], mont, ctx))\n            goto err;\n        j = 1 << (window - 1);\n        for (i = 1; i < j; i++) {\n            if (((val[i] = BN_CTX_get(ctx)) == NULL) ||\n                !bn_mul_mont_fixed_top(val[i], val[i - 1], d, mont, ctx))\n                goto err;\n        }\n    }\n    start = 1;\n    wvalue = 0;\n    wstart = bits - 1;\n    wend = 0;\n#if 1\n    j = m->top;\n    if (m->d[j - 1] & (((BN_ULONG)1) << (BN_BITS2 - 1))) {\n        if (bn_wexpand(r, j) == NULL)\n            goto err;\n        r->d[0] = (0 - m->d[0]) & BN_MASK2;\n        for (i = 1; i < j; i++)\n            r->d[i] = (~m->d[i]) & BN_MASK2;\n        r->top = j;\n        r->flags |= BN_FLG_FIXED_TOP;\n    } else\n#endif\n    if (!bn_to_mont_fixed_top(r, BN_value_one(), mont, ctx))\n        goto err;\n    for (;;) {\n        if (BN_is_bit_set(p, wstart) == 0) {\n            if (!start) {\n                if (!bn_mul_mont_fixed_top(r, r, r, mont, ctx))\n                    goto err;\n            }\n            if (wstart == 0)\n                break;\n            wstart--;\n            continue;\n        }\n        j = wstart;\n        wvalue = 1;\n        wend = 0;\n        for (i = 1; i < window; i++) {\n            if (wstart - i < 0)\n                break;\n            if (BN_is_bit_set(p, wstart - i)) {\n                wvalue <<= (i - wend);\n                wvalue |= 1;\n                wend = i;\n            }\n        }\n        j = wend + 1;\n        if (!start)\n            for (i = 0; i < j; i++) {\n                if (!bn_mul_mont_fixed_top(r, r, r, mont, ctx))\n                    goto err;\n            }\n        if (!bn_mul_mont_fixed_top(r, r, val[wvalue >> 1], mont, ctx))\n            goto err;\n        wstart -= wend + 1;\n        wvalue = 0;\n        start = 0;\n        if (wstart < 0)\n            break;\n    }\n#if defined(SPARC_T4_MONT)\n    if (OPENSSL_sparcv9cap_P[0] & (SPARCV9_VIS3 | SPARCV9_PREFER_FPU)) {\n        j = mont->N.top;\n        val[0]->d[0] = 1;\n        for (i = 1; i < j; i++)\n            val[0]->d[i] = 0;\n        val[0]->top = j;\n        if (!BN_mod_mul_montgomery(rr, r, val[0], mont, ctx))\n            goto err;\n    } else\n#endif\n    if (!BN_from_montgomery(rr, r, mont, ctx))\n        goto err;\n    ret = 1;\n err:\n    if (in_mont == NULL)\n        BN_MONT_CTX_free(mont);\n    BN_CTX_end(ctx);\n    bn_check_top(rr);\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, wmask, window0;\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 = p->top * BN_BITS2;\n    if (bits == 0) {\n        if (BN_abs_is_word(m, 1)) {\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    if (a->neg || BN_ucmp(a, m) >= 0) {\n        BIGNUM *reduced = BN_CTX_get(ctx);\n        if (reduced == NULL\n            || !BN_nnmod(reduced, a, m, ctx)) {\n            goto err;\n        }\n        a = reduced;\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        powerbufLen += top * sizeof(mont->N.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_mont_fixed_top(&tmp, BN_value_one(), mont, ctx))\n        goto err;\n    if (!bn_to_mont_fixed_top(&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        window0 = (bits - 1) % 5 + 1;\n        wmask = (1 << window0) - 1;\n        bits -= window0;\n        wvalue = bn_get_bits(p, bits) & wmask;\n        bn_gather5_t4(tmp.d, top, powerbuf, wvalue);\n        while (bits > 0) {\n            if (bits < stride)\n                stride = bits;\n            bits -= stride;\n            wvalue = bn_get_bits(p, bits);\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 *n0 = mont->n0, *np;\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        for (np = am.d + top, i = 0; i < top; i++)\n            np[i] = mont->N.d[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, np, 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, np, 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, np, 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, np, n0, top, i - 1);\n            bn_scatter5(tmp.d, top, powerbuf, i);\n        }\n# endif\n        window0 = (bits - 1) % 5 + 1;\n        wmask = (1 << window0) - 1;\n        bits -= window0;\n        wvalue = bn_get_bits(p, bits) & wmask;\n        bn_gather5(tmp.d, top, powerbuf, wvalue);\n        if (top & 7) {\n            while (bits > 0) {\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                                    bn_get_bits5(p->d, bits -= 5));\n            }\n        } else {\n            while (bits > 0) {\n                bn_power5(tmp.d, tmp.d, powerbuf, np, n0, top,\n                          bn_get_bits5(p->d, bits -= 5));\n            }\n        }\n        ret = bn_from_montgomery(tmp.d, tmp.d, NULL, np, 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, window))\n            goto err;\n        if (!MOD_EXP_CTIME_COPY_TO_PREBUF(&am, top, powerbuf, 1, window))\n            goto err;\n        if (window > 1) {\n            if (!bn_mul_mont_fixed_top(&tmp, &am, &am, mont, ctx))\n                goto err;\n            if (!MOD_EXP_CTIME_COPY_TO_PREBUF(&tmp, top, powerbuf, 2,\n                                              window))\n                goto err;\n            for (i = 3; i < numPowers; i++) {\n                if (!bn_mul_mont_fixed_top(&tmp, &am, &tmp, mont, ctx))\n                    goto err;\n                if (!MOD_EXP_CTIME_COPY_TO_PREBUF(&tmp, top, powerbuf, i,\n                                                  window))\n                    goto err;\n            }\n        }\n        window0 = (bits - 1) % window + 1;\n        wmask = (1 << window0) - 1;\n        bits -= window0;\n        wvalue = bn_get_bits(p, bits) & wmask;\n        if (!MOD_EXP_CTIME_COPY_FROM_PREBUF(&tmp, top, powerbuf, wvalue,\n                                            window))\n            goto err;\n        wmask = (1 << window) - 1;\n        while (bits > 0) {\n            for (i = 0; i < window; i++)\n                if (!bn_mul_mont_fixed_top(&tmp, &tmp, &tmp, mont, ctx))\n                    goto err;\n            bits -= window;\n            wvalue = bn_get_bits(p, bits) & wmask;\n            if (!MOD_EXP_CTIME_COPY_FROM_PREBUF(&am, top, powerbuf, wvalue,\n                                                window))\n                goto err;\n            if (!bn_mul_mont_fixed_top(&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_mont_fixed_top(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont,\n                         BN_CTX *ctx)\n{\n    return bn_mul_mont_fixed_top(r, a, &(mont->RR), mont, ctx);\n}', 'int bn_mul_mont_fixed_top(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    int num = mont->N.top;\n#if defined(OPENSSL_BN_ASM_MONT) && defined(MONT_WORD)\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            r->flags |= BN_FLG_FIXED_TOP;\n            return 1;\n        }\n    }\n#endif\n    if ((a->top + b->top) > 2 * num)\n        return 0;\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_fixed_top(tmp, a, ctx))\n            goto err;\n    } else {\n        if (!bn_mul_fixed_top(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    ret = 1;\n err:\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}']