aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuss Housley <housley@vigilsec.com>2019-10-22 16:50:27 -0400
committerIlya Etingof <etingof@gmail.com>2019-10-22 22:50:27 +0200
commite6aca617f808e2ae1ddcc0c1221a41eef73644b4 (patch)
treebb1bae6903cd368d4783c7664279ad28339881c6
parenta080f0bfbcd43a84a95e6118e0b258dd2184f28d (diff)
downloadpyasn1-modules-e6aca617f808e2ae1ddcc0c1221a41eef73644b4.tar.gz
Add support for RFC 6486 (#90)
-rw-r--r--CHANGES.txt1
-rw-r--r--pyasn1_modules/rfc6486.py68
-rw-r--r--tests/__main__.py1
-rw-r--r--tests/test_rfc6486.py123
4 files changed, 193 insertions, 0 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index 2b942e6..006a913 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -10,6 +10,7 @@ Revision 0.2.8, released XX-XX-2019
- Added RFC6960 providing Online Certificate Status Protocol (OCSP)
- Added RFC6955 providing Diffie-Hellman Proof-of-Possession Algorithms
- Updated the handling of maps for use with openType for RFC 3279
+- Added RFC6486 providing RPKI Manifests
Revision 0.2.7, released 09-10-2019
-----------------------------------
diff --git a/pyasn1_modules/rfc6486.py b/pyasn1_modules/rfc6486.py
new file mode 100644
index 0000000..31c936a
--- /dev/null
+++ b/pyasn1_modules/rfc6486.py
@@ -0,0 +1,68 @@
+#
+# This file is part of pyasn1-modules software.
+#
+# Created by Russ Housley with assistance from asn1ate v.0.6.0.
+#
+# Copyright (c) 2019, Vigil Security, LLC
+# License: http://snmplabs.com/pyasn1/license.html
+#
+# RPKI Manifests
+#
+# ASN.1 source from:
+# https://www.rfc-editor.org/rfc/rfc6486.txt
+#
+
+from pyasn1.type import char
+from pyasn1.type import constraint
+from pyasn1.type import namedtype
+from pyasn1.type import tag
+from pyasn1.type import useful
+from pyasn1.type import univ
+
+from pyasn1_modules import rfc5652
+
+MAX = float('inf')
+
+
+id_smime = univ.ObjectIdentifier('1.2.840.113549.1.9.16')
+
+id_ct = id_smime + (1, )
+
+id_ct_rpkiManifest = id_ct + (26, )
+
+
+class FileAndHash(univ.Sequence):
+ componentType = namedtype.NamedTypes(
+ namedtype.NamedType('file', char.IA5String()),
+ namedtype.NamedType('hash', univ.BitString())
+ )
+
+
+class Manifest(univ.Sequence):
+ componentType = namedtype.NamedTypes(
+ namedtype.DefaultedNamedType('version',
+ univ.Integer().subtype(explicitTag=tag.Tag(
+ tag.tagClassContext, tag.tagFormatSimple, 0)).subtype(value=0)),
+ namedtype.NamedType('manifestNumber',
+ univ.Integer().subtype(
+ subtypeSpec=constraint.ValueRangeConstraint(0, MAX))),
+ namedtype.NamedType('thisUpdate',
+ useful.GeneralizedTime()),
+ namedtype.NamedType('nextUpdate',
+ useful.GeneralizedTime()),
+ namedtype.NamedType('fileHashAlg',
+ univ.ObjectIdentifier()),
+ namedtype.NamedType('fileList',
+ univ.SequenceOf(componentType=FileAndHash()).subtype(
+ subtypeSpec=constraint.ValueSizeConstraint(0, MAX)))
+ )
+
+
+# Map of Content Type OIDs to Content Types added to the
+# ones that are in rfc5652.py
+
+_cmsContentTypesMapUpdate = {
+ id_ct_rpkiManifest: Manifest(),
+}
+
+rfc5652.cmsContentTypesMap.update(_cmsContentTypesMapUpdate)
diff --git a/tests/__main__.py b/tests/__main__.py
index c852b56..48e674d 100644
--- a/tests/__main__.py
+++ b/tests/__main__.py
@@ -59,6 +59,7 @@ suite = unittest.TestLoader().loadTestsFromNames(
'tests.test_rfc6032.suite',
'tests.test_rfc6210.suite',
'tests.test_rfc6211.suite',
+ 'tests.test_rfc6486.suite',
'tests.test_rfc6955.suite',
'tests.test_rfc6960.suite',
'tests.test_rfc7030.suite',
diff --git a/tests/test_rfc6486.py b/tests/test_rfc6486.py
new file mode 100644
index 0000000..70e9160
--- /dev/null
+++ b/tests/test_rfc6486.py
@@ -0,0 +1,123 @@
+#
+# This file is part of pyasn1-modules software.
+#
+# Copyright (c) 2019, Vigil Security, LLC
+# License: http://snmplabs.com/pyasn1/license.html
+#
+import sys
+
+from pyasn1.codec.der.decoder import decode as der_decode
+from pyasn1.codec.der.encoder import encode as der_encode
+
+from pyasn1_modules import pem
+from pyasn1_modules import rfc5652
+from pyasn1_modules import rfc6486
+
+try:
+ import unittest2 as unittest
+except ImportError:
+ import unittest
+
+
+class SignedManifestTestCase(unittest.TestCase):
+ manifest_pem_text = """\
+MIIHVAYJKoZIhvcNAQcCoIIHRTCCB0ECAQMxDTALBglghkgBZQMEAgEwgYwGCyqGSIb3DQEJ
+EAEaoH0EezB5AgIK5xgPMjAxMjEwMjMyMjI2MDNaGA8yMDEyMTAyNTIyMjYwM1oGCWCGSAFl
+AwQCATBGMEQWH1pYU0dCREJrTDgyVEZHSHVFNFZPWXRKUC1FNC5jcmwDIQCzTdC3GsuONsRq
+RFnYf8+AJ2NnCIgmnc3O8PyfGvn18aCCBO4wggTqMIID0qADAgECAgIK5zANBgkqhkiG9w0B
+AQsFADATMREwDwYDVQQDEwhBOTE5OTg4NTAeFw0xMjEwMjMyMjI2MDNaFw0xMjEwMjUyMjI2
+MDNaMBgxFjAUBgNVBAMTDTUwODcxOTdjLTIwZjcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQDEl4R4LiCs6zyR/IAeaRCfz0O0mXXAUKt8bmG6DXzaDYNG8dnBjbrsM1L05sb4
+2Ti4TyE1UXtwFFEwatsFQ2uRBn9gsKmDGOjW8TH1AYObmZW+hZlEN7OLSz2bmPLtxIMwiCq/
+vqmBJlMWPyCSym4iPnjzwWbJechqHSiTMOYGICF1QSW5xjJDAhRfeZG3nRY7TqfW8R2KJXeN
+cKSYSGNKzv79B8GCswmwU8J8kcuryIiqb7WtcK2B6VBsROIQHGXM0UV4Zbnvv9m9Fl0SjvZJ
+XyrzRjGzV2C00hM0f4jAplD9nJhAJ7nOTe8OnadrFABRga+Ge1HooeDQJGmTekLXAgMBAAGj
+ggJBMIICPTAdBgNVHQ4EFgQUbcbOyNBHkRXXDaMq51jC7vOSHFUwHwYDVR0jBBgwFoAUZXSG
+BDBkL82TFGHuE4VOYtJP+E4wDgYDVR0PAQH/BAQDAgeAMIGDBgNVHR8EfDB6MHigdqB0hnJy
+c3luYzovL3Jwa2kuYXBuaWMubmV0L21lbWJlcl9yZXBvc2l0b3J5L0E5MTk5ODg1LzY1RkQ0
+M0FBNUJFRjExREZBQjYxQjNFNzU1QUZFN0NGL1pYU0dCREJrTDgyVEZHSHVFNFZPWXRKUC1F
+NC5jcmwwfgYIKwYBBQUHAQEEcjBwMG4GCCsGAQUFBzAChmJyc3luYzovL3Jwa2kuYXBuaWMu
+bmV0L3JlcG9zaXRvcnkvQTNDMzhBMjRENjAzMTFEQ0FCMDhGMzE5NzlCREJFMzkvWlhTR0JE
+QmtMODJURkdIdUU0Vk9ZdEpQLUU0LmNlcjAYBgNVHSABAf8EDjAMMAoGCCsGAQUFBw4CMIGQ
+BggrBgEFBQcBCwSBgzCBgDB+BggrBgEFBQcwC4ZycnN5bmM6Ly9ycGtpLmFwbmljLm5ldC9t
+ZW1iZXJfcmVwb3NpdG9yeS9BOTE5OTg4NS82NUZENDNBQTVCRUYxMURGQUI2MUIzRTc1NUFG
+RTdDRi9aWFNHQkRCa0w4MlRGR0h1RTRWT1l0SlAtRTQubWZ0MBUGCCsGAQUFBwEIAQH/BAYw
+BKACBQAwIQYIKwYBBQUHAQcBAf8EEjAQMAYEAgABBQAwBgQCAAIFADANBgkqhkiG9w0BAQsF
+AAOCAQEAyBl1J+ql1O3d6JiaQEG2UAjDSKHSMVau++QcB6/yd4RuWv2KpQxk1cp+awf4Ttoh
+GYakbUZQl7lJaXzbluG5siRSv6AowEWxf99iLhDx+pE1htklRfmmTE9oFpKnITAYZAUjarNC
+sYGCZ00vSwRu27OdpSQbZQ7WdyDAhyHS0Sun0pkImVSqPO11gqyKV9ZCwCJUa5U/zsWDMNrj
+MSZl1I3VoPs2rx997rLoiQiMqwGeoqfl7snpsL9OR/CazPmepuq3SyZNWcCrUGcGRhRdGScj
+Tm2EHne1GiRHapn46HWQ3am8jumEKv5u0gLT4Mi9CyZwkDyhotGTJZmdAmN7zzGCAaowggGm
+AgEDgBRtxs7I0EeRFdcNoyrnWMLu85IcVTALBglghkgBZQMEAgGgazAaBgkqhkiG9w0BCQMx
+DQYLKoZIhvcNAQkQARowHAYJKoZIhvcNAQkFMQ8XDTEyMTAyMzIyMjYwNFowLwYJKoZIhvcN
+AQkEMSIEIIu2XV8dT+rqQy5Cbpm3Tv5I1dwkLK8n2GesMGOr6/pEMA0GCSqGSIb3DQEBAQUA
+BIIBAFsd0zkl4dIHrqZts441T+w/5/ekymDLFwftk6W+Mi35Htjvm2IHOthnKHQsK5h6dnEh
+6DfNfc6tACmzLnM+UG7ve+uAhfpA+CUJIoVhpQvDH7Ntql0cD1X3d9ng484jpkVoHhbUIYNR
+TyxvV4DV5EBbLYpx2HYf6wWa8TCobxUXNtw53OVA24ceavS+KvuDa0JQPFpbYUCS0UPMt/Im
+mtKrWTmRUr8sYWdIQn+SStUh8iAR5rmSVr+Pe7aFbe2ju2FPf08gnIjH/SdCrJuFK8q7Z5MT
+C9ijmXiajracUe+7eCluqgXRE8yRtnscWoA/9fVFz1lPwgEeNHLoaK7Sqew=
+"""
+
+ def testDerCodec(self):
+ substrate = pem.readBase64fromText(self.manifest_pem_text)
+
+ layers = { }
+ layers.update(rfc5652.cmsContentTypesMap)
+
+ getNextLayer = {
+ rfc5652.id_ct_contentInfo: lambda x: x['contentType'],
+ rfc5652.id_signedData: lambda x: x['encapContentInfo']['eContentType'],
+ rfc6486.id_ct_rpkiManifest: lambda x: None
+ }
+
+ getNextSubstrate = {
+ rfc5652.id_ct_contentInfo: lambda x: x['content'],
+ rfc5652.id_signedData: lambda x: x['encapContentInfo']['eContent'],
+ rfc6486.id_ct_rpkiManifest: lambda x: None
+ }
+
+ next_layer = rfc5652.id_ct_contentInfo
+ while next_layer:
+ asn1Object, rest = der_decode(substrate, asn1Spec=layers[next_layer])
+ assert not rest
+ assert asn1Object.prettyPrint()
+ assert der_encode(asn1Object) == substrate
+
+ substrate = getNextSubstrate[next_layer](asn1Object)
+ next_layer = getNextLayer[next_layer](asn1Object)
+
+ assert asn1Object['version'] == 0
+ for f in asn1Object['fileList']:
+ assert f['file'] == 'ZXSGBDBkL82TFGHuE4VOYtJP-E4.crl'
+
+ def testOpenTypes(self):
+ substrate = pem.readBase64fromText(self.manifest_pem_text)
+ asn1Object, rest = der_decode(substrate,
+ asn1Spec=rfc5652.ContentInfo(),
+ decodeOpenTypes=True)
+ assert not rest
+ assert asn1Object.prettyPrint()
+ assert der_encode(asn1Object) == substrate
+
+ oid = asn1Object['content']['encapContentInfo']['eContentType']
+ substrate = asn1Object['content']['encapContentInfo']['eContent']
+ assert oid in rfc5652.cmsContentTypesMap.keys()
+ asn1Object, rest = der_decode(substrate,
+ asn1Spec=rfc5652.cmsContentTypesMap[oid],
+ decodeOpenTypes=True)
+ assert not rest
+ assert asn1Object.prettyPrint()
+ assert der_encode(asn1Object) == substrate
+
+ assert asn1Object['version'] == 0
+ for f in asn1Object['fileList']:
+ assert f['file'] == 'ZXSGBDBkL82TFGHuE4VOYtJP-E4.crl'
+
+
+suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__])
+
+if __name__ == '__main__':
+ import sys
+
+ result = unittest.TextTestRunner(verbosity=2).run(suite)
+ sys.exit(not result.wasSuccessful())