Skip to content

Commit f1a8280

Browse files
librpc:bcrypt_rsakey_blob: exponent and modulus lengths can't be zero
Apart from it making no sense, without these ranges we end up allocating a NULL buffer and aborting. We also put a maximum size on the RSA key, in case we could get tricked into a DoS by pulling a large buffer and trying crypto maths on it. 6 0x572ebce2749a in talloc_abort samba/lib/talloc/talloc.c:506:3 7 0x572ebce271d4 in talloc_chunk_from_ptr samba/lib/talloc/talloc.c:0 8 0x572ebce271d4 in __talloc_with_prefix samba/lib/talloc/talloc.c:762:12 9 0x572ebce235f9 in __talloc samba/lib/talloc/talloc.c:825:9 10 0x572ebce235f9 in _talloc_named_const samba/lib/talloc/talloc.c:982:8 11 0x572ebce235f9 in _talloc_memdup samba/lib/talloc/talloc.c:2441:9 12 0x572ebc8f6a4f in data_blob_talloc_named samba/lib/util/data_blob.c:56:25 13 0x572ebc7d23bd in pull_BCRYPT_RSAPUBLIC_BLOB samba/librpc/ndr/ndr_keycredlink.c:878:17 14 0x572ebc7d23bd in ndr_pull_KeyMaterialInternal samba/librpc/ndr/ndr_keycredlink.c:959:10 15 0x572ebc788e90 in LLVMFuzzerTestOneInput samba/bin/default/lib/fuzzing/fuzz_ndr_keycredlink_TYPE_STRUCT.c:282:13 REF: https://issues.oss-fuzz.com/issues/435039896 Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz> Reviewed-by: Gary Lockyer <gary@catalyst.net.nz> Autobuild-User(master): Douglas Bagnall <dbagnall@samba.org> Autobuild-Date(master): Thu Jul 31 05:45:07 UTC 2025 on atb-devel-224
1 parent c1ee6fe commit f1a8280

File tree

2 files changed

+35
-31
lines changed

2 files changed

+35
-31
lines changed

