Commit fcc4ee09 authored by Andy Polyakov's avatar Andy Polyakov
Browse files

crypto/bn: add more fixed-top routines.



Add bn_{mul|sqr}_fixed_top, bn_from_mont_fixed_top, bn_mod_sub_fixed_top.
Switch to bn_{mul|sqr}_fixed_top in bn_mul_mont_fixed_top and remove
memset in bn_from_montgomery_word.

Reviewed-by: default avatarPaul Dale <paul.dale@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/6915)
parent 0b89db6b
Loading
Loading
Loading
Loading
+66 −1
Original line number Diff line number Diff line
@@ -83,6 +83,7 @@ int bn_mod_add_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
        ((volatile BN_ULONG *)tp)[i] = 0;
    }
    r->top = mtop;
    r->flags |= BN_FLG_FIXED_TOP;
    r->neg = 0;

    if (tp != storage)
@@ -110,6 +111,70 @@ int BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m,
    return BN_nnmod(r, r, m, ctx);
}

/*
 * BN_mod_sub variant that may be used if both a and b are non-negative,
 * a is less than m, while b is of same bit width as m. It's implemented
 * as subtraction followed by two conditional additions.
 *
 * 0 <= a < m
 * 0 <= b < 2^w < 2*m
 *
 * after subtraction
 *
 * -2*m < r = a - b < m
 *
 * Thus it takes up to two conditional additions to make |r| positive.
 */
int bn_mod_sub_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
                         const BIGNUM *m)
{
    size_t i, ai, bi, mtop = m->top;
    BN_ULONG borrow, carry, ta, tb, mask, *rp;
    const BN_ULONG *ap, *bp;

    if (bn_wexpand(r, mtop) == NULL)
        return 0;

    rp = r->d;
    ap = a->d != NULL ? a->d : rp;
    bp = b->d != NULL ? b->d : rp;

    for (i = 0, ai = 0, bi = 0, borrow = 0; i < mtop;) {
        mask = (BN_ULONG)0 - ((i - a->top) >> (8 * sizeof(i) - 1));
        ta = ap[ai] & mask;

        mask = (BN_ULONG)0 - ((i - b->top) >> (8 * sizeof(i) - 1));
        tb = bp[bi] & mask;
        rp[i] = ta - tb - borrow;
        if (ta != tb)
            borrow = (ta < tb);

        i++;
        ai += (i - a->dmax) >> (8 * sizeof(i) - 1);
        bi += (i - b->dmax) >> (8 * sizeof(i) - 1);
    }
    ap = m->d;
    for (i = 0, mask = 0 - borrow, carry = 0; i < mtop; i++) {
        ta = ((ap[i] & mask) + carry) & BN_MASK2;
        carry = (ta < carry);
        rp[i] = (rp[i] + ta) & BN_MASK2;
        carry += (rp[i] < ta);
    }
    borrow -= carry;
    for (i = 0, mask = 0 - borrow, carry = 0; i < mtop; i++) {
        ta = ((ap[i] & mask) + carry) & BN_MASK2;
        carry = (ta < carry);
        rp[i] = (rp[i] + ta) & BN_MASK2;
        carry += (rp[i] < ta);
    }

    r->top = mtop;
    r->flags |= BN_FLG_FIXED_TOP;
    r->neg = 0;

    return 1;
}

/*
 * BN_mod_sub variant that may be used if both a and b are non-negative and
 * less than m
+19 −7
Original line number Diff line number Diff line
@@ -64,10 +64,10 @@ int bn_mul_mont_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,

    bn_check_top(tmp);
    if (a == b) {
        if (!BN_sqr(tmp, a, ctx))
        if (!bn_sqr_fixed_top(tmp, a, ctx))
            goto err;
    } else {
        if (!BN_mul(tmp, a, b, ctx))
        if (!bn_mul_fixed_top(tmp, a, b, ctx))
            goto err;
    }
    /* reduce from aRR to aR */
@@ -90,6 +90,7 @@ static int bn_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont)
    BIGNUM *n;
    BN_ULONG *ap, *np, *rp, n0, v, carry;
    int nl, max, i;
    unsigned int rtop;

    n = &(mont->N);
    nl = n->top;
@@ -107,9 +108,10 @@ static int bn_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont)
    rp = r->d;

    /* clear the top words of T */
    i = max - r->top;
    if (i)
        memset(&rp[r->top], 0, sizeof(*rp) * i);
    for (rtop = r->top, i = 0; i < max; i++) {
        v = (BN_ULONG)0 - ((i - rtop) >> (8 * sizeof(rtop) - 1));
        rp[i] &= v;
    }

    r->top = max;
    r->flags |= BN_FLG_FIXED_TOP;
@@ -159,6 +161,18 @@ static int bn_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont)

int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, BN_MONT_CTX *mont,
                       BN_CTX *ctx)
{
    int retn;

    retn = bn_from_mont_fixed_top(ret, a, mont, ctx);
    bn_correct_top(ret);
    bn_check_top(ret);

    return retn;
}

int bn_from_mont_fixed_top(BIGNUM *ret, const BIGNUM *a, BN_MONT_CTX *mont,
                           BN_CTX *ctx)
{
    int retn = 0;
#ifdef MONT_WORD
@@ -167,8 +181,6 @@ int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, BN_MONT_CTX *mont,
    BN_CTX_start(ctx);
    if ((t = BN_CTX_get(ctx)) && BN_copy(t, a)) {
        retn = bn_from_montgomery_word(ret, t, mont);
        bn_correct_top(ret);
        bn_check_top(ret);
    }
    BN_CTX_end(ctx);
#else                           /* !MONT_WORD */
+11 −1
Original line number Diff line number Diff line
@@ -495,6 +495,16 @@ void bn_mul_low_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2,
#endif                          /* BN_RECURSION */

int BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
{
    int ret = bn_mul_fixed_top(r, a, b, ctx);

    bn_correct_top(r);
    bn_check_top(r);

    return ret;
}

int bn_mul_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
{
    int ret = 0;
    int top, al, bl;
@@ -598,7 +608,7 @@ int BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
 end:
#endif
    rr->neg = a->neg ^ b->neg;
    bn_correct_top(rr);
    rr->flags |= BN_FLG_FIXED_TOP;
    if (r != rr && BN_copy(r, rr) == NULL)
        goto err;

+11 −1
Original line number Diff line number Diff line
@@ -15,6 +15,16 @@
 * I've just gone over this and it is now %20 faster on x86 - eay - 27 Jun 96
 */
int BN_sqr(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx)
{
    int ret = bn_sqr_fixed_top(r, a, ctx);

    bn_correct_top(r);
    bn_check_top(r);

    return ret;
}

int bn_sqr_fixed_top(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx)
{
    int max, al;
    int ret = 0;
@@ -83,7 +93,7 @@ int BN_sqr(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx)

    rr->neg = 0;
    rr->top = max;
    bn_correct_top(rr);
    rr->flags |= BN_FLG_FIXED_TOP;
    if (r != rr && BN_copy(r, rr) == NULL)
        goto err;

+6 −0
Original line number Diff line number Diff line
@@ -71,7 +71,13 @@ int bn_mul_mont_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
                          BN_MONT_CTX *mont, BN_CTX *ctx);
int bn_to_mont_fixed_top(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont,
                         BN_CTX *ctx);
int bn_from_mont_fixed_top(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont,
                           BN_CTX *ctx);
int bn_mod_add_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
                         const BIGNUM *m);
int bn_mod_sub_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
                         const BIGNUM *m);
int bn_mul_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
int bn_sqr_fixed_top(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx);

#endif