aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJörn Heissler <nosuchaddress@joern.heissler.de>2020-01-05 01:42:13 +0100
committerJörn Heissler <nosuchaddress@joern.heissler.de>2020-01-05 01:42:13 +0100
commit8fa8792edd5f6eb29e5b766350ef333543e000d1 (patch)
tree48b39ba2ae08a187986c08e695400bb992104d7b
parentc09b87c647150e1b4b1f65d7ebff4981ddfd6174 (diff)
downloadplatform_external_python_asn1crypto-8fa8792edd5f6eb29e5b766350ef333543e000d1.tar.gz
platform_external_python_asn1crypto-8fa8792edd5f6eb29e5b766350ef333543e000d1.tar.bz2
platform_external_python_asn1crypto-8fa8792edd5f6eb29e5b766350ef333543e000d1.zip
Fix parsing of ObjectIdentifier's first octet.
X.660 §7.6 specifies that the first arc of an OID must be 0 to 2 and the second arc below arcs 0 and 1 must be 0 to 39. Arc 2 is not restricted in that way. The algorithm for parsing ObjectIdentifiers did not work for OID 2.X with X >= 40. This change also enforces above restrictions when setting an ObjectIdentifier.
-rw-r--r--asn1crypto/core.py15
-rw-r--r--tests/test_core.py37
2 files changed, 46 insertions, 6 deletions
diff --git a/asn1crypto/core.py b/asn1crypto/core.py
index 933f8ca..2b79d11 100644
--- a/asn1crypto/core.py
+++ b/asn1crypto/core.py
@@ -3104,6 +3104,10 @@ class ObjectIdentifier(Primitive, ValueMap):
first = part
continue
elif index == 1:
+ if first > 2:
+ raise ValueError("First arc is restricted to 0,1,2")
+ elif first < 2 and part >= 40:
+ raise ValueError("Second arc is restricted to 0..39 if first arc is 0 or 1")
part = (first * 40) + part
encoded_part = chr_cls(0x7F & part)
@@ -3145,8 +3149,15 @@ class ObjectIdentifier(Primitive, ValueMap):
# Last byte in subidentifier has the eighth bit set to 0
if byte & 0x80 == 0:
if len(output) == 0:
- output.append(str_cls(part // 40))
- output.append(str_cls(part % 40))
+ if part >= 80:
+ output.append(str_cls(2))
+ output.append(str_cls(part - 80))
+ elif part >= 40:
+ output.append(str_cls(1))
+ output.append(str_cls(part - 40))
+ else:
+ output.append(str_cls(0))
+ output.append(str_cls(part))
else:
output.append(str_cls(part))
part = 0
diff --git a/tests/test_core.py b/tests/test_core.py
index b9a7a82..c339ae5 100644
--- a/tests/test_core.py
+++ b/tests/test_core.py
@@ -64,7 +64,7 @@ class NestSeqAny(core.Sequence):
_oid_pair = ('id', 'value')
_oid_specs = {
- '3.4.5': Seq,
+ '2.3.4.5': Seq,
}
@@ -76,7 +76,7 @@ class NestSeqExplicit(core.Sequence):
_oid_pair = ('id', 'value')
_oid_specs = {
- '3.4.5': Seq,
+ '2.3.4.5': Seq,
}
@@ -1314,14 +1314,14 @@ class CoreTests(unittest.TestCase):
def test_wrong_asn1value3(self):
with self.assertRaises(TypeError):
NestSeqAny({
- 'id': '3.4.5',
+ 'id': '2.3.4.5',
'value': core.Integer(1)
})
def test_wrong_asn1value4(self):
with self.assertRaises(TypeError):
NestSeqExplicit({
- 'id': '3.4.5',
+ 'id': '2.3.4.5',
'value': core.Integer(1)
})
@@ -1334,3 +1334,32 @@ class CoreTests(unittest.TestCase):
b.set_encoded_width(4)
self.assertEqual(1, b.native)
self.assertEqual(b'\x04\x04\x00\x00\x00\x01', b.dump())
+
+ @staticmethod
+ def object_identifier_info():
+ return (
+ ("0.0", b"\x06\x01\x00"),
+ ("0.39", b"\x06\x01\x27"),
+ ("1.0", b"\x06\x01\x28"),
+ ("1.39", b"\x06\x01\x4f"),
+ ("2.0", b"\x06\x01\x50"),
+ ("2.39", b"\x06\x01\x77"),
+ ("2.100.3", b"\x06\x03\x81\x34\x03"),
+ ("2.16.840.1.113730.1.1", b"\x06\x09\x60\x86\x48\x01\x86\xf8\x42\x01\x01"),
+ )
+
+ @data('object_identifier_info')
+ def object_identifier(self, native, der_bytes):
+ oid = core.ObjectIdentifier(native)
+ self.assertEqual(der_bytes, oid.dump())
+ self.assertEqual(native, core.ObjectIdentifier.load(der_bytes).native)
+
+ def test_broken_object_identifier(self):
+ with self.assertRaisesRegex(ValueError, "First arc is restricted"):
+ core.ObjectIdentifier("3.4.5")
+
+ with self.assertRaisesRegex(ValueError, "Second arc is restricted"):
+ core.ObjectIdentifier("1.100.1000")
+
+ with self.assertRaisesRegex(ValueError, "Second arc is restricted"):
+ core.ObjectIdentifier("0.40")