Detect truncated ASN data as UnparsableKeyError

This commit is contained in:
Stuart D. Gathman
2013-03-13 23:41:01 -04:00
parent d7d0979a7e
commit 188515ddf7
3 changed files with 47 additions and 39 deletions
+40 -38
View File
@@ -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.
+1
View File
@@ -0,0 +1 @@
v=DKIM1; g=*; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDkHlOQoBTzWRiGs5V6NpP3idY6Wk08a5qhdR6wy5bdOKb2jLQiY/J16JYi0Qvx/byYzCNb3W91y3FutACDfzwQ/BC/e/8uBsCR+yz1Lxj+PL6lHvqMKrM3rG4hstT5QjvHO9PzoxZyVYLzBfO2EeC3Ip3G+2kryOTIKT+l/K4w3QIDAQA=
+6 -1
View File
@@ -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):