librpc/idl/bcrypt_rsakey_blob.idl

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,22 @@ interface bcrypt_rsakey_blob
2121
/* Currently only handle RSA Public Key blobs */
2222
[value(0x31415352), range(0x31415352, 0x31415352)]
2323
uint32 magic; /* RSA1 */
24-
uint32 bit_length;
24+
/*
25+
* In key_credential_links we expect bit_length to be
26+
* 2048, but we accept a wider range in part because
27+
* testing is much easier with small numbers.
28+
*/
29+
[range(1,65536)]uint32 bit_length;
2530
/*
2631
* As of Windows 10 version 1903, public exponents larger
2732
* than (2^64 - 1) are no longer supported.
2833
*/
29-
[range(0x0,0x8)] uint32 public_exponent_len;
30-
uint32 modulus_len;
34+
[range(0x1,0x8)] uint32 public_exponent_len;
35+
/*
36+
* modulus_len is the key size in bytes, more or less
37+
* bit_length / 8.
38+
*/
39+
[range(0x1, 0x2001)] uint32 modulus_len;
3140
/*
3241
* We're only supporting public keys, so the private
3342
* key prime lengths should be zero

python/samba/tests/bcrypt_rsakey_blob.py

Lines changed: 23 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ class BcryptRsaKeyBlobTests(TestCase):
3535
def test_unpack_empty_key_blob(self):
3636
"""
3737
Ensure that a minimal header only BCRYPT_RSAPUBLIC_BLOB
38-
can be unpacked, then packed into identical bytes
38+
can't be unpacked, because it would imply zero length modulus
39+
and exponent numbers, which is meaningless.
3940
"""
4041
empty_key_blob = bytes.fromhex(
4142
"52 53 41 31" # Magic value RSA1
@@ -45,20 +46,11 @@ def test_unpack_empty_key_blob(self):
4546
"00 00 00 00" # prime one length"
4647
"00 00 00 00" # prime two length"
4748
)
48-
blob = ndr_unpack(
49-
bcrypt_rsakey_blob.BCRYPT_RSAPUBLIC_BLOB, empty_key_blob)
50-
51-
self.assertEqual(blob.magic, 0x31415352)
52-
self.assertEqual(blob.bit_length, 0)
53-
self.assertEqual(blob.public_exponent_len, 0)
54-
self.assertEqual(blob.modulus_len, 0)
55-
self.assertEqual(blob.prime1_len_unused, 0)
56-
self.assertEqual(blob.prime2_len_unused, 0)
57-
self.assertEqual(len(blob.public_exponent), 0)
58-
self.assertEqual(len(blob.modulus), 0)
59-
60-
packed = ndr_pack(blob)
61-
self.assertEqual(empty_key_blob, packed)
49+
with self.assertRaises(RuntimeError) as e:
50+
ndr_unpack(bcrypt_rsakey_blob.BCRYPT_RSAPUBLIC_BLOB,
51+
empty_key_blob)
52+
self.assertEqual(e.exception.args[0], 13)
53+
self.assertEqual(e.exception.args[1], "Range Error")
6254

6355
def test_unpack_invalid_magic(self):
6456
"""
@@ -67,11 +59,12 @@ def test_unpack_invalid_magic(self):
6759
"""
6860
invalid_magic_key_blob = bytes.fromhex(
6961
"52 53 41 30" # Magic value RSA0
70-
"00 00 00 00" # bit length
71-
"00 00 00 00" # public exponent length
72-
"00 00 00 00" # modulus length
62+
"04 00 00 00" # bit length
63+
"01 00 00 00" # public exponent length
64+
"01 00 00 00" # modulus length
7365
"00 00 00 00" # prime one length
7466
"00 00 00 00" # prime two length"
67+
"01 02" # exponent and modulus, one byte each
7568
)
7669
with self.assertRaises(RuntimeError) as e:
7770
ndr_unpack(bcrypt_rsakey_blob.BCRYPT_RSAPUBLIC_BLOB,
@@ -87,11 +80,12 @@ def test_unpack_extra_data(self):
8780
"""
8881
extra_data_key_blob = bytes.fromhex(
8982
"52 53 41 31" # Magic value RSA1
90-
"00 00 00 00" # bit length
91-
"00 00 00 00" # public exponent length
92-
"00 00 00 00" # modulus length
83+
"04 00 00 00" # bit length
84+
"01 00 00 00" # public exponent length
85+
"01 00 00 00" # modulus length
9386
"00 00 00 00" # prime one length
9487
"00 00 00 00" # prime two length
88+
"01 02" # exponent and modulus, one byte each
9589
"01" # a trailing byte of data
9690
)
9791
with self.assertRaises(RuntimeError) as e:
@@ -127,9 +121,9 @@ def test_unpack_invalid_exponent_length(self):
127121
"""
128122
invalid_magic_key_blob = bytes.fromhex(
129123
"52 53 41 31" # Magic value RSA1
130-
"00 00 00 00" # bit length
124+
"08 00 00 00" # bit length
131125
"09 00 00 00" # public exponent length, 9 bytes
132-
"00 00 00 00" # modulus length
126+
"01 00 00 00" # modulus length
133127
"00 00 00 00" # prime one length
134128
"00 00 00 00" # prime two length"
135129
)
@@ -147,11 +141,12 @@ def test_unpack_non_zero_prime1(self):
147141
"""
148142
invalid_prime1_key_blob = bytes.fromhex(
149143
"52 53 41 31" # Magic value RSA1
150-
"00 00 00 00" # bit length
151-
"00 00 00 00" # public exponent length, 9 bytes
152-
"00 00 00 00" # modulus length
144+
"04 00 00 00" # bit length
145+
"01 00 00 00" # public exponent length
146+
"01 00 00 00" # modulus length
153147
"01 00 00 00" # prime one length
154148
"00 00 00 00" # prime two length"
149+
"01 02" # exponent and modulus, one byte each
155150
)
156151
with self.assertRaises(RuntimeError) as e:
157152
ndr_unpack(bcrypt_rsakey_blob.BCRYPT_RSAPUBLIC_BLOB,
@@ -168,8 +163,8 @@ def test_unpack_non_zero_prime2(self):
168163
invalid_prime2_key_blob = bytes.fromhex(
169164
"52 53 41 31" # Magic value RSA1
170165
"00 00 00 00" # bit length
171-
"00 00 00 00" # public exponent length, 9 bytes
172-
"00 00 00 00" # modulus length
166+
"01 00 00 00" # public exponent length
167+
"01 00 00 00" # modulus length
173168
"00 00 00 00" # prime one length
174169
"01 00 00 00" # prime two length"
175170
)

0 commit comments

Comments
 (0)