Pārlūkot izejas kodu

Fix for CVE-2014-3570.

(With minor bn/generic.c revamp.)

(Imported from upstream's 56df92efb6)

Change-Id: I9d85cfde4dfb29e64ff7417f781d0c9f1685e905
Reviewed-on: https://boringssl-review.googlesource.com/2780
Reviewed-by: Adam Langley <agl@google.com>
kris/onging/CECPQ3_patch15
Adam Langley pirms 9 gadiem
vecāks
revīzija
a83cc803b1
3 mainītis faili ar 265 papildinājumiem un 244 dzēšanām
  1. +27
    -65
      crypto/bn/asm/x86_64-gcc.c
  2. +79
    -21
      crypto/bn/bn_test.c
  3. +159
    -158
      crypto/bn/generic.c

+ 27
- 65
crypto/bn/asm/x86_64-gcc.c Parādīt failu

@@ -292,80 +292,45 @@ BN_ULONG bn_sub_words(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n) {
/* sqr_add_c2(a,i,c0,c1,c2) -- c+=2*a[i]*a[j] for three word number c=(c2,c1,c0)
*/

#if 0
/* original macros are kept for reference purposes */
#define mul_add_c(a, b, c0, c1, c2) \
{ \
BN_ULONG ta = (a), tb = (b); \
t1 = ta * tb; \
t2 = BN_UMULT_HIGH(ta, tb); \
c0 += t1; \
t2 += (c0 < t1) ? 1 : 0; \
c1 += t2; \
c2 += (c1 < t2) ? 1 : 0; \
}

#define mul_add_c2(a, b, c0, c1, c2) \
{ \
BN_ULONG ta = (a), tb = (b), t0; \
t1 = BN_UMULT_HIGH(ta, tb); \
t0 = ta * tb; \
t2 = t1 + t1; \
c2 += (t2 < t1) ? 1 : 0; \
t1 = t0 + t0; \
t2 += (t1 < t0) ? 1 : 0; \
c0 += t1; \
t2 += (c0 < t1) ? 1 : 0; \
c1 += t2; \
c2 += (c1 < t2) ? 1 : 0; \
}
#else
#define mul_add_c(a, b, c0, c1, c2) \
do { \
/* Keep in mind that carrying into high part of multiplication result can not
* overflow, because it cannot be all-ones. */
#define mul_add_c(a, b, c0, c1, c2) \
do { \
BN_ULONG t1, t2; \
asm("mulq %3" : "=a"(t1), "=d"(t2) : "a"(a), "m"(b) : "cc"); \
asm("addq %2,%0; adcq %3,%1" \
: "+r"(c0), "+d"(t2) \
: "a"(t1), "g"(0) \
: "cc"); \
asm("addq %2,%0; adcq %3,%1" \
: "+r"(c1), "+r"(c2) \
: "d"(t2), "g"(0) \
: "cc"); \
asm("addq %3,%0; adcq %4,%1; adcq %5,%2" \
: "+r"(c0), "+r"(c1), "+r"(c2) \
: "r"(t1), "r"(t2), "g"(0) \
: "cc"); \
} while (0)

#define sqr_add_c(a, i, c0, c1, c2) \
do { \
#define sqr_add_c(a, i, c0, c1, c2) \
do { \
BN_ULONG t1, t2; \
asm("mulq %2" : "=a"(t1), "=d"(t2) : "a"(a[i]) : "cc"); \
asm("addq %2,%0; adcq %3,%1" \
: "+r"(c0), "+d"(t2) \
: "a"(t1), "g"(0) \
: "cc"); \
asm("addq %2,%0; adcq %3,%1" \
: "+r"(c1), "+r"(c2) \
: "d"(t2), "g"(0) \
: "cc"); \
asm("addq %3,%0; adcq %4,%1; adcq %5,%2" \
: "+r"(c0), "+r"(c1), "+r"(c2) \
: "r"(t1), "r"(t2), "g"(0) \
: "cc"); \
} while (0)

#define mul_add_c2(a, b, c0, c1, c2) \
do { \
#define mul_add_c2(a, b, c0, c1, c2) \
do { \
BN_ULONG t1, t2; \
asm("mulq %3" : "=a"(t1), "=d"(t2) : "a"(a), "m"(b) : "cc"); \
asm("addq %0,%0; adcq %2,%1" : "+d"(t2), "+r"(c2) : "g"(0) : "cc"); \
asm("addq %0,%0; adcq %2,%1" : "+a"(t1), "+d"(t2) : "g"(0) : "cc"); \
asm("addq %2,%0; adcq %3,%1" \
: "+r"(c0), "+d"(t2) \
: "a"(t1), "g"(0) \
: "cc"); \
asm("addq %2,%0; adcq %3,%1" \
: "+r"(c1), "+r"(c2) \
: "d"(t2), "g"(0) \
: "cc"); \
asm("addq %3,%0; adcq %4,%1; adcq %5,%2" \
: "+r"(c0), "+r"(c1), "+r"(c2) \
: "r"(t1), "r"(t2), "g"(0) \
: "cc"); \
asm("addq %3,%0; adcq %4,%1; adcq %5,%2" \
: "+r"(c0), "+r"(c1), "+r"(c2) \
: "r"(t1), "r"(t2), "g"(0) \
: "cc"); \
} while (0)
#endif

#define sqr_add_c2(a, i, j, c0, c1, c2) mul_add_c2((a)[i], (a)[j], c0, c1, c2)

void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) {
BN_ULONG t1, t2;
BN_ULONG c1, c2, c3;

c1 = 0;
@@ -468,7 +433,6 @@ void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) {
}

void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) {
BN_ULONG t1, t2;
BN_ULONG c1, c2, c3;

c1 = 0;
@@ -507,7 +471,6 @@ void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) {
}

void bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a) {
BN_ULONG t1, t2;
BN_ULONG c1, c2, c3;

c1 = 0;
@@ -582,7 +545,6 @@ void bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a) {
}

void bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a) {
BN_ULONG t1, t2;
BN_ULONG c1, c2, c3;

c1 = 0;


+ 79
- 21
crypto/bn/bn_test.c Parādīt failu

@@ -653,40 +653,98 @@ int test_mul(BIO *bp) {
}

int test_sqr(BIO *bp, BN_CTX *ctx) {
BIGNUM a, c, d, e;
int i;
BIGNUM *a, *c, *d, *e;
int i, ret = 0;

BN_init(&a);
BN_init(&c);
BN_init(&d);
BN_init(&e);
a = BN_new();
c = BN_new();
d = BN_new();
e = BN_new();
if (a == NULL || c == NULL || d == NULL || e == NULL) {
goto err;
}

for (i = 0; i < num0; i++) {
BN_rand(&a, 40 + i * 10, 0, 0);
a.neg = rand_neg();
BN_sqr(&c, &a, ctx);
BN_rand(a, 40 + i * 10, 0, 0);
a->neg = rand_neg();
BN_sqr(c, a, ctx);
if (bp != NULL) {
if (!results) {
BN_print(bp, &a);
BN_print(bp, a);
BIO_puts(bp, " * ");
BN_print(bp, &a);
BN_print(bp, a);
BIO_puts(bp, " - ");
}
BN_print(bp, &c);
BN_print(bp, c);
BIO_puts(bp, "\n");
}
BN_div(&d, &e, &c, &a, ctx);
BN_sub(&d, &d, &a);
if (!BN_is_zero(&d) || !BN_is_zero(&e)) {
BN_div(d, e, c, a, ctx);
BN_sub(d, d, a);
if (!BN_is_zero(d) || !BN_is_zero(e)) {
fprintf(stderr, "Square test failed!\n");
return 0;
goto err;
}
}
BN_free(&a);
BN_free(&c);
BN_free(&d);
BN_free(&e);
return (1);

/* Regression test for a BN_sqr overflow bug. */
BN_hex2bn(&a,
"80000000000000008000000000000001FFFFFFFFFFFFFFFE0000000000000000");
BN_sqr(c, a, ctx);
if (bp != NULL) {
if (!results) {
BN_print(bp, a);
BIO_puts(bp, " * ");
BN_print(bp, a);
BIO_puts(bp, " - ");
}
BN_print(bp, c);
BIO_puts(bp, "\n");
}
BN_mul(d, a, a, ctx);
if (BN_cmp(c, d)) {
fprintf(stderr,
"Square test failed: BN_sqr and BN_mul produce "
"different results!\n");
goto err;
}

/* Regression test for a BN_sqr overflow bug. */
BN_hex2bn(&a,
"80000000000000000000000080000001FFFFFFFE000000000000000000000000");
BN_sqr(c, a, ctx);
if (bp != NULL) {
if (!results) {
BN_print(bp, a);
BIO_puts(bp, " * ");
BN_print(bp, a);
BIO_puts(bp, " - ");
}
BN_print(bp, c);
BIO_puts(bp, "\n");
}
BN_mul(d, a, a, ctx);
if (BN_cmp(c, d)) {
fprintf(stderr,
"Square test failed: BN_sqr and BN_mul produce "
"different results!\n");
goto err;
}
ret = 1;

err:
if (a != NULL) {
BN_free(a);
}
if (c != NULL) {
BN_free(c);
}
if (d != NULL) {
BN_free(d);
}
if (e != NULL) {
BN_free(e);
}
return ret;
}




+ 159
- 158
crypto/bn/generic.c Parādīt failu

@@ -659,175 +659,194 @@ BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
/* sqr_add_c2(a,i,c0,c1,c2) -- c+=2*a[i]*a[j] for three word number c=(c2,c1,c0) */

#ifdef BN_LLONG
#define mul_add_c(a, b, c0, c1, c2) \
t = (BN_ULLONG)a * b; \
t1 = (BN_ULONG)Lw(t); \
t2 = (BN_ULONG)Hw(t); \
c0 = (c0 + t1) & BN_MASK2; \
if ((c0) < t1) \
t2++; \
c1 = (c1 + t2) & BN_MASK2; \
if ((c1) < t2) \
c2++;

#define mul_add_c2(a, b, c0, c1, c2) \
t = (BN_ULLONG)a * b; \
tt = (t + t) & BN_MASK; \
if (tt < t) \
c2++; \
t1 = (BN_ULONG)Lw(tt); \
t2 = (BN_ULONG)Hw(tt); \
c0 = (c0 + t1) & BN_MASK2; \
if ((c0 < t1) && (((++t2) & BN_MASK2) == 0)) \
c2++; \
c1 = (c1 + t2) & BN_MASK2; \
if ((c1) < t2) \
c2++;

#define sqr_add_c(a, i, c0, c1, c2) \
t = (BN_ULLONG)a[i] * a[i]; \
t1 = (BN_ULONG)Lw(t); \
t2 = (BN_ULONG)Hw(t); \
c0 = (c0 + t1) & BN_MASK2; \
if ((c0) < t1) \
t2++; \
c1 = (c1 + t2) & BN_MASK2; \
if ((c1) < t2) \
c2++;
/* Keep in mind that additions to multiplication result can not overflow,
* because its high half cannot be all-ones. */
#define mul_add_c(a, b, c0, c1, c2) \
do { \
BN_ULONG hi; \
BN_ULLONG t = (BN_ULLONG)(a) * (b); \
t += c0; /* no carry */ \
c0 = (BN_ULONG)Lw(t); \
hi = (BN_ULONG)Hw(t); \
c1 = (c1 + hi) & BN_MASK2; \
if (c1 < hi) \
c2++; \
} while (0)

#define mul_add_c2(a, b, c0, c1, c2) \
do { \
BN_ULONG hi; \
BN_ULLONG t = (BN_ULLONG)(a) * (b); \
BN_ULLONG tt = t + c0; /* no carry */ \
c0 = (BN_ULONG)Lw(tt); \
hi = (BN_ULONG)Hw(tt); \
c1 = (c1 + hi) & BN_MASK2; \
if (c1 < hi) \
c2++; \
t += c0; /* no carry */ \
c0 = (BN_ULONG)Lw(t); \
hi = (BN_ULONG)Hw(t); \
c1 = (c1 + hi) & BN_MASK2; \
if (c1 < hi) \
c2++; \
} while (0)

#define sqr_add_c(a, i, c0, c1, c2) \
do { \
BN_ULONG hi; \
BN_ULLONG t = (BN_ULLONG)a[i] * a[i]; \
t += c0; /* no carry */ \
c0 = (BN_ULONG)Lw(t); \
hi = (BN_ULONG)Hw(t); \
c1 = (c1 + hi) & BN_MASK2; \
if (c1 < hi) \
c2++; \
} while (0)

#define sqr_add_c2(a, i, j, c0, c1, c2) mul_add_c2((a)[i], (a)[j], c0, c1, c2)

#elif defined(BN_UMULT_LOHI)

/* Keep in mind that additions to hi can not overflow, because the high word of
* a multiplication result cannot be all-ones. */
#define mul_add_c(a, b, c0, c1, c2) \
{ \
do { \
BN_ULONG ta = (a), tb = (b); \
BN_UMULT_LOHI(t1, t2, ta, tb); \
c0 += t1; \
t2 += (c0 < t1) ? 1 : 0; \
c1 += t2; \
c2 += (c1 < t2) ? 1 : 0; \
}
BN_ULONG lo, hi; \
BN_UMULT_LOHI(lo, hi, ta, tb); \
c0 += lo; \
hi += (c0 < lo) ? 1 : 0; \
c1 += hi; \
c2 += (c1 < hi) ? 1 : 0; \
} while (0)

#define mul_add_c2(a, b, c0, c1, c2) \
{ \
BN_ULONG ta = (a), tb = (b), t0; \
BN_UMULT_LOHI(t0, t1, ta, tb); \
t2 = t1 + t1; \
c2 += (t2 < t1) ? 1 : 0; \
t1 = t0 + t0; \
t2 += (t1 < t0) ? 1 : 0; \
c0 += t1; \
t2 += (c0 < t1) ? 1 : 0; \
c1 += t2; \
c2 += (c1 < t2) ? 1 : 0; \
}
do { \
BN_ULONG ta = (a), tb = (b); \
BN_ULONG lo, hi, tt; \
BN_UMULT_LOHI(lo, hi, ta, tb); \
c0 += lo; \
tt = hi + ((c0 < lo) ? 1 : 0); \
c1 += tt; \
c2 += (c1 < tt) ? 1 : 0; \
c0 += lo; \
hi += (c0 < lo) ? 1 : 0; \
c1 += hi; \
c2 += (c1 < hi) ? 1 : 0; \
} while (0)

#define sqr_add_c(a, i, c0, c1, c2) \
{ \
do { \
BN_ULONG ta = (a)[i]; \
BN_UMULT_LOHI(t1, t2, ta, ta); \
c0 += t1; \
t2 += (c0 < t1) ? 1 : 0; \
c1 += t2; \
c2 += (c1 < t2) ? 1 : 0; \
}
BN_ULONG lo, hi; \
BN_UMULT_LOHI(lo, hi, ta, ta); \
c0 += lo; \
hi += (c0 < lo) ? 1 : 0; \
c1 += hi; \
c2 += (c1 < hi) ? 1 : 0; \
} while (0)

#define sqr_add_c2(a, i, j, c0, c1, c2) mul_add_c2((a)[i], (a)[j], c0, c1, c2)

#elif defined(BN_UMULT_HIGH)

#define mul_add_c(a, b, c0, c1, c2) \
{ \
BN_ULONG ta = (a), tb = (b); \
t1 = ta * tb; \
t2 = BN_UMULT_HIGH(ta, tb); \
c0 += t1; \
t2 += (c0 < t1) ? 1 : 0; \
c1 += t2; \
c2 += (c1 < t2) ? 1 : 0; \
}

#define mul_add_c2(a, b, c0, c1, c2) \
{ \
BN_ULONG ta = (a), tb = (b), t0; \
t1 = BN_UMULT_HIGH(ta, tb); \
t0 = ta * tb; \
t2 = t1 + t1; \
c2 += (t2 < t1) ? 1 : 0; \
t1 = t0 + t0; \
t2 += (t1 < t0) ? 1 : 0; \
c0 += t1; \
t2 += (c0 < t1) ? 1 : 0; \
c1 += t2; \
c2 += (c1 < t2) ? 1 : 0; \
}

#define sqr_add_c(a, i, c0, c1, c2) \
{ \
BN_ULONG ta = (a)[i]; \
t1 = ta * ta; \
t2 = BN_UMULT_HIGH(ta, ta); \
c0 += t1; \
t2 += (c0 < t1) ? 1 : 0; \
c1 += t2; \
c2 += (c1 < t2) ? 1 : 0; \
}
/* Keep in mind that additions to hi can not overflow, because
* the high word of a multiplication result cannot be all-ones. */
#define mul_add_c(a, b, c0, c1, c2) \
do { \
BN_ULONG ta = (a), tb = (b); \
BN_ULONG lo = ta * tb; \
BN_ULONG hi = BN_UMULT_HIGH(ta, tb); \
c0 += lo; \
hi += (c0 < lo) ? 1 : 0; \
c1 += hi; \
c2 += (c1 < hi) ? 1 : 0; \
} while (0)

#define mul_add_c2(a, b, c0, c1, c2) \
do { \
BN_ULONG ta = (a), tb = (b), tt; \
BN_ULONG lo = ta * tb; \
BN_ULONG hi = BN_UMULT_HIGH(ta, tb); \
c0 += lo; \
tt = hi + ((c0 < lo) ? 1 : 0); \
c1 += tt; \
c2 += (c1 < tt) ? 1 : 0; \
c0 += lo; \
hi += (c0 < lo) ? 1 : 0; \
c1 += hi; \
c2 += (c1 < hi) ? 1 : 0; \
} while (0)

#define sqr_add_c(a, i, c0, c1, c2) \
do { \
BN_ULONG ta = (a)[i]; \
BN_ULONG lo = ta * ta; \
BN_ULONG hi = BN_UMULT_HIGH(ta, ta); \
c0 += lo; \
hi += (c0 < lo) ? 1 : 0; \
c1 += hi; \
c2 += (c1 < hi) ? 1 : 0; \
} while (0)

#define sqr_add_c2(a, i, j, c0, c1, c2) mul_add_c2((a)[i], (a)[j], c0, c1, c2)

#else /* !BN_LLONG */
#define mul_add_c(a, b, c0, c1, c2) \
t1 = LBITS(a); \
t2 = HBITS(a); \
bl = LBITS(b); \
bh = HBITS(b); \
mul64(t1, t2, bl, bh); \
c0 = (c0 + t1) & BN_MASK2; \
if ((c0) < t1) \
t2++; \
c1 = (c1 + t2) & BN_MASK2; \
if ((c1) < t2) \
c2++;

#define mul_add_c2(a, b, c0, c1, c2) \
t1 = LBITS(a); \
t2 = HBITS(a); \
bl = LBITS(b); \
bh = HBITS(b); \
mul64(t1, t2, bl, bh); \
if (t2 & BN_TBIT) \
c2++; \
t2 = (t2 + t2) & BN_MASK2; \
if (t1 & BN_TBIT) \
t2++; \
t1 = (t1 + t1) & BN_MASK2; \
c0 = (c0 + t1) & BN_MASK2; \
if ((c0 < t1) && (((++t2) & BN_MASK2) == 0)) \
c2++; \
c1 = (c1 + t2) & BN_MASK2; \
if ((c1) < t2) \
c2++;

/* Keep in mind that additions to hi can not overflow, because
* the high word of a multiplication result cannot be all-ones. */

#define mul_add_c(a, b, c0, c1, c2) \
do { \
BN_ULONG lo = LBITS(a), hi = HBITS(a); \
BN_ULONG bl = LBITS(b), bh = HBITS(b); \
mul64(lo, hi, bl, bh); \
c0 = (c0 + lo) & BN_MASK2; \
if (c0 < lo) \
hi++; \
c1 = (c1 + hi) & BN_MASK2; \
if (c1 < hi) \
c2++; \
} while (0)

#define mul_add_c2(a, b, c0, c1, c2) \
do { \
BN_ULONG tt; \
BN_ULONG lo = LBITS(a), hi = HBITS(a); \
BN_ULONG bl = LBITS(b), bh = HBITS(b); \
mul64(lo, hi, bl, bh); \
tt = hi; \
c0 = (c0 + lo) & BN_MASK2; \
if (c0 < lo) \
tt++; \
c1 = (c1 + tt) & BN_MASK2; \
if (c1 < tt) \
c2++; \
c0 = (c0 + lo) & BN_MASK2; \
if (c0 < lo) \
hi++; \
c1 = (c1 + hi) & BN_MASK2; \
if (c1 < hi) \
c2++; \
} while (0)

#define sqr_add_c(a, i, c0, c1, c2) \
sqr64(t1, t2, (a)[i]); \
c0 = (c0 + t1) & BN_MASK2; \
if ((c0) < t1) \
t2++; \
c1 = (c1 + t2) & BN_MASK2; \
if ((c1) < t2) \
c2++;
do { \
BN_ULONG lo, hi; \
sqr64(lo, hi, (a)[i]); \
c0 = (c0 + lo) & BN_MASK2; \
if (c0 < lo) \
hi++; \
c1 = (c1 + hi) & BN_MASK2; \
if (c1 < hi) \
c2++; \
} while (0)

#define sqr_add_c2(a, i, j, c0, c1, c2) mul_add_c2((a)[i], (a)[j], c0, c1, c2)
#endif /* !BN_LLONG */

void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) {
#if defined(BN_LLONG)
BN_ULLONG t;
#elif !defined(BN_UMULT_LOHI) && !defined(BN_UMULT_HIGH)
BN_ULONG bl, bh;
#endif
BN_ULONG t1, t2;
BN_ULONG c1, c2, c3;

c1 = 0;
@@ -930,12 +949,6 @@ void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) {
}

void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) {
#if defined(BN_LLONG)
BN_ULLONG t;
#elif !defined(BN_UMULT_LOHI) && !defined(BN_UMULT_HIGH)
BN_ULONG bl, bh;
#endif
BN_ULONG t1, t2;
BN_ULONG c1, c2, c3;

c1 = 0;
@@ -974,12 +987,6 @@ void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) {
}

void bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a) {
#if defined(BN_LLONG)
BN_ULLONG t, tt;
#elif !defined(BN_UMULT_LOHI) && !defined(BN_UMULT_HIGH)
BN_ULONG bl, bh;
#endif
BN_ULONG t1, t2;
BN_ULONG c1, c2, c3;

c1 = 0;
@@ -1054,12 +1061,6 @@ void bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a) {
}

void bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a) {
#if defined(BN_LLONG)
BN_ULLONG t, tt;
#elif !defined(BN_UMULT_LOHI) && !defined(BN_UMULT_HIGH)
BN_ULONG bl, bh;
#endif
BN_ULONG t1, t2;
BN_ULONG c1, c2, c3;

c1 = 0;


Notiek ielāde…
Atcelt
Saglabāt