From f2c70a401ccb1af92267f285f43c09ea9cd093e7 Mon Sep 17 00:00:00 2001 From: Russ Housley Date: Fri, 15 Nov 2019 13:13:04 -0500 Subject: Add support for RFC 4334 and fix errata for RFC 3770 (#105) --- CHANGES.txt | 3 ++ pyasn1_modules/rfc3770.py | 14 +++++++- pyasn1_modules/rfc4334.py | 75 +++++++++++++++++++++++++++++++++++++++++ tests/__main__.py | 1 + tests/test_rfc4334.py | 85 +++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 177 insertions(+), 1 deletion(-) create mode 100644 pyasn1_modules/rfc4334.py create mode 100644 tests/test_rfc4334.py diff --git a/CHANGES.txt b/CHANGES.txt index 0838373..1b5e1ac 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -36,6 +36,9 @@ Revision 0.2.8, released XX-XX-2019 - Add RFC4043 providing Internet X.509 PKI Permanent Identifier - Add RFC7585 providing Network Access Identifier (NAI) Realm Name for Certificates +- Update RFC3770 to support openType for attributes and reported errata +- Add RFC4334 providing Certificate Extensions and Attributes for + Authentication in PPP and Wireless LAN Networks Revision 0.2.7, released 09-10-2019 ----------------------------------- diff --git a/pyasn1_modules/rfc3770.py b/pyasn1_modules/rfc3770.py index a347fb3..3fefe1d 100644 --- a/pyasn1_modules/rfc3770.py +++ b/pyasn1_modules/rfc3770.py @@ -11,6 +11,7 @@ # # ASN.1 source from: # https://www.rfc-editor.org/rfc/rfc3770.txt +# https://www.rfc-editor.org/errata/eid234 # from pyasn1.type import constraint @@ -49,8 +50,9 @@ SSIDList.subtypeSpec=constraint.ValueSizeConstraint(1, MAX) # Wireless LAN SSID Attribute Certificate Attribute # Uses same syntax as the certificate extension: SSIDList +# Correction for https://www.rfc-editor.org/errata/eid234 -id_aca_wlanSSID = univ.ObjectIdentifier('1.3.6.1.5.5.7.10.6') +id_aca_wlanSSID = univ.ObjectIdentifier('1.3.6.1.5.5.7.10.7') # Map of Certificate Extension OIDs to Extensions @@ -61,3 +63,13 @@ _certificateExtensionsMap = { } rfc5280.certificateExtensionsMap.update(_certificateExtensionsMap) + + +# Map of AttributeType OIDs to AttributeValue added to the +# ones that are in rfc5280.py + +_certificateAttributesMapUpdate = { + id_aca_wlanSSID: SSIDList(), +} + +rfc5280.certificateAttributesMap.update(_certificateAttributesMapUpdate) diff --git a/pyasn1_modules/rfc4334.py b/pyasn1_modules/rfc4334.py new file mode 100644 index 0000000..44cd31b --- /dev/null +++ b/pyasn1_modules/rfc4334.py @@ -0,0 +1,75 @@ +# +# 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 +# +# Certificate Extensions and Attributes Supporting Authentication +# in PPP and Wireless LAN Networks +# +# ASN.1 source from: +# https://www.rfc-editor.org/rfc/rfc4334.txt +# + +from pyasn1.type import constraint +from pyasn1.type import univ + +from pyasn1_modules import rfc5280 + +MAX = float('inf') + + +# OID Arcs + +id_pe = univ.ObjectIdentifier('1.3.6.1.5.5.7.1') + +id_kp = univ.ObjectIdentifier('1.3.6.1.5.5.7.3') + +id_aca = univ.ObjectIdentifier('1.3.6.1.5.5.7.10') + + +# Extended Key Usage Values + +id_kp_eapOverPPP = id_kp + (13, ) + +id_kp_eapOverLAN = id_kp + (14, ) + + +# Wireless LAN SSID Extension + +id_pe_wlanSSID = id_pe + (13, ) + +class SSID(univ.OctetString): + constraint.ValueSizeConstraint(1, 32) + + +class SSIDList(univ.SequenceOf): + componentType = SSID() + subtypeSpec=constraint.ValueSizeConstraint(1, MAX) + + +# Wireless LAN SSID Attribute Certificate Attribute + +id_aca_wlanSSID = id_aca + (7, ) + + +# Map of Certificate Extension OIDs to Extensions +# To be added to the ones that are in rfc5280.py + +_certificateExtensionsMap = { + id_pe_wlanSSID: SSIDList(), +} + +rfc5280.certificateExtensionsMap.update(_certificateExtensionsMap) + + +# Map of AttributeType OIDs to AttributeValue added to the +# ones that are in rfc5280.py + +_certificateAttributesMapUpdate = { + id_aca_wlanSSID: SSIDList(), +} + +rfc5280.certificateAttributesMap.update(_certificateAttributesMapUpdate) diff --git a/tests/__main__.py b/tests/__main__.py index a019541..dd0bc32 100644 --- a/tests/__main__.py +++ b/tests/__main__.py @@ -41,6 +41,7 @@ suite = unittest.TestLoader().loadTestsFromNames( 'tests.test_rfc4108.suite', 'tests.test_rfc4210.suite', 'tests.test_rfc4211.suite', + 'tests.test_rfc4334.suite', 'tests.test_rfc4985.suite', 'tests.test_rfc5035.suite', 'tests.test_rfc5083.suite', diff --git a/tests/test_rfc4334.py b/tests/test_rfc4334.py new file mode 100644 index 0000000..ff4b252 --- /dev/null +++ b/tests/test_rfc4334.py @@ -0,0 +1,85 @@ +# +# This file is part of pyasn1-modules software. +# +# Created by Russ Housley +# 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.compat.octets import str2octs + +from pyasn1_modules import pem +from pyasn1_modules import rfc5280 +from pyasn1_modules import rfc4334 + +try: + import unittest2 as unittest +except ImportError: + import unittest + +class CertificateTestCase(unittest.TestCase): + cert_pem_text = """\ +MIICqzCCAjCgAwIBAgIJAKWzVCgbsG4/MAoGCCqGSM49BAMDMD8xCzAJBgNVBAYT +AlVTMQswCQYDVQQIDAJWQTEQMA4GA1UEBwwHSGVybmRvbjERMA8GA1UECgwIQm9n +dXMgQ0EwHhcNMTkwNzE5MTk0MjQ3WhcNMjAwNzE4MTk0MjQ3WjBjMQswCQYDVQQG +EwJVUzELMAkGA1UECBMCVkExEDAOBgNVBAcTB0hlcm5kb24xGzAZBgNVBAoTElZp +Z2lsIFNlY3VyaXR5IExMQzEYMBYGA1UEAxMPZWFwLmV4YW1wbGUuY29tMHYwEAYH +KoZIzj0CAQYFK4EEACIDYgAEMMbnIp2BUbuyMgH9HhNHrh7VBy7ql2lBjGRSsefR +Wa7+vCWs4uviW6On4eem5YoP9/UdO7DaIL+/J9/3DJHERI17oFxn+YWiE4JwXofy +QwfSu3cncVNMqpiDjEkUGGvBo4HTMIHQMAsGA1UdDwQEAwIHgDBCBglghkgBhvhC +AQ0ENRYzVGhpcyBjZXJ0aWZpY2F0ZSBjYW5ub3QgYmUgdHJ1c3RlZCBmb3IgYW55 +IHB1cnBvc2UuMB0GA1UdDgQWBBSDjPGr7M742rsE4oQGwBvGvllZ+zAfBgNVHSME +GDAWgBTyNds0BNqlVfK9aQOZsGLs4hUIwTAeBggrBgEFBQcBDQQSMBAEB0V4YW1w +bGUEBUJvZ3VzMB0GA1UdJQQWMBQGCCsGAQUFBwMOBggrBgEFBQcDDTAKBggqhkjO +PQQDAwNpADBmAjEAmCPZnnlUQOKlcOIIOgFrRCkOqO0ESs+dobYwAc2rFCBtQyP7 +C3N00xkX8WZZpiAZAjEAi1Z5+nGbJg5eJTc8fwudutN/HNwJEIS6mHds9kfcy26x +DAlVlhox680Jxy5J8Pkx +""" + + def setUp(self): + self.asn1Spec = rfc5280.Certificate() + + def testDerCodec(self): + substrate = pem.readBase64fromText(self.cert_pem_text) + asn1Object, rest = der_decode(substrate, asn1Spec=self.asn1Spec) + assert not rest + assert asn1Object.prettyPrint() + assert der_encode(asn1Object) == substrate + + def testOpenTypes(self): + substrate = pem.readBase64fromText(self.cert_pem_text) + asn1Object, rest = der_decode(substrate, + asn1Spec=self.asn1Spec, + decodeOpenTypes=True) + assert not rest + assert asn1Object.prettyPrint() + assert der_encode(asn1Object) == substrate + + extn_list = [ ] + for extn in asn1Object['tbsCertificate']['extensions']: + extn_list.append(extn['extnID']) + if extn['extnID'] in rfc5280.certificateExtensionsMap.keys(): + extnValue, rest = der_decode(extn['extnValue'], + asn1Spec=rfc5280.certificateExtensionsMap[extn['extnID']]) + assert der_encode(extnValue) == extn['extnValue'] + + if extn['extnID'] == rfc4334.id_pe_wlanSSID: + assert str2octs('Example') in extnValue + + if extn['extnID'] == rfc5280.id_ce_extKeyUsage: + assert rfc4334.id_kp_eapOverLAN in extnValue + assert rfc4334.id_kp_eapOverPPP in extnValue + + assert rfc4334.id_pe_wlanSSID in extn_list + assert rfc5280.id_ce_extKeyUsage in extn_list + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == '__main__': + unittest.TextTestRunner(verbosity=2).run(suite) -- cgit v1.2.3