Use bn_rshift_words for the ECDSA bit-shift.

May as well use it. Also avoid an overflow with digest_len if someone
asks to sign a truly enormous digest.

Change-Id: Ia0a53007a496f9c7cadd44b1020ec2774b310936
Reviewed-on: https://boringssl-review.googlesource.com/26966
Reviewed-by: Adam Langley <agl@google.com>
This commit is contained in:
David Benjamin 2018-03-31 21:56:00 -04:00 committed by Adam Langley
parent 0645c05f5e
commit 2257e8f3bf
3 changed files with 12 additions and 11 deletions

View File

@ -370,6 +370,11 @@ int bn_odd_number_is_obviously_composite(const BIGNUM *bn);
// bn_rshift1_words sets |r| to |a| >> 1, where both arrays are |num| bits wide. // bn_rshift1_words sets |r| to |a| >> 1, where both arrays are |num| bits wide.
void bn_rshift1_words(BN_ULONG *r, const BN_ULONG *a, size_t num); void bn_rshift1_words(BN_ULONG *r, const BN_ULONG *a, size_t num);
// bn_rshift_words sets |r| to |a| >> |shift|, where both arrays are |num| bits
// wide.
void bn_rshift_words(BN_ULONG *r, const BN_ULONG *a, unsigned shift,
size_t num);
// bn_rshift_secret_shift behaves like |BN_rshift| but runs in time independent // bn_rshift_secret_shift behaves like |BN_rshift| but runs in time independent
// of both |a| and |n|. // of both |a| and |n|.
OPENSSL_EXPORT int bn_rshift_secret_shift(BIGNUM *r, const BIGNUM *a, OPENSSL_EXPORT int bn_rshift_secret_shift(BIGNUM *r, const BIGNUM *a,

View File

@ -133,8 +133,8 @@ int BN_lshift1(BIGNUM *r, const BIGNUM *a) {
return 1; return 1;
} }
static void bn_rshift_words(BN_ULONG *r, const BN_ULONG *a, unsigned shift, void bn_rshift_words(BN_ULONG *r, const BN_ULONG *a, unsigned shift,
size_t num) { size_t num) {
unsigned shift_bits = shift % BN_BITS2; unsigned shift_bits = shift % BN_BITS2;
size_t shift_words = shift / BN_BITS2; size_t shift_words = shift / BN_BITS2;
if (shift_words >= num) { if (shift_words >= num) {

View File

@ -116,22 +116,18 @@ static void digest_to_scalar(const EC_GROUP *group, EC_LOOSE_SCALAR *out,
const BIGNUM *order = &group->order; const BIGNUM *order = &group->order;
size_t num_bits = BN_num_bits(order); size_t num_bits = BN_num_bits(order);
// Need to truncate digest if it is too long: first truncate whole bytes. // Need to truncate digest if it is too long: first truncate whole bytes.
if (8 * digest_len > num_bits) { size_t num_bytes = (num_bits + 7) / 8;
digest_len = (num_bits + 7) / 8; if (digest_len > num_bytes) {
digest_len = num_bytes;
} }
OPENSSL_memset(out, 0, sizeof(EC_SCALAR)); OPENSSL_memset(out, 0, sizeof(EC_SCALAR));
for (size_t i = 0; i < digest_len; i++) { for (size_t i = 0; i < digest_len; i++) {
out->bytes[i] = digest[digest_len - 1 - i]; out->bytes[i] = digest[digest_len - 1 - i];
} }
// If still too long truncate remaining bits with a shift // If it is still too long, truncate remaining bits with a shift.
if (8 * digest_len > num_bits) { if (8 * digest_len > num_bits) {
size_t shift = 8 - (num_bits & 0x7); bn_rshift_words(out->words, out->words, 8 - (num_bits & 0x7), order->width);
for (int i = 0; i < order->width - 1; i++) {
out->words[i] =
(out->words[i] >> shift) | (out->words[i + 1] << (BN_BITS2 - shift));
}
out->words[order->width - 1] >>= shift;
} }
} }