Skip to content

Commit e03dcc4

Browse files
committed
Make secp256k1_scalar_get_bits support 32-bit reads
The old code would trigger UB when count=32.
1 parent 5005abe commit e03dcc4

File tree

4 files changed

+15
-11
lines changed

4 files changed

+15
-11
lines changed

src/scalar.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@
2222
/** Clear a scalar to prevent the leak of sensitive data. */
2323
static void secp256k1_scalar_clear(secp256k1_scalar *r);
2424

25-
/** Access bits from a scalar. All requested bits must belong to the same 32-bit limb. */
25+
/** Access bits (1 < count <= 32) from a scalar. All requested bits must belong to the same 32-bit limb. */
2626
static uint32_t secp256k1_scalar_get_bits_limb32(const secp256k1_scalar *a, unsigned int offset, unsigned int count);
2727

28-
/** Access bits from a scalar. Not constant time in offset and count. */
28+
/** Access bits (1 < count <= 32) from a scalar. offset + count must be < 256. Not constant time in offset and count. */
2929
static uint32_t secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count);
3030

3131
/** Set a scalar from a big endian byte array. The scalar will be reduced modulo group order `n`.

src/scalar_4x64_impl.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,21 +47,22 @@ SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsig
4747

4848
SECP256K1_INLINE static uint32_t secp256k1_scalar_get_bits_limb32(const secp256k1_scalar *a, unsigned int offset, unsigned int count) {
4949
SECP256K1_SCALAR_VERIFY(a);
50+
VERIFY_CHECK(count > 0 && count <= 32);
5051
VERIFY_CHECK((offset + count - 1) >> 6 == offset >> 6);
5152

52-
return (a->d[offset >> 6] >> (offset & 0x3F)) & ((((uint64_t)1) << count) - 1);
53+
return (a->d[offset >> 6] >> (offset & 0x3F)) & (0xFFFFFFFF >> (32 - count));
5354
}
5455

5556
SECP256K1_INLINE static uint32_t secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count) {
5657
SECP256K1_SCALAR_VERIFY(a);
57-
VERIFY_CHECK(count < 32);
58+
VERIFY_CHECK(count > 0 && count <= 32);
5859
VERIFY_CHECK(offset + count <= 256);
5960

6061
if ((offset + count - 1) >> 6 == offset >> 6) {
6162
return secp256k1_scalar_get_bits_limb32(a, offset, count);
6263
} else {
6364
VERIFY_CHECK((offset >> 6) + 1 < 4);
64-
return ((a->d[offset >> 6] >> (offset & 0x3F)) | (a->d[(offset >> 6) + 1] << (64 - (offset & 0x3F)))) & ((((uint64_t)1) << count) - 1);
65+
return ((a->d[offset >> 6] >> (offset & 0x3F)) | (a->d[(offset >> 6) + 1] << (64 - (offset & 0x3F)))) & (0xFFFFFFFF >> (32 - count));
6566
}
6667
}
6768

src/scalar_8x32_impl.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,21 +64,22 @@ SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsig
6464

6565
SECP256K1_INLINE static uint32_t secp256k1_scalar_get_bits_limb32(const secp256k1_scalar *a, unsigned int offset, unsigned int count) {
6666
SECP256K1_SCALAR_VERIFY(a);
67+
VERIFY_CHECK(count > 0 && count <= 32);
6768
VERIFY_CHECK((offset + count - 1) >> 5 == offset >> 5);
6869

69-
return (a->d[offset >> 5] >> (offset & 0x1F)) & ((1 << count) - 1);
70+
return (a->d[offset >> 5] >> (offset & 0x1F)) & (0xFFFFFFFF >> (32 - count));
7071
}
7172

7273
SECP256K1_INLINE static uint32_t secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count) {
7374
SECP256K1_SCALAR_VERIFY(a);
74-
VERIFY_CHECK(count < 32);
75+
VERIFY_CHECK(count > 0 && count <= 32);
7576
VERIFY_CHECK(offset + count <= 256);
7677

7778
if ((offset + count - 1) >> 5 == offset >> 5) {
7879
return secp256k1_scalar_get_bits_limb32(a, offset, count);
7980
} else {
8081
VERIFY_CHECK((offset >> 5) + 1 < 8);
81-
return ((a->d[offset >> 5] >> (offset & 0x1F)) | (a->d[(offset >> 5) + 1] << (32 - (offset & 0x1F)))) & ((((uint32_t)1) << count) - 1);
82+
return ((a->d[offset >> 5] >> (offset & 0x1F)) | (a->d[(offset >> 5) + 1] << (32 - (offset & 0x1F)))) & (0xFFFFFFFF >> (32 - count));
8283
}
8384
}
8485

src/scalar_low_impl.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,12 @@ SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsig
3030
SECP256K1_INLINE static uint32_t secp256k1_scalar_get_bits_limb32(const secp256k1_scalar *a, unsigned int offset, unsigned int count) {
3131
SECP256K1_SCALAR_VERIFY(a);
3232

33-
if (offset < 32)
34-
return ((*a >> offset) & ((((uint32_t)1) << count) - 1));
35-
else
33+
VERIFY_CHECK(count > 0 && count <= 32);
34+
if (offset < 32) {
35+
return (*a >> offset) & (0xFFFFFFFF >> (32 - count));
36+
} else {
3637
return 0;
38+
}
3739
}
3840

3941
SECP256K1_INLINE static uint32_t secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count) {

0 commit comments

Comments
 (0)