diff --git a/dkim/asn1.py b/dkim/asn1.py index 79ebeaf..0bb8bbd 100644 --- a/dkim/asn1.py +++ b/dkim/asn1.py @@ -53,44 +53,46 @@ def asn1_parse(template, data): data = bytearray(data) r = [] i = 0 - for t in template: - tag = data[i] - i += 1 - if tag == t[0]: - length = data[i] - i += 1 - if length & 0x80: - n = length & 0x7f - length = 0 - for j in range(n): - length = (length << 8) | data[i] - i += 1 - if tag == INTEGER: - n = 0 - for j in range(length): - n = (n << 8) | data[i] - i += 1 - r.append(n) - elif tag == BIT_STRING: - r.append(data[i:i+length]) - i += length - elif tag == NULL: - assert length == 0 - r.append(None) - elif tag == OBJECT_IDENTIFIER: - r.append(data[i:i+length]) - i += length - elif tag == SEQUENCE: - r.append(asn1_parse(t[1], data[i:i+length])) - i += length - else: - raise ASN1FormatError( - "Unexpected tag in template: %02x" % tag) - else: - raise ASN1FormatError( - "Unexpected tag (got %02x, expecting %02x)" % (tag, t[0])) - return r - + try: + for t in template: + tag = data[i] + i += 1 + if tag == t[0]: + length = data[i] + i += 1 + if length & 0x80: + n = length & 0x7f + length = 0 + for j in range(n): + length = (length << 8) | data[i] + i += 1 + if tag == INTEGER: + n = 0 + for j in range(length): + n = (n << 8) | data[i] + i += 1 + r.append(n) + elif tag == BIT_STRING: + r.append(data[i:i+length]) + i += length + elif tag == NULL: + assert length == 0 + r.append(None) + elif tag == OBJECT_IDENTIFIER: + r.append(data[i:i+length]) + i += length + elif tag == SEQUENCE: + r.append(asn1_parse(t[1], data[i:i+length])) + i += length + else: + raise ASN1FormatError( + "Unexpected tag in template: %02x" % tag) + else: + raise ASN1FormatError( + "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): """Return a string representing a field length in ASN.1 format. diff --git a/dkim/tests/data/test_bad.txt b/dkim/tests/data/test_bad.txt new file mode 100644 index 0000000..0ab8016 --- /dev/null +++ b/dkim/tests/data/test_bad.txt @@ -0,0 +1 @@ +v=DKIM1; g=*; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDkHlOQoBTzWRiGs5V6NpP3idY6Wk08a5qhdR6wy5bdOKb2jLQiY/J16JYi0Qvx/byYzCNb3W91y3FutACDfzwQ/BC/e/8uBsCR+yz1Lxj+PL6lHvqMKrM3rG4hstT5QjvHO9PzoxZyVYLzBfO2EeC3Ip3G+2kryOTIKT+l/K4w3QIDAQA= diff --git a/dkim/tests/test_crypto.py b/dkim/tests/test_crypto.py index 6c55f44..4cc841e 100644 --- a/dkim/tests/test_crypto.py +++ b/dkim/tests/test_crypto.py @@ -23,6 +23,7 @@ import unittest from dkim.crypto import ( DigestTooLargeError, + UnparsableKeyError, EMSA_PKCS1_v1_5_encode, int2str, parse_pem_private_key, @@ -108,7 +109,11 @@ class TestParseKeys(unittest.TestCase): key = parse_public_key(base64.b64decode(parse_tag_value(data)[b'p'])) self.assertEqual(key['modulus'], TEST_KEY_MODULUS) 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):