From 2257e8f3bfa096baab1799560e210cf219cda855 Mon Sep 17 00:00:00 2001 From: David Benjamin Date: Sat, 31 Mar 2018 21:56:00 -0400 Subject: [PATCH] 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 --- crypto/fipsmodule/bn/internal.h | 5 +++++ crypto/fipsmodule/bn/shift.c | 4 ++-- crypto/fipsmodule/ecdsa/ecdsa.c | 14 +++++--------- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/crypto/fipsmodule/bn/internal.h b/crypto/fipsmodule/bn/internal.h index 7d96151a..8c121a07 100644 --- a/crypto/fipsmodule/bn/internal.h +++ b/crypto/fipsmodule/bn/internal.h @@ -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. 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 // of both |a| and |n|. OPENSSL_EXPORT int bn_rshift_secret_shift(BIGNUM *r, const BIGNUM *a, diff --git a/crypto/fipsmodule/bn/shift.c b/crypto/fipsmodule/bn/shift.c index 3e717396..ccf7141a 100644 --- a/crypto/fipsmodule/bn/shift.c +++ b/crypto/fipsmodule/bn/shift.c @@ -133,8 +133,8 @@ int BN_lshift1(BIGNUM *r, const BIGNUM *a) { return 1; } -static void bn_rshift_words(BN_ULONG *r, const BN_ULONG *a, unsigned shift, - size_t num) { +void bn_rshift_words(BN_ULONG *r, const BN_ULONG *a, unsigned shift, + size_t num) { unsigned shift_bits = shift % BN_BITS2; size_t shift_words = shift / BN_BITS2; if (shift_words >= num) { diff --git a/crypto/fipsmodule/ecdsa/ecdsa.c b/crypto/fipsmodule/ecdsa/ecdsa.c index 1d08123b..2f73718a 100644 --- a/crypto/fipsmodule/ecdsa/ecdsa.c +++ b/crypto/fipsmodule/ecdsa/ecdsa.c @@ -116,22 +116,18 @@ static void digest_to_scalar(const EC_GROUP *group, EC_LOOSE_SCALAR *out, const BIGNUM *order = &group->order; size_t num_bits = BN_num_bits(order); // Need to truncate digest if it is too long: first truncate whole bytes. - if (8 * digest_len > num_bits) { - digest_len = (num_bits + 7) / 8; + size_t num_bytes = (num_bits + 7) / 8; + if (digest_len > num_bytes) { + digest_len = num_bytes; } OPENSSL_memset(out, 0, sizeof(EC_SCALAR)); for (size_t i = 0; i < digest_len; 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) { - size_t shift = 8 - (num_bits & 0x7); - 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; + bn_rshift_words(out->words, out->words, 8 - (num_bits & 0x7), order->width); } }