Skip to content

Commit bd66899

Browse files
authored
Merge commit from fork
DER: reject truncated lengths and add regression tests
2 parents 55aca78 + 9c046ee commit bd66899

File tree

2 files changed

+26
-0
lines changed

2 files changed

+26
-0
lines changed

src/ecdsa/der.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,8 @@ def remove_constructed(string):
163163
)
164164
tag = s0 & 0x1F
165165
length, llen = read_length(string[1:])
166+
if length > len(string) - 1 - llen:
167+
raise UnexpectedDER("Length longer than the provided buffer")
166168
body = string[1 + llen : 1 + llen + length]
167169
rest = string[1 + llen + length :]
168170
return tag, body, rest
@@ -206,6 +208,8 @@ def remove_implicit(string, exp_class="context-specific"):
206208

207209
tag = s0 & 0x1F
208210
length, llen = read_length(string[1:])
211+
if length > len(string) - 1 - llen:
212+
raise UnexpectedDER("Length longer than the provided buffer")
209213
body = string[1 + llen : 1 + llen + length]
210214
rest = string[1 + llen + length :]
211215
return tag, body, rest
@@ -229,6 +233,8 @@ def remove_octet_string(string):
229233
n = str_idx_as_int(string, 0)
230234
raise UnexpectedDER("wanted type 'octetstring' (0x04), got 0x%02x" % n)
231235
length, llen = read_length(string[1:])
236+
if length > len(string) - 1 - llen:
237+
raise UnexpectedDER("Length longer than the provided buffer")
232238
body = string[1 + llen : 1 + llen + length]
233239
rest = string[1 + llen + length :]
234240
return body, rest

src/ecdsa/test_der.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -600,3 +600,23 @@ def test_oids(ids):
600600
decoded_oid, rest = remove_object(encoded_oid)
601601
assert rest == b""
602602
assert decoded_oid == ids
603+
604+
def test_remove_octet_string_rejects_truncated_length():
605+
# OCTET STRING: declared length 4096, but only 3 bytes present
606+
bad = b"\x04\x82\x10\x00" + b"ABC"
607+
with pytest.raises(UnexpectedDER, match="Length longer than the provided buffer"):
608+
remove_octet_string(bad)
609+
610+
def test_remove_constructed_rejects_truncated_length():
611+
# Constructed tag: 0xA0 (context-specific constructed, tag=0)
612+
# declared length 4096, but only 3 bytes present
613+
bad = b"\xA0\x82\x10\x00" + b"ABC"
614+
with pytest.raises(UnexpectedDER, match="Length longer than the provided buffer"):
615+
remove_constructed(bad)
616+
617+
def test_remove_implicit_rejects_truncated_length():
618+
# IMPLICIT primitive context-specific tag 0: 0x80
619+
# declared length 4096, but only 3 bytes present
620+
bad = b"\x80\x82\x10\x00" + b"ABC"
621+
with pytest.raises(UnexpectedDER, match="Length longer than the provided buffer"):
622+
remove_implicit(bad)

0 commit comments

Comments
 (0)