| Index: crypto/p224.cc
|
| diff --git a/crypto/p224.cc b/crypto/p224.cc
|
| index 575b51f4ce946cf06b4443ddf68cda8667240752..ac0a081037f2de25c0d3d40aaf07a0a173c3bcbe 100644
|
| --- a/crypto/p224.cc
|
| +++ b/crypto/p224.cc
|
| @@ -32,6 +32,46 @@ using base::NetToHost32;
|
|
|
| using crypto::p224::FieldElement;
|
|
|
| +// kP is the P224 prime.
|
| +const FieldElement kP = {
|
| + 1, 0, 0, 268431360,
|
| + 268435455, 268435455, 268435455, 268435455,
|
| +};
|
| +
|
| +void Contract(FieldElement* inout);
|
| +
|
| +// IsZero returns 0xffffffff if a == 0 mod p and 0 otherwise.
|
| +uint32 IsZero(const FieldElement& a) {
|
| + FieldElement minimal;
|
| + memcpy(&minimal, &a, sizeof(minimal));
|
| + Contract(&minimal);
|
| +
|
| + uint32 is_zero = 0, is_p = 0;
|
| + for (unsigned i = 0; i < 8; i++) {
|
| + is_zero |= minimal[i];
|
| + is_p |= minimal[i] - kP[i];
|
| + }
|
| +
|
| + // If either is_zero or is_p is 0, then we should return 1.
|
| + is_zero |= is_zero >> 16;
|
| + is_zero |= is_zero >> 8;
|
| + is_zero |= is_zero >> 4;
|
| + is_zero |= is_zero >> 2;
|
| + is_zero |= is_zero >> 1;
|
| +
|
| + is_p |= is_p >> 16;
|
| + is_p |= is_p >> 8;
|
| + is_p |= is_p >> 4;
|
| + is_p |= is_p >> 2;
|
| + is_p |= is_p >> 1;
|
| +
|
| + // For is_zero and is_p, the LSB is 0 iff all the bits are zero.
|
| + is_zero &= is_p & 1;
|
| + is_zero = (~is_zero) << 31;
|
| + is_zero = static_cast<int32>(is_zero) >> 31;
|
| + return is_zero;
|
| +}
|
| +
|
| // Add computes *out = a+b
|
| //
|
| // a[i] + b[i] < 2**32
|
| @@ -313,52 +353,52 @@ void Contract(FieldElement* inout) {
|
| // unique, minimal value we see if the value is >= p and, if so, subtract p.
|
|
|
| // First we build a mask from the top four limbs, which must all be
|
| - // equal to bottom28Bits if the whole value is >= p. If top4AllOnes
|
| + // equal to bottom28Bits if the whole value is >= p. If top_4_all_ones
|
| // ends up with any zero bits in the bottom 28 bits, then this wasn't
|
| // true.
|
| - uint32 top4AllOnes = 0xffffffffu;
|
| + uint32 top_4_all_ones = 0xffffffffu;
|
| for (int i = 4; i < 8; i++) {
|
| - top4AllOnes &= (out[i] & kBottom28Bits) - 1;
|
| - }
|
| - top4AllOnes |= 0xf0000000;
|
| - // Now we replicate any zero bits to all the bits in top4AllOnes.
|
| - top4AllOnes &= top4AllOnes >> 16;
|
| - top4AllOnes &= top4AllOnes >> 8;
|
| - top4AllOnes &= top4AllOnes >> 4;
|
| - top4AllOnes &= top4AllOnes >> 2;
|
| - top4AllOnes &= top4AllOnes >> 1;
|
| - top4AllOnes =
|
| - static_cast<uint32>(static_cast<int32>(top4AllOnes << 31) >> 31);
|
| + top_4_all_ones &= out[i];
|
| + }
|
| + top_4_all_ones |= 0xf0000000;
|
| + // Now we replicate any zero bits to all the bits in top_4_all_ones.
|
| + top_4_all_ones &= top_4_all_ones >> 16;
|
| + top_4_all_ones &= top_4_all_ones >> 8;
|
| + top_4_all_ones &= top_4_all_ones >> 4;
|
| + top_4_all_ones &= top_4_all_ones >> 2;
|
| + top_4_all_ones &= top_4_all_ones >> 1;
|
| + top_4_all_ones =
|
| + static_cast<uint32>(static_cast<int32>(top_4_all_ones << 31) >> 31);
|
|
|
| // Now we test whether the bottom three limbs are non-zero.
|
| - uint32 bottom3NonZero = out[0] | out[1] | out[2];
|
| - bottom3NonZero |= bottom3NonZero >> 16;
|
| - bottom3NonZero |= bottom3NonZero >> 8;
|
| - bottom3NonZero |= bottom3NonZero >> 4;
|
| - bottom3NonZero |= bottom3NonZero >> 2;
|
| - bottom3NonZero |= bottom3NonZero >> 1;
|
| - bottom3NonZero =
|
| - static_cast<uint32>(static_cast<int32>(bottom3NonZero << 31) >> 31);
|
| + uint32 bottom_3_non_zero = out[0] | out[1] | out[2];
|
| + bottom_3_non_zero |= bottom_3_non_zero >> 16;
|
| + bottom_3_non_zero |= bottom_3_non_zero >> 8;
|
| + bottom_3_non_zero |= bottom_3_non_zero >> 4;
|
| + bottom_3_non_zero |= bottom_3_non_zero >> 2;
|
| + bottom_3_non_zero |= bottom_3_non_zero >> 1;
|
| + bottom_3_non_zero =
|
| + static_cast<uint32>(static_cast<int32>(bottom_3_non_zero) >> 31);
|
|
|
| // Everything depends on the value of out[3].
|
| - // If it's > 0xffff000 and top4AllOnes != 0 then the whole value is >= p
|
| - // If it's = 0xffff000 and top4AllOnes != 0 and bottom3NonZero != 0,
|
| + // If it's > 0xffff000 and top_4_all_ones != 0 then the whole value is >= p
|
| + // If it's = 0xffff000 and top_4_all_ones != 0 and bottom_3_non_zero != 0,
|
| // then the whole value is >= p
|
| // If it's < 0xffff000, then the whole value is < p
|
| uint32 n = out[3] - 0xffff000;
|
| - uint32 out3Equal = n;
|
| - out3Equal |= out3Equal >> 16;
|
| - out3Equal |= out3Equal >> 8;
|
| - out3Equal |= out3Equal >> 4;
|
| - out3Equal |= out3Equal >> 2;
|
| - out3Equal |= out3Equal >> 1;
|
| - out3Equal =
|
| - ~static_cast<uint32>(static_cast<int32>(out3Equal << 31) >> 31);
|
| + uint32 out_3_equal = n;
|
| + out_3_equal |= out_3_equal >> 16;
|
| + out_3_equal |= out_3_equal >> 8;
|
| + out_3_equal |= out_3_equal >> 4;
|
| + out_3_equal |= out_3_equal >> 2;
|
| + out_3_equal |= out_3_equal >> 1;
|
| + out_3_equal =
|
| + ~static_cast<uint32>(static_cast<int32>(out_3_equal << 31) >> 31);
|
|
|
| // If out[3] > 0xffff000 then n's MSB will be zero.
|
| - uint32 out3GT = ~static_cast<uint32>(static_cast<int32>(n << 31) >> 31);
|
| + uint32 out_3_gt = ~static_cast<uint32>(static_cast<int32>(n << 31) >> 31);
|
|
|
| - uint32 mask = top4AllOnes & ((out3Equal & bottom3NonZero) | out3GT);
|
| + uint32 mask = top_4_all_ones & ((out_3_equal & bottom_3_non_zero) | out_3_gt);
|
| out[0] -= 1 & mask;
|
| out[3] -= 0xffff000 & mask;
|
| out[4] -= 0xfffffff & mask;
|
| @@ -375,18 +415,15 @@ void Contract(FieldElement* inout) {
|
|
|
| using crypto::p224::Point;
|
|
|
| -// kP is the P224 prime.
|
| -const FieldElement kP = {
|
| - 1, 0, 0, 268431360,
|
| - 268435455, 268435455, 268435455, 268435455,
|
| -};
|
| -
|
| // kB is parameter of the elliptic curve.
|
| const FieldElement kB = {
|
| 55967668, 11768882, 265861671, 185302395,
|
| 39211076, 180311059, 84673715, 188764328,
|
| };
|
|
|
| +void CopyConditional(Point* out, const Point& a, uint32 mask);
|
| +void DoubleJacobian(Point* out, const Point& a);
|
| +
|
| // AddJacobian computes *out = a+b where a != b.
|
| void AddJacobian(Point *out,
|
| const Point& a,
|
| @@ -394,6 +431,9 @@ void AddJacobian(Point *out,
|
| // See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl
|
| FieldElement z1z1, z2z2, u1, u2, s1, s2, h, i, j, r, v;
|
|
|
| + uint32 z1_is_zero = IsZero(a.z);
|
| + uint32 z2_is_zero = IsZero(b.z);
|
| +
|
| // Z1Z1 = Z1²
|
| Square(&z1z1, a.z);
|
|
|
| @@ -417,6 +457,7 @@ void AddJacobian(Point *out,
|
| // H = U2-U1
|
| Subtract(&h, u2, u1);
|
| Reduce(&h);
|
| + uint32 x_equal = IsZero(h);
|
|
|
| // I = (2*H)²
|
| for (int j = 0; j < 8; j++) {
|
| @@ -430,6 +471,15 @@ void AddJacobian(Point *out,
|
| // r = 2*(S2-S1)
|
| Subtract(&r, s2, s1);
|
| Reduce(&r);
|
| + uint32 y_equal = IsZero(r);
|
| +
|
| + if (x_equal && y_equal && !z1_is_zero && !z2_is_zero) {
|
| + // The two input points are the same therefore we must use the dedicated
|
| + // doubling function as the slope of the line is undefined.
|
| + DoubleJacobian(out, a);
|
| + return;
|
| + }
|
| +
|
| for (int i = 0; i < 8; i++) {
|
| r[i] <<= 1;
|
| }
|
| @@ -467,6 +517,9 @@ void AddJacobian(Point *out,
|
| Mul(&z1z1, z1z1, r);
|
| Subtract(&out->y, z1z1, s1);
|
| Reduce(&out->y);
|
| +
|
| + CopyConditional(out, a, z2_is_zero);
|
| + CopyConditional(out, b, z1_is_zero);
|
| }
|
|
|
| // DoubleJacobian computes *out = a+a.
|
| @@ -542,16 +595,13 @@ void ScalarMult(Point* out, const Point& a,
|
| memset(out, 0, sizeof(*out));
|
| Point tmp;
|
|
|
| - uint32 first_bit = 0xffffffff;
|
| for (size_t i = 0; i < scalar_len; i++) {
|
| for (unsigned int bit_num = 0; bit_num < 8; bit_num++) {
|
| DoubleJacobian(out, *out);
|
| uint32 bit = static_cast<uint32>(static_cast<int32>(
|
| (((scalar[i] >> (7 - bit_num)) & 1) << 31) >> 31));
|
| AddJacobian(&tmp, a, *out);
|
| - CopyConditional(out, a, first_bit & bit);
|
| - CopyConditional(out, tmp, ~first_bit & bit);
|
| - first_bit = first_bit & ~bit;
|
| + CopyConditional(out, tmp, bit);
|
| }
|
| }
|
| }
|
| @@ -628,6 +678,12 @@ bool Point::SetFromString(const base::StringPiece& in) {
|
| std::string Point::ToString() const {
|
| FieldElement zinv, zinv_sq, x, y;
|
|
|
| + // If this is the point at infinity we return a string of all zeros.
|
| + if (IsZero(this->z)) {
|
| + static const char zeros[56] = {0};
|
| + return std::string(zeros, sizeof(zeros));
|
| + }
|
| +
|
| Invert(&zinv, this->z);
|
| Square(&zinv_sq, zinv);
|
| Mul(&x, this->x, zinv_sq);
|
|
|