Detect truncated ASN data as UnparsableKeyError
This commit is contained in:
+40
-38
@@ -53,44 +53,46 @@ def asn1_parse(template, data):
|
|||||||
data = bytearray(data)
|
data = bytearray(data)
|
||||||
r = []
|
r = []
|
||||||
i = 0
|
i = 0
|
||||||
for t in template:
|
try:
|
||||||
tag = data[i]
|
for t in template:
|
||||||
i += 1
|
tag = data[i]
|
||||||
if tag == t[0]:
|
i += 1
|
||||||
length = data[i]
|
if tag == t[0]:
|
||||||
i += 1
|
length = data[i]
|
||||||
if length & 0x80:
|
i += 1
|
||||||
n = length & 0x7f
|
if length & 0x80:
|
||||||
length = 0
|
n = length & 0x7f
|
||||||
for j in range(n):
|
length = 0
|
||||||
length = (length << 8) | data[i]
|
for j in range(n):
|
||||||
i += 1
|
length = (length << 8) | data[i]
|
||||||
if tag == INTEGER:
|
i += 1
|
||||||
n = 0
|
if tag == INTEGER:
|
||||||
for j in range(length):
|
n = 0
|
||||||
n = (n << 8) | data[i]
|
for j in range(length):
|
||||||
i += 1
|
n = (n << 8) | data[i]
|
||||||
r.append(n)
|
i += 1
|
||||||
elif tag == BIT_STRING:
|
r.append(n)
|
||||||
r.append(data[i:i+length])
|
elif tag == BIT_STRING:
|
||||||
i += length
|
r.append(data[i:i+length])
|
||||||
elif tag == NULL:
|
i += length
|
||||||
assert length == 0
|
elif tag == NULL:
|
||||||
r.append(None)
|
assert length == 0
|
||||||
elif tag == OBJECT_IDENTIFIER:
|
r.append(None)
|
||||||
r.append(data[i:i+length])
|
elif tag == OBJECT_IDENTIFIER:
|
||||||
i += length
|
r.append(data[i:i+length])
|
||||||
elif tag == SEQUENCE:
|
i += length
|
||||||
r.append(asn1_parse(t[1], data[i:i+length]))
|
elif tag == SEQUENCE:
|
||||||
i += length
|
r.append(asn1_parse(t[1], data[i:i+length]))
|
||||||
else:
|
i += length
|
||||||
raise ASN1FormatError(
|
else:
|
||||||
"Unexpected tag in template: %02x" % tag)
|
raise ASN1FormatError(
|
||||||
else:
|
"Unexpected tag in template: %02x" % tag)
|
||||||
raise ASN1FormatError(
|
else:
|
||||||
"Unexpected tag (got %02x, expecting %02x)" % (tag, t[0]))
|
raise ASN1FormatError(
|
||||||
return r
|
"Unexpected tag (got %02x, expecting %02x)" % (tag, t[0]))
|
||||||
|
return r
|
||||||
|
except IndexError:
|
||||||
|
raise ASN1FormatError("Data truncated at byte %d"%i)
|
||||||
|
|
||||||
def asn1_length(n):
|
def asn1_length(n):
|
||||||
"""Return a string representing a field length in ASN.1 format.
|
"""Return a string representing a field length in ASN.1 format.
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
v=DKIM1; g=*; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDkHlOQoBTzWRiGs5V6NpP3idY6Wk08a5qhdR6wy5bdOKb2jLQiY/J16JYi0Qvx/byYzCNb3W91y3FutACDfzwQ/BC/e/8uBsCR+yz1Lxj+PL6lHvqMKrM3rG4hstT5QjvHO9PzoxZyVYLzBfO2EeC3Ip3G+2kryOTIKT+l/K4w3QIDAQA=
|
||||||
@@ -23,6 +23,7 @@ import unittest
|
|||||||
|
|
||||||
from dkim.crypto import (
|
from dkim.crypto import (
|
||||||
DigestTooLargeError,
|
DigestTooLargeError,
|
||||||
|
UnparsableKeyError,
|
||||||
EMSA_PKCS1_v1_5_encode,
|
EMSA_PKCS1_v1_5_encode,
|
||||||
int2str,
|
int2str,
|
||||||
parse_pem_private_key,
|
parse_pem_private_key,
|
||||||
@@ -108,7 +109,11 @@ class TestParseKeys(unittest.TestCase):
|
|||||||
key = parse_public_key(base64.b64decode(parse_tag_value(data)[b'p']))
|
key = parse_public_key(base64.b64decode(parse_tag_value(data)[b'p']))
|
||||||
self.assertEqual(key['modulus'], TEST_KEY_MODULUS)
|
self.assertEqual(key['modulus'], TEST_KEY_MODULUS)
|
||||||
self.assertEqual(key['publicExponent'], TEST_KEY_PUBLIC_EXPONENT)
|
self.assertEqual(key['publicExponent'], TEST_KEY_PUBLIC_EXPONENT)
|
||||||
|
try:
|
||||||
|
data = read_test_data('test_bad.txt')
|
||||||
|
key = parse_public_key(base64.b64decode(parse_tag_value(data)[b'p']))
|
||||||
|
except UnparsableKeyError: return
|
||||||
|
self.fail("failed to reject invalid public key")
|
||||||
|
|
||||||
class TestEMSA_PKCS1_v1_5(unittest.TestCase):
|
class TestEMSA_PKCS1_v1_5(unittest.TestCase):
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user